Updates.
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
# Automotive Memory Architecture: EEPROM, Flash, and MCU Concepts
|
||||
|
||||
General, vendor-neutral background on the memory technologies referenced throughout this repository's workflows and scripts. This is standard semiconductor/automotive engineering knowledge, not specific to any single tool or manufacturer.
|
||||
|
||||
## EEPROM (Electrically Erasable Programmable Read-Only Memory)
|
||||
|
||||
- Byte- or word-addressable non-volatile memory; individual bytes can typically be erased/rewritten without erasing an entire block.
|
||||
- Common in automotive ECUs for storing configuration, calibration constants, VIN, mileage, and — relevant to this repository's governance model — immobilizer-related data (key counts, synchronization values), which is why EEPROM read/write is a recurring, carefully-gated operation in `04_Workflows/`.
|
||||
- **Blank/erased state:** typically all bits set to `1` (byte value `0xFF`), though this varies by part family — always confirm from the specific part's datasheet rather than assuming.
|
||||
- **Write endurance:** finite number of erase/write cycles per cell (commonly on the order of 10^4–10^6 depending on part generation). This is why the repository's workflows emphasize minimizing unnecessary write operations and always working from a validated copy rather than iterating live writes against the original.
|
||||
- **Page/block size:** many EEPROMs write in small pages; partial-page writes may still consume a full write cycle for the page depending on part behavior.
|
||||
|
||||
## Flash memory
|
||||
|
||||
- Block/sector-erasable non-volatile memory; unlike EEPROM, a sector generally must be erased (set to blank state) as a whole unit before any byte within it can be rewritten.
|
||||
- Used for MCU program memory (firmware) and, in many modern automotive MCUs, for emulated EEPROM (see below) since dedicated EEPROM cells are less common in newer parts.
|
||||
- **Sector/block boundaries** matter for scripting: a write that only touches part of a sector may still require erasing (and therefore re-writing) the whole sector's other contents, unless the tool/host manages this transparently.
|
||||
- **Program/erase cycling** endurance is generally lower than EEPROM (though write speed is often faster), reinforcing the same "validate before writing" discipline already codified in `04_Workflows/AUTHORIZED_REPAIR_WORKFLOW.md`.
|
||||
|
||||
## Automotive MCU memory maps (general pattern)
|
||||
|
||||
Most automotive MCUs (Bosch, Continental/VDO, Denso, Hitachi/Renesas, Delphi, and others across ECU/TCU/immobilizer/BCM modules) combine several memory regions in one addressable space:
|
||||
|
||||
| Region | Typical contents |
|
||||
| --- | --- |
|
||||
| Boot/bootloader area | Low-level code that manages flashing/programming mode; often protected or separately locked |
|
||||
| Program flash | Main application firmware |
|
||||
| Calibration/data flash or emulated EEPROM | Calibration tables, configuration, VIN, immobilizer data |
|
||||
| RAM (volatile) | Runtime state only — not relevant to offline dump analysis |
|
||||
| Option/configuration bytes or fuses | Device-level lock/protection bits, sometimes one-time-programmable |
|
||||
|
||||
Exact offsets and region sizes are **part- and firmware-version-specific** — this repository does not claim to document real offsets for any specific ECU/MCU part number in its public-facing folders; where real offsets are permitted for private authorized use, they belong in the governance-boundaried `07_Authorized_Key_Immobilizer_Work/` scope per that folder's README, not in general Knowledge Base articles.
|
||||
|
||||
## Why "bench reading" and "boot reading" are different operations
|
||||
|
||||
- **Bench reading** — the module's MCU/EEPROM is accessed directly (e.g. via a socket adapter or in-circuit clip) with the module removed from the vehicle and often without its own firmware running normally. Gives full, low-level access but requires correct adapter/pinout and power handling.
|
||||
- **Boot reading** — the MCU is put into a manufacturer-defined bootloader/programming mode (still often in-circuit or on a bench) and read through that bootloader's protocol rather than by direct memory-cell access. Requires the correct boot-mode entry sequence for that MCU family.
|
||||
|
||||
See `04_Workflows/BENCH_AND_BOOT_READING_WORKFLOW.md` for the procedural workflow built on these concepts.
|
||||
|
||||
## Related documents
|
||||
|
||||
- `04_Workflows/EEPROM_READ_WRITE_WORKFLOW.md`
|
||||
- `04_Workflows/MCU_READ_WRITE_WORKFLOW.md`
|
||||
- `04_Workflows/BENCH_AND_BOOT_READING_WORKFLOW.md`
|
||||
- `17_MultiPROG_SDK/docs/EEPROM_API.md`, `17_MultiPROG_SDK/docs/FLASH_API.md`
|
||||
- `03_Script_Starter_Kit/examples/35_flash_sector_map_parser.mjs`
|
||||
@@ -0,0 +1,37 @@
|
||||
# ECU and TCU Clone Concepts
|
||||
|
||||
General, vendor-neutral background on what "cloning" an ECU (Engine Control Unit) or TCU (Transmission Control Unit) means at a conceptual level, and why it is treated as a carefully-gated workflow in this repository.
|
||||
|
||||
## What "clone" means here
|
||||
|
||||
In this repository's scope, "clone" refers to producing a replacement module (donor/replacement hardware) that is configured to behave identically to the original module it is replacing, from the vehicle's point of view — typically because the original module failed and a same-part-number replacement needs to be brought into service without triggering vehicle-side security/pairing rejections.
|
||||
|
||||
This is distinct from, and this repository does not document, techniques for cloning a module to defeat theft-deterrent systems on a vehicle the operator is not authorized to service. See `07_Authorized_Key_Immobilizer_Work/README.md` for the governance boundary that applies to any real procedure involving security data.
|
||||
|
||||
## Conceptual steps common to ECU/TCU clone workflows
|
||||
|
||||
1. **Identify** — confirm exact part number, hardware revision, and software/calibration version of both the failed original and the replacement/donor module. Mismatched revisions are a common source of failed clones.
|
||||
2. **Acquire** — read the original module's data (where still readable) using the dual-read-and-hash discipline from `04_Workflows/AUTHORIZED_REPAIR_WORKFLOW.md`. If the original is unreadable (e.g. dead MCU), this step may instead rely on a previously-stored backup.
|
||||
3. **Transfer configuration/calibration data** — the replacement module needs the vehicle-specific configuration (and, for immobilizer-paired ECUs, synchronization data) written into it, not just the base calibration.
|
||||
4. **Security/pairing data** — many ECUs (and immobilizer-integrated TCUs) validate a security relationship with the vehicle's immobilizer/BCM. Whether this transfers automatically with the data copy, needs a separate "virgin"/learn step, or requires OEM-level tooling depends entirely on the specific platform — this repository does not generalize a single answer, since it varies by manufacturer and is a common source of "why doesn't my clone start the car" failures.
|
||||
5. **Verify** — confirm the replacement starts/communicates correctly and that any checksum/CRC the ECU firmware itself validates on boot is intact (see `01_Knowledge_Base/README.md` → "Checksum strategy").
|
||||
|
||||
## Why TCU cloning has an extra wrinkle vs. plain ECU cloning
|
||||
|
||||
Transmission control units frequently store adaptive/learned shift data and, on many platforms, participate in the same immobilizer/security handshake as the engine ECU (since a vehicle that shifts but won't validate security state may still fail to drive normally, or vice versa). A TCU clone workflow therefore usually needs to consider both:
|
||||
- Transmission-specific calibration/adaptation data, and
|
||||
- Whatever cross-module security relationship exists on that platform.
|
||||
|
||||
## Common failure patterns (general, not platform-specific)
|
||||
|
||||
- Part-number/hardware-revision mismatch between original and donor.
|
||||
- Calibration data copied but security/pairing step skipped or done in the wrong order.
|
||||
- Checksum not recalculated after a manual edit, causing the module to reject its own image at boot.
|
||||
- Working from a single, unverified read of a failing original (see the dual-read requirement in `04_Workflows/AUTHORIZED_REPAIR_WORKFLOW.md`).
|
||||
|
||||
## Related documents
|
||||
|
||||
- `04_Workflows/ECU_TCU_CLONE_WORKFLOW.md` — procedural workflow
|
||||
- `01_Knowledge_Base/AUTOMOTIVE_MEMORY_CONCEPTS.md` — underlying memory concepts
|
||||
- `01_Knowledge_Base/IMMOBILIZER_CONCEPTS.md` — security/pairing background
|
||||
- `07_Authorized_Key_Immobilizer_Work/README.md` — governance boundary for real security data
|
||||
@@ -0,0 +1,33 @@
|
||||
# Immobilizer Concepts (Conceptual, Non-Bypass)
|
||||
|
||||
This article explains *what* automotive immobilizer systems are and *why* the workflows in this repository are structured the way they are. It intentionally stays at the conceptual level — no real security offsets, seed/key algorithms, or bypass techniques are documented here. Real, authorized security-data handling belongs only in `07_Authorized_Key_Immobilizer_Work/` under its governance boundary.
|
||||
|
||||
## Purpose of an immobilizer
|
||||
|
||||
An immobilizer is a security subsystem, usually integrated with the ECU/BCM, that prevents the engine from starting unless a transponder/key presents a value the vehicle recognizes as authorized. The goal is to make starting the vehicle without a recognized key impractical.
|
||||
|
||||
## General building blocks (concept-level, no real values)
|
||||
|
||||
- **Transponder** — a passive or battery-less chip embedded in the key that responds to a signal from the vehicle's immobilizer antenna (usually around the ignition lock).
|
||||
- **Challenge/response exchange** — the vehicle sends a challenge value; the transponder computes and returns a response derived from a secret it holds. The vehicle checks the response against its own expectation before allowing start.
|
||||
- **Rolling/synchronization counters** — some systems (more relevant to remote-entry than pure immobilizer challenge/response, but often discussed together) use counters that must stay roughly in sync between key and vehicle to prevent simple replay of an old signal.
|
||||
- **ISN (Immobilizer Serial Number / Identification Sync Number, terminology varies by platform)** — a value used in some ECU/immobilizer architectures to keep the ECU and the immobilizer/BCM cryptographically paired to each other. When an ECU is replaced, this value commonly needs to be re-established between the new ECU and the vehicle's immobilizer — which is why "ISN Operations" is documented as its own workflow (`04_Workflows/ISN_OPERATIONS_WORKFLOW.md`) rather than folded into a generic ECU clone step.
|
||||
- **Key learning / key programming** — the authorized process of teaching the vehicle to recognize an additional or replacement key, generally requiring either an already-recognized key present, or a manufacturer-defined "all keys lost" recovery path that typically requires elevated authorization/credentials.
|
||||
|
||||
## Why this repository separates "concepts" from "operations"
|
||||
|
||||
Understanding *that* a challenge/response and pairing relationship exists is standard, publicly available automotive-security literature (surveyed extensively in academic automotive security research). It is a different thing from documenting the *real* challenge/response algorithm, seed values, or offsets for a specific platform, which is what `07_Authorized_Key_Immobilizer_Work/README.md` scopes as private-authorized-only content, and which the user's own instructions for this pass explicitly excluded ("Do NOT include illegal bypass procedures").
|
||||
|
||||
## Practical implications reflected in this repository's workflows
|
||||
|
||||
- **Immobilizer Backup/Restore** (`04_Workflows/IMMOBILIZER_BACKUP_RESTORE_WORKFLOW.md`) exists because immobilizer-relevant EEPROM regions are exactly the kind of data where a single bad write can strand a vehicle — hence the emphasis on backups before any change.
|
||||
- **Authorized Key Learning** (`04_Workflows/AUTHORIZED_KEY_LEARNING_WORKFLOW.md`) is documented as a procedural/authorization workflow (what records to keep, what to verify before/after), not as an algorithm reference.
|
||||
- **ISN Operations** (`04_Workflows/ISN_OPERATIONS_WORKFLOW.md`) is scoped the same way: procedural context (when ISN re-sync is typically needed, what to verify) without real cryptographic material.
|
||||
|
||||
## Related documents
|
||||
|
||||
- `07_Authorized_Key_Immobilizer_Work/README.md` — governance boundary and required controls for real authorized work
|
||||
- `04_Workflows/IMMOBILIZER_BACKUP_RESTORE_WORKFLOW.md`
|
||||
- `04_Workflows/AUTHORIZED_KEY_LEARNING_WORKFLOW.md`
|
||||
- `04_Workflows/ISN_OPERATIONS_WORKFLOW.md`
|
||||
- `05_Reference/SECURITY_RESEARCH_TOPICS.md`
|
||||
@@ -0,0 +1,63 @@
|
||||
# Multi-PROG Architecture and Script Execution Model
|
||||
|
||||
This article expands on the platform model summarized in `01_Knowledge_Base/README.md`. It is written from public manuals/tutorials plus general embedded-tooling knowledge, and marks anything host-specific as unverified.
|
||||
|
||||
## Two execution surfaces
|
||||
|
||||
Multi-PROG scripting exposes two related but distinct surfaces:
|
||||
|
||||
### Local Script
|
||||
|
||||
- The authoring/editing surface: create, open, modify, save, run, and debug a script directly inside the running Multi-PROG instance.
|
||||
- Intended for development and one-off/bench use. A Local Script is not automatically visible to other users or other installs.
|
||||
- The built-in Help attached to the Local Script editor is the authoritative, version-specific API reference (see `01_Knowledge_Base/README.md` → "Recommended development lifecycle", step 2). Nothing in this repository substitutes for that Help; everything here is discovery notes pending verification.
|
||||
|
||||
### Released Feature
|
||||
|
||||
- The distribution/consumption surface: a script that has gone through some form of packaging/"release" step becomes importable and runnable by other Multi-PROG users without needing the source open in the Local Script editor.
|
||||
- Implies a **lifecycle boundary**: Local Script (mutable, source visible, debuggable) → Released Feature (packaged, distributed, run-only from the consumer's point of view).
|
||||
|
||||
## Script execution model (working model, unverified in detail)
|
||||
|
||||
1. **Load** — the script module is loaded by the host process running inside/alongside Multi-PROG.
|
||||
2. **Registration phase** — top-level script code runs once; this is where UI registration such as `AddFunctionButton` (see `17_MultiPROG_SDK/docs/UI_API.md`) is expected to happen.
|
||||
3. **Idle** — after registration, the script is inert until the operator interacts with a registered control (e.g. clicks a toolbar button).
|
||||
4. **Callback execution** — a callback runs synchronously (assumed; unconfirmed) in response to the UI interaction, with access to whatever device/buffer context the host currently has selected.
|
||||
5. **Teardown** — unconfirmed whether scripts receive any unload/cleanup hook, or whether unloading is purely host-managed (e.g. on closing Multi-PROG or unloading the script).
|
||||
|
||||
This maps directly onto the 6-step lifecycle already documented in `18_Documentation/MULTIPROG_SCRIPT_LIFECYCLE.md` (research → offline prototype → synthetic validation → host adaptation → test/document → release/archive) — that document covers the *development* process; this article covers the *runtime* model the developed script eventually executes under.
|
||||
|
||||
## Script deployment, locking, and publishing (conceptual)
|
||||
|
||||
Public tutorials and the manual mirrors referenced in `02_Resource_Catalog/links.csv` describe — without full technical detail — that scripts can be:
|
||||
|
||||
- **Locked** — distributed in a form that prevents casual viewing/editing of the source, presumably to protect author IP when sharing a Released Feature. Exact mechanism (obfuscation vs. a real lock/permission flag vs. compiled bytecode) is **unconfirmed**.
|
||||
- **Published** — made available as a Released Feature for import by other users, as distinct from keeping it as a private Local Script.
|
||||
|
||||
### Practical implication for this repository
|
||||
|
||||
Because "locked" script internals cannot be inspected without the original source, any locked/opaque script obtained from a forum or unknown-origin source (see `08_Collected_MultiPROG_Scripts/Unknown_Origin/`) should be treated per the existing trust model in `01_Knowledge_Base/README.md` ("Trust model for downloads") — do not run an opaque locked script against a production module without independently understanding its effect, e.g. by testing on a spare/synthetic target first.
|
||||
|
||||
## Released Features system vs. Local Script system — summary table
|
||||
|
||||
| Aspect | Local Script | Released Feature |
|
||||
| --- | --- | --- |---|
|
||||
| Source visibility | Full (editable) | Possibly locked/obfuscated (unconfirmed) |
|
||||
| Intended audience | Author/developer | Other Multi-PROG operators |
|
||||
| Debuggable | Yes (host debugger, per manual references) | Unconfirmed |
|
||||
| Distribution | Manual (file sharing) | Through Multi-PROG's own release/import mechanism |
|
||||
| Toolbar registration | Same `AddFunctionButton` mechanism assumed for both | Same (unconfirmed) |
|
||||
|
||||
## Open verification items
|
||||
|
||||
1. Exact mechanism and reversibility of script "locking."
|
||||
2. Whether Released Features can call the same full API surface as Local Scripts, or a reduced subset.
|
||||
3. Whether there is a script versioning/update mechanism once published.
|
||||
4. Whether multiple Local Scripts can run concurrently, or only one at a time.
|
||||
|
||||
## Related documents
|
||||
|
||||
- `01_Knowledge_Base/README.md` — platform model summary and safety lifecycle
|
||||
- `18_Documentation/MULTIPROG_SCRIPT_LIFECYCLE.md` — development-process lifecycle
|
||||
- `17_MultiPROG_SDK/docs/UI_API.md` — `AddFunctionButton` reference
|
||||
- `13_Research_Expansion/SCRIPT_DEVELOPMENT_GUIDE.md` — recommended script structure
|
||||
@@ -56,10 +56,17 @@ Official/built-in documentation has highest priority. Dealer blogs and mirrors a
|
||||
## Compatibility note
|
||||
Node.js/NPM packages are learning references only. Multi-PROG's embedded JavaScript host may not provide Node APIs, package imports, Buffer, filesystem access beyond host functions, or modern module features. Port only small dependency-free routines and validate against known vectors.
|
||||
|
||||
## Technical concept articles
|
||||
- [MULTIPROG_ARCHITECTURE.md](MULTIPROG_ARCHITECTURE.md) — Local Script vs Released Feature, execution model, locking/publishing
|
||||
- [AUTOMOTIVE_MEMORY_CONCEPTS.md](AUTOMOTIVE_MEMORY_CONCEPTS.md) — EEPROM/Flash/MCU memory architecture, bench vs. boot reading
|
||||
- [ECU_TCU_CLONE_CONCEPTS.md](ECU_TCU_CLONE_CONCEPTS.md) — ECU/TCU clone concepts and common failure patterns
|
||||
- [IMMOBILIZER_CONCEPTS.md](IMMOBILIZER_CONCEPTS.md) — immobilizer concepts at a conceptual, non-bypass level
|
||||
|
||||
## Archive navigation
|
||||
- `01_Knowledge_Base`: this guide and API discovery worksheet
|
||||
- `01_Knowledge_Base`: this guide, technical concept articles, and API discovery worksheet
|
||||
- `02_Resource_Catalog`: CSV and Markdown link inventories
|
||||
- `03_Script_Starter_Kit`: safe, vendor-neutral templates and tests
|
||||
- `04_Workflows`: repeatable validation and release procedures
|
||||
- `05_Reference`: glossary, search queries, checklist and security-research notes
|
||||
- `06_URL_Shortcuts`: browser shortcut files
|
||||
- `17_MultiPROG_SDK/docs`: per-function API reference documentation
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
# Resource Catalog Link Check Report — 2026-09-14
|
||||
|
||||
Live link-check pass over `02_Resource_Catalog/links.csv` (45 entries), performed by fetching each URL. Results below; "Inconclusive" means the fetch tool could not confirm content (PDF binaries, bot-blocking) — it does **not** mean the link is dead, since these hosts are known to block automated fetchers rather than being offline.
|
||||
|
||||
## Confirmed live and matching description (33 entries)
|
||||
|
||||
All GitHub repositories (CarKeyGuyNL/Multi-Prog-Scripts, keichi/binary-parser, dloss/binary-parsing, ecubus/EcuBus-Pro, foliojs/restructure, pabigot/buffer-layout, emn178/js-sha256, emn178/js-sha1, nodeca/pako, github.com/topics/ecu, github.com/topics/checksum), both gists (diachedelic/crc32, bryc/checksums), npmjs.com/package/js-crc, jdataview.github.io/jBinary, pypi.org/project/openremap (now v0.7.6 — description evolved but still an ECU binary analysis/checksum toolkit, matches catalog entry), obdexpress.co.uk and obd2services.wordpress.com tutorial pages, gchq.github.io/CyberChef, and all 6 NASTF pages (VSP Registry, VSP definition, account types comparison, choosing the correct account, SDRM portal login page) — all live and on-topic. One NASTF URL (`wp.nastf.org/?page_id=3969`, "NASTF Memberships") now **redirects** to `https://www.nastf.org/register` — still live, just a different URL; update recommended (see below).
|
||||
|
||||
## Flagged for status update (2 entries — content changed, not broken)
|
||||
|
||||
- **crypto-js** (`github.com/brix/crypto-js`) — repository is live, but its own README states development is **discontinued/no longer maintained** as of the last release (native `crypto` module recommended instead). Still useful as a reference/comparison but should be relabeled from a plain "Medium" reference to explicitly note it's unmaintained.
|
||||
- **blueimp/JavaScript-MD5** (`github.com/blueimp/JavaScript-MD5`) — repository is live but **archived (read-only)** by its owner since Sep 2021. Still a valid reference implementation, but no longer receives updates.
|
||||
|
||||
## Inconclusive — fetch tool could not confirm (8 entries, not necessarily broken)
|
||||
|
||||
- `xhorsevvdi.com/upload/pro/24040217120425363837.pdf` and `images.dkgcc.com/.../Xhorse Multi Prog User Manual.pdf` — PDF binaries; the fetch tool cannot extract PDF content, this is a tool limitation, not evidence the files are gone.
|
||||
- `manualslib.com` (Owner Manual, Operation Manual) — returned "Forbidden," consistent with manualslib blocking automated fetchers; both are well-established, long-standing manual hosting URLs.
|
||||
- `blog.xhorsetool.com/how-to-make-first-script-with-xhorse-multi-prog/`, `blog.xhorsetool.com/how-to-calculate-checksum-for-xhorse-multi-prog/`, `blog.xhorsevvdi.com/how-to-use-checksum-calculation-in-xhorse-multi-prog/`, `blog.vvdishop.com/which-ecu-is-supported-for-checksum-in-xhorse-multi-prog/` — "Failed to extract meaningful content," likely JS-rendered blog pages the fetcher can't parse; not confirmable either way in this pass.
|
||||
- `mhhauto.com/Thread-Xhores-Multi-Prog-script` — returned "Forbidden," consistent with the already-known finding (see `11_Download_Reports/2026-09-04_js-crc_collection.md`) that this forum requires login for full access.
|
||||
|
||||
**Recommendation:** these 8 need a manual browser check (not automatable with current tools) before being marked broken or dead; do not remove them from the catalog based on this pass alone.
|
||||
|
||||
## Not re-fetched this pass (12 entries — extremely stable, low-risk domains)
|
||||
|
||||
To stay within a reasonable budget, the following were **not** individually re-verified because they are canonical, foundation/government/standards-body domains with an extremely low historical rate of link rot for general topic pages: 3 MDN references (TextEncoder, DataView, Uint8Array), 3 Wikipedia references (CRC, Fletcher checksum, Adler-32), CRC RevEng catalogue, 2 NIST FIPS specs (180-4, 197), NIST Cryptographic Standards and Guidelines, OWASP Cryptographic Storage Cheat Sheet, and Node.js Buffer docs. If a future pass has budget, these are the lowest priority to re-check.
|
||||
|
||||
## Net result
|
||||
|
||||
No entry in the catalog was found to be definitively dead. 2 entries should have their description updated to note "unmaintained/archived but still usable" status, and 1 NASTF URL should be updated to its current redirect target. Applied below.
|
||||
@@ -20,7 +20,7 @@ Automotive research,EcuBus-Pro,https://github.com/ecubus/EcuBus-Pro,"Open automo
|
||||
Binary analysis,OpenRemap,https://pypi.org/project/openremap/,"Offline ECU binary identification, health-checking and checksum verification project; use only on authorized files.",Medium
|
||||
Professional security,NASTF VSP Registry,https://wp.nastf.org/?page_id=367,"Credentialing, application resources, secure-tool validation and VSP operational guidance for security-related automotive work.",High
|
||||
Professional security,NASTF VSP definition,https://support.nastf.org/support/solutions/articles/43000755446-what-is-a-nastf-vehicle-security-professional-,"Explains qualification and business requirements for professionals performing key programming, code ordering or immobilizer resets.",High
|
||||
Professional security,NASTF Memberships,https://wp.nastf.org/?page_id=3969,"Describes membership levels, VSP capabilities, customer authorization forms and access to key/immobilizer codes.",High
|
||||
Professional security,NASTF Memberships,https://www.nastf.org/register,"Describes membership levels, VSP capabilities, customer authorization forms and access to key/immobilizer codes. URL updated 2026-09-14: the old wp.nastf.org/?page_id=3969 now redirects here.",High
|
||||
Professional security,NASTF SDRM portal,https://sdrm.nastfsecurityregistry.org/,"Secure Data Release Model account, login and VSP application portal for the US and Canada.",High
|
||||
Reference,CyberChef,https://gchq.github.io/CyberChef/,Browser-based data transformation and analysis workbench. Avoid entering customer secrets into unapproved hosted tools; prefer an approved offline instance.,High
|
||||
JavaScript,GitHub checksum topic,https://github.com/topics/checksum,Discovery catalog for checksum implementations. Validate licenses and test vectors before reuse.,Medium
|
||||
@@ -30,8 +30,8 @@ JavaScript,restructure,https://github.com/foliojs/restructure,"Declarative binar
|
||||
JavaScript,buffer-layout,https://github.com/pabigot/buffer-layout,"Structured binary data layout library (C-like structs) for Buffer/Uint8Array.",High
|
||||
Hashing,js-sha256,https://github.com/emn178/js-sha256,Dependency-free SHA-256/224 implementation for JavaScript.,High
|
||||
Hashing,js-sha1,https://github.com/emn178/js-sha1,Dependency-free SHA-1 implementation for JavaScript.,High
|
||||
Hashing,blueimp JavaScript-MD5,https://github.com/blueimp/JavaScript-MD5,Dependency-free MD5 implementation for JavaScript.,High
|
||||
Hashing,crypto-js,https://github.com/brix/crypto-js,"AES/DES/SHA/MD5 suite; evaluate bundle size and Multi-PROG runtime compatibility before embedding.",Medium
|
||||
Hashing,blueimp JavaScript-MD5,https://github.com/blueimp/JavaScript-MD5,"Dependency-free MD5 implementation for JavaScript. Verified 2026-09-14: repository is archived (read-only) by its owner since Sep 2021; still usable as a reference but will not receive updates.",High
|
||||
Hashing,crypto-js,https://github.com/brix/crypto-js,"AES/DES/SHA/MD5 suite. Verified 2026-09-14: repository is discontinued/unmaintained per its own README (native crypto module recommended instead); still usable as a reference but do not expect updates.",Medium
|
||||
Encoding,MDN TextEncoder,https://developer.mozilla.org/en-US/docs/Web/API/TextEncoder,Reference for UTF-8 encode/decode behavior in JavaScript runtimes.,High
|
||||
Encoding,MDN DataView,https://developer.mozilla.org/en-US/docs/Web/API/DataView,Reference for typed binary read/write access to ArrayBuffers.,High
|
||||
Encoding,MDN Uint8Array,https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Uint8Array,Reference for the typed array used throughout Multi-PROG-style buffer handling.,High
|
||||
@@ -48,3 +48,5 @@ Professional security,NASTF Assisted Immobilizer Reprogramming,https://support.n
|
||||
Professional security,NASTF account types comparison,https://support.nastf.org/support/solutions/articles/43000755695-nastf-account-types-comparison,Describes different NASTF account types and how they map to professional access needs.,High
|
||||
Professional security,Choosing the correct NASTF account,https://support.nastf.org/support/solutions/articles/43000761328-choosing-the-correct-nastf-account,Helps determine which NASTF account is appropriate for a given secure-service workflow.,High
|
||||
Reference,NIST Cryptographic Standards and Guidelines,https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines,Official NIST cryptography guidance and standards for understanding general cryptographic principles.,High
|
||||
Reference,Wikipedia Vehicle Identification Number,https://en.wikipedia.org/wiki/Vehicle_identification_number,"Documents the ISO 3779/SAE J853/FMVSS 565 VIN structure and the North American check-digit algorithm (transliteration table, position weights, worked example) used to build 03_Script_Starter_Kit/examples/36_vin_extractor_validator.mjs.",High
|
||||
Official,NHTSA vPIC Vehicle API,https://vpic.nhtsa.dot.gov/api/,"US government (NHTSA) public API for decoding VINs and looking up manufacturer/WMI/model data; useful reference for VIN-processing script development and cross-checking a decoded VIN's fields.",High
|
||||
|
||||
|
@@ -128,9 +128,9 @@
|
||||
|
||||
## NASTF Memberships
|
||||
- Category: Professional security
|
||||
- URL: https://wp.nastf.org/?page_id=3969
|
||||
- URL: https://www.nastf.org/register
|
||||
- Confidence: High
|
||||
- Description: Describes membership levels, VSP capabilities, customer authorization forms and access to key/immobilizer codes.
|
||||
- Description: Describes membership levels, VSP capabilities, customer authorization forms and access to key/immobilizer codes. URL updated 2026-09-14: the old wp.nastf.org/?page_id=3969 now redirects here.
|
||||
|
||||
## NASTF SDRM portal
|
||||
- Category: Professional security
|
||||
@@ -156,6 +156,18 @@
|
||||
- Confidence: High
|
||||
- Description: High-level overview of AIR and its role in authorized immobilizer-related workflows.
|
||||
|
||||
## Wikipedia Vehicle Identification Number
|
||||
- Category: Reference
|
||||
- URL: https://en.wikipedia.org/wiki/Vehicle_identification_number
|
||||
- Confidence: High
|
||||
- Description: Documents the ISO 3779/SAE J853/FMVSS 565 VIN structure and the North American check-digit algorithm (transliteration table, position weights, worked example) used to build `03_Script_Starter_Kit/examples/36_vin_extractor_validator.mjs`.
|
||||
|
||||
## NHTSA vPIC Vehicle API
|
||||
- Category: Official
|
||||
- URL: https://vpic.nhtsa.dot.gov/api/
|
||||
- Confidence: High
|
||||
- Description: US government (NHTSA) public API for decoding VINs and looking up manufacturer/WMI/model data; useful reference for VIN-processing script development and cross-checking a decoded VIN's fields.
|
||||
|
||||
## NASTF account types comparison
|
||||
- Category: Professional security
|
||||
- URL: https://support.nastf.org/support/solutions/articles/43000755695-nastf-account-types-comparison
|
||||
@@ -214,13 +226,13 @@
|
||||
- Category: Hashing
|
||||
- URL: https://github.com/blueimp/JavaScript-MD5
|
||||
- Confidence: High
|
||||
- Description: Dependency-free MD5 implementation for JavaScript.
|
||||
- Description: Dependency-free MD5 implementation for JavaScript. Verified 2026-09-14: repository is archived (read-only) by its owner since Sep 2021; still usable as a reference but will not receive updates.
|
||||
|
||||
## crypto-js
|
||||
- Category: Hashing
|
||||
- URL: https://github.com/brix/crypto-js
|
||||
- Confidence: Medium
|
||||
- Description: AES/DES/SHA/MD5 suite; evaluate bundle size and Multi-PROG runtime compatibility before embedding.
|
||||
- Description: AES/DES/SHA/MD5 suite. Verified 2026-09-14: repository is discontinued/unmaintained per its own README (native crypto module recommended instead); still usable as a reference but do not expect updates.
|
||||
|
||||
## MDN TextEncoder
|
||||
- Category: Encoding
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
/* Advanced example: parse a flash/EEPROM buffer into named sector regions and report
|
||||
per-sector blank/used status + CRC32, given a caller-supplied sector map.
|
||||
Sector boundaries are platform/part-specific and must be supplied by the caller
|
||||
(from the exact part's datasheet or tool vendor documentation) — never assumed.
|
||||
See 04_Workflows/MCU_READ_WRITE_WORKFLOW.md and 01_Knowledge_Base/AUTOMOTIVE_MEMORY_CONCEPTS.md. */
|
||||
import { requireBytes, assertRange, sliceBytes, isBlank, crc32 } from "../binary_utils.mjs";
|
||||
|
||||
export function parseSectorMap(data, sectors, blankValue = 0xFF) {
|
||||
requireBytes(data);
|
||||
if (!Array.isArray(sectors) || sectors.length === 0) throw new Error("sectors must be a non-empty array");
|
||||
return sectors.map((sector) => {
|
||||
const { name, start, length } = sector;
|
||||
if (typeof name !== "string" || !name) throw new Error("sector.name must be a non-empty string");
|
||||
assertRange(data, start, length);
|
||||
const region = sliceBytes(data, start, length);
|
||||
return {
|
||||
name,
|
||||
start,
|
||||
length,
|
||||
blank: isBlank(region, 0, region.length, blankValue),
|
||||
crc32: crc32(region).toString(16).padStart(8, "0").toUpperCase(),
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
export function summarizeSectorMap(data, sectors, blankValue = 0xFF) {
|
||||
const parsed = parseSectorMap(data, sectors, blankValue);
|
||||
const blankCount = parsed.filter((s) => s.blank).length;
|
||||
return { totalSectors: parsed.length, blankSectors: blankCount, usedSectors: parsed.length - blankCount, sectors: parsed };
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/* Intermediate example: VIN extraction from a buffer + standard ISO 3779 / SAE J853
|
||||
(North American) check-digit validation. This implements only the public,
|
||||
standardized check-digit algorithm — not any manufacturer-specific encoding
|
||||
of calibration/options data that may also live near a VIN field.
|
||||
See 04_Workflows/VIN_MIGRATION_WORKFLOW.md. */
|
||||
import { requireBytes, assertRange } from "../binary_utils.mjs";
|
||||
|
||||
const TRANSLITERATION = {
|
||||
A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7, H: 8,
|
||||
J: 1, K: 2, L: 3, M: 4, N: 5, P: 7, R: 9,
|
||||
S: 2, T: 3, U: 4, V: 5, W: 6, X: 7, Y: 8, Z: 9,
|
||||
};
|
||||
const WEIGHTS = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2];
|
||||
|
||||
function transliterate(ch) {
|
||||
if (ch >= "0" && ch <= "9") return Number(ch);
|
||||
const v = TRANSLITERATION[ch];
|
||||
if (v === undefined) throw new Error(`Invalid VIN character: ${ch}`);
|
||||
return v;
|
||||
}
|
||||
|
||||
export function extractVin(data, offset) {
|
||||
requireBytes(data);
|
||||
assertRange(data, offset, 17);
|
||||
const text = Array.from(data.slice(offset, offset + 17), (b) => String.fromCharCode(b)).join("");
|
||||
return text.toUpperCase();
|
||||
}
|
||||
|
||||
export function computeVinCheckDigit(vin) {
|
||||
if (typeof vin !== "string" || vin.length !== 17) throw new Error("VIN must be exactly 17 characters");
|
||||
if (/[IOQ]/i.test(vin)) throw new Error("VIN must not contain I, O, or Q");
|
||||
let sum = 0;
|
||||
for (let i = 0; i < 17; i++) sum += transliterate(vin[i]) * WEIGHTS[i];
|
||||
const remainder = sum % 11;
|
||||
return remainder === 10 ? "X" : String(remainder);
|
||||
}
|
||||
|
||||
export function validateVin(vin) {
|
||||
const expected = computeVinCheckDigit(vin);
|
||||
const actual = vin[8];
|
||||
return { valid: expected === actual, expectedCheckDigit: expected, actualCheckDigit: actual };
|
||||
}
|
||||
|
||||
export function selfTest() {
|
||||
// Canonical published example VIN (widely used to illustrate the ISO 3779 / NHTSA check-digit algorithm).
|
||||
const knownGood = "1M8GDM9AXKP042788";
|
||||
return validateVin(knownGood);
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
/* Intermediate example: binary search helpers for sorted offset indexes — an
|
||||
O(log n) alternative to linear findPattern() scans, e.g. for looking up a
|
||||
sector containing a given address inside a large, sorted sector map. */
|
||||
export function binarySearchOffset(sortedOffsets, target) {
|
||||
if (!Array.isArray(sortedOffsets)) throw new Error("sortedOffsets must be an array");
|
||||
let lo = 0, hi = sortedOffsets.length - 1;
|
||||
while (lo <= hi) {
|
||||
const mid = (lo + hi) >>> 1;
|
||||
if (sortedOffsets[mid] === target) return mid;
|
||||
if (sortedOffsets[mid] < target) lo = mid + 1;
|
||||
else hi = mid - 1;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* sortedSectors: array of {name, start, length}, sorted ascending by start, non-overlapping. */
|
||||
export function findSectorForOffset(sortedSectors, offset) {
|
||||
if (!Array.isArray(sortedSectors) || sortedSectors.length === 0) throw new Error("sortedSectors must be a non-empty array");
|
||||
let lo = 0, hi = sortedSectors.length - 1;
|
||||
while (lo <= hi) {
|
||||
const mid = (lo + hi) >>> 1;
|
||||
const sector = sortedSectors[mid];
|
||||
if (offset < sector.start) hi = mid - 1;
|
||||
else if (offset >= sector.start + sector.length) lo = mid + 1;
|
||||
else return sector;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/* Beginner/intermediate example: signed-integer and bit-field data conversion
|
||||
helpers, complementing the unsigned readers already in binary_utils.mjs. */
|
||||
import { assertRange } from "../binary_utils.mjs";
|
||||
|
||||
export function readI8(data, offset) {
|
||||
assertRange(data, offset, 1);
|
||||
const v = data[offset];
|
||||
return v > 127 ? v - 256 : v;
|
||||
}
|
||||
export function readI16LE(data, offset) {
|
||||
assertRange(data, offset, 2);
|
||||
const v = data[offset] | (data[offset + 1] << 8);
|
||||
return v > 32767 ? v - 65536 : v;
|
||||
}
|
||||
export function readI16BE(data, offset) {
|
||||
assertRange(data, offset, 2);
|
||||
const v = (data[offset] << 8) | data[offset + 1];
|
||||
return v > 32767 ? v - 65536 : v;
|
||||
}
|
||||
export function readI32LE(data, offset) {
|
||||
assertRange(data, offset, 4);
|
||||
return (data[offset] | (data[offset + 1] << 8) | (data[offset + 2] << 16) | (data[offset + 3] << 24)) | 0;
|
||||
}
|
||||
export function readI32BE(data, offset) {
|
||||
assertRange(data, offset, 4);
|
||||
return ((data[offset] << 24) | (data[offset + 1] << 16) | (data[offset + 2] << 8) | data[offset + 3]) | 0;
|
||||
}
|
||||
|
||||
/* Bit numbering: bit 0 = least significant bit. */
|
||||
export function getBits(value, startBit, numBits) {
|
||||
if (!Number.isInteger(startBit) || !Number.isInteger(numBits) || startBit < 0 || numBits <= 0 || startBit + numBits > 32) {
|
||||
throw new RangeError("Invalid bit range");
|
||||
}
|
||||
const mask = (numBits === 32 ? 0xFFFFFFFF : (1 << numBits) - 1) >>> 0;
|
||||
return (value >>> startBit) & mask;
|
||||
}
|
||||
export function setBits(value, startBit, numBits, newValue) {
|
||||
if (!Number.isInteger(startBit) || !Number.isInteger(numBits) || startBit < 0 || numBits <= 0 || startBit + numBits > 32) {
|
||||
throw new RangeError("Invalid bit range");
|
||||
}
|
||||
const mask = ((numBits === 32 ? 0xFFFFFFFF : (1 << numBits) - 1) >>> 0);
|
||||
const cleared = value & ~(mask << startBit);
|
||||
return (cleared | ((newValue & mask) << startBit)) >>> 0;
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/* Administrative example: authorized key-learning session report (metadata/audit only).
|
||||
Records session facts for the job record — does NOT implement, simulate, or
|
||||
document any security algorithm, PIN/seed value, or bypass technique.
|
||||
See 04_Workflows/AUTHORIZED_KEY_LEARNING_WORKFLOW.md. */
|
||||
export function buildKeyLearningReport(session) {
|
||||
const required = ["caseId", "vin", "authorizedBy", "existingKeyCountBefore", "keysAddedCount", "keysRemovedCount"];
|
||||
for (const field of required) {
|
||||
if (session[field] === undefined || session[field] === null || session[field] === "") {
|
||||
throw new Error(`Missing required field: ${field}`);
|
||||
}
|
||||
}
|
||||
if (!Number.isInteger(session.existingKeyCountBefore) || session.existingKeyCountBefore < 0) {
|
||||
throw new Error("existingKeyCountBefore must be a non-negative integer");
|
||||
}
|
||||
if (!Number.isInteger(session.keysAddedCount) || session.keysAddedCount < 0) {
|
||||
throw new Error("keysAddedCount must be a non-negative integer");
|
||||
}
|
||||
if (!Number.isInteger(session.keysRemovedCount) || session.keysRemovedCount < 0) {
|
||||
throw new Error("keysRemovedCount must be a non-negative integer");
|
||||
}
|
||||
const expectedKeyCountAfter = session.existingKeyCountBefore + session.keysAddedCount - session.keysRemovedCount;
|
||||
return {
|
||||
caseId: session.caseId,
|
||||
vin: session.vin,
|
||||
authorizedBy: session.authorizedBy,
|
||||
existingKeyCountBefore: session.existingKeyCountBefore,
|
||||
keysAddedCount: session.keysAddedCount,
|
||||
keysRemovedCount: session.keysRemovedCount,
|
||||
expectedKeyCountAfter,
|
||||
timestamp: session.timestamp ?? new Date().toISOString(),
|
||||
};
|
||||
}
|
||||
|
||||
export function verifyKeyCountReconciliation(report, actualKeyCountAfter) {
|
||||
return {
|
||||
matches: report.expectedKeyCountAfter === actualKeyCountAfter,
|
||||
expected: report.expectedKeyCountAfter,
|
||||
actual: actualKeyCountAfter,
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
import { strict as assert } from "node:assert";
|
||||
import { crc32 } from "../binary_utils.mjs";
|
||||
import { parseSectorMap, summarizeSectorMap } from "../examples/35_flash_sector_map_parser.mjs";
|
||||
import { extractVin, computeVinCheckDigit, validateVin, selfTest as vinSelfTest } from "../examples/36_vin_extractor_validator.mjs";
|
||||
import { binarySearchOffset, findSectorForOffset } from "../examples/37_binary_search_pattern_locator.mjs";
|
||||
import { readI8, readI16LE, readI16BE, readI32LE, readI32BE, getBits, setBits } from "../examples/38_bitfield_and_signed_int_utils.mjs";
|
||||
import { buildKeyLearningReport, verifyKeyCountReconciliation } from "../examples/39_key_learning_session_report.mjs";
|
||||
|
||||
// 35_flash_sector_map_parser
|
||||
{
|
||||
const data = new Uint8Array(16).fill(0xFF);
|
||||
data.set([1, 2, 3, 4], 8);
|
||||
const sectors = [
|
||||
{ name: "boot", start: 0, length: 8 },
|
||||
{ name: "data", start: 8, length: 8 },
|
||||
];
|
||||
const parsed = parseSectorMap(data, sectors);
|
||||
assert.equal(parsed[0].blank, true);
|
||||
assert.equal(parsed[1].blank, false);
|
||||
assert.equal(parsed[1].crc32, crc32(data.slice(8, 16)).toString(16).padStart(8, "0").toUpperCase());
|
||||
const summary = summarizeSectorMap(data, sectors);
|
||||
assert.equal(summary.blankSectors, 1);
|
||||
assert.equal(summary.usedSectors, 1);
|
||||
assert.throws(() => parseSectorMap(data, [{ name: "oob", start: 10, length: 100 }]));
|
||||
}
|
||||
|
||||
// 36_vin_extractor_validator
|
||||
{
|
||||
const knownGood = "1M8GDM9AXKP042788";
|
||||
assert.equal(computeVinCheckDigit(knownGood), "X");
|
||||
assert.equal(validateVin(knownGood).valid, true);
|
||||
assert.equal(vinSelfTest().valid, true);
|
||||
const tampered = "1M8GDM9A0KP042788"; // check digit changed to '0'
|
||||
assert.equal(validateVin(tampered).valid, false);
|
||||
const bytes = new TextEncoder().encode("PREFIX_" + knownGood);
|
||||
assert.equal(extractVin(bytes, 7), knownGood);
|
||||
assert.throws(() => computeVinCheckDigit("1M8GDM9AXKP04278")); // 16 chars
|
||||
}
|
||||
|
||||
// 37_binary_search_pattern_locator
|
||||
{
|
||||
const offsets = [10, 20, 30, 40, 50];
|
||||
assert.equal(binarySearchOffset(offsets, 30), 2);
|
||||
assert.equal(binarySearchOffset(offsets, 25), -1);
|
||||
const sectors = [
|
||||
{ name: "a", start: 0, length: 10 },
|
||||
{ name: "b", start: 10, length: 10 },
|
||||
{ name: "c", start: 20, length: 10 },
|
||||
];
|
||||
assert.equal(findSectorForOffset(sectors, 15).name, "b");
|
||||
assert.equal(findSectorForOffset(sectors, 29).name, "c");
|
||||
assert.equal(findSectorForOffset(sectors, 30), null);
|
||||
}
|
||||
|
||||
// 38_bitfield_and_signed_int_utils
|
||||
{
|
||||
assert.equal(readI8(new Uint8Array([0xFF]), 0), -1);
|
||||
assert.equal(readI8(new Uint8Array([0x7F]), 0), 127);
|
||||
assert.equal(readI16LE(new Uint8Array([0x00, 0x01]), 0), 256);
|
||||
assert.equal(readI16BE(new Uint8Array([0x00, 0x01]), 0), 1);
|
||||
assert.equal(readI16LE(new Uint8Array([0xFF, 0xFF]), 0), -1);
|
||||
assert.equal(readI16BE(new Uint8Array([0xFF, 0xFF]), 0), -1);
|
||||
assert.equal(readI32LE(new Uint8Array([0x00, 0x00, 0x00, 0x01]), 0), 16777216);
|
||||
assert.equal(readI32BE(new Uint8Array([0x00, 0x00, 0x00, 0x01]), 0), 1);
|
||||
assert.equal(readI32LE(new Uint8Array([0xFF, 0xFF, 0xFF, 0xFF]), 0), -1);
|
||||
assert.equal(readI32BE(new Uint8Array([0xFF, 0xFF, 0xFF, 0xFF]), 0), -1);
|
||||
|
||||
assert.equal(getBits(0b10110100, 2, 3), 0b101);
|
||||
assert.equal(setBits(0b10110100, 2, 3, 0b011), 172);
|
||||
assert.throws(() => getBits(0, 30, 5));
|
||||
}
|
||||
|
||||
// 39_key_learning_session_report
|
||||
{
|
||||
const session = {
|
||||
caseId: "CASE-1",
|
||||
vin: "1M8GDM9AXKP042788",
|
||||
authorizedBy: "Tech A",
|
||||
existingKeyCountBefore: 2,
|
||||
keysAddedCount: 1,
|
||||
keysRemovedCount: 0,
|
||||
};
|
||||
const report = buildKeyLearningReport(session);
|
||||
assert.equal(report.expectedKeyCountAfter, 3);
|
||||
assert.equal(verifyKeyCountReconciliation(report, 3).matches, true);
|
||||
assert.equal(verifyKeyCountReconciliation(report, 2).matches, false);
|
||||
assert.throws(() => buildKeyLearningReport({ ...session, caseId: "" }), /Missing required field/);
|
||||
assert.throws(() => buildKeyLearningReport({ ...session, keysAddedCount: -1 }), /non-negative integer/);
|
||||
}
|
||||
|
||||
console.log("Expansion examples passed");
|
||||
@@ -0,0 +1,43 @@
|
||||
# Authorized Key Learning Workflow
|
||||
|
||||
## Purpose
|
||||
Document the procedural/record-keeping steps around learning (programming) an authorized key to a vehicle. This workflow describes authorization, verification, and audit steps — it does not document platform-specific security algorithms or bypass techniques. See `01_Knowledge_Base/IMMOBILIZER_CONCEPTS.md` for conceptual background.
|
||||
|
||||
## Prerequisites
|
||||
- Full authorization controls from `07_Authorized_Key_Immobilizer_Work/README.md`: government ID and proof of ownership/agent authority, VIN/registration on file, requested service recorded.
|
||||
- Confirmed key/transponder type compatible with the vehicle (part number match).
|
||||
- A backup of immobilizer-relevant data taken beforehand (see `04_Workflows/IMMOBILIZER_BACKUP_RESTORE_WORKFLOW.md`).
|
||||
- Access to the OEM-approved or NASTF-recognized (US/Canada) or equivalent regional-authorized process for the platform in question, especially for "all keys lost" scenarios.
|
||||
|
||||
## Required adapters
|
||||
- Whatever official/OEM-approved key-programming tool interface the platform requires; this repository does not generalize a specific adapter list since it is tool- and platform-specific.
|
||||
|
||||
## Wiring references
|
||||
- Not applicable beyond the standard diagnostic connector (OBD-II or platform-specific) used by the official key-programming tool/process.
|
||||
|
||||
## Safety notes
|
||||
- Confirm existing key count and status before starting — some platforms limit total learnable keys or require all existing keys present during learning.
|
||||
- Never proceed with an "all keys lost" recovery path without confirming the authorized, OEM/NASTF-recognized process is being used; unofficial workarounds are out of scope for this repository.
|
||||
- Keep any credential/PIN/code used strictly in encrypted storage, redacted from shared reports (see `07_Authorized_Key_Immobilizer_Work/README.md`).
|
||||
|
||||
## Procedure
|
||||
1. **Intake** — verify ID/ownership, record VIN, requested service, and existing key count/status (see `03_Script_Starter_Kit/examples/12_authorized_key_count_reconciliation.mjs`).
|
||||
2. **Pre-operation backup** — back up immobilizer-relevant data per `04_Workflows/IMMOBILIZER_BACKUP_RESTORE_WORKFLOW.md`.
|
||||
3. **Execute learning** — use the OEM-approved or NASTF-recognized process for the platform; log which key(s) were added/removed.
|
||||
4. **Verify** — confirm all keys (new and pre-existing) start the vehicle; confirm key count matches the intended end state.
|
||||
5. **Completion audit** — record final key count, authorization reference, and verification result (see `03_Script_Starter_Kit/examples/16_immo_service_completion_audit.mjs`).
|
||||
|
||||
## Common failures
|
||||
- Key learned successfully in the tool but not actually validated by physically test-starting the vehicle with that key before completing the job.
|
||||
- Key count mismatch after the operation (e.g. an old key unintentionally deleted from the system during learning).
|
||||
- Skipping the pre-operation backup, leaving no rollback path if the learning process leaves the immobilizer in an inconsistent state.
|
||||
|
||||
## Recovery procedures
|
||||
- If post-learning verification shows a key that should still work no longer does, check whether the learning process removed it from the system, and re-learn it using the same authorized process if appropriate and authorized.
|
||||
- If the immobilizer ends up in an inconsistent state (no key starts the vehicle), restore from the pre-operation backup (`04_Workflows/IMMOBILIZER_BACKUP_RESTORE_WORKFLOW.md`) and re-diagnose before re-attempting.
|
||||
|
||||
## Related documents
|
||||
- `01_Knowledge_Base/IMMOBILIZER_CONCEPTS.md`
|
||||
- `04_Workflows/IMMOBILIZER_BACKUP_RESTORE_WORKFLOW.md`
|
||||
- `07_Authorized_Key_Immobilizer_Work/README.md`, `AUTHORIZATION_TEMPLATE.csv`
|
||||
- `03_Script_Starter_Kit/examples/12_authorized_key_count_reconciliation.mjs`, `16_immo_service_completion_audit.mjs`
|
||||
@@ -0,0 +1,44 @@
|
||||
# Bench Reading / Boot Reading Workflow
|
||||
|
||||
## Purpose
|
||||
Decide between, and safely execute, bench (direct/in-circuit chip access) reading versus boot-mode (bootloader protocol) reading of a module's MCU/EEPROM, and document the trade-offs. See `01_Knowledge_Base/AUTOMOTIVE_MEMORY_CONCEPTS.md` for the conceptual distinction.
|
||||
|
||||
## Purpose of choosing correctly
|
||||
Using the wrong method for a given MCU family can range from "doesn't work" to "risks damaging the part" (e.g. forcing bench-clip access on a part that expects boot-mode entry sequencing, or vice versa).
|
||||
|
||||
## Prerequisites
|
||||
- Confirmed MCU/EEPROM part number and, ideally, known guidance (from the tool/adapter vendor's supported-device list) on which method that exact part supports.
|
||||
- For boot reading: confirmed boot-mode entry sequence for that MCU family from the adapter/tool vendor's documentation.
|
||||
- For bench reading: confirmed clip/socket compatibility with the part's package and pinout.
|
||||
|
||||
## Required adapters
|
||||
- Bench reading: chip-specific clip/socket adapter.
|
||||
- Boot reading: cable/harness matching the module's connector plus whatever boot-mode entry hardware (e.g. specific resistor/jumper condition, or a tool-provided boot adapter) the MCU family requires.
|
||||
|
||||
## Wiring references
|
||||
- Use the adapter/tool vendor's documented pinout and boot-entry sequence for the exact part; do not improvise from a similar-looking part in the same family, since boot-entry conditions are often part-specific.
|
||||
|
||||
## Safety notes
|
||||
- Bench (chip-off or clip) reading risks physical damage to the part/board from clip pressure or accidental short; boot reading avoids desoldering but depends on getting the entry sequence exactly right, and an incorrect sequence can sometimes leave the MCU in an unexpected state.
|
||||
- Always attempt the least invasive method first if the adapter/tool documentation confirms it's supported for the exact part.
|
||||
- Use current-limited bench power throughout.
|
||||
|
||||
## Procedure
|
||||
1. **Identify** — confirm exact part number and check adapter/tool vendor documentation for supported access method(s) for that part.
|
||||
2. **Choose method** — prefer boot-mode reading if supported and non-invasive; use bench/clip reading if boot mode is unsupported or unreliable for that part.
|
||||
3. **Acquisition** — two independent reads regardless of method, byte-for-byte compared and hashed (per baseline workflow).
|
||||
4. **Validation** — confirm expected buffer size/signatures for that part before treating the read as usable.
|
||||
|
||||
## Common failures
|
||||
- Boot-mode entry sequence slightly wrong (timing, pin state) resulting in a read that returns unexpected data (e.g. all zeros/all `0xFF`) rather than an explicit error.
|
||||
- Clip misalignment on bench reads producing an inconsistent second read (caught by the dual-read comparison).
|
||||
- Attempting boot mode on a part/revision that does not support it for that specific tool/adapter.
|
||||
|
||||
## Recovery procedures
|
||||
- If a read attempt returns clearly invalid data (wrong size, uniform blank pattern where real data is expected), do not proceed to any write step — re-seat the adapter/re-check the boot sequence and re-read before continuing.
|
||||
- If repeated attempts fail, treat this as an adapter/method mismatch rather than a hardware fault until an alternate, tool-vendor-confirmed method has also been tried.
|
||||
|
||||
## Related documents
|
||||
- `01_Knowledge_Base/AUTOMOTIVE_MEMORY_CONCEPTS.md`
|
||||
- `04_Workflows/EEPROM_READ_WRITE_WORKFLOW.md`
|
||||
- `04_Workflows/MCU_READ_WRITE_WORKFLOW.md`
|
||||
@@ -0,0 +1,46 @@
|
||||
# ECU Clone / TCU Clone Workflow
|
||||
|
||||
## Purpose
|
||||
Bring a replacement ECU or TCU into service so it behaves identically to the original module it replaces, from the vehicle's point of view. See `01_Knowledge_Base/ECU_TCU_CLONE_CONCEPTS.md` for background concepts.
|
||||
|
||||
## Prerequisites
|
||||
- Confirmed authorization for the vehicle and both the original and replacement/donor module.
|
||||
- Exact part number and hardware/software revision match (or documented compatibility) between original and donor.
|
||||
- A readable original, or a previously-stored known-good backup if the original is no longer readable (e.g. dead MCU).
|
||||
- Understanding of whether this platform requires an ISN re-sync or equivalent security pairing step — see `04_Workflows/ISN_OPERATIONS_WORKFLOW.md`.
|
||||
|
||||
## Required adapters
|
||||
- Same adapters as `04_Workflows/EEPROM_READ_WRITE_WORKFLOW.md` / `04_Workflows/MCU_READ_WRITE_WORKFLOW.md`, matched to the specific ECU/TCU's memory devices.
|
||||
- Bench harness/breakout matching the module's connector, if bench power-up (rather than chip-off read/write) is used.
|
||||
|
||||
## Wiring references
|
||||
- Use the connector pinout documented for the exact module part number; ECU/TCU connectors vary significantly even within one vehicle platform across model years.
|
||||
|
||||
## Safety notes
|
||||
- Confirm hardware revision compatibility before starting — physically identical connectors do not guarantee compatible internal hardware.
|
||||
- Treat any immobilizer/security-pairing data within the module under `07_Authorized_Key_Immobilizer_Work/README.md` governance.
|
||||
- Keep the failed original module and its last readable backup even after a successful clone, in case the replacement needs re-verification later.
|
||||
|
||||
## Procedure
|
||||
1. **Identify** — confirm exact part number, hardware revision, and calibration/software version of both original and donor.
|
||||
2. **Acquire** — read the original (dual-read + hash) or retrieve the last known-good backup.
|
||||
3. **Transfer** — write vehicle-specific configuration/calibration data to the donor module, following that module's data-region layout.
|
||||
4. **Security/pairing** — determine whether this platform requires a separate pairing/sync step (see `04_Workflows/ISN_OPERATIONS_WORKFLOW.md`); do not assume it happens automatically with a data copy.
|
||||
5. **Verify** — confirm the replacement communicates/starts correctly and that its self-checked firmware checksum is valid.
|
||||
|
||||
## Common failures
|
||||
- Part-number/hardware-revision mismatch between original and donor.
|
||||
- Calibration data copied but the pairing/security step skipped or performed in the wrong order relative to the data write.
|
||||
- Checksum not recalculated after manual edits, causing the module to reject its own image at boot.
|
||||
- Working from a single, unverified read of a failing/intermittent original instead of a dual-verified read.
|
||||
|
||||
## Recovery procedures
|
||||
- If the donor module fails to start the vehicle after cloning, first re-verify the data write against the source backup (byte-for-byte) before assuming a pairing/security issue.
|
||||
- If pairing fails and the platform has an "all keys lost"/recovery procedure, that is an authorized-key-learning matter — see `04_Workflows/AUTHORIZED_KEY_LEARNING_WORKFLOW.md` and `07_Authorized_Key_Immobilizer_Work/README.md`, not a generic clone retry.
|
||||
- Preserve the donor's pre-clone factory state backup (read before any writes) in case the clone needs to be reversed for warranty/return purposes.
|
||||
|
||||
## Related documents
|
||||
- `01_Knowledge_Base/ECU_TCU_CLONE_CONCEPTS.md`
|
||||
- `04_Workflows/ISN_OPERATIONS_WORKFLOW.md`
|
||||
- `04_Workflows/VIN_MIGRATION_WORKFLOW.md`
|
||||
- `07_Authorized_Key_Immobilizer_Work/README.md`
|
||||
@@ -0,0 +1,45 @@
|
||||
# EEPROM Read/Write Workflow
|
||||
|
||||
## Purpose
|
||||
Safely read and, where authorized, write EEPROM contents on an automotive module (ECU/BCM/immobilizer/instrument cluster) while preserving recoverability at every step.
|
||||
|
||||
## Prerequisites
|
||||
- Confirmed authorization for the specific vehicle/module (see `07_Authorized_Key_Immobilizer_Work/README.md` if immobilizer-relevant data is involved).
|
||||
- Exact EEPROM part number and package (identified visually or via schematic/service reference) — memory size and pinout vary by part family.
|
||||
- Spare, known-good bench power supply with current limiting.
|
||||
- Multi-PROG (or equivalent) with a device/adapter entry matching the exact part; confirm the "supported" indicator (see `01_Knowledge_Base/README.md` → "Checksum strategy") rather than assuming compatibility from a similar part number.
|
||||
|
||||
## Required adapters
|
||||
- In-circuit clip or socket adapter matching the EEPROM package (e.g. SOIC8, TSSOP8, DIP8 — package varies by part).
|
||||
- If desoldering is required: appropriate rework station and ESD protection; note desoldering as a higher-risk path with its own recovery burden if the part is damaged.
|
||||
|
||||
## Wiring references
|
||||
- Use the adapter/tool manufacturer's official pinout documentation for the specific clip/socket model in use; this repository does not maintain a general pinout table since it is adapter- and part-specific and changes across hardware revisions.
|
||||
- Confirm orientation (pin 1 marking) before applying power — reversed orientation is a common cause of part damage.
|
||||
|
||||
## Safety notes
|
||||
- Never power the EEPROM in-circuit and out-of-circuit simultaneously.
|
||||
- Use current-limited bench supply on first power-up of any in-circuit read to catch a short before it damages the part.
|
||||
- Keep the module's original harness connections photographed/documented before disconnecting (per `04_Workflows/AUTHORIZED_REPAIR_WORKFLOW.md` intake step).
|
||||
|
||||
## Procedure (maps onto the baseline workflow)
|
||||
1. **Intake** — record authorization, module identity, exact EEPROM part number.
|
||||
2. **Acquisition** — two independent reads, byte-for-byte compared, SHA-256 recorded (see `03_Script_Starter_Kit/examples/02_double_read_verifier.mjs`).
|
||||
3. **Development** — work on a copy; maintain an explicit allow-list of writable offsets (see `03_Script_Starter_Kit/examples/04_allowlisted_patch_demo.mjs`).
|
||||
4. **Validation** — verify size, blank regions outside the allow-list are untouched, and checksum where applicable.
|
||||
5. **Release** — write only after validation passes; save the original read under a preserved filename before writing anything back.
|
||||
|
||||
## Common failures
|
||||
- Wrong part/package selected in the tool's device list, producing a read that is the wrong size or all-blank/all-`0xFF`.
|
||||
- Clip misalignment causing an intermittent read that differs between the two required reads (this is exactly what the dual-read check is designed to catch — do not proceed if reads differ).
|
||||
- Write interrupted mid-cycle (power loss, clip slip) leaving the part in a partially-written, inconsistent state.
|
||||
|
||||
## Recovery procedures
|
||||
- If a write is interrupted or verification fails: do not attempt another write from the same (possibly corrupted) working copy. Re-read the module first to establish its actual current state, then restore from the last known-good backup.
|
||||
- Always keep the original pre-write backup and at least one prior known-good backup, named with case ID/module/region/date, per `04_Workflows/AUTHORIZED_REPAIR_WORKFLOW.md` → "Release".
|
||||
- If the part appears bricked (reads as all-blank/garbage after a failed write and does not respond normally), the module is a candidate for the same "bench reading" recovery path documented in `04_Workflows/BENCH_AND_BOOT_READING_WORKFLOW.md`, or physical EEPROM replacement/reprogramming with a known-good backup.
|
||||
|
||||
## Related documents
|
||||
- `01_Knowledge_Base/AUTOMOTIVE_MEMORY_CONCEPTS.md`
|
||||
- `17_MultiPROG_SDK/docs/EEPROM_API.md`
|
||||
- `17_MultiPROG_SDK/templates/template_eeprom.mjs`
|
||||
@@ -0,0 +1,41 @@
|
||||
# Immobilizer Backup / Restore Workflow
|
||||
|
||||
## Purpose
|
||||
Create and, when needed, restore a verified backup of immobilizer-relevant data before any operation that could put the vehicle in a no-start state. See `01_Knowledge_Base/IMMOBILIZER_CONCEPTS.md` for background and `07_Authorized_Key_Immobilizer_Work/README.md` for the governance boundary this workflow operates under.
|
||||
|
||||
## Prerequisites
|
||||
- Confirmed authorization per `07_Authorized_Key_Immobilizer_Work/README.md` (ID/ownership verification, job record).
|
||||
- Identified which module(s) hold the immobilizer-relevant data for this platform (commonly ECU and/or BCM/immobilizer module; varies by manufacturer).
|
||||
- Encrypted storage location for the backup, consistent with the "keep credentials/PINs/codes in encrypted systems" control in `07_Authorized_Key_Immobilizer_Work/README.md`.
|
||||
|
||||
## Required adapters
|
||||
- Same as the underlying module's EEPROM/MCU read workflow (`04_Workflows/EEPROM_READ_WRITE_WORKFLOW.md` / `04_Workflows/MCU_READ_WRITE_WORKFLOW.md`).
|
||||
|
||||
## Wiring references
|
||||
- Same as the underlying module's read workflow.
|
||||
|
||||
## Safety notes
|
||||
- Take the backup **before** any other operation on the vehicle that could plausibly touch immobilizer data (key learning, ECU replacement, ISN operations) — not after something has already gone wrong.
|
||||
- Store backups with case ID, VIN, module identity, and date in the filename, and log the SHA-256 hash in the chain-of-custody record (`07_Authorized_Key_Immobilizer_Work/CHAIN_OF_CUSTODY.csv`).
|
||||
- Restrict access to backups containing security-relevant data to authorized personnel only; redact before including in any shared report (see `03_Script_Starter_Kit/examples/08_redacted_security_report.mjs` and `13_security_value_redactor.mjs`).
|
||||
|
||||
## Procedure
|
||||
1. **Intake** — record authorization, VIN, module(s) in scope, and reason for backup (routine precaution vs. pre-operation requirement).
|
||||
2. **Acquisition** — two independent reads of each in-scope module, byte-for-byte compared and hashed.
|
||||
3. **Storage** — save to encrypted storage with a clear, consistent naming convention; log in chain-of-custody.
|
||||
4. **Restore (when needed)** — before restoring, dual-read the module's *current* state and hash it (so the pre-restore state is also preserved), then write the backup and verify byte-for-byte against the stored backup after writing.
|
||||
5. **Post-restore validation** — confirm the vehicle starts and immobilizer-related fault codes are clear.
|
||||
|
||||
## Common failures
|
||||
- Backup taken after an issue already occurred rather than proactively, leaving no clean baseline to restore to.
|
||||
- Backup stored without a hash, making it impossible to later prove the backup was unmodified.
|
||||
- Restoring an outdated backup to a module whose data has legitimately changed since (e.g. after a since-completed authorized key-learning event), reverting that change unintentionally.
|
||||
|
||||
## Recovery procedures
|
||||
- If a restore fails verification (written data doesn't match stored backup byte-for-byte), do not release the vehicle — re-read, re-diagnose the write path, and retry from the same verified backup.
|
||||
- If multiple backups exist for the same module, always confirm which is most recent and relevant before restoring, using the chain-of-custody log as the source of truth.
|
||||
|
||||
## Related documents
|
||||
- `01_Knowledge_Base/IMMOBILIZER_CONCEPTS.md`
|
||||
- `07_Authorized_Key_Immobilizer_Work/README.md`, `CHAIN_OF_CUSTODY.csv`
|
||||
- `03_Script_Starter_Kit/examples/11_immo_dump_quality_report.mjs`, `13_security_value_redactor.mjs`, `14_immo_backup_naming_policy.mjs`
|
||||
@@ -0,0 +1,41 @@
|
||||
# ISN Operations Workflow
|
||||
|
||||
## Purpose
|
||||
Handle ISN (Immobilizer Serial Number / Identification Sync Number — terminology varies by platform) re-synchronization when an ECU or immobilizer-paired module is replaced. See `01_Knowledge_Base/IMMOBILIZER_CONCEPTS.md` for conceptual background.
|
||||
|
||||
## Prerequisites
|
||||
- Confirmed authorization under `07_Authorized_Key_Immobilizer_Work/README.md` — ISN operations inherently touch immobilizer-relevant security data.
|
||||
- Confirmed which modules on the target platform participate in the ISN/pairing relationship (commonly ECU ↔ immobilizer/BCM, sometimes also instrument cluster or TCU).
|
||||
- A recorded, authorized reason for the operation (module replacement, confirmed repair need) and chain-of-custody entry (`07_Authorized_Key_Immobilizer_Work/CHAIN_OF_CUSTODY.csv`).
|
||||
|
||||
## Required adapters
|
||||
- Same as the underlying module's read/write workflow (EEPROM/MCU), plus whatever official or OEM-approved tooling path the platform requires for ISN write/verification (platform-specific; not generalized here).
|
||||
|
||||
## Wiring references
|
||||
- Same as the underlying module's read/write workflow.
|
||||
|
||||
## Safety notes
|
||||
- ISN mismatches commonly present as "will not start" rather than a clear error message — treat any ISN operation as a "no room for a single unverified write" step; back up before touching it.
|
||||
- Where the platform requires OEM-level tooling or an authorized security-access process for ISN writes (common on more recent platforms), do not attempt an unofficial workaround — that falls outside this repository's scope (see `CONTRIBUTING.md`'s boundary against operational bypass instructions).
|
||||
|
||||
## Procedure
|
||||
1. **Intake** — record authorization, platform, and which modules are involved in the ISN relationship.
|
||||
2. **Acquisition** — back up all involved modules' relevant data regions before any change (dual-read + hash, per baseline workflow).
|
||||
3. **Development/Execution** — perform the ISN write/sync using the OEM-approved or platform-documented method available to the shop; log exactly what was changed on which module.
|
||||
4. **Validation** — confirm the vehicle starts and runs without immobilizer-related fault codes; confirm no unrelated bytes changed in the backed-up regions (diff report).
|
||||
5. **Release** — record completion, module part numbers, and final verification result in the job record (see `03_Script_Starter_Kit/examples/06_authorized_job_record_validator.mjs`).
|
||||
|
||||
## Common failures
|
||||
- ISN written to only one side of the pairing relationship (e.g. new ECU updated but immobilizer/BCM not updated to match).
|
||||
- Attempting the operation without the platform-required authorized tooling/credential path, resulting in a module that silently rejects the write.
|
||||
- Skipping the pre-operation backup, leaving no rollback path if the sync attempt fails.
|
||||
|
||||
## Recovery procedures
|
||||
- Restore all involved modules from their pre-operation backups if the vehicle fails to start after the attempt, then re-diagnose before retrying.
|
||||
- If the platform's authorized ISN process itself fails or is unavailable, escalate through the OEM/NASTF-recognized channel referenced in `05_Reference/SECURITY_RESEARCH_TOPICS.md` rather than attempting an unofficial method.
|
||||
|
||||
## Related documents
|
||||
- `01_Knowledge_Base/IMMOBILIZER_CONCEPTS.md`
|
||||
- `04_Workflows/ECU_TCU_CLONE_WORKFLOW.md`
|
||||
- `07_Authorized_Key_Immobilizer_Work/README.md`
|
||||
- `05_Reference/SECURITY_RESEARCH_TOPICS.md`
|
||||
@@ -0,0 +1,45 @@
|
||||
# MCU Read/Write Workflow
|
||||
|
||||
## Purpose
|
||||
Read and, where authorized, write the combined program-flash/data (EEPROM-emulated) memory of an automotive MCU — distinct from a standalone EEPROM chip because most of the address space is program flash with its own erase/program discipline (see `01_Knowledge_Base/AUTOMOTIVE_MEMORY_CONCEPTS.md`).
|
||||
|
||||
## Prerequisites
|
||||
- Confirmed authorization for the specific vehicle/module.
|
||||
- Exact MCU part number and package identified (silicon markings can be sanded/relabeled on some counterfeit or reworked boards — cross-check against known-good reference photos for that platform where possible).
|
||||
- Understanding of whether this MCU family requires bench (direct pin) access, boot-mode access, or supports in-circuit reading through a bootloader — see `04_Workflows/BENCH_AND_BOOT_READING_WORKFLOW.md` for how to decide.
|
||||
|
||||
## Required adapters
|
||||
- MCU-family-specific adapter/socket (BGA/QFP adapters differ significantly by package and pitch).
|
||||
- A programmer/tool profile that explicitly lists the exact MCU part — do not assume a "similar" part number behaves identically; flash geometry (sector size/count) varies even within a family.
|
||||
|
||||
## Wiring references
|
||||
- Follow the adapter manufacturer's documented pinout for the specific MCU package; do not improvise pin mapping from a different package variant of the "same" chip.
|
||||
- Confirm boot-mode entry pins (if boot reading) match the documented sequence for that exact MCU family before applying power.
|
||||
|
||||
## Safety notes
|
||||
- MCU packages are more prone to adapter-pressure damage (BGA pads, fine-pitch QFP) than simple 8-pin EEPROMs — inspect solder/pad condition before and after.
|
||||
- Program flash erase/write endurance is typically lower than EEPROM; avoid repeated write cycles during development — validate against a copy before committing to hardware.
|
||||
- If the module has an immobilizer-relevant data region within the same MCU (common on modern combined ECUs), treat that region under `07_Authorized_Key_Immobilizer_Work/README.md` governance even though the rest of the read is general firmware.
|
||||
|
||||
## Procedure
|
||||
1. **Intake** — record authorization, exact MCU part number/package, and which regions (program flash vs. data/EEPROM-emulated) are in scope.
|
||||
2. **Acquisition** — two independent full reads, byte-for-byte compared and hashed, per the baseline workflow.
|
||||
3. **Development** — segment the buffer logically (program flash region vs. data region) before editing anything; treat program flash edits as higher risk than data-region edits.
|
||||
4. **Validation** — verify checksum/CRC the firmware itself checks at boot (if known for that platform) in addition to the generic allow-list diff check.
|
||||
5. **Release** — write only after validation; preserve rollback image.
|
||||
|
||||
## Common failures
|
||||
- Confusing flash sector boundaries and only erasing/rewriting part of a sector, corrupting adjacent data that wasn't intended to change.
|
||||
- Firmware checksum not recalculated after a manual patch, causing the MCU to refuse to boot or run in a degraded/limp mode.
|
||||
- Wrong MCU variant selected (same die, different flash size) truncating or misreading the image.
|
||||
|
||||
## Recovery procedures
|
||||
- Keep the original full read as the baseline recovery image regardless of how far development/validation proceeds.
|
||||
- If a write leaves the MCU unresponsive, attempt boot-mode recovery (see `04_Workflows/BENCH_AND_BOOT_READING_WORKFLOW.md`) before considering the module unrecoverable.
|
||||
- If checksum validation fails post-write, do not attempt to "patch around" it live — restore from backup and re-diagnose offline against a copy.
|
||||
|
||||
## Related documents
|
||||
- `01_Knowledge_Base/AUTOMOTIVE_MEMORY_CONCEPTS.md`
|
||||
- `04_Workflows/BENCH_AND_BOOT_READING_WORKFLOW.md`
|
||||
- `17_MultiPROG_SDK/docs/FLASH_API.md`, `17_MultiPROG_SDK/docs/EEPROM_API.md`
|
||||
- `03_Script_Starter_Kit/examples/35_flash_sector_map_parser.mjs`
|
||||
@@ -0,0 +1,19 @@
|
||||
# Workflows Index
|
||||
|
||||
All workflows in this folder follow the same validation/release discipline established in [AUTHORIZED_REPAIR_WORKFLOW.md](AUTHORIZED_REPAIR_WORKFLOW.md) (intake → acquisition → development → validation → release). That file remains the generic, module-agnostic baseline. The module/operation-specific workflows below add prerequisites, adapters, wiring, safety notes, common failures, and recovery procedures particular to that operation type.
|
||||
|
||||
| Workflow | File |
|
||||
| --- | --- |
|
||||
| Generic validation and release (baseline) | [AUTHORIZED_REPAIR_WORKFLOW.md](AUTHORIZED_REPAIR_WORKFLOW.md) |
|
||||
| EEPROM Read/Write | [EEPROM_READ_WRITE_WORKFLOW.md](EEPROM_READ_WRITE_WORKFLOW.md) |
|
||||
| MCU Read/Write | [MCU_READ_WRITE_WORKFLOW.md](MCU_READ_WRITE_WORKFLOW.md) |
|
||||
| ECU Clone / TCU Clone | [ECU_TCU_CLONE_WORKFLOW.md](ECU_TCU_CLONE_WORKFLOW.md) |
|
||||
| VIN Migration | [VIN_MIGRATION_WORKFLOW.md](VIN_MIGRATION_WORKFLOW.md) |
|
||||
| ISN Operations | [ISN_OPERATIONS_WORKFLOW.md](ISN_OPERATIONS_WORKFLOW.md) |
|
||||
| Bench Reading / Boot Reading | [BENCH_AND_BOOT_READING_WORKFLOW.md](BENCH_AND_BOOT_READING_WORKFLOW.md) |
|
||||
| Immobilizer Backup / Restore | [IMMOBILIZER_BACKUP_RESTORE_WORKFLOW.md](IMMOBILIZER_BACKUP_RESTORE_WORKFLOW.md) |
|
||||
| Authorized Key Learning | [AUTHORIZED_KEY_LEARNING_WORKFLOW.md](AUTHORIZED_KEY_LEARNING_WORKFLOW.md) |
|
||||
|
||||
## Scope note
|
||||
|
||||
These workflows are procedural and adapter-agnostic. They describe *what to verify and record*, not exact security algorithms, real memory offsets, or bypass techniques — that boundary is intentional (see `CONTRIBUTING.md` and `07_Authorized_Key_Immobilizer_Work/README.md`). Real, platform-specific security data belongs only in the governance-boundaried `07_Authorized_Key_Immobilizer_Work/` scope, never in this general-purpose folder.
|
||||
@@ -0,0 +1,40 @@
|
||||
# VIN Migration Workflow
|
||||
|
||||
## Purpose
|
||||
Update the VIN (Vehicle Identification Number) stored in a replacement or repaired module so it matches the vehicle it is installed in, where this is a legitimate, authorized part of a repair (e.g. replacement ECU/instrument cluster taking on the VIN of the vehicle it's fitted to).
|
||||
|
||||
## Prerequisites
|
||||
- Confirmed authorization and documented reason for the VIN change (e.g. warranty replacement module, confirmed vehicle ownership).
|
||||
- Correct target VIN recorded from the vehicle's official source (VIN plate, registration document) — not from a possibly-already-incorrect module.
|
||||
- A validated VIN using the standard check-digit algorithm before writing anything (see `03_Script_Starter_Kit/examples/36_vin_extractor_validator.mjs`), to catch transcription errors before they are written into hardware.
|
||||
|
||||
## Required adapters
|
||||
- Whatever adapter is required for the specific module's memory (see `04_Workflows/EEPROM_READ_WRITE_WORKFLOW.md` / `04_Workflows/MCU_READ_WRITE_WORKFLOW.md`).
|
||||
|
||||
## Wiring references
|
||||
- Same as the underlying EEPROM/MCU workflow for the module in question.
|
||||
|
||||
## Safety notes
|
||||
- VIN is frequently cross-checked by multiple modules on modern vehicles (ECU, instrument cluster, BCM, sometimes TCU) — changing it in only one module can cause mismatched-VIN warnings/faults elsewhere. Confirm which modules on the target platform need to agree before starting.
|
||||
- Double-check the target VIN's check digit (9th character) independently before writing — a single mistyped character is otherwise easy to miss, and some platforms may not display the VIN back to you for confirmation.
|
||||
|
||||
## Procedure
|
||||
1. **Intake** — record authorization, target VIN, and which module(s) need updating.
|
||||
2. **Validate the target VIN** — run it through a standard check-digit validator (see `03_Script_Starter_Kit/examples/36_vin_extractor_validator.mjs`) before touching hardware.
|
||||
3. **Acquisition** — dual-read and hash the module's current data (per baseline workflow).
|
||||
4. **Development** — locate and change only the VIN field/region; keep every other byte identical (allow-list scoped to just the VIN field).
|
||||
5. **Validation** — diff report confirms only the VIN bytes changed; re-validate the written VIN's check digit by reading it back and re-running the validator.
|
||||
6. **Release** — confirm all cross-checking modules (if applicable) agree on the new VIN before returning the vehicle to service.
|
||||
|
||||
## Common failures
|
||||
- VIN written with a transposed or mistyped character that still "looks right" at a glance but fails check-digit validation.
|
||||
- Only one of several VIN-storing modules updated, leaving a mismatch that surfaces as an intermittent fault later.
|
||||
- VIN field boundaries in the buffer misidentified, accidentally overwriting adjacent configuration bytes.
|
||||
|
||||
## Recovery procedures
|
||||
- If a VIN mismatch fault appears after the change, re-run the check-digit validator against every module storing the VIN before assuming a deeper fault.
|
||||
- Restore from the pre-change backup if the wrong field was edited; re-attempt with a tighter allow-list scoped to only the confirmed VIN byte range.
|
||||
|
||||
## Related documents
|
||||
- `03_Script_Starter_Kit/examples/36_vin_extractor_validator.mjs`
|
||||
- `04_Workflows/ECU_TCU_CLONE_WORKFLOW.md`
|
||||
@@ -9,7 +9,7 @@ This note gathers high-level, legitimate references for topics that are often di
|
||||
|
||||
## Real immobilizer memory offsets
|
||||
- OpenRemap — offline ECU binary identification and health-checking workflows.
|
||||
- EcuBus-Pro — ECU development and test-tool architecture reference for understanding how ECUs and security-related data are organized.
|
||||
- EcuBus-Pro (referenced by URL only, see `02_Resource_Catalog/links.csv`) — ECU development and test-tool architecture reference for understanding how ECUs and security-related data are organized.
|
||||
- Binary parser and checksum references in this kit — useful for safe, read-only inspection of dumps and binary images.
|
||||
|
||||
## Key or transponder cloning
|
||||
|
||||
@@ -1,9 +0,0 @@
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
@@ -1,14 +0,0 @@
|
||||
node_modules
|
||||
dist
|
||||
out
|
||||
cli
|
||||
build
|
||||
tools
|
||||
.gitignore
|
||||
resources/bin
|
||||
resources/lib
|
||||
resources/docs/scriptApi
|
||||
resources/buildInScript
|
||||
src/renderer/src/views/uds/panel/panel-designer
|
||||
src/renderer/src/views/ostrace/timeline
|
||||
src/main/worker/canopen/source
|
||||
@@ -1,23 +0,0 @@
|
||||
/* eslint-env node */
|
||||
require('@rushstack/eslint-patch/modern-module-resolution')
|
||||
|
||||
module.exports = {
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:vue/vue3-recommended',
|
||||
'@electron-toolkit',
|
||||
'@electron-toolkit/eslint-config-ts/eslint-recommended',
|
||||
'@vue/eslint-config-typescript/recommended',
|
||||
'@vue/eslint-config-prettier'
|
||||
],
|
||||
rules: {
|
||||
'vue/require-default-prop': 'off',
|
||||
'vue/multi-word-component-names': 'off',
|
||||
'no-unused-vars': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
'@typescript-eslint/no-explicit-any': 'off',
|
||||
'@typescript-eslint/no-empty-function': 'off',
|
||||
'@typescript-eslint/ban-types': 'off',
|
||||
'prettier/prettier': 'off'
|
||||
}
|
||||
}
|
||||
@@ -1,55 +0,0 @@
|
||||
node_modules
|
||||
dist
|
||||
out
|
||||
.DS_Store
|
||||
*.log*
|
||||
__pycache__
|
||||
.env.local
|
||||
build
|
||||
cache
|
||||
!/build
|
||||
.env
|
||||
.ScriptBuild
|
||||
resources/docs/scriptApi
|
||||
resources/lib/kerneldlls/devices_property/*.xml
|
||||
ecb_cli.exe
|
||||
resources/examples/**/tsconfig.json
|
||||
resources/examples/**/*.code-workspace
|
||||
resources/examples/**/*.html
|
||||
resources/examples/**/**/*.html
|
||||
resources/examples/**/**/*.csv
|
||||
resources/examples/**/**/*.blf
|
||||
resources/examples/**/**/*.txt
|
||||
resources/examples/**/**/*.bin
|
||||
resources/examples/**/**/.claude
|
||||
*.bak
|
||||
log.txt
|
||||
tools/a.bin
|
||||
tools/a.txt
|
||||
tools/a.csv
|
||||
|
||||
.env.development
|
||||
doip-certs
|
||||
|
||||
|
||||
# generated lib js and d.ts docs
|
||||
resources/lib/js/cryptoExt.js
|
||||
resources/lib/js/cryptoExt.js.map
|
||||
resources/lib/js/plugin.js
|
||||
resources/lib/js/plugin.js.map
|
||||
resources/lib/js/secureAccess.js
|
||||
resources/lib/js/uds.js
|
||||
resources/lib/js/uds.js.map
|
||||
resources/lib/js/utli.js
|
||||
resources/lib/js/utli.js.map
|
||||
resources/lib/js/index.js
|
||||
resources/lib/js/index.js.map
|
||||
src/main/share/crc.d.ts.html
|
||||
src/main/share/cryptoExt.d.ts.html
|
||||
src/main/share/uds.d.ts.html
|
||||
src/main/share/utli.d.ts.html
|
||||
src/main/share/index.d.ts.html
|
||||
# python
|
||||
|
||||
resources/python
|
||||
resources/get-pip.py*.tsbuildinfo
|
||||
@@ -1,2 +0,0 @@
|
||||
electron_mirror=https://npmmirror.com/mirrors/electron/
|
||||
electron_builder_binaries_mirror=https://npmmirror.com/mirrors/electron-builder-binaries/
|
||||
@@ -1,13 +0,0 @@
|
||||
out
|
||||
dist
|
||||
/cli
|
||||
build
|
||||
tools
|
||||
pnpm-lock.yaml
|
||||
LICENSE.md
|
||||
tsconfig.json
|
||||
tsconfig.*.json
|
||||
resources/bin
|
||||
resources/lib
|
||||
**/*.html
|
||||
webpack.config.js
|
||||
@@ -1,4 +0,0 @@
|
||||
singleQuote: true
|
||||
semi: false
|
||||
printWidth: 100
|
||||
trailingComma: none
|
||||
@@ -1,106 +0,0 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
EcuBus-Pro is an open-source automotive ECU (Electronic Control Unit) development and testing tool built with Electron. It serves as an alternative to commercial tools like CAN-OE.
|
||||
|
||||
**Key Features:**
|
||||
- Cross-platform (Windows, Linux, macOS)
|
||||
- Multi-hardware support (PEAK, Kvaser, Vector, ZLG, Toomotss, EcuBus-LinCable, SLCAN, GS_USB)
|
||||
- Protocol support: CAN/CAN-FD, LIN, DoIP, SOME/IP
|
||||
- UDS diagnostic capabilities
|
||||
- TypeScript-based scripting and HIL testing framework
|
||||
- DBC/LDF database support
|
||||
- Panel builder for custom UI creation
|
||||
|
||||
## Architecture
|
||||
|
||||
This is an Electron application with a clear separation between main and renderer processes:
|
||||
|
||||
**Main Process (src/main/):**
|
||||
- `docan/` - CAN protocol native module (C++)
|
||||
- `dolin/` - LIN protocol native module (C++)
|
||||
- `doip/` - DoIP protocol implementation
|
||||
- `uds/` - Unified Diagnostic Services
|
||||
- `vsomeip/` - SOME/IP protocol with C++ bindings
|
||||
- `worker/` - **Third-party scripts provided to users** (must run `npm run worker:js` after any changes)
|
||||
- `ipc/` - IPC communication handlers
|
||||
|
||||
**Renderer Process (src/renderer/src/):**
|
||||
- Vue 3 + TypeScript frontend
|
||||
- `views/` - UI pages (home, uds, ostrace, etc.)
|
||||
- `stores/` - Pinia state management
|
||||
- `router/` - Vue Router
|
||||
- `database/` - DBC/LDF/ORTI parsers
|
||||
|
||||
**CLI (src/cli/):** Command-line interface for automation
|
||||
|
||||
## Development Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `npm run dev` | Start development server with HMR |
|
||||
| `npm run build` | Build production version (runs typecheck first) |
|
||||
| `npm run start` | Preview production build |
|
||||
| `npm run test` | Run tests with Vitest |
|
||||
| `npm run lint` | Run ESLint with auto-fix |
|
||||
| `npm run format` | Run Prettier format |
|
||||
| `npm run typecheck` | Run TypeScript type checks for both node and web |
|
||||
| `npm run worker` | Build worker processes (requires Python/build tools) |
|
||||
| `npm run worker:js` | **Build worker scripts (JS only) - MUST RUN after any changes to `src/main/worker/`** |
|
||||
| `npm run native` | Build all native modules (docan, dolin, someip) |
|
||||
| `npm run docan` | Build CAN native module |
|
||||
| `npm run dolin` | Build LIN native module |
|
||||
| `npm run someip` | Build SOME/IP native module |
|
||||
| `npm run build:win` | Build for Windows (NSIS installer) |
|
||||
| `npm run build:linux` | Build for Linux (deb, rpm) |
|
||||
| `npm run build:mac` | Build for macOS |
|
||||
| `npm run docs:dev` | Start VitePress docs dev server |
|
||||
| `npm run docs:build` | Build VitePress documentation |
|
||||
|
||||
**Note:** Native module builds require Python and build tools (Visual Studio on Windows, gcc on Linux).
|
||||
|
||||
## Key Configuration Files
|
||||
|
||||
- `package.json` - Dependencies, scripts, and vendor hardware support config
|
||||
- `electron-builder.yml` - Electron builder configuration
|
||||
- `electron.vite.config.ts` - Vite configuration for Electron
|
||||
- `tsconfig.json`, `tsconfig.node.json`, `tsconfig.web.json` - TypeScript configs
|
||||
- `vitest.config.ts` - Vitest test configuration
|
||||
- `webpack.config.js` - Webpack config for workers
|
||||
|
||||
## Internationalization
|
||||
|
||||
The project uses i18next for internationalization with support for English and Chinese. Translation files are located in `resources/locales/`.
|
||||
|
||||
## Frontend Development Guidelines
|
||||
|
||||
**UI Component Library:**
|
||||
- Prefer using **Element Plus** components for all UI implementation
|
||||
- For tables:
|
||||
- Simple tables: Use `el-table` (from Element Plus)
|
||||
- Complex tables: Use `vxe-table`
|
||||
|
||||
## Important Notes
|
||||
|
||||
**SWIG Generated Files:** All `*_wrap.cxx` files are generated by SWIG (Simplified Wrapper and Interface Generator). These files should be ignored and never modified manually. They are generated from the corresponding `.i` interface files.
|
||||
|
||||
**Worker Scripts:** The `src/main/worker/` directory contains scripts provided to third-party users, all code in here should has detailed typedoc format comments. **Any changes to this directory must be followed by running `npm run worker:js`** to rebuild the worker scripts.
|
||||
|
||||
## Cursor Cloud specific instructions
|
||||
|
||||
This section captures non-obvious, durable notes for developing EcuBus-Pro in a Cursor Cloud VM. Standard commands live in the tables above and in `package.json`; only the caveats specific to this Linux headless environment are listed here.
|
||||
|
||||
**Environment startup layer (already handled by the update script):** `npm install`, downloading the embedded standalone Python into `resources/python` plus `pip install -r resources/requirements.txt`, `npm run native`, and `npm run worker:js`. You do NOT need to rerun these manually on a fresh session unless you change the relevant sources.
|
||||
|
||||
**Node version:** CI uses Node 24, but the VM ships Node 22 and everything (install, native build, lint, typecheck, tests, `npm run dev`) works on it. Don't switch Node versions unless you hit a concrete incompatibility.
|
||||
|
||||
**Native modules on Linux:** `src/main/docan|dolin|vsomeip/binding.gyp` compile only `fake_linux.cxx` stubs on Linux — no SWIG or vendor SDKs are needed to build them, and the committed `*_wrap.cxx` files are only used on Windows. Only the `simulate` and `slcan` CAN vendors are functional on Linux (see `ecubusPro.vendor` in `package.json`); other vendors are stubbed. After changing `src/main/worker/`, rerun `npm run worker:js`.
|
||||
|
||||
**Python for diagnostic DB parsing:** ODX (`test/odx`) and CDD (`test/cdd`) parsing shell out to `resources/python/bin/python3` (see `getPythonPath()`). If that embedded Python or its packages (`odxtools`, `canmatrix`, `openpyxl`, ...) are missing, those tests and the app's ODX/CDD features fail with `spawn ... ENOENT`.
|
||||
|
||||
**Running the GUI:** This is an Electron desktop app. Run it with `DISPLAY=:1 npm run dev` (a headless X server is already running on display `:1`). It launches without extra `--no-sandbox` flags. The `Autofill.enable`/`Autofill.setAddresses` DevTools console errors at startup are harmless.
|
||||
|
||||
**Known pre-existing test failures on Linux (not environment issues):** There is no CI job that runs the Vitest suite, so some tests only pass on the original author's setup. `test/util/s19Parse.spec.ts > ok1` reads `./CMSIS-DAP_OpenSDA.s19` but the committed fixture is `CMSIS-DAP_OpenSDA.S19` (case mismatch, fails on case-sensitive Linux filesystems). `test/dbc/dbc.test.ts > id2001.dbc` has the same problem: it reads `id2001.dbc` but the committed fixture is `ID2001.dbc`. One `test/odx` assertion (`subfunc as first param`) is sensitive to the installed `odxtools` version. Hardware-backed suites under `test/docan`, `test/dolin`, `test/pwm`, `test/sa_dll` require physical devices and are expected to fail/skip. For a quick smoke run of hardware-independent tests: `npm run test -- --run test/util test/dbc test/odx test/viewer test/cdd test/encoding`.
|
||||
@@ -1,118 +0,0 @@
|
||||
# CLAUDE.md
|
||||
|
||||
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
||||
|
||||
## Project Overview
|
||||
|
||||
EcuBus-Pro is an open-source automotive ECU (Electronic Control Unit) development and testing tool built with Electron. It serves as an alternative to commercial tools like CAN-OE.
|
||||
|
||||
**Key Features:**
|
||||
- Cross-platform (Windows, Linux, macOS)
|
||||
- Multi-hardware support (PEAK, Kvaser, Vector, ZLG, Toomotss, EcuBus-LinCable, SLCAN, GS_USB)
|
||||
- Protocol support: CAN/CAN-FD, LIN, DoIP, SOME/IP
|
||||
- UDS diagnostic capabilities
|
||||
- TypeScript-based scripting and HIL testing framework
|
||||
- DBC/LDF database support
|
||||
- Panel builder for custom UI creation
|
||||
|
||||
## Development Commands
|
||||
|
||||
| Command | Description |
|
||||
|---------|-------------|
|
||||
| `npm run dev` | Start development server with HMR |
|
||||
| `npm run build` | Build production version (runs typecheck first) |
|
||||
| `npm run start` | Preview production build |
|
||||
| `npm run test` | Run all tests with Vitest |
|
||||
| `npm run test -- test/util/hexParse.spec.ts` | Run single test file |
|
||||
| `npm run test -- test/util/hexParse.spec.ts -t "test name"` | Run single test by name pattern |
|
||||
| `npm run lint` | Run ESLint with auto-fix |
|
||||
| `npm run format` | Run Prettier format |
|
||||
| `npm run typecheck` | Run TypeScript type checks (node + web) |
|
||||
| `npm run typecheck:node` | Type-check main/preload/CLI/tests only |
|
||||
| `npm run typecheck:web` | Type-check renderer only |
|
||||
| `npm run worker:js` | **Build worker scripts (JS only) - MUST RUN after any changes to `src/main/worker/`** |
|
||||
| `npm run worker` | Build worker bundle including native secure-access addon |
|
||||
| `npm run native` | Build all native modules (docan, dolin, someip) |
|
||||
| `npm run docan` / `dolin` / `someip` | Build individual native modules |
|
||||
| `npm run build:win` / `build:linux` / `build:mac` | Platform-specific builds |
|
||||
| `npm run docs:dev` / `docs:build` | VitePress documentation |
|
||||
| `npm run cli:build` | Build CLI |
|
||||
|
||||
**Note:** Native module builds require Python and platform build tools (Visual Studio on Windows, gcc on Linux).
|
||||
|
||||
## Architecture
|
||||
|
||||
This is an Electron application with clear separation between processes:
|
||||
|
||||
**Main Process (`src/main/`):**
|
||||
- `index.ts` - Creates frameless BrowserWindow, registers `local-resource://` protocol, initializes logging/analytics/i18n
|
||||
- `docan/`, `dolin/` - CAN/LIN protocol native modules (C++ with SWIG bindings)
|
||||
- `doip/`, `uds/`, `vsomeip/` - DoIP, UDS, SOME/IP protocol implementations
|
||||
- `worker/` - **Public worker script API provided to users** (must run `npm run worker:js` after changes)
|
||||
- `workerClient.ts` - Runs user scripts in Node `worker_threads`, handles RPC/event messages
|
||||
- `ipc/*.ts` - IPC handlers registered via side-effect imports in `ipc/index.ts`
|
||||
- `multiWin.ts` - Manages extra Electron windows with MessageChannelMain for log sharing
|
||||
- `share/` - Shared types and utilities accessible via `nodeCan/*` alias
|
||||
|
||||
**Preload (`src/preload/`):**
|
||||
- Exposes `window.electron`, `window.api`, `window.store`, `window.path`, `window.dataParseWorker`
|
||||
- Renderer must use these bridges instead of importing Electron/Node APIs directly
|
||||
|
||||
**Renderer (`src/renderer/src/`):**
|
||||
- Vue 3 + Pinia + Vue Router (memory history) + Element Plus + VXE components
|
||||
- `stores/` - `project.ts` (project metadata), `data.ts` (ECU/device/data), `runtime.ts` (runtime flags)
|
||||
- `views/uds/layout.ts` - UDS workspace panels declared as `layoutMap` items
|
||||
- State sync between windows uses `BroadcastChannel` pattern in `main.ts`
|
||||
|
||||
**CLI (`src/cli/`):** Automation CLI with separate Electron Vite config (`cli.vite.ts`)
|
||||
|
||||
## Path Aliases
|
||||
|
||||
| Alias | Target |
|
||||
|-------|--------|
|
||||
| `src/*` | Repository source root |
|
||||
| `@r/*` | `src/renderer/src/` |
|
||||
| `nodeCan/*` | `src/main/share/` |
|
||||
|
||||
Use existing aliases instead of long relative paths.
|
||||
|
||||
## Key Configuration Files
|
||||
|
||||
- `package.json` - Dependencies, scripts, vendor hardware support under `ecubusPro.vendor`
|
||||
- `electron-builder.yml` - Electron builder configuration
|
||||
- `electron.vite.config.ts` - Vite configuration for Electron
|
||||
- `vitest.config.ts` - Vitest test configuration with path aliases
|
||||
- `webpack.config.js` - Webpack config for worker bundling
|
||||
|
||||
## Repository Conventions
|
||||
|
||||
**UI Components:** Prefer Element Plus. Use `el-table` for simple tables, `vxe-table` for complex tables.
|
||||
|
||||
**Theme:** Dark mode maps to `VxeUI.setTheme('dark')` via `useDark()` watcher in `App.vue`.
|
||||
|
||||
**Plugin State Sync:** Use Wujie `bus` events (`update:dataStore`, `update:dataStore:fromMain`, `update:globalStart:fromMain`).
|
||||
|
||||
**Worker API Documentation:** Keep `src/main/worker/` documented with TSDoc (`@param`, `@returns`, `@throws`, `@example`, `@category`). This is shipped to users via TypeDoc.
|
||||
|
||||
**Formatter:** Single quotes, no semicolons, print width 100, no trailing commas.
|
||||
|
||||
**SWIG Generated Files:** Never edit `*_wrap.cxx` files - they are generated from `.i` interface files.
|
||||
|
||||
## Tests
|
||||
|
||||
Tests live under `test/` and run with Vitest.
|
||||
|
||||
- Hardware-dependent: `test/docan/`, `test/dolin/`, `test/pwm/` (require matching devices)
|
||||
- Hardware-independent: `test/util/*.spec.ts`, `test/dbc/`, `test/odx/`, `test/viewer/` (good smoke tests)
|
||||
|
||||
## Internationalization
|
||||
|
||||
i18next-based. App translations in `resources/locales/<lang>/translation.json`. Plugin translations loaded from `locales/<lang>/translation.json` and merged via IPC.
|
||||
|
||||
## Git Commit Rules
|
||||
|
||||
- Do NOT add `Co-authored-by` trailers to commit messages.
|
||||
|
||||
## MCP Servers
|
||||
|
||||
Workspace MCP config in `.vscode/mcp.json`. The `playwright` server (`npx -y @playwright/mcp@latest`) is useful for browser-based UI exploration when dev server is running.
|
||||
@@ -1,118 +0,0 @@
|
||||
<div align="center">
|
||||
<a href="https://app.whyengineer.com">
|
||||
<img width="160" height="160" src="https://ecubus.oss-cn-chengdu.aliyuncs.com/img/logo256.png">
|
||||
</a>
|
||||
|
||||
<h1>EcuBus-Pro</h1>
|
||||
|
||||
<div style="margin:5px; display: flex; justify-content: center; align-items: center;gap:4px">
|
||||
<a href="https://github.com/ecubus/EcuBus-Pro/releases">
|
||||
<img src="https://github.com/ecubus/EcuBus-Pro/actions/workflows/build.yml/badge.svg" alt="github-ci" />
|
||||
</a>
|
||||
<a href="https://github.com/ecubus/EcuBus-Pro/releases">
|
||||
<img src="https://github.com/ecubus/EcuBus-Pro/actions/workflows/build-linux.yml/badge.svg" alt="github-ci" />
|
||||
</a>
|
||||
<a href="https://repology.org/project/ecubus-pro/versions">
|
||||
<img src="https://repology.org/badge/version-for-repo/aur/ecubus-pro.svg" alt="AUR package">
|
||||
</a>
|
||||
<a href="https://github.com/ecubus/EcuBus-Pro">
|
||||
<img src="https://img.shields.io/github/stars/ecubus/EcuBus-Pro"/>
|
||||
</a>
|
||||
</div>
|
||||
<b style="font-size:20px;margin:10px;display:block">A powerful automotive ECU development tool</b>
|
||||
<i>Easy of use, Cross platform, Multi dongle, Powerful script ability, CLI support</i><br/>
|
||||
Document: <a href="https://app.whyengineer.com">https://app.whyengineer.com</a> | <a href="https://app.whyengineer.com/zh">中文文档</a>
|
||||
</div>
|
||||
|
||||
## Overview
|
||||
|
||||

|
||||
|
||||
EcuBus-Pro is an open-source alternative to commercial automotive diagnostic tools like `CAN-OE`. It provides a comprehensive solution for ECU development and testing with:
|
||||
|
||||
- 🆓 Open-source and free to use
|
||||
- 🚀 Modern, intuitive user interface
|
||||
- 💻 Cross-platform support (Windows, Linux, MacOS) - [Install](./docs/about/install.md)
|
||||
- 🔌 Multi-hardware support
|
||||
- **[EcuBus-LinCable](https://app.whyengineer.com/docs/um/hardware/lincable.html)**: LIN (Support Lin conformance test), [PWM](https://app.whyengineer.com/docs/um/pwm/pwm.html)
|
||||
- **PEAK**: CAN, CAN-FD, LIN
|
||||
- **KVASER**: CAN, CAN-FD, LIN
|
||||
- **ZLG**: CAN, CAN-FD
|
||||
- **Toomotss**: CAN, CAN-FD, LIN
|
||||
- **VECTOR**: CAN, CAN-FD, LIN
|
||||
- **SLCAN**: CAN, CAN-FD [Detail](https://app.whyengineer.com/docs/um/can/can.html#slcan-special)
|
||||
- **GS_USB (CANDLE)**: CAN, CAN-FD [Detail](https://app.whyengineer.com/docs/um/can/can.html#gs-usb)
|
||||
- 🛠️ Comprehensive diagnostic capabilities
|
||||
- **Diagnostic Protocols**: CAN/CAN-FD, DoIP, LIN
|
||||
- 🌐 **SOME/IP**: SOME/IP protocol support - [Details](./docs/um/someip/index.md)
|
||||
- 📝 **Scripting**: Advanced TypeScript-based automation - [Details](./docs/um/script.md)
|
||||
- 🧪 **Test**: HIL Test Framework - [Details](./docs/um/test/test.md)
|
||||
- 📊 **Database Support**: LIN LDF (edit & export), CAN DBC (view) - [Details](./docs/um/database.md)
|
||||
- 📈 **Data Visualization**: Real-time signal graphing and analysis - [Details](./docs/um/graph/graph.md)
|
||||
- ⌨️ **Command Line**: Full-featured CLI for automation and integration - [Details](./docs/um/cli.md)
|
||||
- 🎨 **Panel**: Drag-and-drop interface builder for custom UI - [Details](./docs/um/panel/index.md)
|
||||
|
||||
[Read the Docs to Learn More.](https://app.whyengineer.com)
|
||||
|
||||
|
||||
## Support & Sponsorship
|
||||
|
||||
<div align="center">
|
||||
<h3 style="padding:20px;font-size:22px">Platinum Sponsors</h3>
|
||||
<table style="width: 80%; margin: 0 auto; border-collapse: collapse;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 33.33%; text-align: center; padding: 20px; border: 1px solid #eee;">
|
||||
<a href="./docs/about/sponsor">Become a Sponsor</a>
|
||||
</td>
|
||||
<td style="width: 33.33%; text-align: center; padding: 20px; border: 1px solid #eee;">
|
||||
<a href="./docs/about/sponsor">Become a Sponsor</a>
|
||||
</td>
|
||||
<td style="width: 33.33%; text-align: center; padding: 20px; border: 1px solid #eee;">
|
||||
<a href="./docs/about/sponsor">Become a Sponsor</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 style="padding:20px;font-size:20px">Gold Sponsors</h3>
|
||||
|
||||
<table style="width: 90%; margin: 0 auto; border-collapse: collapse;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 25%; text-align: center; padding: 20px; border: 1px solid #eee;">
|
||||
<a href="http://www.cdkhdz.com" target="_blank">
|
||||
<img src="./public/logo/KUNHONG-LOGO - re-E1.png" alt="KUNHONG" width="120"/>
|
||||
</a>
|
||||
</td>
|
||||
<td style="width: 25%; text-align: center; padding: 20px; border: 1px solid #eee;">
|
||||
<a href="./docs/about/sponsor">Become a Sponsor</a>
|
||||
</td>
|
||||
<td style="width: 25%; text-align: center; padding: 20px; border: 1px solid #eee;">
|
||||
<a href="./docs/about/sponsor">Become a Sponsor</a>
|
||||
</td>
|
||||
<td style="width: 25%; text-align: center; padding: 20px; border: 1px solid #eee;">
|
||||
<a href="./docs/about/sponsor">Become a Sponsor</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
Consider [becoming a sponsor](./docs/about/sponsor) to support ongoing development. Sponsors receive prominent logo placement with website links. 🙏
|
||||
|
||||
|
||||
## Contributors
|
||||
|
||||
Thanks to all the contributors who have helped shape EcuBus-Pro:
|
||||
|
||||
<a href="https://github.com/ecubus/EcuBus-Pro/graphs/contributors" target="_blank"><img src="https://contrib.rocks/image?repo=ecubus/EcuBus-Pro"></a>
|
||||
|
||||
We welcome contributions! Please review our [contribution guidelines](./.github/contributing.md) before getting started.
|
||||
|
||||
## License
|
||||
|
||||
[Apache License 2.0](./license.txt)
|
||||
|
||||
|
||||
@@ -1,117 +0,0 @@
|
||||
<div align="center">
|
||||
<a href="https://app.whyengineer.com/zh">
|
||||
<img width="160" height="160" src="https://ecubus.oss-cn-chengdu.aliyuncs.com/img/logo256.png">
|
||||
</a>
|
||||
|
||||
<h1>EcuBus-Pro</h1>
|
||||
|
||||
<div style="margin:5px; display: flex; justify-content: center; align-items: center;gap:4px">
|
||||
<a href="https://github.com/ecubus/EcuBus-Pro/releases">
|
||||
<img src="https://github.com/ecubus/EcuBus-Pro/actions/workflows/build.yml/badge.svg" alt="github-ci" />
|
||||
</a>
|
||||
<a href="https://github.com/ecubus/EcuBus-Pro/releases">
|
||||
<img src="https://github.com/ecubus/EcuBus-Pro/actions/workflows/build-linux.yml/badge.svg" alt="github-ci" />
|
||||
</a>
|
||||
<a href="https://repology.org/project/ecubus-pro/versions">
|
||||
<img src="https://repology.org/badge/version-for-repo/aur/ecubus-pro.svg" alt="AUR package">
|
||||
</a>
|
||||
<a href="https://github.com/ecubus/EcuBus-Pro">
|
||||
<img src="https://img.shields.io/github/stars/ecubus/EcuBus-Pro"/>
|
||||
</a>
|
||||
</div>
|
||||
<b style="font-size:20px;margin:10px;display:block">功能强大的汽车ECU开发工具</b>
|
||||
<i>易于使用、跨平台、多适配器支持、强大的脚本能力、CLI支持</i><br/>
|
||||
文档: <a href="https://app.whyengineer.com/zh">https://app.whyengineer.com/zh</a> | <a href="https://app.whyengineer.com">English Document</a>
|
||||
</div>
|
||||
|
||||
## 概览
|
||||
|
||||

|
||||
|
||||
EcuBus-Pro是商业汽车诊断工具(如`CAN-OE`)的开源替代品。它为ECU开发和测试提供了全面的解决方案,具有以下特点:
|
||||
|
||||
- 🆓 开源且免费使用
|
||||
- 🚀 现代化、直观的用户界面
|
||||
- 💻 跨平台支持(Windows、Linux、MacOS)- [安装指南](./docs/about/install.md)
|
||||
- 🔌 多硬件支持
|
||||
- **[EcuBus-LinCable](https://app.whyengineer.com/zh/docs/um/hardware/lincable.html)**: LIN(支持LIN一致性测试)、[PWM](https://app.whyengineer.com/zh/docs/um/pwm/pwm.html)
|
||||
- **PEAK**: CAN、CAN-FD、LIN
|
||||
- **KVASER**: CAN、CAN-FD、LIN
|
||||
- **ZLG**: CAN、CAN-FD
|
||||
- **Toomotss**: CAN、CAN-FD、LIN
|
||||
- **VECTOR**: CAN、CAN-FD、LIN
|
||||
- **SLCAN**: CAN、CAN-FD [详情](https://app.whyengineer.com/zh/docs/um/can/can.html#slcan-special)
|
||||
- **GS_USB (CANDLE)**: CAN、CAN-FD [详情](https://app.whyengineer.com/zh/docs/um/can/can.html#gs-usb)
|
||||
- 🛠️ 全面的诊断功能
|
||||
- **诊断协议**: CAN/CAN-FD、DoIP、LIN
|
||||
- 🌐 **SOME/IP**: SOME/IP协议支持 - [详情](https://app.whyengineer.com/zh/docs/um/someip/index.html)
|
||||
- 📝 **脚本**: 基于TypeScript的高级自动化 - [详情](./docs/um/script.md)
|
||||
- 🧪 **测试**: HIL测试框架 - [详情](./docs/um/test/test.md)
|
||||
- 📊 **数据库支持**: LIN LDF(编辑和导出)、CAN DBC(查看) - [详情](./docs/um/database.md)
|
||||
- 📈 **数据可视化**: 实时信号图表和分析 - [详情](./docs/um/graph/graph.md)
|
||||
- ⌨️ **命令行**: 功能齐全的CLI,支持自动化和集成 - [详情](./docs/um/cli.md)
|
||||
- 🎨 **面板**: 拖拽式界面构建器,用于自定义UI - [详情](./docs/um/panel/index.md)
|
||||
|
||||
[阅读文档了解更多](https://app.whyengineer.com/zh/)
|
||||
|
||||
|
||||
## 支持与赞助
|
||||
|
||||
<div align="center">
|
||||
<h3 style="padding:20px;font-size:22px">白金赞助商</h3>
|
||||
<table style="width: 80%; margin: 0 auto; border-collapse: collapse;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 33.33%; text-align: center; padding: 20px; border: 1px solid #eee;">
|
||||
<a href="./docs/about/sponsor">成为赞助商</a>
|
||||
</td>
|
||||
<td style="width: 33.33%; text-align: center; padding: 20px; border: 1px solid #eee;">
|
||||
<a href="./docs/about/sponsor">成为赞助商</a>
|
||||
</td>
|
||||
<td style="width: 33.33%; text-align: center; padding: 20px; border: 1px solid #eee;">
|
||||
<a href="./docs/about/sponsor">成为赞助商</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<h3 style="padding:20px;font-size:20px">金牌赞助商</h3>
|
||||
|
||||
<table style="width: 90%; margin: 0 auto; border-collapse: collapse;">
|
||||
<tbody>
|
||||
<tr>
|
||||
<td style="width: 25%; text-align: center; padding: 20px; border: 1px solid #eee;">
|
||||
<a href="http://www.cdkhdz.com" target="_blank">
|
||||
<img src="./public/logo/KUNHONG-LOGO - re-E1.png" alt="KUNHONG" width="120"/>
|
||||
</a>
|
||||
</td>
|
||||
<td style="width: 25%; text-align: center; padding: 20px; border: 1px solid #eee;">
|
||||
<a href="./docs/about/sponsor">成为赞助商</a>
|
||||
</td>
|
||||
<td style="width: 25%; text-align: center; padding: 20px; border: 1px solid #eee;">
|
||||
<a href="./docs/about/sponsor">成为赞助商</a>
|
||||
</td>
|
||||
<td style="width: 25%; text-align: center; padding: 20px; border: 1px solid #eee;">
|
||||
<a href="./docs/about/sponsor">成为赞助商</a>
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
|
||||
---
|
||||
|
||||
考虑[成为赞助商](./docs/about/sponsor)以支持持续开发。赞助商将获得显著的徽标展示位置和网站链接。🙏
|
||||
|
||||
## 贡献者
|
||||
|
||||
感谢所有帮助塑造EcuBus-Pro的贡献者:
|
||||
|
||||
<a href="https://github.com/ecubus/EcuBus-Pro/graphs/contributors" target="_blank"><img src="https://contrib.rocks/image?repo=ecubus/EcuBus-Pro"></a>
|
||||
|
||||
我们欢迎贡献!在开始之前,请查看我们的[贡献指南](./.github/contributing.md)。
|
||||
|
||||
|
||||
## 许可证
|
||||
|
||||
[Apache License 2.0](./license.zh.txt)
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
import { resolve } from 'path'
|
||||
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
|
||||
import ConditionalCompile from 'vite-plugin-conditional-compiler'
|
||||
|
||||
export default defineConfig({
|
||||
main: {
|
||||
plugins: [externalizeDepsPlugin(), ConditionalCompile()],
|
||||
resolve: {
|
||||
// src
|
||||
alias: {
|
||||
src: resolve(__dirname, 'src')
|
||||
}
|
||||
},
|
||||
build: {
|
||||
target: 'node18',
|
||||
sourcemap: true,
|
||||
rollupOptions: {
|
||||
input: {
|
||||
index: resolve(__dirname, 'src/cli/index.ts'),
|
||||
fake: resolve(__dirname, 'src/cli/fake.ts'),
|
||||
vsomeip: resolve(__dirname, 'src/main/vsomeip/worker.ts')
|
||||
},
|
||||
output: {
|
||||
entryFileNames: (chunk) => {
|
||||
if (chunk.name === 'vsomeip') return 'vsomeip.js'
|
||||
if (chunk.name === 'index') return 'ecb_cli.js'
|
||||
return chunk.name + '.js'
|
||||
},
|
||||
format: 'cjs',
|
||||
dir: resolve(__dirname, 'cli/out/')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
@@ -1,11 +0,0 @@
|
||||
project_id_env: CROWDIN_PROJECT_ID
|
||||
api_token_env: CROWDIN_PERSONAL_TOKEN
|
||||
|
||||
|
||||
files:
|
||||
- source: /docs/en/**/*.md
|
||||
translation: /docs/%two_letters_code%/**/%original_file_name%
|
||||
- source: /resources/examples/**/readme.md
|
||||
translation: /resources/examples/**/readme.%two_letters_code%.md
|
||||
- source: /.vitepress/en.json
|
||||
translation: /.vitepress/%two_letters_code%.json
|
||||
@@ -1,3 +0,0 @@
|
||||
provider: generic
|
||||
url: https://example.com/auto-updates
|
||||
updaterCacheDirName: ecubus-pro-updater
|
||||
@@ -1,17 +0,0 @@
|
||||
{
|
||||
"folders": [
|
||||
{
|
||||
"path": "."
|
||||
},
|
||||
{
|
||||
"path": "../ecubus-plugin-template"
|
||||
},
|
||||
{
|
||||
"path": "../ecubus-lang-zh"
|
||||
}
|
||||
],
|
||||
"settings": {
|
||||
"typescript.tsserver.log": "off",
|
||||
"typescript.experimental.useTsgo": false
|
||||
}
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
appId: EcuBus-Pro
|
||||
productName: EcuBus-Pro
|
||||
fileAssociations:
|
||||
ext: ecb
|
||||
description: EcuBus-Pro
|
||||
|
||||
directories:
|
||||
buildResources: build
|
||||
files:
|
||||
- '!**/.vscode/*'
|
||||
- '!src/*'
|
||||
- '!electron.vite.config.{js,ts,mjs,cjs}'
|
||||
- '!{.eslintignore,.eslintrc.cjs,.prettierignore,.prettierrc.yaml,dev-app-update.yml,CHANGELOG.md,README.md}'
|
||||
- '!{.env,.env.*,.npmrc,pnpm-lock.yaml,package-lock.json}'
|
||||
- '!{tsconfig.json,tsconfig.node.json,tsconfig.web.json}'
|
||||
asarUnpack:
|
||||
- resources/**
|
||||
nodeGypRebuild: false
|
||||
win:
|
||||
target:
|
||||
- target: nsis
|
||||
arch:
|
||||
- x64
|
||||
publish:
|
||||
provider: generic
|
||||
url: ''
|
||||
nsis:
|
||||
oneClick: false
|
||||
allowElevation: true
|
||||
perMachine: false
|
||||
license: license.txt
|
||||
allowToChangeInstallationDirectory: true
|
||||
installerIcon: ./build/icon.ico
|
||||
uninstallerIcon: ./build/icon.ico
|
||||
installerHeaderIcon: ./build/icon.ico
|
||||
installerSidebar: ./build/sidebar.bmp
|
||||
uninstallerSidebar: ./build/sidebar.bmp
|
||||
createDesktopShortcut: true
|
||||
createStartMenuShortcut: true
|
||||
artifactName: EcuBus-Pro ${version}.exe
|
||||
guid: 98123fde-012f-5ff3-8b50-881449dac91a
|
||||
include: build/installer.nsh
|
||||
mac:
|
||||
target:
|
||||
- target: dmg
|
||||
icon: ./build/icon.icns
|
||||
entitlements: build/entitlements.mac.plist
|
||||
entitlementsInherit: build/entitlements.mac.plist
|
||||
identity: null
|
||||
artifactName: EcuBus-Pro-${version}-${arch}.dmg
|
||||
linux:
|
||||
target:
|
||||
- target: deb
|
||||
- target: rpm
|
||||
icon: ./build/icon.icns
|
||||
executableName: ecubuspro
|
||||
description: EcuBus-Pro
|
||||
category: Development
|
||||
desktop:
|
||||
entry:
|
||||
Name: EcuBus-Pro
|
||||
Comment: EcuBus-Pro
|
||||
Terminal: false
|
||||
Type: Application
|
||||
Icon: ecubuspro
|
||||
Categories: Development
|
||||
maintainer: https://github.com/ecubus/EcuBus-Pro
|
||||
@@ -1,47 +0,0 @@
|
||||
import { resolve } from 'path'
|
||||
import { defineConfig, externalizeDepsPlugin } from 'electron-vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import vueJsx from '@vitejs/plugin-vue-jsx'
|
||||
import { nodePolyfills } from 'vite-plugin-node-polyfills'
|
||||
import ConditionalCompile from 'vite-plugin-conditional-compiler'
|
||||
|
||||
export default defineConfig({
|
||||
main: {
|
||||
resolve: {
|
||||
alias: {
|
||||
src: resolve(__dirname, 'src')
|
||||
}
|
||||
},
|
||||
plugins: [externalizeDepsPlugin(), ConditionalCompile()],
|
||||
build: {
|
||||
rollupOptions: {
|
||||
input: {
|
||||
index: resolve(__dirname, 'src/main/index.ts'),
|
||||
vsomeip: resolve(__dirname, 'src/main/vsomeip/worker.ts')
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
preload: {
|
||||
plugins: [externalizeDepsPlugin()]
|
||||
},
|
||||
renderer: {
|
||||
resolve: {
|
||||
alias: {
|
||||
src: resolve(__dirname, 'src'),
|
||||
'@r': resolve('src/renderer/src'),
|
||||
nodeCan: resolve(__dirname, 'src/main/share')
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
vue(),
|
||||
vueJsx(),
|
||||
nodePolyfills({
|
||||
include: ['buffer'],
|
||||
globals: {
|
||||
Buffer: true
|
||||
}
|
||||
})
|
||||
]
|
||||
}
|
||||
})
|
||||
@@ -1,11 +0,0 @@
|
||||
param(
|
||||
[Parameter(Mandatory=$false)]
|
||||
[string]$PackageName
|
||||
)
|
||||
|
||||
Write-Host "Installing $PackageName"
|
||||
./resources/python/python -m pip install --upgrade $PackageName --no-warn-script-location
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,202 +0,0 @@
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "[]"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,205 +0,0 @@
|
||||
{
|
||||
"name": "ecubuspro",
|
||||
"version": "0.8.66",
|
||||
"description": "EcuBus-Pro",
|
||||
"main": "./out/main/index.js",
|
||||
"author": "frankie.zengfu@gmail.com",
|
||||
"homepage": "https://app.whyengineer.com",
|
||||
"license": "Apache-2.0",
|
||||
"ecubusPro": {
|
||||
"vendor": {
|
||||
"win32": [
|
||||
"simulate",
|
||||
"kvaser",
|
||||
"peak",
|
||||
"zlg",
|
||||
"toomoss",
|
||||
"vector",
|
||||
"slcan",
|
||||
"ecubus",
|
||||
"candle"
|
||||
],
|
||||
"linux": [
|
||||
"simulate",
|
||||
"slcan"
|
||||
],
|
||||
"darwin": [
|
||||
"simulate",
|
||||
"slcan"
|
||||
]
|
||||
}
|
||||
},
|
||||
"lint-staged": {
|
||||
"*.{ts,vue}": [
|
||||
"prettier --write",
|
||||
"eslint --ext .ts,.vue --fix"
|
||||
]
|
||||
},
|
||||
"scripts": {
|
||||
"format": "prettier --write .",
|
||||
"lint": "eslint . --ext .ts,.vue --fix",
|
||||
"typecheck:node": "tsgo --noEmit -p tsconfig.node.json --composite false",
|
||||
"typecheck:web": "vue-tsc --noEmit -p tsconfig.web.json --composite false",
|
||||
"typecheck": "npm run typecheck:node && npm run typecheck:web",
|
||||
"worker": "cd src/main/worker/secureAccess && npx node-gyp rebuild && cd ../../../.. && npx webpack --config webpack.config.js --mode production",
|
||||
"worker:js": "npx webpack --config webpack.config.js --mode production",
|
||||
"start": "electron-vite preview",
|
||||
"dev": "electron-vite dev",
|
||||
"test": "vitest --config vitest.config.ts",
|
||||
"build": "npm run typecheck && electron-vite build",
|
||||
"build:sdk": "vite build --config vite.sdk.config.ts",
|
||||
"cli:dev": "electron-vite dev -c cli.vite.ts -w --entry cli/out/ecb_cli2.js",
|
||||
"cli:build": "electron-vite build -c cli.vite.ts",
|
||||
"cli:build:win": "electron-vite build -c cli.vite.ts && cd cli && npm run win",
|
||||
"cli:build:linux": "electron-vite build -c cli.vite.ts && cd cli && npm run linux",
|
||||
"cli:build:mac": "electron-vite build -c cli.vite.ts && cd cli && npm run mac",
|
||||
"postinstall": "electron-builder install-app-deps",
|
||||
"build:unpack": "npm run build && electron-builder --dir",
|
||||
"build:win": "npm run build && electron-builder --win",
|
||||
"build:mac": "npm run build && electron-builder --mac",
|
||||
"build:linux": "npm run build && electron-builder --linux",
|
||||
"native": "npm run docan && npm run dolin && npm run someip",
|
||||
"api": "typedoc --tsconfig tsconfig.worker.json --lang en-US",
|
||||
"docan": "cd src/main/docan && npx node-gyp rebuild",
|
||||
"dolin": "cd src/main/dolin && npx node-gyp rebuild",
|
||||
"someip": "cd src/main/vsomeip && npx node-gyp rebuild",
|
||||
"docs:dev": "vitepress dev",
|
||||
"docs:build": "vitepress build",
|
||||
"docs:preview": "vitepress preview",
|
||||
"prepare": "husky"
|
||||
},
|
||||
"dependencies": {
|
||||
"@electron-toolkit/preload": "^3.0.0",
|
||||
"@electron-toolkit/utils": "^3.0.0",
|
||||
"@element-plus/icons-vue": "^2.3.1",
|
||||
"@form-create/element-ui": "^3.2.22",
|
||||
"@iconify/icons-grommet-icons": "^1.2.5",
|
||||
"@iconify/icons-mdi": "^1.2.48",
|
||||
"@joint/core": "^4.0.4",
|
||||
"@vitejs/plugin-vue-jsx": "^3.1.0",
|
||||
"@vueuse/core": "^10.7.2",
|
||||
"@vxe-ui/plugin-render-element": "^4.0.10",
|
||||
"@xterm/addon-canvas": "^0.7.0",
|
||||
"@xterm/addon-fit": "^0.10.0",
|
||||
"@xterm/xterm": "^5.5.0",
|
||||
"adm-zip": "^0.5.16",
|
||||
"ajv": "^8.18.0",
|
||||
"animate.css": "^4.1.1",
|
||||
"async": "^3.2.6",
|
||||
"async-validator": "^4.2.5",
|
||||
"axios": "^1.8.2",
|
||||
"body-parser": "^2.2.1",
|
||||
"chevrotain": "^12.0.0",
|
||||
"codemirror": "^6.65.7",
|
||||
"colors": "^1.4.0",
|
||||
"commander": "^12.1.0",
|
||||
"conf": "^15.1.0",
|
||||
"dayjs": "^1.11.13",
|
||||
"e-virt-table": "^1.2.35",
|
||||
"echarts": "^6.0.0",
|
||||
"electron-log": "^5.1.2",
|
||||
"electron-updater": "^6.3.9",
|
||||
"element-plus": "^2.11.0",
|
||||
"emittery": "^1.2.0",
|
||||
"events": "^3.3.0",
|
||||
"exceljs": "^4.4.0",
|
||||
"glob": "^11.1.0",
|
||||
"handlebars": "^4.7.9",
|
||||
"i18next": "^25.6.2",
|
||||
"i18next-vue": "^5.3.0",
|
||||
"iconv-lite": "^0.7.0",
|
||||
"javascript-obfuscator": "^5.2.0",
|
||||
"jquery": "^3.7.1",
|
||||
"jquery-ui": "^1.14.1",
|
||||
"js-beautify": "^1.15.4",
|
||||
"json5": "^2.2.3",
|
||||
"lodash": "^4.17.23",
|
||||
"marked": "^14.1.3",
|
||||
"mitt": "^3.0.1",
|
||||
"path-browserify": "^1.0.1",
|
||||
"pinia": "^3.0.2",
|
||||
"pixi.js-legacy": "^5.3.3",
|
||||
"python-shell": "^5.0.0",
|
||||
"serialport": "^13.0.0",
|
||||
"sortablejs": "^1.15.2",
|
||||
"ts-morph": "^26.0.0",
|
||||
"uuid": "^14.0.0",
|
||||
"vite-plugin-string": "^1.2.3",
|
||||
"vite-raw-plugin": "^1.0.2",
|
||||
"vitepress-plugin-image-viewer": "^1.1.6",
|
||||
"vue-grid-layout-v3": "^3.1.2",
|
||||
"vue-router": "^4.2.5",
|
||||
"vuedraggable": "4.1.0",
|
||||
"vxe-pc-ui": "^4.2.53",
|
||||
"vxe-table": "^4.16.11",
|
||||
"winston": "^3.17.0",
|
||||
"wujie-polyfill": "^1.1.3",
|
||||
"wujie-vue3": "^1.0.29",
|
||||
"xterm": "^5.3.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@electron-toolkit/eslint-config": "^1.0.2",
|
||||
"@electron-toolkit/eslint-config-ts": "^1.0.1",
|
||||
"@electron-toolkit/tsconfig": "^1.0.1",
|
||||
"@electron/rebuild": "^4.0.4",
|
||||
"@iconify/icons-ep": "^1.2.12",
|
||||
"@iconify/icons-material-symbols": "^1.2.58",
|
||||
"@iconify/icons-ph": "^1.2.5",
|
||||
"@iconify/vue": "^4.1.1",
|
||||
"@liudonghua123/pkg": "^6.0.1",
|
||||
"@rollup/plugin-node-resolve": "^15.3.0",
|
||||
"@rushstack/eslint-patch": "^1.7.1",
|
||||
"@types/adm-zip": "^0.5.7",
|
||||
"@types/async": "^3.2.24",
|
||||
"@types/node": "^22.9.1",
|
||||
"@types/path-browserify": "^1.0.3",
|
||||
"@types/uuid": "^10.0.0",
|
||||
"@typescript/native-preview": "^7.0.0-dev.20260124.1",
|
||||
"@vitejs/plugin-vue": "^5.0.3",
|
||||
"@vue/eslint-config-prettier": "^9.0.0",
|
||||
"@vue/eslint-config-typescript": "^12.0.0",
|
||||
"ali-oss": "^6.21.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"electron": "^39.8.6",
|
||||
"electron-builder": "26.8.1",
|
||||
"electron-vite": "^2.3.0",
|
||||
"eslint": "^8.57.1",
|
||||
"eslint-plugin-vue": "^9.32.0",
|
||||
"husky": "^9.1.7",
|
||||
"lint-staged": "^15.4.3",
|
||||
"mermaid": "^11.12.3",
|
||||
"node-addon-api": "^8.2.2",
|
||||
"node-gyp": "^12.3.0",
|
||||
"node-loader": "^2.1.0",
|
||||
"prettier": "^3.5.2",
|
||||
"rollup": "^4.59.0",
|
||||
"rollup-plugin-dts": "^6.3.0",
|
||||
"sass": "^1.83.0",
|
||||
"ts-loader": "^9.5.4",
|
||||
"typedoc": "^0.27.6",
|
||||
"typescript": "^5.3.3",
|
||||
"viewerjs": "^1.11.6",
|
||||
"vite": "^5.4.21",
|
||||
"vite-plugin-conditional-compiler": "^0.3.1",
|
||||
"vite-plugin-dts": "^4.5.4",
|
||||
"vite-plugin-node-polyfills": "^0.21.0",
|
||||
"vitepress": "^2.0.0-alpha.16",
|
||||
"vitepress-mermaid-renderer": "^1.1.11",
|
||||
"vitest": "^3.2.4",
|
||||
"vue": "^3.5.13",
|
||||
"vue-tsc": "^2.1.6",
|
||||
"webpack": "^5.105.0",
|
||||
"webpack-cli": "^5.1.4",
|
||||
"yaml": "^2.6.0"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"@rollup/rollup-linux-x64-gnu": "4.46.2"
|
||||
},
|
||||
"overrides": {
|
||||
"esbuild": "^0.25.0",
|
||||
"axios": "^1.8.2",
|
||||
"@babel/runtime": "^7.26.10",
|
||||
"tar-fs": "2.1.4",
|
||||
"node-gyp": "^12.3.0"
|
||||
}
|
||||
}
|
||||
@@ -1,199 +0,0 @@
|
||||
import { app, ipcMain, net } from 'electron'
|
||||
import { exec } from 'child_process'
|
||||
import { readFile } from 'fs'
|
||||
import { hostname, release } from 'os'
|
||||
import log from 'electron-log'
|
||||
|
||||
export type AptabaseOptions = {
|
||||
host?: string
|
||||
}
|
||||
|
||||
const SDK_VERSION = 'ecubus-analytics@1.0.0'
|
||||
|
||||
const _hosts: Record<string, string> = {
|
||||
US: 'https://us.aptabase.com',
|
||||
EU: 'https://eu.aptabase.com',
|
||||
DEV: 'http://localhost:3000',
|
||||
SH: ''
|
||||
}
|
||||
|
||||
type EnvironmentInfo = {
|
||||
appVersion: string
|
||||
isDebug: boolean
|
||||
locale: string
|
||||
osName: string
|
||||
osVersion: string
|
||||
engineName: string
|
||||
engineVersion: string
|
||||
sdkVersion: string
|
||||
}
|
||||
|
||||
const _sessionId = newSessionId()
|
||||
let _appKey = ''
|
||||
let _apiUrl = ''
|
||||
let _env: EnvironmentInfo | undefined
|
||||
|
||||
function newSessionId(): string {
|
||||
return (process.env.COMPUTERNAME ?? hostname()).trim()
|
||||
}
|
||||
|
||||
async function getOsVersion(): Promise<[string, string]> {
|
||||
switch (process.platform) {
|
||||
case 'win32':
|
||||
return ['Windows', release()]
|
||||
case 'darwin':
|
||||
try {
|
||||
const v = await new Promise<string>((resolve, reject) => {
|
||||
exec('/usr/bin/sw_vers -productVersion', (err, stdout) => {
|
||||
if (err) reject(err)
|
||||
else resolve(stdout.trim())
|
||||
})
|
||||
})
|
||||
return ['macOS', v]
|
||||
} catch {
|
||||
return ['macOS', '']
|
||||
}
|
||||
default: {
|
||||
try {
|
||||
const text = await new Promise<string>((resolve, reject) => {
|
||||
readFile('/etc/os-release', 'utf8', (err, data) => {
|
||||
if (err) reject(err)
|
||||
else resolve(data)
|
||||
})
|
||||
})
|
||||
const lines = text.split('\n')
|
||||
const map: Record<string, string> = {}
|
||||
for (const line of lines) {
|
||||
const [k, ...rest] = line.split('=')
|
||||
if (k && rest.length) {
|
||||
map[k] = rest.join('=').replace(/"/g, '')
|
||||
}
|
||||
}
|
||||
const name = map.NAME ?? 'Linux'
|
||||
const ver = map.VERSION_ID ?? ''
|
||||
return [name, ver]
|
||||
} catch {
|
||||
return ['Linux', '']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function getEnvironmentInfo(): Promise<EnvironmentInfo> {
|
||||
const [osName, osVersion] = await getOsVersion()
|
||||
return {
|
||||
appVersion: app.getVersion(),
|
||||
isDebug: !app.isPackaged,
|
||||
locale: app.getLocale(),
|
||||
osName,
|
||||
osVersion,
|
||||
engineName: 'Chromium',
|
||||
engineVersion: process.versions.chrome ?? '',
|
||||
sdkVersion: SDK_VERSION
|
||||
}
|
||||
}
|
||||
|
||||
function getBaseUrl(region: string, options?: AptabaseOptions): string | undefined {
|
||||
if (region === 'SH') {
|
||||
if (!options?.host) {
|
||||
log.warn('Aptabase: Host parameter must be defined when using Self-Hosted App Key.')
|
||||
return undefined
|
||||
}
|
||||
return options.host
|
||||
}
|
||||
return _hosts[region]
|
||||
}
|
||||
|
||||
function registerEventHandler(): void {
|
||||
ipcMain.on(
|
||||
'aptabase-track-event',
|
||||
(
|
||||
_event,
|
||||
payload: {
|
||||
eventName?: string
|
||||
name?: string
|
||||
props?: Record<string, string | number | boolean>
|
||||
properties?: Record<string, string | number | boolean>
|
||||
}
|
||||
) => {
|
||||
const eventName = payload.eventName ?? payload.name
|
||||
if (!eventName) return
|
||||
const props = payload.props ?? payload.properties
|
||||
void trackEvent(eventName, props)
|
||||
}
|
||||
)
|
||||
}
|
||||
|
||||
export async function initialize(appKey: string, options?: AptabaseOptions): Promise<void> {
|
||||
const parts = appKey.split('-')
|
||||
if (parts.length !== 3 || _hosts[parts[1]] === undefined) {
|
||||
log.warn(`Analytics: App Key "${appKey}" is invalid. Tracking will be disabled.`)
|
||||
return
|
||||
}
|
||||
|
||||
const baseUrl = getBaseUrl(parts[1], options)
|
||||
if (!baseUrl) return
|
||||
|
||||
_apiUrl = `${baseUrl}/api/v0/event`
|
||||
_env = await getEnvironmentInfo()
|
||||
_appKey = appKey
|
||||
|
||||
registerEventHandler()
|
||||
}
|
||||
|
||||
export function trackEvent(
|
||||
eventName: string,
|
||||
props?: Record<string, string | number | boolean>
|
||||
): Promise<void> {
|
||||
if (!_appKey || !_env) {
|
||||
return Promise.resolve()
|
||||
}
|
||||
|
||||
const now = new Date()
|
||||
|
||||
const body = {
|
||||
timestamp: now.toISOString(),
|
||||
sessionId: _sessionId,
|
||||
eventName,
|
||||
systemProps: {
|
||||
isDebug: _env.isDebug,
|
||||
locale: _env.locale,
|
||||
osName: _env.osName,
|
||||
osVersion: _env.osVersion,
|
||||
engineName: _env.engineName,
|
||||
engineVersion: _env.engineVersion,
|
||||
appVersion: _env.appVersion,
|
||||
sdkVersion: _env.sdkVersion
|
||||
},
|
||||
props
|
||||
}
|
||||
|
||||
return new Promise((resolve) => {
|
||||
const onReject = (err: Error) => {
|
||||
log.error('Analytics: Failed to send event', err)
|
||||
resolve()
|
||||
}
|
||||
|
||||
const req = net.request({
|
||||
method: 'POST',
|
||||
url: _apiUrl,
|
||||
credentials: 'omit'
|
||||
})
|
||||
|
||||
req.setHeader('Content-Type', 'application/json')
|
||||
req.setHeader('App-Key', _appKey)
|
||||
|
||||
req.on('error', onReject)
|
||||
req.on('response', (res) => {
|
||||
if (res.statusCode && res.statusCode >= 300) {
|
||||
log.warn(
|
||||
`Analytics: Failed to send event "${eventName}": ${res.statusCode} ${res.statusMessage}`
|
||||
)
|
||||
}
|
||||
resolve()
|
||||
})
|
||||
|
||||
req.write(JSON.stringify(body))
|
||||
req.end()
|
||||
})
|
||||
}
|
||||
@@ -1,121 +0,0 @@
|
||||
import { CanDB } from './share/can'
|
||||
import { execBinary } from './util'
|
||||
import { getPythonPath } from './python'
|
||||
import fsP from 'fs/promises'
|
||||
import path from 'path'
|
||||
import iconv from 'iconv-lite'
|
||||
|
||||
/** Common encodings for DBC comments/units (Chinese etc.). Tried in order when encoding is not specified. */
|
||||
const DEFAULT_ENCODINGS = ['gbk', 'gb2312', 'gb18030', 'big5', 'cp936'] as const
|
||||
|
||||
/**
|
||||
* Fix strings that were encoded (e.g. GBK/Big5) but misinterpreted as Latin-1 during DBC parse.
|
||||
* Each byte (0x80-0xFF) becomes U+00XX; convert back to bytes and decode with given encoding(s).
|
||||
* Only applies when all chars are in 0-255 (indicating misinterpreted bytes).
|
||||
*/
|
||||
function fixMisencodedString(
|
||||
str: string,
|
||||
encodings: readonly string[] = DEFAULT_ENCODINGS
|
||||
): string {
|
||||
if (typeof str !== 'string' || str.length === 0) return str
|
||||
const chars = [...str]
|
||||
const allSingleByte = chars.every((c) => (c.codePointAt(0) ?? 0) <= 0xff)
|
||||
const hasHighBytes = chars.some((c) => {
|
||||
const cp = c.codePointAt(0) ?? 0
|
||||
return cp >= 0x80 && cp <= 0xff
|
||||
})
|
||||
if (!allSingleByte || !hasHighBytes) return str
|
||||
const bytes = Buffer.from(chars.map((c) => c.charCodeAt(0) & 0xff))
|
||||
for (const enc of encodings) {
|
||||
try {
|
||||
const decoded = iconv.decode(bytes, enc)
|
||||
if (!decoded.includes('�')) return decoded
|
||||
} catch {
|
||||
/* try next */
|
||||
}
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
function fixMisencodedInValue(val: unknown, encodings: readonly string[]): unknown {
|
||||
if (typeof val === 'string') return fixMisencodedString(val, encodings)
|
||||
if (Array.isArray(val)) return val.map((v) => fixMisencodedInValue(v, encodings))
|
||||
if (val !== null && typeof val === 'object') {
|
||||
const out: Record<string, unknown> = {}
|
||||
for (const [k, v] of Object.entries(val)) out[k] = fixMisencodedInValue(v, encodings)
|
||||
return out
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
export interface ParseFileOptions {
|
||||
/** Encoding(s) to try when fixing misinterpreted strings (e.g. gbk, big5). If omitted, tries gbk, gb2312, gb18030, big5, cp936. */
|
||||
encoding?: string | string[]
|
||||
}
|
||||
|
||||
export async function parseFile(
|
||||
filePath: string,
|
||||
outputJsonPath: string,
|
||||
options?: ParseFileOptions
|
||||
): Promise<{ data: CanDB; msg: string }> {
|
||||
const pythonPath = getPythonPath()
|
||||
const result = await execBinary(pythonPath, [
|
||||
'-m',
|
||||
'canmatrix.cli.convert',
|
||||
filePath,
|
||||
outputJsonPath,
|
||||
'--jsonExportAll'
|
||||
])
|
||||
if (result.success) {
|
||||
if (result.stdout.toLowerCase().includes('error')) {
|
||||
throw new Error(result.stdout)
|
||||
}
|
||||
if (result.stderr.toLowerCase().includes('error')) {
|
||||
throw new Error(result.stderr)
|
||||
}
|
||||
const json = await fsP.readFile(outputJsonPath, 'utf-8')
|
||||
const encodings =
|
||||
options?.encoding === undefined
|
||||
? DEFAULT_ENCODINGS
|
||||
: Array.isArray(options.encoding)
|
||||
? options.encoding
|
||||
: [options.encoding]
|
||||
const data = fixMisencodedInValue(JSON.parse(json), encodings) as CanDB
|
||||
return {
|
||||
data,
|
||||
msg: result.stdout
|
||||
}
|
||||
} else {
|
||||
throw new Error(result.stderr)
|
||||
}
|
||||
}
|
||||
|
||||
export async function exportOtherFile(
|
||||
tmpDir: string,
|
||||
fileType: string,
|
||||
candb: CanDB,
|
||||
outputFilePath: string
|
||||
): Promise<void> {
|
||||
//covert candb to json firstly, then conver the json file to the other file
|
||||
const jsonFilePath = path.join(tmpDir, 'canmatrix.json')
|
||||
await fsP.writeFile(jsonFilePath, JSON.stringify(candb, null, 2))
|
||||
const pythonPath = getPythonPath()
|
||||
// Omit -f to infer format from output path extension; avoids KeyError when a
|
||||
// format module failed to load (e.g. arxml when lxml is missing)
|
||||
const result = await execBinary(pythonPath, [
|
||||
'-m',
|
||||
'canmatrix.cli.convert',
|
||||
jsonFilePath,
|
||||
outputFilePath
|
||||
])
|
||||
if (result.success) {
|
||||
if (result.stdout.toLowerCase().includes('error')) {
|
||||
throw new Error(result.stdout)
|
||||
}
|
||||
if (result.stderr.toLowerCase().includes('error')) {
|
||||
throw new Error(result.stderr)
|
||||
}
|
||||
} else {
|
||||
throw new Error(result.stderr)
|
||||
}
|
||||
}
|
||||
@@ -1,40 +0,0 @@
|
||||
/* eslint-disable no-var */
|
||||
import type { Logger } from 'winston'
|
||||
import type { EventEmitter } from 'events'
|
||||
import { LDF } from 'src/renderer/src/database/ldfParse'
|
||||
import { DBC } from 'src/renderer/src/database/dbc/dbcVisitor'
|
||||
import { VarItem } from 'src/preload/data'
|
||||
import { BrowserWindow } from 'electron'
|
||||
import { IntervalHistogram } from 'node:perf_hooks'
|
||||
import type { DataSet } from 'src/preload/data'
|
||||
|
||||
type VarUpdateItem = {
|
||||
name: string
|
||||
value: number | string | number[]
|
||||
id: string
|
||||
uuid?: string
|
||||
}
|
||||
type VarEvent = {
|
||||
update: [VarUpdateItem | VarUpdateItem[]]
|
||||
}
|
||||
|
||||
declare global {
|
||||
var sysLog: Logger
|
||||
var scriptLog: Logger
|
||||
var keyEvent: EventEmitter | undefined
|
||||
var varEvent: EventEmitter<VarEvent> | undefined
|
||||
var dataSet: DataSet
|
||||
var startTs: number
|
||||
var vars: Record<string, VarItem>
|
||||
var deviceIndexMap: Map<string, number>
|
||||
var mainWindow: BrowserWindow
|
||||
var toomossDeviceHandles:
|
||||
| Map<
|
||||
number,
|
||||
{
|
||||
refCount: number // 引用计数
|
||||
channels: Set<number> // 当前使用的通道
|
||||
}
|
||||
>
|
||||
| undefined
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
import i18next from 'i18next'
|
||||
import { dirname, join, relative } from 'path'
|
||||
import fs from 'fs/promises'
|
||||
import { glob } from 'glob'
|
||||
import localesPath from '../../resources/locales/.gitkeep?asset&asarUnpack'
|
||||
import log from 'electron-log'
|
||||
import { getPluginsDirectory } from './ipc/plugin'
|
||||
|
||||
// 缓存
|
||||
const translationsCache = new Map<string, Record<string, any>>()
|
||||
let supportedLanguagesCache: string[] | null = null
|
||||
|
||||
// 获取主应用 locales 目录路径
|
||||
export const getAppLocalesPath = () => {
|
||||
// localesPath 会指向 resources/locales/en/translation.json
|
||||
// 我们需要返回 resources/locales 目录
|
||||
const localesDir = dirname(localesPath)
|
||||
return localesDir
|
||||
}
|
||||
|
||||
// 使用 glob 加载指定语言的所有翻译文件并合并为一个大的 JSON
|
||||
async function loadAllTranslations(lng: string): Promise<Record<string, any>> {
|
||||
const merged: Record<string, any> = {}
|
||||
const appLocalesPath = getAppLocalesPath()
|
||||
|
||||
try {
|
||||
// 加载主应用翻译:locales/{lng}/translation.json
|
||||
const appPattern = join(appLocalesPath, lng, 'translation.json').replace(/\\/g, '/')
|
||||
const appFiles = await glob(appPattern)
|
||||
|
||||
for (const file of appFiles) {
|
||||
try {
|
||||
const content = await fs.readFile(file, 'utf-8')
|
||||
const translations = JSON.parse(content)
|
||||
Object.assign(merged, translations)
|
||||
} catch (error) {
|
||||
log.error(`Failed to load app translation from ${file}:`, error)
|
||||
}
|
||||
}
|
||||
|
||||
// 加载插件翻译:plugins/*/locales/{lng}/translation.json
|
||||
const pluginsDir = getPluginsDirectory()
|
||||
const pluginPattern = join(pluginsDir, '*', 'locales', lng, 'translation.json').replace(
|
||||
/\\/g,
|
||||
'/'
|
||||
)
|
||||
const pluginFiles = await glob(pluginPattern)
|
||||
|
||||
for (const file of pluginFiles) {
|
||||
try {
|
||||
const content = await fs.readFile(file, 'utf-8')
|
||||
const translations = JSON.parse(content)
|
||||
// 插件翻译直接覆盖主应用翻译
|
||||
Object.assign(merged, translations)
|
||||
} catch (error) {
|
||||
log.error(`Failed to load plugin translation from ${file}:`, error)
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
log.error(`Failed to load translations for ${lng}:`, error)
|
||||
}
|
||||
|
||||
return merged
|
||||
}
|
||||
|
||||
// 从 i18next 获取已加载的翻译(如果已初始化)
|
||||
export function getAllTranslationsFromI18next(lng: string): Record<string, any> | null {
|
||||
if (!i18next.isInitialized) {
|
||||
return null
|
||||
}
|
||||
|
||||
// 使用 hasResourceBundle 检查该语言是否已加载
|
||||
if (!i18next.hasResourceBundle(lng, 'translation')) {
|
||||
return null
|
||||
}
|
||||
|
||||
// 获取 translation 命名空间的翻译(插件翻译已合并到其中)
|
||||
const bundle = i18next.getResourceBundle(lng, 'translation')
|
||||
return bundle || null
|
||||
}
|
||||
|
||||
// 获取所有翻译 - 供 IPC 使用
|
||||
// 优先从 i18next 获取,如果未初始化则读取文件
|
||||
export async function getAllTranslations(lng: string): Promise<Record<string, any>> {
|
||||
// 优先从已加载的 i18next 获取
|
||||
const cachedTranslations = getAllTranslationsFromI18next(lng)
|
||||
if (cachedTranslations) {
|
||||
return cachedTranslations
|
||||
}
|
||||
|
||||
// 检查缓存
|
||||
if (translationsCache.has(lng)) {
|
||||
return translationsCache.get(lng)!
|
||||
}
|
||||
|
||||
// 如果 i18next 未初始化或该语言未加载,则使用 glob 读取文件
|
||||
const translations = await loadAllTranslations(lng)
|
||||
translationsCache.set(lng, translations)
|
||||
return translations
|
||||
}
|
||||
|
||||
export const initMainI18n = async (lng: string = 'en') => {
|
||||
// 使用 glob 加载所有翻译并合并为一个大的 JSON
|
||||
const mergedTranslations = await loadAllTranslations(lng)
|
||||
|
||||
// 更新缓存
|
||||
translationsCache.set(lng, mergedTranslations)
|
||||
|
||||
// 构建资源对象
|
||||
const resources = {
|
||||
[lng]: {
|
||||
translation: mergedTranslations
|
||||
}
|
||||
}
|
||||
|
||||
await i18next.init({
|
||||
lng,
|
||||
fallbackLng: 'en',
|
||||
resources,
|
||||
ns: ['translation'],
|
||||
defaultNS: 'translation',
|
||||
debug: false,
|
||||
interpolation: {
|
||||
escapeValue: false
|
||||
}
|
||||
})
|
||||
|
||||
return i18next
|
||||
}
|
||||
|
||||
// 重新加载翻译(用于语言切换或插件动态加载)
|
||||
export const reloadTranslations = async (lng: string) => {
|
||||
// 使用 glob 加载所有翻译并合并为一个大的 JSON
|
||||
const mergedTranslations = await loadAllTranslations(lng)
|
||||
|
||||
// 更新缓存
|
||||
translationsCache.set(lng, mergedTranslations)
|
||||
|
||||
// 添加或更新资源
|
||||
i18next.addResourceBundle(lng, 'translation', mergedTranslations, true, true)
|
||||
|
||||
await i18next.changeLanguage(lng)
|
||||
}
|
||||
|
||||
// 清除翻译缓存(用于插件加载/卸载后)
|
||||
export function clearTranslationsCache(lng?: string) {
|
||||
if (lng) {
|
||||
translationsCache.delete(lng)
|
||||
} else {
|
||||
translationsCache.clear()
|
||||
}
|
||||
}
|
||||
|
||||
// 清除支持语言缓存
|
||||
export function clearSupportedLanguagesCache() {
|
||||
supportedLanguagesCache = null
|
||||
}
|
||||
|
||||
// 获取所有支持的语言(使用 glob 从主应用和插件中扫描)
|
||||
export async function getAllSupportedLanguages(): Promise<string[]> {
|
||||
// 检查缓存
|
||||
if (supportedLanguagesCache) {
|
||||
return supportedLanguagesCache
|
||||
}
|
||||
|
||||
const languageSet = new Set<string>()
|
||||
const appLocalesPath = getAppLocalesPath()
|
||||
|
||||
try {
|
||||
// 扫描主应用支持的语言:locales/*/translation.json
|
||||
const appPattern = join(appLocalesPath, '*', 'translation.json').replace(/\\/g, '/')
|
||||
const appFiles = await glob(appPattern)
|
||||
|
||||
for (const file of appFiles) {
|
||||
const relativePath = relative(appLocalesPath, file)
|
||||
const lng = relativePath.split(/[/\\]/)[0]
|
||||
languageSet.add(lng)
|
||||
}
|
||||
|
||||
// 扫描插件支持的语言:plugins/*/locales/*/translation.json
|
||||
const pluginsDir = getPluginsDirectory()
|
||||
const pluginPattern = join(pluginsDir, '*', 'locales', '*', 'translation.json').replace(
|
||||
/\\/g,
|
||||
'/'
|
||||
)
|
||||
const pluginFiles = await glob(pluginPattern)
|
||||
|
||||
for (const file of pluginFiles) {
|
||||
const relativePath = relative(pluginsDir, file)
|
||||
const parts = relativePath.split(/[/\\]/)
|
||||
const lng = parts[parts.length - 2] // locales 目录下的子目录名
|
||||
languageSet.add(lng)
|
||||
}
|
||||
} catch (error) {
|
||||
log.error('Failed to scan supported languages:', error)
|
||||
}
|
||||
|
||||
// 返回排序后的语言列表(确保 en 在前)
|
||||
const languages = Array.from(languageSet).sort((a, b) => {
|
||||
if (a === 'en') return -1
|
||||
if (b === 'en') return 1
|
||||
return a.localeCompare(b)
|
||||
})
|
||||
|
||||
// 更新缓存
|
||||
supportedLanguagesCache = languages
|
||||
|
||||
return languages
|
||||
}
|
||||
@@ -1,265 +0,0 @@
|
||||
import { app, shell, BrowserWindow, ipcMain, dialog, protocol as eProtocol, net } from 'electron'
|
||||
import path, { join } from 'path'
|
||||
import { electronApp, optimizer, is } from '@electron-toolkit/utils'
|
||||
import icon from '../../resources/icon.png?asset'
|
||||
import { store } from './store'
|
||||
import './ipc'
|
||||
import log from 'electron-log/main'
|
||||
import { initialize as initAnalytics, trackEvent } from './analytics'
|
||||
|
||||
import { createLogs } from './log'
|
||||
import './update'
|
||||
import { globalStop } from './ipc/uds'
|
||||
import { startRpcHost } from './rpcHost'
|
||||
import Transport from 'winston-transport'
|
||||
import { initMainI18n } from './i18n'
|
||||
import { setupCasdoor } from './ipc/casdoor'
|
||||
import 'src/renderer/src/helper'
|
||||
|
||||
import { closeAllWindows, closeWindow, logQ, maximizeWindow, minimizeWindow } from './multiWin'
|
||||
initAnalytics('A-EU-6409047217')
|
||||
log.initialize()
|
||||
|
||||
// Track app exit once (user closes window / app quits).
|
||||
let exitTracked = false
|
||||
app.once('before-quit', async () => {
|
||||
if (exitTracked) return
|
||||
exitTracked = true
|
||||
try {
|
||||
// Small timeout so we don't block quitting too long.
|
||||
await Promise.race([
|
||||
trackEvent('app_exit'),
|
||||
new Promise<void>((resolve) => setTimeout(resolve, 1500))
|
||||
])
|
||||
} catch {
|
||||
// Ignore tracking errors on shutdown.
|
||||
}
|
||||
})
|
||||
|
||||
// Register custom protocol as privileged before app is ready
|
||||
eProtocol.registerSchemesAsPrivileged([
|
||||
{
|
||||
scheme: 'local-resource',
|
||||
privileges: {
|
||||
secure: true,
|
||||
supportFetchAPI: true,
|
||||
bypassCSP: true,
|
||||
corsEnabled: true
|
||||
}
|
||||
}
|
||||
])
|
||||
|
||||
setupCasdoor()
|
||||
|
||||
log.info(app.getGPUFeatureStatus())
|
||||
|
||||
function registerLocalResourceProtocol() {
|
||||
eProtocol.handle('local-resource', (request) => {
|
||||
try {
|
||||
// Remove protocol prefix (handle both // and /// after protocol)
|
||||
const url = request.url.replace(/^local-resource:\/\/\/?/, '')
|
||||
// Decode URL components to handle encoded characters
|
||||
const decodedUrl = decodeURIComponent(url)
|
||||
// Normalize path (handle both forward and back slashes)
|
||||
const normalizedPath = decodedUrl.replace(/\\/g, '/')
|
||||
// For Windows absolute paths (e.g., D:/path), ensure proper file:/// format
|
||||
const fileUrl = /^[a-zA-Z]:\//.test(normalizedPath)
|
||||
? `file:///${normalizedPath}`
|
||||
: `file://${normalizedPath}`
|
||||
|
||||
if (fileUrl.endsWith('.map')) {
|
||||
//404
|
||||
return new Response(null, { status: 404 })
|
||||
}
|
||||
|
||||
return net.fetch(fileUrl)
|
||||
} catch (error) {
|
||||
log.error('ERROR: registerLocalResourceProtocol:', error)
|
||||
return new Response(null, { status: 404 })
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
// process.env.PYTHON_PATH=pythonPath
|
||||
const isDev = process.env.NODE_ENV === 'development'
|
||||
|
||||
ipcMain.on('electron-store-get', async (event, val) => {
|
||||
event.returnValue = store.get(val)
|
||||
})
|
||||
ipcMain.on('electron-store-set', async (event, key, val) => {
|
||||
store.set(key, val)
|
||||
})
|
||||
|
||||
class ElectronLog extends Transport {
|
||||
constructor(
|
||||
private q: typeof logQ,
|
||||
opts?: Transport.TransportStreamOptions
|
||||
) {
|
||||
super(opts)
|
||||
}
|
||||
|
||||
log(info: any, callback: () => void) {
|
||||
if (!info.message.method) {
|
||||
info.message = {
|
||||
method: 'ipc-log-main',
|
||||
message: info.message
|
||||
}
|
||||
}
|
||||
this.q.list.push(info)
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
function createWindow(): void {
|
||||
// Get stored window bounds and state
|
||||
const windowBounds = store.get('windowBounds') as Electron.Rectangle
|
||||
const isMaximized = store.get('windowMaximized', false)
|
||||
|
||||
function getBounds() {
|
||||
const bounds = global.mainWindow.getBounds()
|
||||
// bounds.x += 5
|
||||
// bounds.y += 5
|
||||
return bounds
|
||||
}
|
||||
// Create the browser window.
|
||||
const mainWindow = new BrowserWindow({
|
||||
minWidth: 1000,
|
||||
minHeight: 600,
|
||||
width: 1000,
|
||||
height: 600,
|
||||
|
||||
frame: false,
|
||||
show: false,
|
||||
...(process.platform === 'linux' ? { icon } : {}),
|
||||
webPreferences: {
|
||||
backgroundThrottling: false,
|
||||
preload: join(__dirname, '../preload/index.js'),
|
||||
sandbox: false,
|
||||
contextIsolation: true
|
||||
}
|
||||
})
|
||||
if (windowBounds) {
|
||||
mainWindow.setBounds(windowBounds)
|
||||
}
|
||||
global.mainWindow = mainWindow
|
||||
logQ.addWin(mainWindow, true)
|
||||
createLogs(
|
||||
[
|
||||
() =>
|
||||
new ElectronLog(logQ, {
|
||||
level: 'debug'
|
||||
})
|
||||
],
|
||||
[]
|
||||
)
|
||||
ipcMain.on('minimize', (event, id) => {
|
||||
if (id) {
|
||||
minimizeWindow(id)
|
||||
} else {
|
||||
mainWindow?.minimize()
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('maximize', (event, id) => {
|
||||
if (id) {
|
||||
maximizeWindow(id)
|
||||
} else {
|
||||
if (mainWindow.isMaximized()) {
|
||||
mainWindow.unmaximize()
|
||||
store.set('windowMaximized', false)
|
||||
} else {
|
||||
mainWindow.maximize()
|
||||
store.set('windowMaximized', true)
|
||||
}
|
||||
// Save current bounds before maximizing
|
||||
store.set('windowBounds', getBounds())
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('close', (event, id) => {
|
||||
if (id) {
|
||||
closeWindow(id)
|
||||
} else {
|
||||
logQ.stopTimer()
|
||||
globalStop()
|
||||
// Only save bounds if window is not maximized
|
||||
store.set('windowBounds', getBounds())
|
||||
store.set('windowMaximized', mainWindow.isMaximized())
|
||||
closeAllWindows()
|
||||
mainWindow.close()
|
||||
}
|
||||
})
|
||||
mainWindow.on('ready-to-show', () => {
|
||||
mainWindow.show()
|
||||
// Restore maximized state
|
||||
if (isMaximized) {
|
||||
mainWindow.maximize()
|
||||
}
|
||||
if (isDev) {
|
||||
mainWindow.webContents.openDevTools()
|
||||
}
|
||||
})
|
||||
|
||||
mainWindow.webContents.setWindowOpenHandler((details) => {
|
||||
shell.openExternal(details.url)
|
||||
return { action: 'deny' }
|
||||
})
|
||||
|
||||
// HMR for renderer base on electron-vite cli.
|
||||
// Load the remote URL for development or the local html file for production.
|
||||
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
|
||||
mainWindow.loadURL(process.env['ELECTRON_RENDERER_URL'])
|
||||
} else {
|
||||
mainWindow.loadFile(join(__dirname, '../renderer/index.html'))
|
||||
}
|
||||
}
|
||||
|
||||
// This method will be called when Electron has finished
|
||||
// initialization and is ready to create browser windows.
|
||||
// Some APIs can only be used after this event occurs.
|
||||
app.whenReady().then(async () => {
|
||||
// Set app user model id for windows
|
||||
electronApp.setAppUserModelId('com.electron')
|
||||
|
||||
// Default open or close DevTools by F12 in development
|
||||
// and ignore CommandOrControl + R in production.
|
||||
// see https://github.com/alex8088/electron-toolkit/tree/master/packages/utils
|
||||
app.on('browser-window-created', (_, window) => {
|
||||
optimizer.watchWindowShortcuts(window)
|
||||
})
|
||||
|
||||
registerLocalResourceProtocol()
|
||||
|
||||
// 初始化主进程 i18n
|
||||
try {
|
||||
const savedLang = store.get('language', 'en') as string
|
||||
await initMainI18n(savedLang)
|
||||
log.info(`Main process i18n initialized with language: ${savedLang}`)
|
||||
} catch (error) {
|
||||
log.error('Failed to initialize main process i18n:', error)
|
||||
}
|
||||
|
||||
createWindow()
|
||||
|
||||
void startRpcHost()
|
||||
|
||||
trackEvent('app_open')
|
||||
|
||||
app.on('activate', function () {
|
||||
// On macOS it's common to re-create a window in the app when the
|
||||
// dock icon is clicked and there are no other windows open.
|
||||
if (BrowserWindow.getAllWindows().length === 0) createWindow()
|
||||
})
|
||||
})
|
||||
|
||||
// Quit when all windows are closed, except on macOS. There, it's common
|
||||
// for applications and their menu bar to stay active until the user quits
|
||||
// explicitly with Cmd + Q.
|
||||
app.on('window-all-closed', () => {
|
||||
if (process.platform !== 'darwin') {
|
||||
app.quit()
|
||||
}
|
||||
})
|
||||
|
||||
// In this file you can include the rest of your app"s specific main process
|
||||
// code. You can also put them in separate files and require them here.
|
||||
@@ -1,934 +0,0 @@
|
||||
/* eslint-disable no-var */
|
||||
import { transport, createLogger, format, Logger, transports } from 'winston'
|
||||
import type { Format } from 'logform'
|
||||
import Transport from 'winston-transport'
|
||||
import { CAN_ERROR_ID, CanAddr, CanMessage, CanMsgType, getTsUs } from './share/can'
|
||||
import EventEmitter from 'events'
|
||||
import type { Sequence, ServiceItem } from './share/uds'
|
||||
import { PayloadType } from './doip'
|
||||
import type { LinMsg } from './share/lin'
|
||||
import type { SerialMessage } from './share/serial'
|
||||
import type { TestEvent } from 'node:test/reporters'
|
||||
import { setVar as setVarMain, setVarByKey, getVar as getVarMain } from './var'
|
||||
import { VarItem } from 'src/preload/data'
|
||||
import { v4 } from 'uuid'
|
||||
import type { SomeipMessage, VsomeipAvailabilityInfo } from './share/someip'
|
||||
import type { OsEvent } from './share/osEvent'
|
||||
import path from 'path'
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
global.deviceIndexMap = new Map<string, number>()
|
||||
|
||||
type LogFunc = (...args: any[]) => Transport
|
||||
|
||||
export function createLogs(logs: LogFunc[], formats: Format[]) {
|
||||
global.sysLog = createLogger({
|
||||
transports: logs.map((t) => t()),
|
||||
format: format.combine(format.json(), format.label({ label: 'System' }), ...formats)
|
||||
})
|
||||
global.scriptLog = createLogger({
|
||||
transports: logs.map((t) => t()),
|
||||
format: format.combine(format.json(), format.label({ label: 'Script' }), ...formats)
|
||||
})
|
||||
|
||||
for (const l of logs) {
|
||||
addTransport(l)
|
||||
}
|
||||
for (const f of formats) {
|
||||
addFormat(f)
|
||||
}
|
||||
}
|
||||
|
||||
class Base extends Transport {
|
||||
constructor(opts?: Transport.TransportStreamOptions) {
|
||||
super(opts)
|
||||
//
|
||||
// Consume any custom options here. e.g.:
|
||||
// - Connection information for databases
|
||||
// - Authentication information for APIs (e.g. loggly, papertrail,
|
||||
// logentries, etc.).
|
||||
//
|
||||
}
|
||||
|
||||
log(info: any, callback: () => void) {
|
||||
if (process.env.VITEST) {
|
||||
console.table(info.message)
|
||||
}
|
||||
// Perform the writing to the remote service
|
||||
callback()
|
||||
}
|
||||
}
|
||||
const instanceFormat = format((info, opts: any) => {
|
||||
info.instance = opts.instance
|
||||
return info
|
||||
})
|
||||
const externalTransport: { id: string; t: () => Transport }[] = []
|
||||
const deviceTransport: { id: string; devices: string[]; logger: Logger }[] = []
|
||||
export function addTransport(t: () => Transport): string {
|
||||
const id = v4()
|
||||
externalTransport.push({ id, t })
|
||||
return id
|
||||
}
|
||||
export function addDeviceTransport(t: () => Transport): string {
|
||||
const id = v4()
|
||||
const transport = t()
|
||||
const devices = (transport as Transport & { devices?: string[] }).devices ?? []
|
||||
const logger = createLogger({ transports: [transport] })
|
||||
deviceTransport.push({ id, devices, logger })
|
||||
return id
|
||||
}
|
||||
|
||||
export function removeDeviceTransport(id: string) {
|
||||
const index = deviceTransport.findIndex((t) => t.id == id)
|
||||
if (index != -1) {
|
||||
const [target] = deviceTransport.splice(index, 1)
|
||||
target.logger.close()
|
||||
}
|
||||
}
|
||||
|
||||
class DeviceTransportRouter extends Transport {
|
||||
constructor() {
|
||||
super({ level: 'debug' })
|
||||
}
|
||||
|
||||
log(info: any, callback: () => void) {
|
||||
const message = typeof info.message === 'object' ? info.message : undefined
|
||||
const deviceId = message?.deviceId
|
||||
|
||||
if (deviceId) {
|
||||
for (const target of deviceTransport) {
|
||||
if (target.devices.includes(deviceId)) {
|
||||
target.logger.log({ level: info.level, message })
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
callback()
|
||||
}
|
||||
}
|
||||
|
||||
function getDeviceTransportRouters(): Transport[] {
|
||||
return deviceTransport.length > 0 ? [new DeviceTransportRouter()] : []
|
||||
}
|
||||
export function removeTransport(id: string) {
|
||||
const index = externalTransport.findIndex((t) => t.id == id)
|
||||
if (index != -1) {
|
||||
externalTransport.splice(index, 1)
|
||||
}
|
||||
}
|
||||
|
||||
const externalFormat: Format[] = []
|
||||
export function addFormat(f: Format) {
|
||||
externalFormat.push(f)
|
||||
}
|
||||
export function clearFormat() {
|
||||
externalFormat.splice(0, externalFormat.length)
|
||||
}
|
||||
|
||||
export class CanLOG {
|
||||
vendor: string
|
||||
log: Logger
|
||||
|
||||
deviceId: string
|
||||
constructor(
|
||||
vendor: string,
|
||||
instance: string,
|
||||
deviceId: string,
|
||||
private event: EventEmitter
|
||||
) {
|
||||
this.deviceId = deviceId
|
||||
this.vendor = vendor
|
||||
const et1 = externalTransport.map((t) => t.t())
|
||||
const dt1 = getDeviceTransportRouters()
|
||||
this.log = createLogger({
|
||||
transports: [new Base(), ...et1, ...dt1],
|
||||
format: format.combine(
|
||||
format.json(),
|
||||
instanceFormat({ instance: instance }),
|
||||
format.label({ label: `Can-${vendor}` }),
|
||||
...externalFormat
|
||||
)
|
||||
})
|
||||
}
|
||||
close() {
|
||||
this.log.close()
|
||||
|
||||
this.event.removeAllListeners()
|
||||
}
|
||||
canBase(data: CanMessage) {
|
||||
this.log.debug({
|
||||
method: 'canBase',
|
||||
deviceId: this.deviceId,
|
||||
data
|
||||
})
|
||||
this.event.emit('can-frame', data)
|
||||
}
|
||||
|
||||
setOption(cmd: string, val: any) {
|
||||
this.log.info({
|
||||
method: 'setOption',
|
||||
deviceId: this.deviceId,
|
||||
data: { cmd, val }
|
||||
})
|
||||
}
|
||||
error(ts: number, msg?: string) {
|
||||
this.log.error({
|
||||
method: 'canError',
|
||||
deviceId: this.deviceId,
|
||||
data: {
|
||||
ts: ts,
|
||||
msg: msg
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export class UdsLOG {
|
||||
log: Logger
|
||||
methodPrefix: string = ''
|
||||
startTime = Date.now()
|
||||
constructor(name: string, instance?: string) {
|
||||
const et = externalTransport.map((t) => t.t())
|
||||
const formatList = [format.json(), format.label({ label: name })]
|
||||
if (instance) {
|
||||
formatList.push(instanceFormat({ instance: instance }))
|
||||
}
|
||||
this.log = createLogger({
|
||||
transports: [new Base(), ...et],
|
||||
format: format.combine(...formatList, ...externalFormat)
|
||||
})
|
||||
}
|
||||
addTransport(t: Transport) {
|
||||
this.log.add(t)
|
||||
}
|
||||
removeTransport(t: Transport) {
|
||||
this.log.remove(t)
|
||||
}
|
||||
sent(testerid: string, service: ServiceItem, ts: number, recvData?: Buffer, msg?: string) {
|
||||
this.log.info({
|
||||
method: this.methodPrefix + 'udsSent',
|
||||
id: testerid,
|
||||
data: {
|
||||
service,
|
||||
ts,
|
||||
recvData,
|
||||
msg
|
||||
}
|
||||
})
|
||||
}
|
||||
recv(testerid: string, service: ServiceItem, ts: number, recvData?: Buffer, msg?: string) {
|
||||
this.log.info({
|
||||
method: this.methodPrefix + 'udsRecv',
|
||||
id: testerid,
|
||||
data: {
|
||||
service,
|
||||
ts,
|
||||
recvData,
|
||||
msg
|
||||
}
|
||||
})
|
||||
}
|
||||
warning(
|
||||
testerid: string,
|
||||
service: ServiceItem,
|
||||
sequence: Sequence,
|
||||
seqIndex: number,
|
||||
index: number,
|
||||
ts: number,
|
||||
recvData?: Buffer,
|
||||
msg?: string
|
||||
) {
|
||||
this.log.warn({
|
||||
method: this.methodPrefix + 'udsWarning',
|
||||
id: testerid,
|
||||
data: {
|
||||
service,
|
||||
sequence,
|
||||
index,
|
||||
seqIndex,
|
||||
ts,
|
||||
recvData,
|
||||
msg
|
||||
}
|
||||
})
|
||||
}
|
||||
addMethodPrefix(prefix: string) {
|
||||
this.methodPrefix = prefix
|
||||
}
|
||||
scriptMsg(msg: string, ts: number, level: 'info' | 'warn' | 'error' = 'info') {
|
||||
this.log[level]({
|
||||
method: this.methodPrefix + 'udsScript',
|
||||
data: {
|
||||
msg,
|
||||
ts
|
||||
}
|
||||
})
|
||||
}
|
||||
systemMsg(msg: string, ts: number, level: 'info' | 'warn' | 'error' = 'info') {
|
||||
this.log[level]({
|
||||
method: this.methodPrefix + 'udsSystem',
|
||||
data: {
|
||||
msg,
|
||||
ts
|
||||
}
|
||||
})
|
||||
}
|
||||
error(testerid: string, msg: string, ts: number, recvData?: Buffer) {
|
||||
this.log.error({
|
||||
method: this.methodPrefix + 'udsError',
|
||||
id: testerid,
|
||||
data: {
|
||||
msg,
|
||||
ts,
|
||||
recvData
|
||||
}
|
||||
})
|
||||
}
|
||||
udsIndex(
|
||||
testerid: string,
|
||||
index: number,
|
||||
serviceName: string,
|
||||
action: 'start' | 'finished' | 'progress',
|
||||
percent?: number
|
||||
) {
|
||||
const l = action == 'start' ? 'debug' : 'info'
|
||||
this.log[l]({
|
||||
method: this.methodPrefix + 'udsIndex',
|
||||
id: testerid,
|
||||
data: {
|
||||
serviceName,
|
||||
index,
|
||||
action,
|
||||
percent
|
||||
}
|
||||
})
|
||||
}
|
||||
close() {
|
||||
this.log.close()
|
||||
}
|
||||
testInfo(id: string | undefined, event: TestEvent, msg?: string) {
|
||||
this.log.info({
|
||||
method: 'testInfo',
|
||||
id,
|
||||
data: event,
|
||||
msg
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export class DoipLOG {
|
||||
vendor: string
|
||||
log: Logger
|
||||
|
||||
deviceId: string
|
||||
|
||||
constructor(
|
||||
vendor: string,
|
||||
instance: string,
|
||||
deviceId: string,
|
||||
private event: EventEmitter,
|
||||
private ts: number
|
||||
) {
|
||||
this.vendor = vendor
|
||||
this.deviceId = deviceId
|
||||
const et1 = externalTransport.map((t) => t.t())
|
||||
const dt1 = getDeviceTransportRouters()
|
||||
this.log = createLogger({
|
||||
transports: [new Base(), ...et1, ...dt1],
|
||||
format: format.combine(
|
||||
format.json(),
|
||||
instanceFormat({ instance: instance }),
|
||||
format.label({ label: `IP-${vendor}` }),
|
||||
...externalFormat
|
||||
)
|
||||
})
|
||||
}
|
||||
close() {
|
||||
this.log.close()
|
||||
this.event.removeAllListeners()
|
||||
}
|
||||
ipBase(
|
||||
type: 'tcp' | 'udp',
|
||||
dir: 'OUT' | 'IN',
|
||||
local: { address?: string; port?: number },
|
||||
remote: { address?: string; port?: number },
|
||||
data: Buffer
|
||||
) {
|
||||
const ts = getTsUs() - this.ts
|
||||
if (data.length < 2) {
|
||||
this.error(ts, `error data lenght, data: ${data.toString('hex')}`)
|
||||
return ts
|
||||
}
|
||||
|
||||
const payloadType = data.readUint16BE(2)
|
||||
let name = ''
|
||||
switch (payloadType) {
|
||||
case PayloadType.DoIP_HeaderNegativeAcknowledge:
|
||||
name = 'Generic DoIP header negative acknowledge'
|
||||
break
|
||||
case PayloadType.DoIP_VehicleIdentificationRequest:
|
||||
name = 'Vehicle identification request message'
|
||||
break
|
||||
case PayloadType.DoIP_VehicleIdentificationRequestWithVIN:
|
||||
name = 'Vehicle identification request message with VIN'
|
||||
break
|
||||
case PayloadType.DoIP_VehicleIdentificationRequestWithEID:
|
||||
name = 'Vehicle identification request message with EID'
|
||||
break
|
||||
case PayloadType.DoIP_VehicleAnnouncementResponse:
|
||||
name = 'Vehicle announcement message/vehicle identification response message'
|
||||
break
|
||||
case PayloadType.DoIP_RouteActivationRequest:
|
||||
name = 'Routing activation request'
|
||||
break
|
||||
case PayloadType.DoIP_RouteActivationResponse:
|
||||
name = 'Routing activation response'
|
||||
break
|
||||
case PayloadType.DoIP_AliveRequest:
|
||||
name = 'Alive check request'
|
||||
break
|
||||
case PayloadType.DoIP_AliveResponse:
|
||||
name = 'Alive check response'
|
||||
break
|
||||
case PayloadType.DoIP_EntityStateRequest:
|
||||
name = 'DoIP entity status request'
|
||||
break
|
||||
case PayloadType.DoIP_EntityStateResponse:
|
||||
name = 'DoIP entity status response'
|
||||
break
|
||||
case PayloadType.DoIP_PowerModeInfoRequest:
|
||||
name = 'Diagnostic power mode information request'
|
||||
break
|
||||
case PayloadType.DoIP_PowerModeInfoResponse:
|
||||
name = 'Diagnostic power mode information response'
|
||||
break
|
||||
case PayloadType.DoIP_DiagnosticMessage:
|
||||
name = 'Diagnostic message'
|
||||
break
|
||||
case PayloadType.DoIP_DiagnosticMessagePositiveAcknowledge:
|
||||
name = 'Diagnostic message positive acknowledgement'
|
||||
break
|
||||
case PayloadType.DoIP_DiagnosticMessageNegativeAcknowledge:
|
||||
name = 'Diagnostic message negative acknowledgement'
|
||||
break
|
||||
}
|
||||
|
||||
const val = {
|
||||
dir,
|
||||
type,
|
||||
local: `${local.address}:${local.port}`,
|
||||
remote: `${remote.address}:${remote.port}`,
|
||||
data,
|
||||
ts: ts,
|
||||
name: name
|
||||
}
|
||||
|
||||
this.log.info({
|
||||
method: 'ipBase',
|
||||
deviceId: this.deviceId,
|
||||
data: val
|
||||
})
|
||||
// this.event.emit('ip-frame', val)
|
||||
return ts
|
||||
}
|
||||
error(ts: number, msg?: string) {
|
||||
this.log.error({
|
||||
method: 'ipError',
|
||||
deviceId: this.deviceId,
|
||||
data: {
|
||||
ts: ts,
|
||||
msg: msg
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export class LinLOG {
|
||||
vendor: string
|
||||
log: Logger
|
||||
deviceId: string
|
||||
|
||||
constructor(
|
||||
vendor: string,
|
||||
instance: string,
|
||||
deviceId: string,
|
||||
private event: EventEmitter
|
||||
) {
|
||||
this.vendor = vendor
|
||||
this.deviceId = deviceId
|
||||
const et1 = externalTransport.map((t) => t.t())
|
||||
const dt1 = getDeviceTransportRouters()
|
||||
this.log = createLogger({
|
||||
transports: [new Base(), ...et1, ...dt1],
|
||||
format: format.combine(
|
||||
format.json(),
|
||||
instanceFormat({ instance: instance }),
|
||||
format.label({ label: `Lin-${vendor}` }),
|
||||
...externalFormat
|
||||
)
|
||||
})
|
||||
}
|
||||
close() {
|
||||
this.log.close()
|
||||
|
||||
this.event.removeAllListeners()
|
||||
}
|
||||
linBase(data: LinMsg) {
|
||||
this.log.debug({
|
||||
method: 'linBase',
|
||||
data,
|
||||
deviceId: this.deviceId
|
||||
})
|
||||
this.event.emit('lin-frame', data)
|
||||
}
|
||||
sendEvent(msg: string, ts: number) {
|
||||
this.log.info({
|
||||
method: 'linEvent',
|
||||
data: {
|
||||
msg,
|
||||
ts
|
||||
},
|
||||
deviceId: this.deviceId
|
||||
})
|
||||
}
|
||||
error(ts: number, msg?: string, data?: LinMsg) {
|
||||
this.log.error({
|
||||
method: 'linError',
|
||||
data: {
|
||||
ts,
|
||||
msg,
|
||||
data
|
||||
},
|
||||
deviceId: this.deviceId
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export class SerialLOG {
|
||||
vendor: string
|
||||
log: Logger
|
||||
deviceId: string
|
||||
|
||||
constructor(
|
||||
vendor: string,
|
||||
instance: string,
|
||||
deviceId: string,
|
||||
private event: EventEmitter
|
||||
) {
|
||||
this.vendor = vendor
|
||||
this.deviceId = deviceId
|
||||
const et1 = externalTransport.map((t) => t.t())
|
||||
const dt1 = getDeviceTransportRouters()
|
||||
this.log = createLogger({
|
||||
transports: [new Base(), ...et1, ...dt1],
|
||||
format: format.combine(
|
||||
format.json(),
|
||||
instanceFormat({ instance: instance }),
|
||||
format.label({ label: `Serial-${vendor}` }),
|
||||
...externalFormat
|
||||
)
|
||||
})
|
||||
}
|
||||
close() {
|
||||
this.log.close()
|
||||
|
||||
this.event.removeAllListeners()
|
||||
}
|
||||
serialBase(data: SerialMessage) {
|
||||
this.log.debug({
|
||||
method: 'serialBase',
|
||||
data,
|
||||
deviceId: this.deviceId
|
||||
})
|
||||
this.event.emit('serial-frame', data)
|
||||
}
|
||||
error(ts: number, msg?: string) {
|
||||
this.log.error({
|
||||
method: 'serialError',
|
||||
data: {
|
||||
ts,
|
||||
msg
|
||||
},
|
||||
deviceId: this.deviceId
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export class VarLOG {
|
||||
log: Logger
|
||||
id?: string
|
||||
constructor(id?: string) {
|
||||
this.id = id
|
||||
|
||||
const et1 = externalTransport.map((t) => t.t())
|
||||
this.log = createLogger({
|
||||
transports: [new Base(), ...et1],
|
||||
format: format.combine(format.json(), ...externalFormat)
|
||||
})
|
||||
}
|
||||
setVarByKey(key: string, value: number | string | number[], ts: number) {
|
||||
const { found, target } = setVarByKey(key, value)
|
||||
if (found && target) {
|
||||
this.log.info({
|
||||
method: 'setVar',
|
||||
data: [{ name: target.name, value, id: target.id, uuid: this.id }],
|
||||
ts
|
||||
})
|
||||
globalThis.varEvent?.emit('update', {
|
||||
name: target.name,
|
||||
value,
|
||||
id: target.id,
|
||||
uuid: this.id
|
||||
})
|
||||
}
|
||||
}
|
||||
setVarByKeyBatch(data: { key: string; value: number | string | number[] }[], ts: number) {
|
||||
const founds: { index: number; var: VarItem }[] = []
|
||||
for (const [index, item] of data.entries()) {
|
||||
const found = setVarByKey(item.key, item.value)
|
||||
if (found) {
|
||||
founds.push({
|
||||
index,
|
||||
var: found.target
|
||||
})
|
||||
}
|
||||
}
|
||||
if (founds.length > 0) {
|
||||
this.log.info({
|
||||
method: 'setVar',
|
||||
data: founds.map((f) => ({
|
||||
index: f.index,
|
||||
name: f.var.name,
|
||||
value: data[f.index].value,
|
||||
id: f.var.id,
|
||||
uuid: this.id
|
||||
})),
|
||||
ts
|
||||
})
|
||||
globalThis.varEvent?.emit(
|
||||
'update',
|
||||
founds.map((f) => ({
|
||||
name: f.var.name,
|
||||
value: data[f.index].value,
|
||||
id: f.var.id,
|
||||
uuid: this.id
|
||||
}))
|
||||
)
|
||||
}
|
||||
}
|
||||
setVar(name: string, value: number | string | number[], ts: number) {
|
||||
const { found, target } = setVarMain(name, value)
|
||||
if (found && target) {
|
||||
this.log.info({
|
||||
method: 'setVar',
|
||||
data: [{ name: target.name, value, id: target.id, uuid: this.id }],
|
||||
ts
|
||||
})
|
||||
globalThis.varEvent?.emit('update', {
|
||||
name: target.name,
|
||||
value,
|
||||
id: target.id,
|
||||
uuid: this.id
|
||||
})
|
||||
}
|
||||
}
|
||||
getVar(name: string): number | string | number[] {
|
||||
return getVarMain(name)
|
||||
}
|
||||
close() {
|
||||
this.log.close()
|
||||
}
|
||||
}
|
||||
|
||||
export class SomeipLOG {
|
||||
vendor: string
|
||||
log: Logger
|
||||
|
||||
deviceId: string
|
||||
|
||||
constructor(
|
||||
vendor: string,
|
||||
instance: string,
|
||||
deviceId: string,
|
||||
private event: EventEmitter,
|
||||
private applicationId?: number
|
||||
) {
|
||||
this.vendor = vendor
|
||||
this.deviceId = deviceId
|
||||
const et1 = externalTransport.map((t) => t.t())
|
||||
const dt1 = getDeviceTransportRouters()
|
||||
this.log = createLogger({
|
||||
transports: [new Base(), ...et1, ...dt1],
|
||||
format: format.combine(
|
||||
format.json(),
|
||||
instanceFormat({ instance: instance }),
|
||||
format.label({ label: `${vendor}` }),
|
||||
...externalFormat
|
||||
)
|
||||
})
|
||||
}
|
||||
close() {
|
||||
this.log.close()
|
||||
|
||||
this.event.removeAllListeners()
|
||||
}
|
||||
|
||||
someipBase(header: Buffer, data: Buffer, ts: number) {
|
||||
try {
|
||||
this.log.info({
|
||||
method: 'someipBase',
|
||||
deviceId: this.deviceId,
|
||||
data: {
|
||||
header,
|
||||
data,
|
||||
ts
|
||||
}
|
||||
})
|
||||
} catch (e: any) {
|
||||
this.log.error({
|
||||
method: 'someipError',
|
||||
deviceId: this.deviceId,
|
||||
data: {
|
||||
ts: ts,
|
||||
error: e.toString()
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
someipMessage(message: SomeipMessage, sending: boolean, ts: number) {
|
||||
const resolvedSending =
|
||||
typeof (message as any).sending === 'boolean' ? (message as any).sending : sending === true
|
||||
// if (
|
||||
// this.applicationId !== undefined &&
|
||||
// Number.isFinite(this.applicationId) &&
|
||||
// !resolvedSending &&
|
||||
// (message.client & 0xffff) === (this.applicationId & 0xffff)
|
||||
// ) {
|
||||
// return
|
||||
// }
|
||||
message.ts = ts
|
||||
message.sending = resolvedSending
|
||||
message.payload = Buffer.from(message.payload)
|
||||
|
||||
this.event.emit('someip-frame', message)
|
||||
setTimeout(() => {
|
||||
this.log.info({
|
||||
method: 'someipBase',
|
||||
deviceId: this.deviceId,
|
||||
data: message
|
||||
})
|
||||
}, 0)
|
||||
}
|
||||
someipServiceValid(info: VsomeipAvailabilityInfo, ts: number) {
|
||||
this.log.info({
|
||||
method: 'someipServiceValid',
|
||||
deviceId: this.deviceId,
|
||||
data: {
|
||||
info,
|
||||
ts: ts
|
||||
}
|
||||
})
|
||||
}
|
||||
error(ts: number, msg?: string) {
|
||||
this.log.error({
|
||||
method: 'someipError',
|
||||
deviceId: this.deviceId,
|
||||
data: {
|
||||
ts: ts,
|
||||
error: msg
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export class OsTraceLOG {
|
||||
vendor: string
|
||||
log: Logger
|
||||
closeFlag = false
|
||||
|
||||
constructor(vendor: string, writerToFile?: string) {
|
||||
this.vendor = vendor
|
||||
|
||||
const et1 = externalTransport.map((t) => t.t())
|
||||
this.log = createLogger({
|
||||
transports: [new Base(), ...et1],
|
||||
format: format.combine(
|
||||
format.json(),
|
||||
|
||||
format.label({ label: `${vendor}` }),
|
||||
...externalFormat
|
||||
)
|
||||
})
|
||||
|
||||
if (writerToFile) {
|
||||
const csvLine = format((info: any, opts: any) => {
|
||||
const d = info.data || {}
|
||||
const method = info.message.method
|
||||
if (method === 'osEvent') {
|
||||
const d = (info.message.data as OsEvent) || {}
|
||||
info[Symbol.for('message')] = `${d.ts},${d.type},${d.id},${d.status},${d.coreId}`
|
||||
return info
|
||||
}
|
||||
return false
|
||||
})
|
||||
|
||||
// 获取当前时间作为时间戳后缀 (格式: YYYYMMDDHHmmss)
|
||||
const timestamp = dayjs().format('YYYYMMDDHHmmss')
|
||||
|
||||
const parsedPath = path.parse(writerToFile)
|
||||
const fileWithSuffix = path.format({
|
||||
dir: parsedPath.dir,
|
||||
name: parsedPath.name + '_' + timestamp,
|
||||
ext: parsedPath.ext
|
||||
})
|
||||
|
||||
const fileTransport = new transports.File({
|
||||
filename: fileWithSuffix,
|
||||
level: 'info',
|
||||
options: {
|
||||
options: { flags: 'w' }
|
||||
},
|
||||
format: format.combine(csvLine())
|
||||
})
|
||||
this.log.add(fileTransport)
|
||||
}
|
||||
}
|
||||
close() {
|
||||
this.closeFlag = true
|
||||
this.log.close()
|
||||
}
|
||||
osEvent(ts: number, event: OsEvent) {
|
||||
if (this.closeFlag) {
|
||||
return
|
||||
}
|
||||
this.log.info({
|
||||
method: 'osEvent',
|
||||
data: event,
|
||||
ts: ts
|
||||
})
|
||||
}
|
||||
|
||||
error(ts: number, msg?: string) {
|
||||
if (this.closeFlag) {
|
||||
return
|
||||
}
|
||||
this.log.error({
|
||||
method: 'osError',
|
||||
|
||||
error: msg,
|
||||
ts: ts
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
export class PluginLOG {
|
||||
log: Logger
|
||||
|
||||
constructor(public pluginId: string) {
|
||||
const et1 = externalTransport.map((t) => t.t())
|
||||
this.log = createLogger({
|
||||
transports: [new Base(), ...et1],
|
||||
format: format.combine(format.json(), ...externalFormat)
|
||||
})
|
||||
}
|
||||
|
||||
pluginEvent(event: string, data: any) {
|
||||
this.log.info({
|
||||
method: 'pluginEvent',
|
||||
id: this.pluginId,
|
||||
event: event,
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
error(msg: string, data?: any) {
|
||||
this.log.error({
|
||||
method: 'pluginError',
|
||||
id: this.pluginId,
|
||||
msg: msg,
|
||||
data: data
|
||||
})
|
||||
}
|
||||
|
||||
close(): void {
|
||||
this.log.close()
|
||||
}
|
||||
}
|
||||
|
||||
export class ReplayLOG {
|
||||
log: Logger
|
||||
closeFlag = false
|
||||
replayId: string
|
||||
|
||||
constructor(replayId: string, instance?: string) {
|
||||
this.replayId = replayId
|
||||
const et1 = externalTransport.map((t) => t.t())
|
||||
const formatList = [format.json(), format.label({ label: 'Replay' })]
|
||||
if (instance) {
|
||||
formatList.push(instanceFormat({ instance: instance }))
|
||||
}
|
||||
this.log = createLogger({
|
||||
transports: [new Base(), ...et1],
|
||||
format: format.combine(...formatList, ...externalFormat)
|
||||
})
|
||||
}
|
||||
|
||||
close() {
|
||||
this.closeFlag = true
|
||||
this.log.close()
|
||||
}
|
||||
|
||||
start(filePath: string, fileFormat: string) {
|
||||
if (this.closeFlag) return
|
||||
this.log.info({
|
||||
method: 'replayStart',
|
||||
replayId: this.replayId,
|
||||
data: { filePath, format: fileFormat }
|
||||
})
|
||||
}
|
||||
|
||||
stop(reason?: string) {
|
||||
if (this.closeFlag) return
|
||||
this.log.info({
|
||||
method: 'replayStop',
|
||||
replayId: this.replayId,
|
||||
data: { reason }
|
||||
})
|
||||
}
|
||||
|
||||
pause() {
|
||||
if (this.closeFlag) return
|
||||
this.log.info({
|
||||
method: 'replayPause',
|
||||
replayId: this.replayId,
|
||||
data: {}
|
||||
})
|
||||
}
|
||||
|
||||
resume() {
|
||||
if (this.closeFlag) return
|
||||
this.log.info({
|
||||
method: 'replayResume',
|
||||
replayId: this.replayId,
|
||||
data: {}
|
||||
})
|
||||
}
|
||||
|
||||
progress(current: number, total: number, percent: number, repeat: number) {
|
||||
if (this.closeFlag) return
|
||||
this.log.info({
|
||||
method: 'replayProgress',
|
||||
replayId: this.replayId,
|
||||
data: { current, total, percent, repeat }
|
||||
})
|
||||
}
|
||||
|
||||
error(msg: string) {
|
||||
if (this.closeFlag) return
|
||||
this.log.error({
|
||||
method: 'replayError',
|
||||
replayId: this.replayId,
|
||||
data: { msg }
|
||||
})
|
||||
}
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
@@ -1,174 +0,0 @@
|
||||
import { is } from '@electron-toolkit/utils'
|
||||
import {
|
||||
app,
|
||||
shell,
|
||||
BrowserWindow,
|
||||
ipcMain,
|
||||
dialog,
|
||||
protocol as eProtocol,
|
||||
net,
|
||||
MessageChannelMain,
|
||||
MessagePortMain
|
||||
} from 'electron'
|
||||
import path, { join } from 'path'
|
||||
import icon from '../../resources/icon.png?asset'
|
||||
let port: MessagePortMain | null = null
|
||||
ipcMain.on('ipc-get-port', (event, id: string) => {
|
||||
if (port) {
|
||||
port.close()
|
||||
}
|
||||
const { port1, port2 } = new MessageChannelMain()
|
||||
port = port1
|
||||
event.sender.postMessage('port', id, [port2])
|
||||
// port2.start()
|
||||
})
|
||||
class LogQueue {
|
||||
private static instance: LogQueue | null = null
|
||||
list: any[] = []
|
||||
timer: any
|
||||
mainWin: BrowserWindow | undefined
|
||||
|
||||
private constructor(
|
||||
public win: BrowserWindow[] = [],
|
||||
private period = 100
|
||||
) {
|
||||
this.startTimer()
|
||||
}
|
||||
|
||||
static getInstance(): LogQueue {
|
||||
if (LogQueue.instance === null) {
|
||||
LogQueue.instance = new LogQueue()
|
||||
}
|
||||
return LogQueue.instance
|
||||
}
|
||||
|
||||
addWin(win: BrowserWindow, isMain: boolean) {
|
||||
this.win.push(win)
|
||||
if (isMain) {
|
||||
this.mainWin = win
|
||||
}
|
||||
}
|
||||
protected startTimer() {
|
||||
this.timer = setInterval(() => {
|
||||
if (this.list.length) {
|
||||
port?.postMessage(this.list)
|
||||
this.list = []
|
||||
}
|
||||
}, this.period)
|
||||
}
|
||||
stopTimer() {
|
||||
clearInterval(this.timer)
|
||||
this.list = []
|
||||
}
|
||||
removeWin(win: BrowserWindow) {
|
||||
this.win = this.win.filter((w) => w !== win)
|
||||
}
|
||||
}
|
||||
|
||||
// Export the singleton instance
|
||||
export const logQ = LogQueue.getInstance()
|
||||
|
||||
// Export a function to get the instance (alternative access method)
|
||||
export const getLogQueue = () => LogQueue.getInstance()
|
||||
|
||||
// Export the class for type annotations if needed
|
||||
export type { LogQueue }
|
||||
|
||||
const winMap = new Map<string, BrowserWindow>()
|
||||
const winPosMap = new Map<string, { x: number; y: number; width: number; height: number }>()
|
||||
|
||||
ipcMain.on('ipc-open-window', (event, arg) => {
|
||||
if (winMap.has(arg.id)) {
|
||||
winMap.get(arg.id)?.show()
|
||||
} else {
|
||||
const pos = winPosMap.get(arg.id)
|
||||
const win = new BrowserWindow({
|
||||
width: pos?.width || arg.w || 800,
|
||||
height: pos?.height || arg.h || 600,
|
||||
x: pos?.x || undefined,
|
||||
y: pos?.y || undefined,
|
||||
...(process.platform === 'linux' ? { icon } : {}),
|
||||
webPreferences: {
|
||||
preload: join(__dirname, '../preload/index.js'),
|
||||
sandbox: false,
|
||||
contextIsolation: true,
|
||||
backgroundThrottling: false
|
||||
},
|
||||
frame: false,
|
||||
show: false
|
||||
})
|
||||
winMap.set(arg.id, win)
|
||||
logQ.addWin(win, false)
|
||||
win.on('closed', () => {
|
||||
winMap.delete(arg.id)
|
||||
logQ.mainWin?.webContents.send('ipc-close-window', arg.id)
|
||||
logQ.removeWin(win)
|
||||
})
|
||||
win.on('ready-to-show', () => {
|
||||
win.show()
|
||||
if (is.dev) {
|
||||
win.webContents.openDevTools()
|
||||
}
|
||||
})
|
||||
|
||||
if (is.dev && process.env['ELECTRON_RENDERER_URL']) {
|
||||
const url = new URL(process.env['ELECTRON_RENDERER_URL'])
|
||||
Object.entries(arg).forEach(([key, value]) => {
|
||||
url.searchParams.set(key, String(value))
|
||||
})
|
||||
win.loadURL(url.toString())
|
||||
} else {
|
||||
const filePath = join(__dirname, '../renderer/index.html')
|
||||
const searchParams = new URLSearchParams()
|
||||
Object.entries(arg).forEach(([key, value]) => {
|
||||
searchParams.set(key, String(value))
|
||||
})
|
||||
win.loadFile(filePath, {
|
||||
search: searchParams.toString()
|
||||
})
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
ipcMain.on('ipc-close-others-windows', (event, arg) => {
|
||||
closeAllWindows()
|
||||
})
|
||||
export function closeAllWindows() {
|
||||
winMap.forEach((win, key) => {
|
||||
//store pos
|
||||
|
||||
const pos = win.getBounds()
|
||||
winPosMap.set(key, {
|
||||
x: pos?.x,
|
||||
y: pos?.y,
|
||||
width: pos?.width,
|
||||
height: pos?.height
|
||||
})
|
||||
win.close()
|
||||
})
|
||||
}
|
||||
|
||||
export function closeWindow(id: string) {
|
||||
const win = winMap.get(id)
|
||||
if (win) {
|
||||
//store pos
|
||||
const pos = win.getBounds()
|
||||
winPosMap.set(id, {
|
||||
x: pos?.x,
|
||||
y: pos?.y,
|
||||
width: pos?.width,
|
||||
height: pos?.height
|
||||
})
|
||||
win.close()
|
||||
}
|
||||
}
|
||||
export function minimizeWindow(id: string) {
|
||||
winMap.get(id)?.minimize()
|
||||
}
|
||||
export function maximizeWindow(id: string) {
|
||||
if (winMap.get(id)?.isMaximized()) {
|
||||
winMap.get(id)?.unmaximize()
|
||||
} else {
|
||||
winMap.get(id)?.maximize()
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,55 +0,0 @@
|
||||
import { PluginLOG } from './log'
|
||||
import path from 'path'
|
||||
import { error, log } from 'electron-log'
|
||||
import { NodeClass } from './nodeItem'
|
||||
|
||||
export default class PluginClient {
|
||||
nodeItem: NodeClass
|
||||
worker: any
|
||||
selfStop = false
|
||||
log: PluginLOG
|
||||
|
||||
constructor(
|
||||
public name: string,
|
||||
private id: string,
|
||||
jsFilePath: string,
|
||||
nodeItem?: NodeClass
|
||||
) {
|
||||
this.log = new PluginLOG(this.id)
|
||||
if (nodeItem) {
|
||||
this.nodeItem = nodeItem
|
||||
} else {
|
||||
const pluginPath = path.dirname(jsFilePath)
|
||||
this.nodeItem = new NodeClass(
|
||||
{
|
||||
id: this.id,
|
||||
name: this.name,
|
||||
channel: [],
|
||||
script: jsFilePath
|
||||
},
|
||||
pluginPath,
|
||||
name
|
||||
)
|
||||
this.nodeItem.pool?.registerHandler('pluginEvent', this.eventHandler.bind(this))
|
||||
}
|
||||
}
|
||||
|
||||
eventHandler(payload: { name: string; data: any }) {
|
||||
const name = payload.name
|
||||
const data = payload.data
|
||||
this.log.pluginEvent(name, data)
|
||||
}
|
||||
|
||||
async exec(method: string, ...params: any[]): Promise<any> {
|
||||
return this.nodeItem.pool?.exec(`plugin.${method}`, params)
|
||||
}
|
||||
stop() {
|
||||
this.nodeItem.pool?.clearHandlers()
|
||||
this.nodeItem.pool?.registerHandler('pluginEvent', this.eventHandler.bind(this))
|
||||
this.nodeItem.pool?.stopEmit()
|
||||
}
|
||||
close() {
|
||||
this.log.close()
|
||||
this.nodeItem.close()
|
||||
}
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
import path from 'path'
|
||||
import { PythonShell, Options, PythonShellError } from 'python-shell'
|
||||
import fs from 'fs'
|
||||
|
||||
import pythonRequirements from '../../resources/requirements.txt?asset&asarUnpack'
|
||||
|
||||
export function getPythonPath(): string {
|
||||
const baseDir = path.dirname(pythonRequirements)
|
||||
const pythonDir = path.join(baseDir, 'python')
|
||||
if (process.platform === 'win32') {
|
||||
return path.join(pythonDir, 'python.exe')
|
||||
}
|
||||
// darwin (macOS) and linux: python-build-standalone uses bin/python3
|
||||
return path.join(pythonDir, 'bin', 'python3')
|
||||
}
|
||||
@@ -1,136 +0,0 @@
|
||||
import { ipcMain } from 'electron'
|
||||
import { startRpcServer, type RpcServerHandle } from 'src/cli/rpc/server'
|
||||
import type { CanBase } from 'src/main/docan/base'
|
||||
import { store } from './store'
|
||||
|
||||
export const DEFAULT_RPC_HOST = '127.0.0.1'
|
||||
export const DEFAULT_RPC_PORT = 17320
|
||||
|
||||
export interface RpcHostStatus {
|
||||
enabled: boolean
|
||||
listening: boolean
|
||||
host: string
|
||||
port: number
|
||||
error?: string
|
||||
controllers: number
|
||||
}
|
||||
|
||||
interface GeneralRpcSettings {
|
||||
rpcEnabled?: boolean
|
||||
rpcHost?: string
|
||||
rpcPort?: number
|
||||
}
|
||||
|
||||
let handle: RpcServerHandle | undefined
|
||||
let liveMap: Map<string, CanBase> | undefined
|
||||
let lastError: string | undefined
|
||||
let ipcRegistered = false
|
||||
|
||||
function readSettings(raw?: GeneralRpcSettings): {
|
||||
enabled: boolean
|
||||
host: string
|
||||
port: number
|
||||
} {
|
||||
const general = raw ?? ((store.get('general.settings') as GeneralRpcSettings | undefined) || {})
|
||||
const port = Number(general.rpcPort)
|
||||
return {
|
||||
enabled: general.rpcEnabled !== false,
|
||||
host:
|
||||
typeof general.rpcHost === 'string' && general.rpcHost ? general.rpcHost : DEFAULT_RPC_HOST,
|
||||
port: Number.isFinite(port) && port > 0 && port < 65536 ? port : DEFAULT_RPC_PORT
|
||||
}
|
||||
}
|
||||
|
||||
function logInfo(msg: string) {
|
||||
if (typeof sysLog !== 'undefined') {
|
||||
sysLog.info(msg)
|
||||
}
|
||||
}
|
||||
|
||||
function logError(msg: string) {
|
||||
if (typeof sysLog !== 'undefined') {
|
||||
sysLog.error(msg)
|
||||
}
|
||||
}
|
||||
|
||||
export function getRpcHostStatus(): RpcHostStatus {
|
||||
const settings = readSettings()
|
||||
return {
|
||||
enabled: settings.enabled,
|
||||
listening: !!handle,
|
||||
host: handle?.host ?? settings.host,
|
||||
port: handle?.port ?? settings.port,
|
||||
error: lastError,
|
||||
controllers: handle?.service.listControllers().controllers.length ?? 0
|
||||
}
|
||||
}
|
||||
|
||||
export function attachRpcCanDevices(map: Map<string, CanBase>) {
|
||||
liveMap = map
|
||||
handle?.service.attachLiveControllers(map)
|
||||
}
|
||||
|
||||
export function detachRpcCanDevices() {
|
||||
handle?.service.detachLiveControllers()
|
||||
liveMap = undefined
|
||||
}
|
||||
|
||||
async function stopRpcServer() {
|
||||
const current = handle
|
||||
handle = undefined
|
||||
if (current) {
|
||||
try {
|
||||
await current.close()
|
||||
} catch {
|
||||
// ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export async function applyRpcSettings(raw?: GeneralRpcSettings): Promise<RpcHostStatus> {
|
||||
const settings = readSettings(raw)
|
||||
await stopRpcServer()
|
||||
lastError = undefined
|
||||
if (!settings.enabled) {
|
||||
logInfo('json-rpc gateway disabled')
|
||||
return getRpcHostStatus()
|
||||
}
|
||||
try {
|
||||
handle = await startRpcServer({
|
||||
host: settings.host,
|
||||
port: settings.port,
|
||||
serviceOptions: {
|
||||
role: 'gateway',
|
||||
onShutdown: async () => {
|
||||
handle = undefined
|
||||
lastError = 'stopped by sys.shutdown'
|
||||
}
|
||||
}
|
||||
})
|
||||
if (liveMap && liveMap.size > 0) {
|
||||
handle.service.attachLiveControllers(liveMap)
|
||||
}
|
||||
logInfo(`json-rpc gateway listening on tcp://${handle.host}:${handle.port}`)
|
||||
} catch (err) {
|
||||
handle = undefined
|
||||
const message = err instanceof Error ? err.message : String(err)
|
||||
lastError = `failed to bind ${settings.host}:${settings.port}: ${message}`
|
||||
logError(`json-rpc gateway ${lastError}`)
|
||||
}
|
||||
return getRpcHostStatus()
|
||||
}
|
||||
|
||||
function registerIpc() {
|
||||
if (ipcRegistered) {
|
||||
return
|
||||
}
|
||||
ipcRegistered = true
|
||||
ipcMain.handle('ipc-rpc-apply', async () => applyRpcSettings())
|
||||
ipcMain.handle('ipc-rpc-status', async () => getRpcHostStatus())
|
||||
}
|
||||
|
||||
/** Start the GUI JSON-RPC gateway from saved settings. Safe to call more than once. */
|
||||
export async function startRpcHost(): Promise<RpcHostStatus> {
|
||||
registerIpc()
|
||||
return applyRpcSettings()
|
||||
}
|
||||
@@ -1,688 +0,0 @@
|
||||
import EventEmitter from 'events'
|
||||
import { cloneDeep } from 'lodash'
|
||||
|
||||
// import type { CanLOG } from '../log'
|
||||
|
||||
export interface CanBitrate {
|
||||
freq: number
|
||||
timeSeg1: number
|
||||
timeSeg2: number
|
||||
sjw: number
|
||||
preScaler: number
|
||||
clock?: string
|
||||
zlgSpec?: string
|
||||
}
|
||||
|
||||
export type CanVendor =
|
||||
| 'peak'
|
||||
| 'simulate'
|
||||
| 'zlg'
|
||||
| 'kvaser'
|
||||
| 'toomoss'
|
||||
| 'vector'
|
||||
| 'slcan'
|
||||
| 'ecubus'
|
||||
| 'candle'
|
||||
export interface CanBaseInfo {
|
||||
id: string
|
||||
handle: any
|
||||
name: string
|
||||
vendor: CanVendor
|
||||
canfd: boolean
|
||||
bitrate: CanBitrate
|
||||
bitratefd?: CanBitrate
|
||||
silent?: boolean
|
||||
database?: string
|
||||
toomossRes?: boolean
|
||||
zlgRes?: boolean
|
||||
candleRes?: boolean
|
||||
slcanDelay?: number
|
||||
}
|
||||
|
||||
export interface SignalDefine {
|
||||
default: string
|
||||
define: string
|
||||
name: string
|
||||
type: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Value tables mapping string keys to string values for CAN signal enumerations.
|
||||
* @category CAN
|
||||
*/
|
||||
export interface ValueTables {
|
||||
string: Record<string, string>
|
||||
}
|
||||
|
||||
/**
|
||||
* CAN database containing messages, signals, ECUs, and related definitions.
|
||||
* @category CAN
|
||||
*/
|
||||
export interface CanDB {
|
||||
id: string
|
||||
name: string
|
||||
attributes: Record<string, any>
|
||||
baudrate: number
|
||||
ecu_defines: EcuDefine[]
|
||||
ecus: Record<string, any>
|
||||
enumerations: Enumerations
|
||||
env_defines: EnvDefine[]
|
||||
env_vars: EnvVars
|
||||
fd_baudrate: number
|
||||
frame_defines: FrameDefine[]
|
||||
global_defines: GlobalDefine[]
|
||||
messages: Message[]
|
||||
signal_defines: SignalDefine[]
|
||||
value_tables: ValueTables
|
||||
version?: string
|
||||
/** Original DBC file path (set during import) */
|
||||
filePath?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* ECU (Electronic Control Unit) definition for CAN database.
|
||||
* @category CAN
|
||||
*/
|
||||
export interface EcuDefine {
|
||||
default: string
|
||||
define: string
|
||||
name: string
|
||||
type: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumerations mapping numeric values to string labels for CAN signals.
|
||||
* @category CAN
|
||||
*/
|
||||
export interface Enumerations {
|
||||
[key: string]: Record<number, string>
|
||||
}
|
||||
|
||||
/**
|
||||
* Environment variable definition for CAN database.
|
||||
* @category CAN
|
||||
*/
|
||||
export interface EnvDefine {
|
||||
default: any
|
||||
define: string
|
||||
name: string
|
||||
type: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Environment variables in CAN database, keyed by variable name.
|
||||
* @category CAN
|
||||
*/
|
||||
export interface EnvVars {
|
||||
[key: string]: {
|
||||
initialValue: string
|
||||
values: Record<string, string>
|
||||
unit?: string
|
||||
varType: string
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Frame (message) attribute definition for CAN database.
|
||||
* @category CAN
|
||||
*/
|
||||
export interface FrameDefine {
|
||||
default: string
|
||||
define: string
|
||||
name: string
|
||||
type: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Global attribute definition for CAN database.
|
||||
* @category CAN
|
||||
*/
|
||||
export interface GlobalDefine {
|
||||
default: string
|
||||
define: string
|
||||
name: string
|
||||
type: string
|
||||
}
|
||||
|
||||
/**
|
||||
* CAN message (frame) definition containing signals and metadata.
|
||||
* @category CAN
|
||||
*/
|
||||
export interface Message {
|
||||
attributes: Record<string, any>
|
||||
comment: string
|
||||
cycle_time: number
|
||||
header_id: any
|
||||
id: number
|
||||
is_complex_multiplexed: boolean
|
||||
is_extended_frame: boolean
|
||||
is_fd: boolean
|
||||
is_j1939: boolean
|
||||
length: number
|
||||
mux_names: Record<string, string>
|
||||
name: string
|
||||
pdu_name: string
|
||||
signals: Signal[]
|
||||
transmitters: string[]
|
||||
}
|
||||
|
||||
/**
|
||||
* CAN signal definition with bit layout, scaling, and value mapping.
|
||||
* @category CAN
|
||||
*/
|
||||
export interface Signal {
|
||||
attributes: Record<string, any>
|
||||
bit_length: number
|
||||
comment?: string
|
||||
comments: Record<string, string>
|
||||
factor: string
|
||||
initial_value: string
|
||||
value?: string
|
||||
physValue?: string
|
||||
is_big_endian: boolean
|
||||
is_float: boolean
|
||||
is_multiplexer: boolean
|
||||
is_signed: boolean
|
||||
max: string
|
||||
min: string
|
||||
mux_val_grp?: number[][]
|
||||
mux_value?: number
|
||||
name: string
|
||||
offset: string
|
||||
receivers: string[]
|
||||
start_bit: number
|
||||
values: Record<string, string>
|
||||
unit?: string
|
||||
multiplex: any
|
||||
muxer_for_signal?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a CAN (Controller Area Network) message.
|
||||
*
|
||||
* @category CAN
|
||||
* @template T - The type of the signal data.
|
||||
*/
|
||||
export type CanMessage<T = any> = {
|
||||
/**
|
||||
* The name of the CAN message.
|
||||
*/
|
||||
name?: string
|
||||
/**
|
||||
* The device associated with the CAN message.
|
||||
*/
|
||||
device?: string
|
||||
|
||||
/**
|
||||
* The direction of the CAN message, either 'IN' for incoming or 'OUT' for outgoing.
|
||||
*/
|
||||
dir: 'IN' | 'OUT'
|
||||
|
||||
/**
|
||||
* The data payload of the CAN message.
|
||||
*/
|
||||
data: Buffer
|
||||
|
||||
/**
|
||||
* The timestamp of when the CAN message was sent/recv.
|
||||
*/
|
||||
ts?: number
|
||||
|
||||
/**
|
||||
* The identifier of the CAN message.
|
||||
*/
|
||||
id: number
|
||||
|
||||
/**
|
||||
* The type of the CAN message.
|
||||
*/
|
||||
msgType: CanMsgType
|
||||
|
||||
/**
|
||||
* Indicates whether the CAN message is simulated.
|
||||
* This property is optional.
|
||||
*/
|
||||
isSimulate?: boolean
|
||||
/**
|
||||
* The database id of the CAN message.
|
||||
*/
|
||||
database?: string
|
||||
|
||||
/**
|
||||
* Absolute UTC time string for display (e.g. "2024-01-15 08:30:12.345").
|
||||
* Set by replay module when using original recording time.
|
||||
*/
|
||||
absTimeStr?: string
|
||||
|
||||
/**
|
||||
* Original timestamp in microseconds from log file (before tsOffset).
|
||||
* Set by replay module when using original recording time.
|
||||
*/
|
||||
originalTs?: number
|
||||
|
||||
/**
|
||||
* The children signals of the CAN message.
|
||||
* internal use
|
||||
*/
|
||||
signals?: T
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumeration representing different CAN (Controller Area Network) ID types.
|
||||
*
|
||||
* @category CAN
|
||||
* @enum {string}
|
||||
* @readonly
|
||||
*/
|
||||
export enum CAN_ID_TYPE {
|
||||
STANDARD = 'STANDARD',
|
||||
EXTENDED = 'EXTENDED'
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumeration representing different CAN (Controller Area Network) address types.
|
||||
*
|
||||
* @category CAN
|
||||
* @enum {string}
|
||||
* @readonly
|
||||
*/
|
||||
export enum CAN_ADDR_TYPE {
|
||||
PHYSICAL = 'PHYSICAL',
|
||||
FUNCTIONAL = 'FUNCTIONAL'
|
||||
}
|
||||
|
||||
/**
|
||||
* Enumeration representing different CAN (Controller Area Network) address formats.
|
||||
*
|
||||
* @category CAN
|
||||
* @enum {string}
|
||||
* @readonly
|
||||
*/
|
||||
export enum CAN_ADDR_FORMAT {
|
||||
NORMAL = 'NORMAL',
|
||||
FIXED_NORMAL = 'NORMAL_FIXED',
|
||||
EXTENDED = 'EXTENDED',
|
||||
MIXED = 'MIXED',
|
||||
ENHANCED = 'ENHANCED'
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a CAN (Controller Area Network) message type.
|
||||
* @category CAN
|
||||
|
||||
*/
|
||||
export interface CanMsgType {
|
||||
/**
|
||||
* The type of CAN ID.
|
||||
*/
|
||||
idType: CAN_ID_TYPE
|
||||
|
||||
/**
|
||||
* Indicates if Bit Rate Switching (BRS) is enabled.
|
||||
*/
|
||||
brs: boolean
|
||||
|
||||
/**
|
||||
* Indicates if CAN FD (Flexible Data-rate) is used.
|
||||
*/
|
||||
canfd: boolean
|
||||
|
||||
/**
|
||||
* Indicates if the message is a remote frame.
|
||||
*/
|
||||
remote: boolean
|
||||
|
||||
/**
|
||||
* Optional unique identifier for the message.
|
||||
*/
|
||||
uuid?: string
|
||||
}
|
||||
|
||||
export enum CAN_ERROR_ID {
|
||||
CAN_BUS_ERROR,
|
||||
CAN_READ_TIMEOUT,
|
||||
CAN_BUS_BUSY,
|
||||
CAN_BUS_CLOSED,
|
||||
CAN_INTERNAL_ERROR,
|
||||
CAN_PARAM_ERROR,
|
||||
CAN_DRIVER_SILENT
|
||||
}
|
||||
|
||||
const canErrorMap: Record<CAN_ERROR_ID, string> = {
|
||||
[CAN_ERROR_ID.CAN_BUS_ERROR]: 'bus error',
|
||||
[CAN_ERROR_ID.CAN_READ_TIMEOUT]: 'read timeout',
|
||||
[CAN_ERROR_ID.CAN_BUS_BUSY]: 'bus busy',
|
||||
[CAN_ERROR_ID.CAN_INTERNAL_ERROR]: 'dll lib internal error',
|
||||
[CAN_ERROR_ID.CAN_BUS_CLOSED]: 'bus closed',
|
||||
[CAN_ERROR_ID.CAN_PARAM_ERROR]: 'param error',
|
||||
[CAN_ERROR_ID.CAN_DRIVER_SILENT]: 'driver silent'
|
||||
}
|
||||
|
||||
export function getTsUs() {
|
||||
const hrtime = process.hrtime()
|
||||
const seconds = hrtime[0]
|
||||
const nanoseconds = hrtime[1]
|
||||
return seconds * 1000000 + Math.floor(nanoseconds / 1000)
|
||||
}
|
||||
|
||||
export interface CanInterAction {
|
||||
uuid: string
|
||||
trigger: {
|
||||
type: 'manual' | 'periodic'
|
||||
period?: number
|
||||
onKey?: string
|
||||
}
|
||||
name: string
|
||||
database?: string
|
||||
id: string
|
||||
channel: string
|
||||
type: 'canfd' | 'can' | 'ecan' | 'ecanfd'
|
||||
dlc: number
|
||||
brs?: boolean
|
||||
remote?: boolean
|
||||
data: string[]
|
||||
}
|
||||
export function formatError(error: unknown) {
|
||||
const errObj =
|
||||
error instanceof Error
|
||||
? error
|
||||
: new Error(
|
||||
typeof error === 'string'
|
||||
? error
|
||||
: error == null
|
||||
? 'Unknown error'
|
||||
: (() => {
|
||||
try {
|
||||
return JSON.stringify(error)
|
||||
} catch {
|
||||
return String(error)
|
||||
}
|
||||
})()
|
||||
)
|
||||
|
||||
const stack = errObj.stack || ''
|
||||
|
||||
// Get first stack line (usually contains error location)
|
||||
const locationLine = stack.split('\n')[1]?.trim() || ''
|
||||
|
||||
// Extract file location info
|
||||
const locationMatch = locationLine.match(/webpack:\\ecubuspro\\(.*):(\d+):(\d+)\)$/)
|
||||
|
||||
let location = ''
|
||||
if (locationMatch) {
|
||||
const [, file, line, column] = locationMatch
|
||||
//
|
||||
// Convert webpack path to GitHub URL,#L${line}C${column}-L${line}C${column}
|
||||
location = `https://github.com/ecubus/EcuBus-Pro/blob/master/${file}#L${line}C${column}`
|
||||
} else {
|
||||
// at listener (D:\code\ecubus-pro\resources\examples\test_simple\node.ts:5:11)
|
||||
const newMatch = locationLine.match(/\((.*):(\d+):(\d+)\)/)
|
||||
if (newMatch) {
|
||||
const [, file, line, column] = newMatch
|
||||
location = `file://${file}:${line}:${column}`
|
||||
} else {
|
||||
location = locationLine || 'unknown'
|
||||
}
|
||||
}
|
||||
|
||||
// Return simplified error message
|
||||
return `Error: ${errObj.message || 'Unknown error'}, Pos: ${location || 'unknown'}`
|
||||
}
|
||||
|
||||
export class CanError extends Error {
|
||||
errorId: CAN_ERROR_ID
|
||||
msgType: CanMsgType
|
||||
data?: Buffer
|
||||
constructor(errorId: CAN_ERROR_ID, msgType: CanMsgType, data?: Buffer, extMsg?: string) {
|
||||
super(canErrorMap[errorId] + (extMsg ? `,${extMsg}` : ''))
|
||||
this.errorId = errorId
|
||||
this.msgType = msgType
|
||||
this.data = data
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @category CAN
|
||||
*/
|
||||
export interface CanAddr extends CanMsgType {
|
||||
name: string
|
||||
addrFormat: CAN_ADDR_FORMAT
|
||||
addrType: CAN_ADDR_TYPE
|
||||
desc?: string
|
||||
SA: string
|
||||
TA: string
|
||||
AE: string
|
||||
canIdTx: string
|
||||
canIdRx: string
|
||||
nAs: number
|
||||
nAr: number
|
||||
nBs: number
|
||||
nCr: number
|
||||
nBr?: number
|
||||
nCs?: number
|
||||
stMin: number
|
||||
bs: number
|
||||
maxWTF: number
|
||||
uuid?: string
|
||||
dlc: number
|
||||
padding: boolean
|
||||
paddingValue: string
|
||||
}
|
||||
|
||||
export interface CandleCapability {
|
||||
feature: number
|
||||
fclk_can: number
|
||||
tseg1_min: number
|
||||
tseg1_max: number
|
||||
tseg2_min: number
|
||||
tseg2_max: number
|
||||
sjw_max: number
|
||||
brp_min: number
|
||||
brp_max: number
|
||||
brp_inc: number
|
||||
}
|
||||
|
||||
export interface CanDevice {
|
||||
label: string
|
||||
id: string
|
||||
handle: any
|
||||
serialNumber?: string
|
||||
busy?: boolean
|
||||
/** Vendor-specific metadata, keyed by vendor name */
|
||||
extra?: {
|
||||
candle?: {
|
||||
cap?: CandleCapability
|
||||
dataCap?: CandleCapability
|
||||
fdSupported?: boolean
|
||||
Res?: boolean
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export interface CanEventMap {
|
||||
sendTp: [
|
||||
info: {
|
||||
data: Buffer
|
||||
ts: number
|
||||
id: number
|
||||
idType: CAN_ID_TYPE
|
||||
canfd: boolean
|
||||
brs: boolean
|
||||
remote: boolean
|
||||
}
|
||||
]
|
||||
sendBase: [
|
||||
info: {
|
||||
data: Buffer
|
||||
ts: number
|
||||
id: number
|
||||
idType: CAN_ID_TYPE
|
||||
canfd: boolean
|
||||
brs: boolean
|
||||
remote: boolean
|
||||
}
|
||||
]
|
||||
recvTp: [
|
||||
info: {
|
||||
data: Buffer
|
||||
ts: number
|
||||
id: number
|
||||
idType: string
|
||||
canfd: boolean
|
||||
brs: boolean
|
||||
remote: boolean
|
||||
}
|
||||
]
|
||||
recvBase: [
|
||||
info: {
|
||||
data: Buffer
|
||||
ts: number
|
||||
id: number
|
||||
idType: string
|
||||
canfd: boolean
|
||||
brs: boolean
|
||||
remote: boolean
|
||||
}
|
||||
]
|
||||
errorTp: [
|
||||
info: {
|
||||
dir: 'send' | 'recv'
|
||||
data: Buffer
|
||||
ts: number
|
||||
id: number
|
||||
idType: string
|
||||
canfd: boolean
|
||||
brs: boolean
|
||||
remote: boolean
|
||||
msg: string
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
export function getLenByDlc(dlc: number, canFd: boolean) {
|
||||
const map: Record<number, number> = {
|
||||
0: 8,
|
||||
1: 8,
|
||||
2: 8,
|
||||
3: 8,
|
||||
4: 8,
|
||||
5: 8,
|
||||
6: 8,
|
||||
7: 8,
|
||||
8: 8,
|
||||
9: 8,
|
||||
10: 8,
|
||||
11: 8,
|
||||
12: 8,
|
||||
13: 8,
|
||||
14: 8,
|
||||
15: 8
|
||||
}
|
||||
const mapFd: Record<number, number> = {
|
||||
0: 8,
|
||||
1: 8,
|
||||
2: 8,
|
||||
3: 8,
|
||||
4: 8,
|
||||
5: 8,
|
||||
6: 8,
|
||||
7: 8,
|
||||
8: 8,
|
||||
9: 12,
|
||||
10: 16,
|
||||
11: 20,
|
||||
12: 24,
|
||||
13: 32,
|
||||
14: 48,
|
||||
15: 64
|
||||
}
|
||||
if (canFd) {
|
||||
return mapFd[dlc] || 0
|
||||
} else {
|
||||
return map[dlc] || 0
|
||||
}
|
||||
}
|
||||
export function getDlcByLen(len: number, canFd: boolean) {
|
||||
const map: Record<number, number> = {
|
||||
0: 0,
|
||||
1: 1,
|
||||
2: 2,
|
||||
3: 3,
|
||||
4: 4,
|
||||
5: 5,
|
||||
6: 6,
|
||||
7: 7,
|
||||
8: 8
|
||||
}
|
||||
const mapFd: Record<number, number> = {
|
||||
0: 0,
|
||||
1: 1,
|
||||
2: 2,
|
||||
3: 3,
|
||||
4: 4,
|
||||
5: 5,
|
||||
6: 6,
|
||||
7: 7,
|
||||
8: 8,
|
||||
12: 9,
|
||||
16: 10,
|
||||
20: 11,
|
||||
24: 12,
|
||||
32: 13,
|
||||
48: 14,
|
||||
64: 15
|
||||
}
|
||||
|
||||
if (canFd) {
|
||||
return mapFd[len] || 0
|
||||
} else {
|
||||
return map[len] || 0
|
||||
}
|
||||
}
|
||||
export function addrToId(addr: CanAddr): number {
|
||||
let id = Number(addr.canIdTx)
|
||||
if (addr.addrFormat == CAN_ADDR_FORMAT.FIXED_NORMAL) {
|
||||
id = calcCanIdNormalFixed(Number(addr.SA), Number(addr.TA), addr.addrType)
|
||||
} else if (addr.addrFormat == CAN_ADDR_FORMAT.MIXED) {
|
||||
if (addr.idType == CAN_ID_TYPE.EXTENDED) {
|
||||
id = calcCanIdMixed(Number(addr.SA), Number(addr.TA), addr.addrType)
|
||||
}
|
||||
}
|
||||
return id
|
||||
}
|
||||
export function addrToStr(addr: CanAddr): string {
|
||||
const cAddr = cloneDeep(addr)
|
||||
delete cAddr.uuid
|
||||
const jsonString = JSON.stringify(cAddr, Object.keys(cAddr).sort())
|
||||
return jsonString
|
||||
}
|
||||
|
||||
export function swapAddr(addr: CanAddr): CanAddr {
|
||||
const cloneAddr = cloneDeep(addr)
|
||||
const tmp = cloneAddr.SA
|
||||
cloneAddr.SA = cloneAddr.TA
|
||||
cloneAddr.TA = tmp
|
||||
const tmpid = cloneAddr.canIdTx
|
||||
cloneAddr.canIdTx = cloneAddr.canIdRx
|
||||
cloneAddr.canIdRx = tmpid
|
||||
return cloneAddr
|
||||
}
|
||||
export function calcCanIdMixed(sa: number, ta: number, addrType: CAN_ADDR_TYPE) {
|
||||
if (addrType === CAN_ADDR_TYPE.PHYSICAL) {
|
||||
//29bit 110|0|0|206|N_TA|N_SA
|
||||
return 0x18ce0000 | (ta << 8) | sa
|
||||
} else {
|
||||
//29bit 110|0|0|205|N_TA|N_SA
|
||||
return 0x18cd0000 | (ta << 8) | sa
|
||||
}
|
||||
}
|
||||
|
||||
export function calcCanIdNormalFixed(sa: number, ta: number, addrType: CAN_ADDR_TYPE) {
|
||||
if (addrType === CAN_ADDR_TYPE.PHYSICAL) {
|
||||
//29bit 110|0|0|218|N_TA|N_SA
|
||||
return 0x18da0000 | (ta << 8) | sa
|
||||
} else {
|
||||
//29bit 110|0|0|219|N_TA|N_SA
|
||||
return 0x18db0000 | (ta << 8) | sa
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
import { NetworkInterfaceInfo } from 'os'
|
||||
|
||||
export interface EthDevice {
|
||||
label: string
|
||||
id: string
|
||||
handle: string
|
||||
detail?: NetworkInterfaceInfo
|
||||
}
|
||||
|
||||
export interface EthBaseInfo {
|
||||
name: string
|
||||
device: EthDevice
|
||||
vendor: string
|
||||
id: string
|
||||
}
|
||||
|
||||
/**
|
||||
* TLS configuration for DoIP v3
|
||||
* @category DOIP
|
||||
*/
|
||||
export interface TlsConfig {
|
||||
/** Enable TLS for TCP connection (DoIP v3) */
|
||||
enabled: boolean
|
||||
/** Path to CA certificate file for verifying peer */
|
||||
ca?: string
|
||||
/** Path to client/server certificate file */
|
||||
cert?: string
|
||||
/** Path to private key file */
|
||||
key?: string
|
||||
/** Skip certificate verification (for testing only) */
|
||||
rejectUnauthorized?: boolean
|
||||
/** TLS port, default is 3496 for DoIP v3 */
|
||||
port?: number
|
||||
enableKeyLog?: boolean
|
||||
keyLogPath?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* @category DOIP
|
||||
*/
|
||||
export interface EthAddr {
|
||||
name: string
|
||||
entity: EntityAddr
|
||||
tester: TesterAddr
|
||||
virReqType: 'unicast' | 'omit' | 'broadcast' | 'multicast'
|
||||
virReqAddr: string
|
||||
entityNotFoundBehavior?:
|
||||
| 'no'
|
||||
| 'normal'
|
||||
| 'withVin'
|
||||
| 'withEid'
|
||||
| 'forceNormal'
|
||||
| 'forceWithVin'
|
||||
| 'forceWithEid'
|
||||
taType: 'physical' | 'functional'
|
||||
udpClientPort?: number
|
||||
tcpClientPort?: number
|
||||
/** TLS configuration for DoIP v3 */
|
||||
tls?: TlsConfig
|
||||
}
|
||||
|
||||
export interface TesterAddr {
|
||||
routeActiveTime: number
|
||||
createConnectDelay: number
|
||||
testerLogicalAddr: number
|
||||
}
|
||||
|
||||
export interface VinInfo {
|
||||
vin: string
|
||||
logicalAddr: number
|
||||
eid: string
|
||||
gid: string
|
||||
}
|
||||
|
||||
/**
|
||||
* @category DOIP
|
||||
*/
|
||||
export interface EntityAddr extends VinInfo {
|
||||
nodeType?: 'node' | 'gateway'
|
||||
nodeAddr?: number
|
||||
ta?: string
|
||||
ip?: string
|
||||
mcts?: number
|
||||
ncts?: number
|
||||
mds?: number
|
||||
powerMode?: number
|
||||
localPort?: number
|
||||
sendSync?: boolean
|
||||
udpLocalPort?: number
|
||||
furtherAction?: number
|
||||
syncStatus?: number
|
||||
}
|
||||
@@ -1,354 +0,0 @@
|
||||
import { EventEmitter } from 'stream'
|
||||
import { CanVendor } from './can'
|
||||
import type { Frame, LDF } from 'src/renderer/src/database/ldfParse'
|
||||
import { cloneDeep, isEqual } from 'lodash'
|
||||
|
||||
// export type LinVendor = 'peak'
|
||||
export interface LinDevice {
|
||||
label: string
|
||||
id: string
|
||||
handle: any
|
||||
serialNumber?: string
|
||||
busy?: boolean
|
||||
toomossVolt?: number
|
||||
lincablePowerEnable?: boolean
|
||||
lincableCustomBaudRateBitMap?: number
|
||||
lincableCustomBaudRatePrescale?: number
|
||||
}
|
||||
|
||||
export interface LinBaseInfo {
|
||||
id: string
|
||||
device: LinDevice
|
||||
baudRate: number
|
||||
mode: LinMode
|
||||
vendor: CanVendor
|
||||
name: string
|
||||
database?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* @category LIN
|
||||
*/
|
||||
export enum LinDirection {
|
||||
SEND = 'SEND',
|
||||
RECV = 'RECV',
|
||||
RECV_AUTO_LEN = 'RECV_AUTO_LEN'
|
||||
}
|
||||
|
||||
/**
|
||||
* @category LIN
|
||||
*/
|
||||
export enum LinMode {
|
||||
MASTER = 'MASTER',
|
||||
SLAVE = 'SLAVE'
|
||||
}
|
||||
|
||||
/**
|
||||
* @category LIN
|
||||
*/
|
||||
export enum LinChecksumType {
|
||||
CLASSIC = 'CLASSIC',
|
||||
ENHANCED = 'ENHANCED'
|
||||
}
|
||||
|
||||
export enum LIN_ERROR_ID {
|
||||
LIN_BUS_ERROR,
|
||||
LIN_READ_TIMEOUT,
|
||||
LIN_BUS_BUSY,
|
||||
LIN_BUS_CLOSED,
|
||||
LIN_INTERNAL_ERROR,
|
||||
LIN_PARAM_ERROR
|
||||
}
|
||||
|
||||
const linErrorMap: Record<LIN_ERROR_ID, string> = {
|
||||
[LIN_ERROR_ID.LIN_BUS_ERROR]: 'bus error',
|
||||
[LIN_ERROR_ID.LIN_READ_TIMEOUT]: 'read timeout',
|
||||
[LIN_ERROR_ID.LIN_BUS_BUSY]: 'bus busy',
|
||||
[LIN_ERROR_ID.LIN_INTERNAL_ERROR]: 'dll lib internal error',
|
||||
[LIN_ERROR_ID.LIN_BUS_CLOSED]: 'bus closed',
|
||||
[LIN_ERROR_ID.LIN_PARAM_ERROR]: 'param error'
|
||||
}
|
||||
|
||||
/**
|
||||
* LinCable Error Inject Control. See {@link https://app.whyengineer.com/docs/um/hardware/lincable.html} for details.
|
||||
* @category LIN
|
||||
*/
|
||||
export interface LinCableErrorInject {
|
||||
/**
|
||||
* Break field length in bits
|
||||
* @default 13
|
||||
* @minimum 13
|
||||
* @maximum 26
|
||||
*/
|
||||
breakLength?: number
|
||||
|
||||
/**
|
||||
* Break delimiter length in bits
|
||||
* @default 1
|
||||
* @minimum 0
|
||||
* @maximum 14.6
|
||||
*/
|
||||
breakDelLength?: number
|
||||
|
||||
/**
|
||||
* Inter-byte space between sync byte field and identifier in bits
|
||||
* @default 0
|
||||
* @minimum 0
|
||||
* @maximum 14
|
||||
*/
|
||||
hInterLength?: number
|
||||
|
||||
/**
|
||||
* Inter-byte spaces between data fields in bits. Array length must match data length.
|
||||
* @default 0
|
||||
* @minimum 0
|
||||
* @maximum 4
|
||||
*/
|
||||
dInterLength?: number[]
|
||||
|
||||
/**
|
||||
* Custom sync byte value. Set to false to prevent master from sending sync.
|
||||
* @default 0x55
|
||||
*/
|
||||
syncVal?: number | false
|
||||
|
||||
/**
|
||||
* Custom PID value. Set to false to prevent master from sending PID.
|
||||
* @default getPID(frameId)
|
||||
*/
|
||||
pid?: number | false
|
||||
|
||||
/**
|
||||
* Fault injection configuration
|
||||
*/
|
||||
errorInject?: {
|
||||
/** Bit position to inject fault, starting from first break bit */
|
||||
bit: number
|
||||
/** Fault value: 1 for high, 0 for low */
|
||||
value: 1 | 0
|
||||
}
|
||||
|
||||
/**
|
||||
* Override the checksum value
|
||||
*/
|
||||
checkSum?: number
|
||||
|
||||
/**
|
||||
* Custom pulses - LIN idle high, alternates high/low.
|
||||
* Array length = pulse count (max 64). Each element = length in bit-time units (uint16).
|
||||
* When set, sends only custom pulses (no LIN frame).
|
||||
*
|
||||
* @example
|
||||
* ```ts
|
||||
* // 2 segments: high 10 bit-times, low 5 bit-times
|
||||
* frame.lincable = { customPulses: [10, 5] }
|
||||
* ```
|
||||
*/
|
||||
customPulses?: number[]
|
||||
}
|
||||
/**
|
||||
* @category LIN
|
||||
*/
|
||||
export interface LinMsg<T = any> {
|
||||
frameId: number
|
||||
data: Buffer
|
||||
direction: LinDirection
|
||||
checksumType: LinChecksumType
|
||||
checksum?: number
|
||||
database?: string
|
||||
device?: string
|
||||
workNode?: string
|
||||
name?: string
|
||||
isEvent?: boolean
|
||||
uuid?: string
|
||||
ts?: number
|
||||
/**
|
||||
* The children signals of the LIN message.
|
||||
* internal use
|
||||
*/
|
||||
signals?: T
|
||||
/* advanced for ecubus lincable */
|
||||
lincable?: LinCableErrorInject
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents a LIN (Local Interconnect Network) signal that defines data within a LIN frame.
|
||||
*
|
||||
* @category LIN
|
||||
*/
|
||||
export interface LinSignal {
|
||||
/**
|
||||
* The name of the LIN signal.
|
||||
*/
|
||||
signalName: string
|
||||
/**
|
||||
* The size of the signal in bits.
|
||||
*/
|
||||
signalSizeBits: number
|
||||
/**
|
||||
* The initial/default value of the signal.
|
||||
* For scalar signals: a single number.
|
||||
* For byte array signals: an array of numbers.
|
||||
*/
|
||||
initValue: number | number[]
|
||||
/**
|
||||
* The current raw value of the signal.
|
||||
* For scalar signals: a single number.
|
||||
* For byte array signals: an array of numbers.
|
||||
*/
|
||||
value?: number | number[]
|
||||
/**
|
||||
* The current physical value of the signal (if applicable).
|
||||
*/
|
||||
physValue?: number | string
|
||||
/**
|
||||
* The current physical value represented as an enumeration label (if applicable).
|
||||
*/
|
||||
physValueEnum?: string
|
||||
/**
|
||||
* Indicates whether the signal value has been updated.
|
||||
*/
|
||||
update?: boolean
|
||||
/**
|
||||
* The name of the node that publishes this signal.
|
||||
*/
|
||||
punishedBy: string
|
||||
/**
|
||||
* List of node names that subscribe to this signal.
|
||||
*/
|
||||
subscribedBy: string[]
|
||||
/**
|
||||
* The type of signal representation.
|
||||
* 'ByteArray' for multi-byte array signals, 'Scalar' for single value signals.
|
||||
*/
|
||||
singleType: 'ByteArray' | 'Scalar'
|
||||
}
|
||||
|
||||
export class LinError extends Error {
|
||||
errorId: LIN_ERROR_ID
|
||||
msgType?: LinMsg
|
||||
|
||||
constructor(errorId: LIN_ERROR_ID, msg?: LinMsg, extMsg?: string) {
|
||||
super(linErrorMap[errorId] + (extMsg ? `,${extMsg}` : ''))
|
||||
this.errorId = errorId
|
||||
this.msgType = msg
|
||||
}
|
||||
}
|
||||
export enum LIN_ADDR_TYPE {
|
||||
PHYSICAL = 'PHYSICAL',
|
||||
FUNCTIONAL = 'FUNCTIONAL'
|
||||
}
|
||||
export enum LIN_SCH_TYPE {
|
||||
DIAG_ONLY = 'DIAG_ONLY',
|
||||
DIAG_INTERLEAVED = 'DIAG_INTERLEAVED'
|
||||
}
|
||||
|
||||
/**
|
||||
* @category LIN
|
||||
*/
|
||||
export interface LinAddr {
|
||||
name: string
|
||||
addrType: LIN_ADDR_TYPE
|
||||
nad: number
|
||||
stMin: number
|
||||
nAs: number
|
||||
nCr: number
|
||||
schType: LIN_SCH_TYPE
|
||||
}
|
||||
|
||||
const LinPidTable = [
|
||||
0x80, 0xc1, 0x42, 0x03, 0xc4, 0x85, 0x06, 0x47, 0x08, 0x49, 0xca, 0x8b, 0x4c, 0x0d, 0x8e, 0xcf,
|
||||
0x50, 0x11, 0x92, 0xd3, 0x14, 0x55, 0xd6, 0x97, 0xd8, 0x99, 0x1a, 0x5b, 0x9c, 0xdd, 0x5e, 0x1f,
|
||||
0x20, 0x61, 0xe2, 0xa3, 0x64, 0x25, 0xa6, 0xe7, 0xa8, 0xe9, 0x6a, 0x2b, 0xec, 0xad, 0x2e, 0x6f,
|
||||
0xf0, 0xb1, 0x32, 0x73, 0xb4, 0xf5, 0x76, 0x37, 0x78, 0x39, 0xba, 0xfb, 0x3c, 0x7d, 0xfe, 0xbf
|
||||
]
|
||||
|
||||
export function getPID(frameId: number) {
|
||||
return LinPidTable[frameId]
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate LIN frame checksum
|
||||
* @category LIN
|
||||
* @param data - Data bytes to calculate checksum for
|
||||
* @param checksumType - Type of checksum (CLASSIC for LIN 1.x or ENHANCED for LIN 2.x)
|
||||
* @param pid - Protected ID, required for enhanced checksum calculation
|
||||
* @returns Calculated checksum byte
|
||||
*/
|
||||
export function getCheckSum(data: Buffer, checksumType: LinChecksumType, pid?: number) {
|
||||
let checksum = 0
|
||||
|
||||
if (checksumType === LinChecksumType.CLASSIC) {
|
||||
// Classic checksum (LIN 1.x): sum all bytes with carry, then NOT
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
checksum += data[i]
|
||||
checksum = (checksum & 0xff) + (checksum >> 8)
|
||||
}
|
||||
checksum = ~checksum & 0xff
|
||||
} else {
|
||||
// Enhanced checksum (LIN 2.x): PID + data, sum with carry handling, then subtract from 0xFF
|
||||
if (pid === undefined) throw new Error('pid required for enhanced checksum')
|
||||
checksum = pid
|
||||
for (let i = 0; i < data.length; i++) {
|
||||
checksum += data[i]
|
||||
checksum = (checksum & 0xff) + (checksum >> 8)
|
||||
}
|
||||
checksum = 0xff - checksum
|
||||
}
|
||||
|
||||
return checksum
|
||||
}
|
||||
|
||||
export function getFrameData(db: LDF, frame: Frame): Buffer {
|
||||
const data = Buffer.alloc(frame.frameSize)
|
||||
for (const signal of frame.signals) {
|
||||
const signalDef = cloneDeep(db.signals[signal.name])
|
||||
if (!signalDef) continue
|
||||
|
||||
if (signalDef.singleType === 'ByteArray') {
|
||||
// Handle byte array type signals
|
||||
const initValues = (
|
||||
signalDef.value != undefined ? signalDef.value : signalDef.initValue
|
||||
) as number[]
|
||||
const bytesToCopy = Math.ceil(signalDef.signalSizeBits / 8)
|
||||
initValues.reverse()
|
||||
for (let i = 0; i < bytesToCopy && i < initValues.length; i++) {
|
||||
const startBit = signal.offset + i * 8
|
||||
const byteOffset = Math.floor(startBit / 8)
|
||||
const bitOffset = startBit % 8
|
||||
|
||||
if (bitOffset === 0) {
|
||||
// Aligned byte
|
||||
data[byteOffset] = initValues[i]
|
||||
} else {
|
||||
// Unaligned byte
|
||||
data[byteOffset] |= (initValues[i] << bitOffset) & 0xff
|
||||
if (byteOffset + 1 < data.length) {
|
||||
data[byteOffset + 1] = (initValues[i] >> (8 - bitOffset)) & 0xff
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// Handle scalar type signals - process bit by bit
|
||||
const value = (signalDef.value != undefined ? signalDef.value : signalDef.initValue) as number
|
||||
let tempValue = value
|
||||
|
||||
for (let i = 0; i < signalDef.signalSizeBits; i++) {
|
||||
const targetBit = signal.offset + i
|
||||
const byteOffset = Math.floor(targetBit / 8)
|
||||
const bitOffset = targetBit % 8
|
||||
|
||||
if (byteOffset < data.length) {
|
||||
// Clear bit
|
||||
data[byteOffset] &= ~(1 << bitOffset)
|
||||
// Set bit if needed
|
||||
if ((tempValue & 1) === 1) {
|
||||
data[byteOffset] |= 1 << bitOffset
|
||||
}
|
||||
tempValue >>= 1
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return data
|
||||
}
|
||||
@@ -1,43 +0,0 @@
|
||||
import dayjs from 'dayjs'
|
||||
|
||||
export const LOG_FILE_FIELD_CODES = {
|
||||
localTime: '{LocalTime}',
|
||||
loggerName: '{LoggerName}',
|
||||
projectName: '{ProjectName}'
|
||||
} as const
|
||||
|
||||
export interface LogFileNameContext {
|
||||
loggerName: string
|
||||
projectName: string
|
||||
}
|
||||
|
||||
const INVALID_FILE_NAME_CHARACTERS = /[<>:"/\\|?*]/g
|
||||
|
||||
export function isValidLogFileNameRule(rule: string): boolean {
|
||||
return rule.trim().length > 0 && !/[<>:"/\\|?*]/.test(rule)
|
||||
}
|
||||
|
||||
function sanitizeFileName(value: string): string {
|
||||
return value.replace(INVALID_FILE_NAME_CHARACTERS, '_').trim()
|
||||
}
|
||||
|
||||
export function resolveLogFileName(
|
||||
rule: string,
|
||||
context: LogFileNameContext,
|
||||
now: Date = new Date()
|
||||
): string {
|
||||
const normalizedRule = rule.trim() || LOG_FILE_FIELD_CODES.localTime
|
||||
const hasLocalTime = normalizedRule.includes(LOG_FILE_FIELD_CODES.localTime)
|
||||
const localTime = dayjs(now).format('YYYY-MM-DD_HH-mm-ss')
|
||||
|
||||
let fileName = normalizedRule
|
||||
.replaceAll(LOG_FILE_FIELD_CODES.localTime, localTime)
|
||||
.replaceAll(LOG_FILE_FIELD_CODES.loggerName, context.loggerName)
|
||||
.replaceAll(LOG_FILE_FIELD_CODES.projectName, context.projectName)
|
||||
|
||||
if (!hasLocalTime) {
|
||||
fileName += `_${dayjs(now).format('YYYYMMDDHHmmss')}`
|
||||
}
|
||||
|
||||
return sanitizeFileName(fileName) || localTime
|
||||
}
|
||||
@@ -1,155 +0,0 @@
|
||||
{
|
||||
"name": "@types/node",
|
||||
"version": "24.3.0",
|
||||
"description": "TypeScript definitions for node",
|
||||
"homepage": "https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/node",
|
||||
"license": "MIT",
|
||||
"contributors": [
|
||||
{
|
||||
"name": "Microsoft TypeScript",
|
||||
"githubUsername": "Microsoft",
|
||||
"url": "https://github.com/Microsoft"
|
||||
},
|
||||
{
|
||||
"name": "Alberto Schiabel",
|
||||
"githubUsername": "jkomyno",
|
||||
"url": "https://github.com/jkomyno"
|
||||
},
|
||||
{
|
||||
"name": "Andrew Makarov",
|
||||
"githubUsername": "r3nya",
|
||||
"url": "https://github.com/r3nya"
|
||||
},
|
||||
{
|
||||
"name": "Benjamin Toueg",
|
||||
"githubUsername": "btoueg",
|
||||
"url": "https://github.com/btoueg"
|
||||
},
|
||||
{
|
||||
"name": "David Junger",
|
||||
"githubUsername": "touffy",
|
||||
"url": "https://github.com/touffy"
|
||||
},
|
||||
{
|
||||
"name": "Mohsen Azimi",
|
||||
"githubUsername": "mohsen1",
|
||||
"url": "https://github.com/mohsen1"
|
||||
},
|
||||
{
|
||||
"name": "Nikita Galkin",
|
||||
"githubUsername": "galkin",
|
||||
"url": "https://github.com/galkin"
|
||||
},
|
||||
{
|
||||
"name": "Sebastian Silbermann",
|
||||
"githubUsername": "eps1lon",
|
||||
"url": "https://github.com/eps1lon"
|
||||
},
|
||||
{
|
||||
"name": "Wilco Bakker",
|
||||
"githubUsername": "WilcoBakker",
|
||||
"url": "https://github.com/WilcoBakker"
|
||||
},
|
||||
{
|
||||
"name": "Marcin Kopacz",
|
||||
"githubUsername": "chyzwar",
|
||||
"url": "https://github.com/chyzwar"
|
||||
},
|
||||
{
|
||||
"name": "Trivikram Kamat",
|
||||
"githubUsername": "trivikr",
|
||||
"url": "https://github.com/trivikr"
|
||||
},
|
||||
{
|
||||
"name": "Junxiao Shi",
|
||||
"githubUsername": "yoursunny",
|
||||
"url": "https://github.com/yoursunny"
|
||||
},
|
||||
{
|
||||
"name": "Ilia Baryshnikov",
|
||||
"githubUsername": "qwelias",
|
||||
"url": "https://github.com/qwelias"
|
||||
},
|
||||
{
|
||||
"name": "ExE Boss",
|
||||
"githubUsername": "ExE-Boss",
|
||||
"url": "https://github.com/ExE-Boss"
|
||||
},
|
||||
{
|
||||
"name": "Piotr Błażejewicz",
|
||||
"githubUsername": "peterblazejewicz",
|
||||
"url": "https://github.com/peterblazejewicz"
|
||||
},
|
||||
{
|
||||
"name": "Anna Henningsen",
|
||||
"githubUsername": "addaleax",
|
||||
"url": "https://github.com/addaleax"
|
||||
},
|
||||
{
|
||||
"name": "Victor Perin",
|
||||
"githubUsername": "victorperin",
|
||||
"url": "https://github.com/victorperin"
|
||||
},
|
||||
{
|
||||
"name": "NodeJS Contributors",
|
||||
"githubUsername": "NodeJS",
|
||||
"url": "https://github.com/NodeJS"
|
||||
},
|
||||
{
|
||||
"name": "Linus Unnebäck",
|
||||
"githubUsername": "LinusU",
|
||||
"url": "https://github.com/LinusU"
|
||||
},
|
||||
{
|
||||
"name": "wafuwafu13",
|
||||
"githubUsername": "wafuwafu13",
|
||||
"url": "https://github.com/wafuwafu13"
|
||||
},
|
||||
{
|
||||
"name": "Matteo Collina",
|
||||
"githubUsername": "mcollina",
|
||||
"url": "https://github.com/mcollina"
|
||||
},
|
||||
{
|
||||
"name": "Dmitry Semigradsky",
|
||||
"githubUsername": "Semigradsky",
|
||||
"url": "https://github.com/Semigradsky"
|
||||
},
|
||||
{
|
||||
"name": "René",
|
||||
"githubUsername": "Renegade334",
|
||||
"url": "https://github.com/Renegade334"
|
||||
},
|
||||
{
|
||||
"name": "Yagiz Nizipli",
|
||||
"githubUsername": "anonrig",
|
||||
"url": "https://github.com/anonrig"
|
||||
}
|
||||
],
|
||||
"main": "",
|
||||
"types": "index.d.ts",
|
||||
"typesVersions": {
|
||||
"<=5.6": {
|
||||
"*": [
|
||||
"ts5.6/*"
|
||||
]
|
||||
},
|
||||
"<=5.7": {
|
||||
"*": [
|
||||
"ts5.7/*"
|
||||
]
|
||||
}
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/DefinitelyTyped/DefinitelyTyped.git",
|
||||
"directory": "types/node"
|
||||
},
|
||||
"scripts": {},
|
||||
"dependencies": {
|
||||
"undici-types": "~7.10.0"
|
||||
},
|
||||
"peerDependencies": {},
|
||||
"typesPublisherContentHash": "1db0510763ba3afd8e54c0591e60a100a7b90926f5d7da28ae32d8f845d725da",
|
||||
"typeScriptVersion": "5.2"
|
||||
}
|
||||
@@ -1,200 +0,0 @@
|
||||
declare module "path/posix" {
|
||||
import path = require("path");
|
||||
export = path;
|
||||
}
|
||||
declare module "path/win32" {
|
||||
import path = require("path");
|
||||
export = path;
|
||||
}
|
||||
/**
|
||||
* The `node:path` module provides utilities for working with file and directory
|
||||
* paths. It can be accessed using:
|
||||
*
|
||||
* ```js
|
||||
* import path from 'node:path';
|
||||
* ```
|
||||
* @see [source](https://github.com/nodejs/node/blob/v24.x/lib/path.js)
|
||||
*/
|
||||
declare module "path" {
|
||||
namespace path {
|
||||
/**
|
||||
* A parsed path object generated by path.parse() or consumed by path.format().
|
||||
*/
|
||||
interface ParsedPath {
|
||||
/**
|
||||
* The root of the path such as '/' or 'c:\'
|
||||
*/
|
||||
root: string;
|
||||
/**
|
||||
* The full directory path such as '/home/user/dir' or 'c:\path\dir'
|
||||
*/
|
||||
dir: string;
|
||||
/**
|
||||
* The file name including extension (if any) such as 'index.html'
|
||||
*/
|
||||
base: string;
|
||||
/**
|
||||
* The file extension (if any) such as '.html'
|
||||
*/
|
||||
ext: string;
|
||||
/**
|
||||
* The file name without extension (if any) such as 'index'
|
||||
*/
|
||||
name: string;
|
||||
}
|
||||
interface FormatInputPathObject {
|
||||
/**
|
||||
* The root of the path such as '/' or 'c:\'
|
||||
*/
|
||||
root?: string | undefined;
|
||||
/**
|
||||
* The full directory path such as '/home/user/dir' or 'c:\path\dir'
|
||||
*/
|
||||
dir?: string | undefined;
|
||||
/**
|
||||
* The file name including extension (if any) such as 'index.html'
|
||||
*/
|
||||
base?: string | undefined;
|
||||
/**
|
||||
* The file extension (if any) such as '.html'
|
||||
*/
|
||||
ext?: string | undefined;
|
||||
/**
|
||||
* The file name without extension (if any) such as 'index'
|
||||
*/
|
||||
name?: string | undefined;
|
||||
}
|
||||
interface PlatformPath {
|
||||
/**
|
||||
* Normalize a string path, reducing '..' and '.' parts.
|
||||
* When multiple slashes are found, they're replaced by a single one; when the path contains a trailing slash, it is preserved. On Windows backslashes are used.
|
||||
*
|
||||
* @param path string path to normalize.
|
||||
* @throws {TypeError} if `path` is not a string.
|
||||
*/
|
||||
normalize(path: string): string;
|
||||
/**
|
||||
* Join all arguments together and normalize the resulting path.
|
||||
*
|
||||
* @param paths paths to join.
|
||||
* @throws {TypeError} if any of the path segments is not a string.
|
||||
*/
|
||||
join(...paths: string[]): string;
|
||||
/**
|
||||
* The right-most parameter is considered {to}. Other parameters are considered an array of {from}.
|
||||
*
|
||||
* Starting from leftmost {from} parameter, resolves {to} to an absolute path.
|
||||
*
|
||||
* If {to} isn't already absolute, {from} arguments are prepended in right to left order,
|
||||
* until an absolute path is found. If after using all {from} paths still no absolute path is found,
|
||||
* the current working directory is used as well. The resulting path is normalized,
|
||||
* and trailing slashes are removed unless the path gets resolved to the root directory.
|
||||
*
|
||||
* @param paths A sequence of paths or path segments.
|
||||
* @throws {TypeError} if any of the arguments is not a string.
|
||||
*/
|
||||
resolve(...paths: string[]): string;
|
||||
/**
|
||||
* The `path.matchesGlob()` method determines if `path` matches the `pattern`.
|
||||
* @param path The path to glob-match against.
|
||||
* @param pattern The glob to check the path against.
|
||||
* @returns Whether or not the `path` matched the `pattern`.
|
||||
* @throws {TypeError} if `path` or `pattern` are not strings.
|
||||
* @since v22.5.0
|
||||
*/
|
||||
matchesGlob(path: string, pattern: string): boolean;
|
||||
/**
|
||||
* Determines whether {path} is an absolute path. An absolute path will always resolve to the same location, regardless of the working directory.
|
||||
*
|
||||
* If the given {path} is a zero-length string, `false` will be returned.
|
||||
*
|
||||
* @param path path to test.
|
||||
* @throws {TypeError} if `path` is not a string.
|
||||
*/
|
||||
isAbsolute(path: string): boolean;
|
||||
/**
|
||||
* Solve the relative path from {from} to {to} based on the current working directory.
|
||||
* At times we have two absolute paths, and we need to derive the relative path from one to the other. This is actually the reverse transform of path.resolve.
|
||||
*
|
||||
* @throws {TypeError} if either `from` or `to` is not a string.
|
||||
*/
|
||||
relative(from: string, to: string): string;
|
||||
/**
|
||||
* Return the directory name of a path. Similar to the Unix dirname command.
|
||||
*
|
||||
* @param path the path to evaluate.
|
||||
* @throws {TypeError} if `path` is not a string.
|
||||
*/
|
||||
dirname(path: string): string;
|
||||
/**
|
||||
* Return the last portion of a path. Similar to the Unix basename command.
|
||||
* Often used to extract the file name from a fully qualified path.
|
||||
*
|
||||
* @param path the path to evaluate.
|
||||
* @param suffix optionally, an extension to remove from the result.
|
||||
* @throws {TypeError} if `path` is not a string or if `ext` is given and is not a string.
|
||||
*/
|
||||
basename(path: string, suffix?: string): string;
|
||||
/**
|
||||
* Return the extension of the path, from the last '.' to end of string in the last portion of the path.
|
||||
* If there is no '.' in the last portion of the path or the first character of it is '.', then it returns an empty string.
|
||||
*
|
||||
* @param path the path to evaluate.
|
||||
* @throws {TypeError} if `path` is not a string.
|
||||
*/
|
||||
extname(path: string): string;
|
||||
/**
|
||||
* The platform-specific file separator. '\\' or '/'.
|
||||
*/
|
||||
readonly sep: "\\" | "/";
|
||||
/**
|
||||
* The platform-specific file delimiter. ';' or ':'.
|
||||
*/
|
||||
readonly delimiter: ";" | ":";
|
||||
/**
|
||||
* Returns an object from a path string - the opposite of format().
|
||||
*
|
||||
* @param path path to evaluate.
|
||||
* @throws {TypeError} if `path` is not a string.
|
||||
*/
|
||||
parse(path: string): ParsedPath;
|
||||
/**
|
||||
* Returns a path string from an object - the opposite of parse().
|
||||
*
|
||||
* @param pathObject path to evaluate.
|
||||
*/
|
||||
format(pathObject: FormatInputPathObject): string;
|
||||
/**
|
||||
* On Windows systems only, returns an equivalent namespace-prefixed path for the given path.
|
||||
* If path is not a string, path will be returned without modifications.
|
||||
* This method is meaningful only on Windows system.
|
||||
* On POSIX systems, the method is non-operational and always returns path without modifications.
|
||||
*/
|
||||
toNamespacedPath(path: string): string;
|
||||
/**
|
||||
* Posix specific pathing.
|
||||
* Same as parent object on posix.
|
||||
*/
|
||||
readonly posix: PlatformPath;
|
||||
/**
|
||||
* Windows specific pathing.
|
||||
* Same as parent object on windows
|
||||
*/
|
||||
readonly win32: PlatformPath;
|
||||
}
|
||||
}
|
||||
const path: path.PlatformPath;
|
||||
export = path;
|
||||
}
|
||||
declare module "node:path" {
|
||||
import path = require("path");
|
||||
export = path;
|
||||
}
|
||||
declare module "node:path/posix" {
|
||||
import path = require("path/posix");
|
||||
export = path;
|
||||
}
|
||||
declare module "node:path/win32" {
|
||||
import path = require("path/win32");
|
||||
export = path;
|
||||
}
|
||||
-984
@@ -1,984 +0,0 @@
|
||||
/**
|
||||
* This module provides an implementation of a subset of the W3C [Web Performance APIs](https://w3c.github.io/perf-timing-primer/) as well as additional APIs for
|
||||
* Node.js-specific performance measurements.
|
||||
*
|
||||
* Node.js supports the following [Web Performance APIs](https://w3c.github.io/perf-timing-primer/):
|
||||
*
|
||||
* * [High Resolution Time](https://www.w3.org/TR/hr-time-2)
|
||||
* * [Performance Timeline](https://w3c.github.io/performance-timeline/)
|
||||
* * [User Timing](https://www.w3.org/TR/user-timing/)
|
||||
* * [Resource Timing](https://www.w3.org/TR/resource-timing-2/)
|
||||
*
|
||||
* ```js
|
||||
* import { PerformanceObserver, performance } from 'node:perf_hooks';
|
||||
*
|
||||
* const obs = new PerformanceObserver((items) => {
|
||||
* console.log(items.getEntries()[0].duration);
|
||||
* performance.clearMarks();
|
||||
* });
|
||||
* obs.observe({ type: 'measure' });
|
||||
* performance.measure('Start to Now');
|
||||
*
|
||||
* performance.mark('A');
|
||||
* doSomeLongRunningProcess(() => {
|
||||
* performance.measure('A to Now', 'A');
|
||||
*
|
||||
* performance.mark('B');
|
||||
* performance.measure('A to B', 'A', 'B');
|
||||
* });
|
||||
* ```
|
||||
* @see [source](https://github.com/nodejs/node/blob/v24.x/lib/perf_hooks.js)
|
||||
*/
|
||||
declare module "perf_hooks" {
|
||||
import { AsyncResource } from "node:async_hooks";
|
||||
type EntryType =
|
||||
| "dns" // Node.js only
|
||||
| "function" // Node.js only
|
||||
| "gc" // Node.js only
|
||||
| "http2" // Node.js only
|
||||
| "http" // Node.js only
|
||||
| "mark" // available on the Web
|
||||
| "measure" // available on the Web
|
||||
| "net" // Node.js only
|
||||
| "node" // Node.js only
|
||||
| "resource"; // available on the Web
|
||||
interface NodeGCPerformanceDetail {
|
||||
/**
|
||||
* When `performanceEntry.entryType` is equal to 'gc', the `performance.kind` property identifies
|
||||
* the type of garbage collection operation that occurred.
|
||||
* See perf_hooks.constants for valid values.
|
||||
*/
|
||||
readonly kind?: number | undefined;
|
||||
/**
|
||||
* When `performanceEntry.entryType` is equal to 'gc', the `performance.flags`
|
||||
* property contains additional information about garbage collection operation.
|
||||
* See perf_hooks.constants for valid values.
|
||||
*/
|
||||
readonly flags?: number | undefined;
|
||||
}
|
||||
/**
|
||||
* The constructor of this class is not exposed to users directly.
|
||||
* @since v8.5.0
|
||||
*/
|
||||
class PerformanceEntry {
|
||||
protected constructor();
|
||||
/**
|
||||
* The total number of milliseconds elapsed for this entry. This value will not
|
||||
* be meaningful for all Performance Entry types.
|
||||
* @since v8.5.0
|
||||
*/
|
||||
readonly duration: number;
|
||||
/**
|
||||
* The name of the performance entry.
|
||||
* @since v8.5.0
|
||||
*/
|
||||
readonly name: string;
|
||||
/**
|
||||
* The high resolution millisecond timestamp marking the starting time of the
|
||||
* Performance Entry.
|
||||
* @since v8.5.0
|
||||
*/
|
||||
readonly startTime: number;
|
||||
/**
|
||||
* The type of the performance entry. It may be one of:
|
||||
*
|
||||
* * `'node'` (Node.js only)
|
||||
* * `'mark'` (available on the Web)
|
||||
* * `'measure'` (available on the Web)
|
||||
* * `'gc'` (Node.js only)
|
||||
* * `'function'` (Node.js only)
|
||||
* * `'http2'` (Node.js only)
|
||||
* * `'http'` (Node.js only)
|
||||
* @since v8.5.0
|
||||
*/
|
||||
readonly entryType: EntryType;
|
||||
/**
|
||||
* Additional detail specific to the `entryType`.
|
||||
* @since v16.0.0
|
||||
*/
|
||||
readonly detail?: NodeGCPerformanceDetail | unknown | undefined; // TODO: Narrow this based on entry type.
|
||||
toJSON(): any;
|
||||
}
|
||||
/**
|
||||
* Exposes marks created via the `Performance.mark()` method.
|
||||
* @since v18.2.0, v16.17.0
|
||||
*/
|
||||
class PerformanceMark extends PerformanceEntry {
|
||||
readonly duration: 0;
|
||||
readonly entryType: "mark";
|
||||
}
|
||||
/**
|
||||
* Exposes measures created via the `Performance.measure()` method.
|
||||
*
|
||||
* The constructor of this class is not exposed to users directly.
|
||||
* @since v18.2.0, v16.17.0
|
||||
*/
|
||||
class PerformanceMeasure extends PerformanceEntry {
|
||||
readonly entryType: "measure";
|
||||
}
|
||||
interface UVMetrics {
|
||||
/**
|
||||
* Number of event loop iterations.
|
||||
*/
|
||||
readonly loopCount: number;
|
||||
/**
|
||||
* Number of events that have been processed by the event handler.
|
||||
*/
|
||||
readonly events: number;
|
||||
/**
|
||||
* Number of events that were waiting to be processed when the event provider was called.
|
||||
*/
|
||||
readonly eventsWaiting: number;
|
||||
}
|
||||
/**
|
||||
* _This property is an extension by Node.js. It is not available in Web browsers._
|
||||
*
|
||||
* Provides timing details for Node.js itself. The constructor of this class
|
||||
* is not exposed to users.
|
||||
* @since v8.5.0
|
||||
*/
|
||||
class PerformanceNodeTiming extends PerformanceEntry {
|
||||
readonly entryType: "node";
|
||||
/**
|
||||
* The high resolution millisecond timestamp at which the Node.js process
|
||||
* completed bootstrapping. If bootstrapping has not yet finished, the property
|
||||
* has the value of -1.
|
||||
* @since v8.5.0
|
||||
*/
|
||||
readonly bootstrapComplete: number;
|
||||
/**
|
||||
* The high resolution millisecond timestamp at which the Node.js environment was
|
||||
* initialized.
|
||||
* @since v8.5.0
|
||||
*/
|
||||
readonly environment: number;
|
||||
/**
|
||||
* The high resolution millisecond timestamp of the amount of time the event loop
|
||||
* has been idle within the event loop's event provider (e.g. `epoll_wait`). This
|
||||
* does not take CPU usage into consideration. If the event loop has not yet
|
||||
* started (e.g., in the first tick of the main script), the property has the
|
||||
* value of 0.
|
||||
* @since v14.10.0, v12.19.0
|
||||
*/
|
||||
readonly idleTime: number;
|
||||
/**
|
||||
* The high resolution millisecond timestamp at which the Node.js event loop
|
||||
* exited. If the event loop has not yet exited, the property has the value of -1\.
|
||||
* It can only have a value of not -1 in a handler of the `'exit'` event.
|
||||
* @since v8.5.0
|
||||
*/
|
||||
readonly loopExit: number;
|
||||
/**
|
||||
* The high resolution millisecond timestamp at which the Node.js event loop
|
||||
* started. If the event loop has not yet started (e.g., in the first tick of the
|
||||
* main script), the property has the value of -1.
|
||||
* @since v8.5.0
|
||||
*/
|
||||
readonly loopStart: number;
|
||||
/**
|
||||
* The high resolution millisecond timestamp at which the Node.js process was initialized.
|
||||
* @since v8.5.0
|
||||
*/
|
||||
readonly nodeStart: number;
|
||||
/**
|
||||
* This is a wrapper to the `uv_metrics_info` function.
|
||||
* It returns the current set of event loop metrics.
|
||||
*
|
||||
* It is recommended to use this property inside a function whose execution was
|
||||
* scheduled using `setImmediate` to avoid collecting metrics before finishing all
|
||||
* operations scheduled during the current loop iteration.
|
||||
* @since v22.8.0, v20.18.0
|
||||
*/
|
||||
readonly uvMetricsInfo: UVMetrics;
|
||||
/**
|
||||
* The high resolution millisecond timestamp at which the V8 platform was
|
||||
* initialized.
|
||||
* @since v8.5.0
|
||||
*/
|
||||
readonly v8Start: number;
|
||||
}
|
||||
interface EventLoopUtilization {
|
||||
idle: number;
|
||||
active: number;
|
||||
utilization: number;
|
||||
}
|
||||
/**
|
||||
* @param utilization1 The result of a previous call to `eventLoopUtilization()`.
|
||||
* @param utilization2 The result of a previous call to `eventLoopUtilization()` prior to `utilization1`.
|
||||
*/
|
||||
type EventLoopUtilityFunction = (
|
||||
utilization1?: EventLoopUtilization,
|
||||
utilization2?: EventLoopUtilization,
|
||||
) => EventLoopUtilization;
|
||||
interface MarkOptions {
|
||||
/**
|
||||
* Additional optional detail to include with the mark.
|
||||
*/
|
||||
detail?: unknown | undefined;
|
||||
/**
|
||||
* An optional timestamp to be used as the mark time.
|
||||
* @default `performance.now()`
|
||||
*/
|
||||
startTime?: number | undefined;
|
||||
}
|
||||
interface MeasureOptions {
|
||||
/**
|
||||
* Additional optional detail to include with the mark.
|
||||
*/
|
||||
detail?: unknown | undefined;
|
||||
/**
|
||||
* Duration between start and end times.
|
||||
*/
|
||||
duration?: number | undefined;
|
||||
/**
|
||||
* Timestamp to be used as the end time, or a string identifying a previously recorded mark.
|
||||
*/
|
||||
end?: number | string | undefined;
|
||||
/**
|
||||
* Timestamp to be used as the start time, or a string identifying a previously recorded mark.
|
||||
*/
|
||||
start?: number | string | undefined;
|
||||
}
|
||||
interface TimerifyOptions {
|
||||
/**
|
||||
* A histogram object created using `perf_hooks.createHistogram()` that will record runtime
|
||||
* durations in nanoseconds.
|
||||
*/
|
||||
histogram?: RecordableHistogram | undefined;
|
||||
}
|
||||
interface Performance {
|
||||
/**
|
||||
* If `name` is not provided, removes all `PerformanceMark` objects from the Performance Timeline.
|
||||
* If `name` is provided, removes only the named mark.
|
||||
* @since v8.5.0
|
||||
*/
|
||||
clearMarks(name?: string): void;
|
||||
/**
|
||||
* If `name` is not provided, removes all `PerformanceMeasure` objects from the Performance Timeline.
|
||||
* If `name` is provided, removes only the named measure.
|
||||
* @since v16.7.0
|
||||
*/
|
||||
clearMeasures(name?: string): void;
|
||||
/**
|
||||
* If `name` is not provided, removes all `PerformanceResourceTiming` objects from the Resource Timeline.
|
||||
* If `name` is provided, removes only the named resource.
|
||||
* @since v18.2.0, v16.17.0
|
||||
*/
|
||||
clearResourceTimings(name?: string): void;
|
||||
/**
|
||||
* eventLoopUtilization is similar to CPU utilization except that it is calculated using high precision wall-clock time.
|
||||
* It represents the percentage of time the event loop has spent outside the event loop's event provider (e.g. epoll_wait).
|
||||
* No other CPU idle time is taken into consideration.
|
||||
*/
|
||||
eventLoopUtilization: EventLoopUtilityFunction;
|
||||
/**
|
||||
* Returns a list of `PerformanceEntry` objects in chronological order with respect to `performanceEntry.startTime`.
|
||||
* If you are only interested in performance entries of certain types or that have certain names, see
|
||||
* `performance.getEntriesByType()` and `performance.getEntriesByName()`.
|
||||
* @since v16.7.0
|
||||
*/
|
||||
getEntries(): PerformanceEntry[];
|
||||
/**
|
||||
* Returns a list of `PerformanceEntry` objects in chronological order with respect to `performanceEntry.startTime`
|
||||
* whose `performanceEntry.name` is equal to `name`, and optionally, whose `performanceEntry.entryType` is equal to `type`.
|
||||
* @param name
|
||||
* @param type
|
||||
* @since v16.7.0
|
||||
*/
|
||||
getEntriesByName(name: string, type?: EntryType): PerformanceEntry[];
|
||||
/**
|
||||
* Returns a list of `PerformanceEntry` objects in chronological order with respect to `performanceEntry.startTime`
|
||||
* whose `performanceEntry.entryType` is equal to `type`.
|
||||
* @param type
|
||||
* @since v16.7.0
|
||||
*/
|
||||
getEntriesByType(type: EntryType): PerformanceEntry[];
|
||||
/**
|
||||
* Creates a new `PerformanceMark` entry in the Performance Timeline.
|
||||
* A `PerformanceMark` is a subclass of `PerformanceEntry` whose `performanceEntry.entryType` is always `'mark'`,
|
||||
* and whose `performanceEntry.duration` is always `0`.
|
||||
* Performance marks are used to mark specific significant moments in the Performance Timeline.
|
||||
*
|
||||
* The created `PerformanceMark` entry is put in the global Performance Timeline and can be queried with
|
||||
* `performance.getEntries`, `performance.getEntriesByName`, and `performance.getEntriesByType`. When the observation is
|
||||
* performed, the entries should be cleared from the global Performance Timeline manually with `performance.clearMarks`.
|
||||
* @param name
|
||||
*/
|
||||
mark(name: string, options?: MarkOptions): PerformanceMark;
|
||||
/**
|
||||
* Creates a new `PerformanceResourceTiming` entry in the Resource Timeline.
|
||||
* A `PerformanceResourceTiming` is a subclass of `PerformanceEntry` whose `performanceEntry.entryType` is always `'resource'`.
|
||||
* Performance resources are used to mark moments in the Resource Timeline.
|
||||
* @param timingInfo [Fetch Timing Info](https://fetch.spec.whatwg.org/#fetch-timing-info)
|
||||
* @param requestedUrl The resource url
|
||||
* @param initiatorType The initiator name, e.g: 'fetch'
|
||||
* @param global
|
||||
* @param cacheMode The cache mode must be an empty string ('') or 'local'
|
||||
* @param bodyInfo [Fetch Response Body Info](https://fetch.spec.whatwg.org/#response-body-info)
|
||||
* @param responseStatus The response's status code
|
||||
* @param deliveryType The delivery type. Default: ''.
|
||||
* @since v18.2.0, v16.17.0
|
||||
*/
|
||||
markResourceTiming(
|
||||
timingInfo: object,
|
||||
requestedUrl: string,
|
||||
initiatorType: string,
|
||||
global: object,
|
||||
cacheMode: "" | "local",
|
||||
bodyInfo: object,
|
||||
responseStatus: number,
|
||||
deliveryType?: string,
|
||||
): PerformanceResourceTiming;
|
||||
/**
|
||||
* Creates a new PerformanceMeasure entry in the Performance Timeline.
|
||||
* A PerformanceMeasure is a subclass of PerformanceEntry whose performanceEntry.entryType is always 'measure',
|
||||
* and whose performanceEntry.duration measures the number of milliseconds elapsed since startMark and endMark.
|
||||
*
|
||||
* The startMark argument may identify any existing PerformanceMark in the the Performance Timeline, or may identify
|
||||
* any of the timestamp properties provided by the PerformanceNodeTiming class. If the named startMark does not exist,
|
||||
* then startMark is set to timeOrigin by default.
|
||||
*
|
||||
* The endMark argument must identify any existing PerformanceMark in the the Performance Timeline or any of the timestamp
|
||||
* properties provided by the PerformanceNodeTiming class. If the named endMark does not exist, an error will be thrown.
|
||||
* @param name
|
||||
* @param startMark
|
||||
* @param endMark
|
||||
* @return The PerformanceMeasure entry that was created
|
||||
*/
|
||||
measure(name: string, startMark?: string, endMark?: string): PerformanceMeasure;
|
||||
measure(name: string, options: MeasureOptions): PerformanceMeasure;
|
||||
/**
|
||||
* _This property is an extension by Node.js. It is not available in Web browsers._
|
||||
*
|
||||
* An instance of the `PerformanceNodeTiming` class that provides performance metrics for specific Node.js operational milestones.
|
||||
* @since v8.5.0
|
||||
*/
|
||||
readonly nodeTiming: PerformanceNodeTiming;
|
||||
/**
|
||||
* Returns the current high resolution millisecond timestamp, where 0 represents the start of the current `node` process.
|
||||
* @since v8.5.0
|
||||
*/
|
||||
now(): number;
|
||||
/**
|
||||
* Sets the global performance resource timing buffer size to the specified number of "resource" type performance entry objects.
|
||||
*
|
||||
* By default the max buffer size is set to 250.
|
||||
* @since v18.8.0
|
||||
*/
|
||||
setResourceTimingBufferSize(maxSize: number): void;
|
||||
/**
|
||||
* The [`timeOrigin`](https://w3c.github.io/hr-time/#dom-performance-timeorigin) specifies the high resolution millisecond timestamp
|
||||
* at which the current `node` process began, measured in Unix time.
|
||||
* @since v8.5.0
|
||||
*/
|
||||
readonly timeOrigin: number;
|
||||
/**
|
||||
* _This property is an extension by Node.js. It is not available in Web browsers._
|
||||
*
|
||||
* Wraps a function within a new function that measures the running time of the wrapped function.
|
||||
* A `PerformanceObserver` must be subscribed to the `'function'` event type in order for the timing details to be accessed.
|
||||
*
|
||||
* ```js
|
||||
* import {
|
||||
* performance,
|
||||
* PerformanceObserver,
|
||||
* } from 'node:perf_hooks';
|
||||
*
|
||||
* function someFunction() {
|
||||
* console.log('hello world');
|
||||
* }
|
||||
*
|
||||
* const wrapped = performance.timerify(someFunction);
|
||||
*
|
||||
* const obs = new PerformanceObserver((list) => {
|
||||
* console.log(list.getEntries()[0].duration);
|
||||
*
|
||||
* performance.clearMarks();
|
||||
* performance.clearMeasures();
|
||||
* obs.disconnect();
|
||||
* });
|
||||
* obs.observe({ entryTypes: ['function'] });
|
||||
*
|
||||
* // A performance timeline entry will be created
|
||||
* wrapped();
|
||||
* ```
|
||||
*
|
||||
* If the wrapped function returns a promise, a finally handler will be attached to the promise and the duration will be reported
|
||||
* once the finally handler is invoked.
|
||||
* @param fn
|
||||
*/
|
||||
timerify<T extends (...params: any[]) => any>(fn: T, options?: TimerifyOptions): T;
|
||||
/**
|
||||
* An object which is JSON representation of the performance object. It is similar to
|
||||
* [`window.performance.toJSON`](https://developer.mozilla.org/en-US/docs/Web/API/Performance/toJSON) in browsers.
|
||||
* @since v16.1.0
|
||||
*/
|
||||
toJSON(): any;
|
||||
}
|
||||
class PerformanceObserverEntryList {
|
||||
/**
|
||||
* Returns a list of `PerformanceEntry` objects in chronological order
|
||||
* with respect to `performanceEntry.startTime`.
|
||||
*
|
||||
* ```js
|
||||
* import {
|
||||
* performance,
|
||||
* PerformanceObserver,
|
||||
* } from 'node:perf_hooks';
|
||||
*
|
||||
* const obs = new PerformanceObserver((perfObserverList, observer) => {
|
||||
* console.log(perfObserverList.getEntries());
|
||||
*
|
||||
* * [
|
||||
* * PerformanceEntry {
|
||||
* * name: 'test',
|
||||
* * entryType: 'mark',
|
||||
* * startTime: 81.465639,
|
||||
* * duration: 0,
|
||||
* * detail: null
|
||||
* * },
|
||||
* * PerformanceEntry {
|
||||
* * name: 'meow',
|
||||
* * entryType: 'mark',
|
||||
* * startTime: 81.860064,
|
||||
* * duration: 0,
|
||||
* * detail: null
|
||||
* * }
|
||||
* * ]
|
||||
*
|
||||
* performance.clearMarks();
|
||||
* performance.clearMeasures();
|
||||
* observer.disconnect();
|
||||
* });
|
||||
* obs.observe({ type: 'mark' });
|
||||
*
|
||||
* performance.mark('test');
|
||||
* performance.mark('meow');
|
||||
* ```
|
||||
* @since v8.5.0
|
||||
*/
|
||||
getEntries(): PerformanceEntry[];
|
||||
/**
|
||||
* Returns a list of `PerformanceEntry` objects in chronological order
|
||||
* with respect to `performanceEntry.startTime` whose `performanceEntry.name` is
|
||||
* equal to `name`, and optionally, whose `performanceEntry.entryType` is equal to`type`.
|
||||
*
|
||||
* ```js
|
||||
* import {
|
||||
* performance,
|
||||
* PerformanceObserver,
|
||||
* } from 'node:perf_hooks';
|
||||
*
|
||||
* const obs = new PerformanceObserver((perfObserverList, observer) => {
|
||||
* console.log(perfObserverList.getEntriesByName('meow'));
|
||||
*
|
||||
* * [
|
||||
* * PerformanceEntry {
|
||||
* * name: 'meow',
|
||||
* * entryType: 'mark',
|
||||
* * startTime: 98.545991,
|
||||
* * duration: 0,
|
||||
* * detail: null
|
||||
* * }
|
||||
* * ]
|
||||
*
|
||||
* console.log(perfObserverList.getEntriesByName('nope')); // []
|
||||
*
|
||||
* console.log(perfObserverList.getEntriesByName('test', 'mark'));
|
||||
*
|
||||
* * [
|
||||
* * PerformanceEntry {
|
||||
* * name: 'test',
|
||||
* * entryType: 'mark',
|
||||
* * startTime: 63.518931,
|
||||
* * duration: 0,
|
||||
* * detail: null
|
||||
* * }
|
||||
* * ]
|
||||
*
|
||||
* console.log(perfObserverList.getEntriesByName('test', 'measure')); // []
|
||||
*
|
||||
* performance.clearMarks();
|
||||
* performance.clearMeasures();
|
||||
* observer.disconnect();
|
||||
* });
|
||||
* obs.observe({ entryTypes: ['mark', 'measure'] });
|
||||
*
|
||||
* performance.mark('test');
|
||||
* performance.mark('meow');
|
||||
* ```
|
||||
* @since v8.5.0
|
||||
*/
|
||||
getEntriesByName(name: string, type?: EntryType): PerformanceEntry[];
|
||||
/**
|
||||
* Returns a list of `PerformanceEntry` objects in chronological order
|
||||
* with respect to `performanceEntry.startTime` whose `performanceEntry.entryType` is equal to `type`.
|
||||
*
|
||||
* ```js
|
||||
* import {
|
||||
* performance,
|
||||
* PerformanceObserver,
|
||||
* } from 'node:perf_hooks';
|
||||
*
|
||||
* const obs = new PerformanceObserver((perfObserverList, observer) => {
|
||||
* console.log(perfObserverList.getEntriesByType('mark'));
|
||||
*
|
||||
* * [
|
||||
* * PerformanceEntry {
|
||||
* * name: 'test',
|
||||
* * entryType: 'mark',
|
||||
* * startTime: 55.897834,
|
||||
* * duration: 0,
|
||||
* * detail: null
|
||||
* * },
|
||||
* * PerformanceEntry {
|
||||
* * name: 'meow',
|
||||
* * entryType: 'mark',
|
||||
* * startTime: 56.350146,
|
||||
* * duration: 0,
|
||||
* * detail: null
|
||||
* * }
|
||||
* * ]
|
||||
*
|
||||
* performance.clearMarks();
|
||||
* performance.clearMeasures();
|
||||
* observer.disconnect();
|
||||
* });
|
||||
* obs.observe({ type: 'mark' });
|
||||
*
|
||||
* performance.mark('test');
|
||||
* performance.mark('meow');
|
||||
* ```
|
||||
* @since v8.5.0
|
||||
*/
|
||||
getEntriesByType(type: EntryType): PerformanceEntry[];
|
||||
}
|
||||
type PerformanceObserverCallback = (list: PerformanceObserverEntryList, observer: PerformanceObserver) => void;
|
||||
/**
|
||||
* @since v8.5.0
|
||||
*/
|
||||
class PerformanceObserver extends AsyncResource {
|
||||
constructor(callback: PerformanceObserverCallback);
|
||||
/**
|
||||
* Disconnects the `PerformanceObserver` instance from all notifications.
|
||||
* @since v8.5.0
|
||||
*/
|
||||
disconnect(): void;
|
||||
/**
|
||||
* Subscribes the `PerformanceObserver` instance to notifications of new `PerformanceEntry` instances identified either by `options.entryTypes` or `options.type`:
|
||||
*
|
||||
* ```js
|
||||
* import {
|
||||
* performance,
|
||||
* PerformanceObserver,
|
||||
* } from 'node:perf_hooks';
|
||||
*
|
||||
* const obs = new PerformanceObserver((list, observer) => {
|
||||
* // Called once asynchronously. `list` contains three items.
|
||||
* });
|
||||
* obs.observe({ type: 'mark' });
|
||||
*
|
||||
* for (let n = 0; n < 3; n++)
|
||||
* performance.mark(`test${n}`);
|
||||
* ```
|
||||
* @since v8.5.0
|
||||
*/
|
||||
observe(
|
||||
options:
|
||||
| {
|
||||
entryTypes: readonly EntryType[];
|
||||
buffered?: boolean | undefined;
|
||||
}
|
||||
| {
|
||||
type: EntryType;
|
||||
buffered?: boolean | undefined;
|
||||
},
|
||||
): void;
|
||||
/**
|
||||
* @since v16.0.0
|
||||
* @returns Current list of entries stored in the performance observer, emptying it out.
|
||||
*/
|
||||
takeRecords(): PerformanceEntry[];
|
||||
}
|
||||
/**
|
||||
* Provides detailed network timing data regarding the loading of an application's resources.
|
||||
*
|
||||
* The constructor of this class is not exposed to users directly.
|
||||
* @since v18.2.0, v16.17.0
|
||||
*/
|
||||
class PerformanceResourceTiming extends PerformanceEntry {
|
||||
readonly entryType: "resource";
|
||||
protected constructor();
|
||||
/**
|
||||
* The high resolution millisecond timestamp at immediately before dispatching the `fetch`
|
||||
* request. If the resource is not intercepted by a worker the property will always return 0.
|
||||
* @since v18.2.0, v16.17.0
|
||||
*/
|
||||
readonly workerStart: number;
|
||||
/**
|
||||
* The high resolution millisecond timestamp that represents the start time of the fetch which
|
||||
* initiates the redirect.
|
||||
* @since v18.2.0, v16.17.0
|
||||
*/
|
||||
readonly redirectStart: number;
|
||||
/**
|
||||
* The high resolution millisecond timestamp that will be created immediately after receiving
|
||||
* the last byte of the response of the last redirect.
|
||||
* @since v18.2.0, v16.17.0
|
||||
*/
|
||||
readonly redirectEnd: number;
|
||||
/**
|
||||
* The high resolution millisecond timestamp immediately before the Node.js starts to fetch the resource.
|
||||
* @since v18.2.0, v16.17.0
|
||||
*/
|
||||
readonly fetchStart: number;
|
||||
/**
|
||||
* The high resolution millisecond timestamp immediately before the Node.js starts the domain name lookup
|
||||
* for the resource.
|
||||
* @since v18.2.0, v16.17.0
|
||||
*/
|
||||
readonly domainLookupStart: number;
|
||||
/**
|
||||
* The high resolution millisecond timestamp representing the time immediately after the Node.js finished
|
||||
* the domain name lookup for the resource.
|
||||
* @since v18.2.0, v16.17.0
|
||||
*/
|
||||
readonly domainLookupEnd: number;
|
||||
/**
|
||||
* The high resolution millisecond timestamp representing the time immediately before Node.js starts to
|
||||
* establish the connection to the server to retrieve the resource.
|
||||
* @since v18.2.0, v16.17.0
|
||||
*/
|
||||
readonly connectStart: number;
|
||||
/**
|
||||
* The high resolution millisecond timestamp representing the time immediately after Node.js finishes
|
||||
* establishing the connection to the server to retrieve the resource.
|
||||
* @since v18.2.0, v16.17.0
|
||||
*/
|
||||
readonly connectEnd: number;
|
||||
/**
|
||||
* The high resolution millisecond timestamp representing the time immediately before Node.js starts the
|
||||
* handshake process to secure the current connection.
|
||||
* @since v18.2.0, v16.17.0
|
||||
*/
|
||||
readonly secureConnectionStart: number;
|
||||
/**
|
||||
* The high resolution millisecond timestamp representing the time immediately before Node.js receives the
|
||||
* first byte of the response from the server.
|
||||
* @since v18.2.0, v16.17.0
|
||||
*/
|
||||
readonly requestStart: number;
|
||||
/**
|
||||
* The high resolution millisecond timestamp representing the time immediately after Node.js receives the
|
||||
* last byte of the resource or immediately before the transport connection is closed, whichever comes first.
|
||||
* @since v18.2.0, v16.17.0
|
||||
*/
|
||||
readonly responseEnd: number;
|
||||
/**
|
||||
* A number representing the size (in octets) of the fetched resource. The size includes the response header
|
||||
* fields plus the response payload body.
|
||||
* @since v18.2.0, v16.17.0
|
||||
*/
|
||||
readonly transferSize: number;
|
||||
/**
|
||||
* A number representing the size (in octets) received from the fetch (HTTP or cache), of the payload body, before
|
||||
* removing any applied content-codings.
|
||||
* @since v18.2.0, v16.17.0
|
||||
*/
|
||||
readonly encodedBodySize: number;
|
||||
/**
|
||||
* A number representing the size (in octets) received from the fetch (HTTP or cache), of the message body, after
|
||||
* removing any applied content-codings.
|
||||
* @since v18.2.0, v16.17.0
|
||||
*/
|
||||
readonly decodedBodySize: number;
|
||||
/**
|
||||
* Returns a `object` that is the JSON representation of the `PerformanceResourceTiming` object
|
||||
* @since v18.2.0, v16.17.0
|
||||
*/
|
||||
toJSON(): any;
|
||||
}
|
||||
namespace constants {
|
||||
const NODE_PERFORMANCE_GC_MAJOR: number;
|
||||
const NODE_PERFORMANCE_GC_MINOR: number;
|
||||
const NODE_PERFORMANCE_GC_INCREMENTAL: number;
|
||||
const NODE_PERFORMANCE_GC_WEAKCB: number;
|
||||
const NODE_PERFORMANCE_GC_FLAGS_NO: number;
|
||||
const NODE_PERFORMANCE_GC_FLAGS_CONSTRUCT_RETAINED: number;
|
||||
const NODE_PERFORMANCE_GC_FLAGS_FORCED: number;
|
||||
const NODE_PERFORMANCE_GC_FLAGS_SYNCHRONOUS_PHANTOM_PROCESSING: number;
|
||||
const NODE_PERFORMANCE_GC_FLAGS_ALL_AVAILABLE_GARBAGE: number;
|
||||
const NODE_PERFORMANCE_GC_FLAGS_ALL_EXTERNAL_MEMORY: number;
|
||||
const NODE_PERFORMANCE_GC_FLAGS_SCHEDULE_IDLE: number;
|
||||
}
|
||||
const performance: Performance;
|
||||
interface EventLoopMonitorOptions {
|
||||
/**
|
||||
* The sampling rate in milliseconds.
|
||||
* Must be greater than zero.
|
||||
* @default 10
|
||||
*/
|
||||
resolution?: number | undefined;
|
||||
}
|
||||
interface Histogram {
|
||||
/**
|
||||
* The number of samples recorded by the histogram.
|
||||
* @since v17.4.0, v16.14.0
|
||||
*/
|
||||
readonly count: number;
|
||||
/**
|
||||
* The number of samples recorded by the histogram.
|
||||
* v17.4.0, v16.14.0
|
||||
*/
|
||||
readonly countBigInt: bigint;
|
||||
/**
|
||||
* The number of times the event loop delay exceeded the maximum 1 hour event
|
||||
* loop delay threshold.
|
||||
* @since v11.10.0
|
||||
*/
|
||||
readonly exceeds: number;
|
||||
/**
|
||||
* The number of times the event loop delay exceeded the maximum 1 hour event loop delay threshold.
|
||||
* @since v17.4.0, v16.14.0
|
||||
*/
|
||||
readonly exceedsBigInt: bigint;
|
||||
/**
|
||||
* The maximum recorded event loop delay.
|
||||
* @since v11.10.0
|
||||
*/
|
||||
readonly max: number;
|
||||
/**
|
||||
* The maximum recorded event loop delay.
|
||||
* v17.4.0, v16.14.0
|
||||
*/
|
||||
readonly maxBigInt: number;
|
||||
/**
|
||||
* The mean of the recorded event loop delays.
|
||||
* @since v11.10.0
|
||||
*/
|
||||
readonly mean: number;
|
||||
/**
|
||||
* The minimum recorded event loop delay.
|
||||
* @since v11.10.0
|
||||
*/
|
||||
readonly min: number;
|
||||
/**
|
||||
* The minimum recorded event loop delay.
|
||||
* v17.4.0, v16.14.0
|
||||
*/
|
||||
readonly minBigInt: bigint;
|
||||
/**
|
||||
* Returns the value at the given percentile.
|
||||
* @since v11.10.0
|
||||
* @param percentile A percentile value in the range (0, 100].
|
||||
*/
|
||||
percentile(percentile: number): number;
|
||||
/**
|
||||
* Returns the value at the given percentile.
|
||||
* @since v17.4.0, v16.14.0
|
||||
* @param percentile A percentile value in the range (0, 100].
|
||||
*/
|
||||
percentileBigInt(percentile: number): bigint;
|
||||
/**
|
||||
* Returns a `Map` object detailing the accumulated percentile distribution.
|
||||
* @since v11.10.0
|
||||
*/
|
||||
readonly percentiles: Map<number, number>;
|
||||
/**
|
||||
* Returns a `Map` object detailing the accumulated percentile distribution.
|
||||
* @since v17.4.0, v16.14.0
|
||||
*/
|
||||
readonly percentilesBigInt: Map<bigint, bigint>;
|
||||
/**
|
||||
* Resets the collected histogram data.
|
||||
* @since v11.10.0
|
||||
*/
|
||||
reset(): void;
|
||||
/**
|
||||
* The standard deviation of the recorded event loop delays.
|
||||
* @since v11.10.0
|
||||
*/
|
||||
readonly stddev: number;
|
||||
}
|
||||
interface IntervalHistogram extends Histogram {
|
||||
/**
|
||||
* Enables the update interval timer. Returns `true` if the timer was
|
||||
* started, `false` if it was already started.
|
||||
* @since v11.10.0
|
||||
*/
|
||||
enable(): boolean;
|
||||
/**
|
||||
* Disables the update interval timer. Returns `true` if the timer was
|
||||
* stopped, `false` if it was already stopped.
|
||||
* @since v11.10.0
|
||||
*/
|
||||
disable(): boolean;
|
||||
/**
|
||||
* Disables the update interval timer when the histogram is disposed.
|
||||
*
|
||||
* ```js
|
||||
* const { monitorEventLoopDelay } = require('node:perf_hooks');
|
||||
* {
|
||||
* using hist = monitorEventLoopDelay({ resolution: 20 });
|
||||
* hist.enable();
|
||||
* // The histogram will be disabled when the block is exited.
|
||||
* }
|
||||
* ```
|
||||
* @since v24.2.0
|
||||
*/
|
||||
[Symbol.dispose](): void;
|
||||
}
|
||||
interface RecordableHistogram extends Histogram {
|
||||
/**
|
||||
* @since v15.9.0, v14.18.0
|
||||
* @param val The amount to record in the histogram.
|
||||
*/
|
||||
record(val: number | bigint): void;
|
||||
/**
|
||||
* Calculates the amount of time (in nanoseconds) that has passed since the
|
||||
* previous call to `recordDelta()` and records that amount in the histogram.
|
||||
* @since v15.9.0, v14.18.0
|
||||
*/
|
||||
recordDelta(): void;
|
||||
/**
|
||||
* Adds the values from `other` to this histogram.
|
||||
* @since v17.4.0, v16.14.0
|
||||
*/
|
||||
add(other: RecordableHistogram): void;
|
||||
}
|
||||
/**
|
||||
* _This property is an extension by Node.js. It is not available in Web browsers._
|
||||
*
|
||||
* Creates an `IntervalHistogram` object that samples and reports the event loop
|
||||
* delay over time. The delays will be reported in nanoseconds.
|
||||
*
|
||||
* Using a timer to detect approximate event loop delay works because the
|
||||
* execution of timers is tied specifically to the lifecycle of the libuv
|
||||
* event loop. That is, a delay in the loop will cause a delay in the execution
|
||||
* of the timer, and those delays are specifically what this API is intended to
|
||||
* detect.
|
||||
*
|
||||
* ```js
|
||||
* import { monitorEventLoopDelay } from 'node:perf_hooks';
|
||||
* const h = monitorEventLoopDelay({ resolution: 20 });
|
||||
* h.enable();
|
||||
* // Do something.
|
||||
* h.disable();
|
||||
* console.log(h.min);
|
||||
* console.log(h.max);
|
||||
* console.log(h.mean);
|
||||
* console.log(h.stddev);
|
||||
* console.log(h.percentiles);
|
||||
* console.log(h.percentile(50));
|
||||
* console.log(h.percentile(99));
|
||||
* ```
|
||||
* @since v11.10.0
|
||||
*/
|
||||
function monitorEventLoopDelay(options?: EventLoopMonitorOptions): IntervalHistogram;
|
||||
interface CreateHistogramOptions {
|
||||
/**
|
||||
* The minimum recordable value. Must be an integer value greater than 0.
|
||||
* @default 1
|
||||
*/
|
||||
lowest?: number | bigint | undefined;
|
||||
/**
|
||||
* The maximum recordable value. Must be an integer value greater than min.
|
||||
* @default Number.MAX_SAFE_INTEGER
|
||||
*/
|
||||
highest?: number | bigint | undefined;
|
||||
/**
|
||||
* The number of accuracy digits. Must be a number between 1 and 5.
|
||||
* @default 3
|
||||
*/
|
||||
figures?: number | undefined;
|
||||
}
|
||||
/**
|
||||
* Returns a `RecordableHistogram`.
|
||||
* @since v15.9.0, v14.18.0
|
||||
*/
|
||||
function createHistogram(options?: CreateHistogramOptions): RecordableHistogram;
|
||||
import {
|
||||
performance as _performance,
|
||||
PerformanceEntry as _PerformanceEntry,
|
||||
PerformanceMark as _PerformanceMark,
|
||||
PerformanceMeasure as _PerformanceMeasure,
|
||||
PerformanceObserver as _PerformanceObserver,
|
||||
PerformanceObserverEntryList as _PerformanceObserverEntryList,
|
||||
PerformanceResourceTiming as _PerformanceResourceTiming,
|
||||
} from "perf_hooks";
|
||||
global {
|
||||
/**
|
||||
* `PerformanceEntry` is a global reference for `import { PerformanceEntry } from 'node:perf_hooks'`
|
||||
* @see https://nodejs.org/docs/latest-v24.x/api/globals.html#performanceentry
|
||||
* @since v19.0.0
|
||||
*/
|
||||
var PerformanceEntry: typeof globalThis extends {
|
||||
onmessage: any;
|
||||
PerformanceEntry: infer T;
|
||||
} ? T
|
||||
: typeof _PerformanceEntry;
|
||||
/**
|
||||
* `PerformanceMark` is a global reference for `import { PerformanceMark } from 'node:perf_hooks'`
|
||||
* @see https://nodejs.org/docs/latest-v24.x/api/globals.html#performancemark
|
||||
* @since v19.0.0
|
||||
*/
|
||||
var PerformanceMark: typeof globalThis extends {
|
||||
onmessage: any;
|
||||
PerformanceMark: infer T;
|
||||
} ? T
|
||||
: typeof _PerformanceMark;
|
||||
/**
|
||||
* `PerformanceMeasure` is a global reference for `import { PerformanceMeasure } from 'node:perf_hooks'`
|
||||
* @see https://nodejs.org/docs/latest-v24.x/api/globals.html#performancemeasure
|
||||
* @since v19.0.0
|
||||
*/
|
||||
var PerformanceMeasure: typeof globalThis extends {
|
||||
onmessage: any;
|
||||
PerformanceMeasure: infer T;
|
||||
} ? T
|
||||
: typeof _PerformanceMeasure;
|
||||
/**
|
||||
* `PerformanceObserver` is a global reference for `import { PerformanceObserver } from 'node:perf_hooks'`
|
||||
* @see https://nodejs.org/docs/latest-v24.x/api/globals.html#performanceobserver
|
||||
* @since v19.0.0
|
||||
*/
|
||||
var PerformanceObserver: typeof globalThis extends {
|
||||
onmessage: any;
|
||||
PerformanceObserver: infer T;
|
||||
} ? T
|
||||
: typeof _PerformanceObserver;
|
||||
/**
|
||||
* `PerformanceObserverEntryList` is a global reference for `import { PerformanceObserverEntryList } from 'node:perf_hooks'`
|
||||
* @see https://nodejs.org/docs/latest-v24.x/api/globals.html#performanceobserverentrylist
|
||||
* @since v19.0.0
|
||||
*/
|
||||
var PerformanceObserverEntryList: typeof globalThis extends {
|
||||
onmessage: any;
|
||||
PerformanceObserverEntryList: infer T;
|
||||
} ? T
|
||||
: typeof _PerformanceObserverEntryList;
|
||||
/**
|
||||
* `PerformanceResourceTiming` is a global reference for `import { PerformanceResourceTiming } from 'node:perf_hooks'`
|
||||
* @see https://nodejs.org/docs/latest-v24.x/api/globals.html#performanceresourcetiming
|
||||
* @since v19.0.0
|
||||
*/
|
||||
var PerformanceResourceTiming: typeof globalThis extends {
|
||||
onmessage: any;
|
||||
PerformanceResourceTiming: infer T;
|
||||
} ? T
|
||||
: typeof _PerformanceResourceTiming;
|
||||
/**
|
||||
* `performance` is a global reference for `import { performance } from 'node:perf_hooks'`
|
||||
* @see https://nodejs.org/docs/latest-v24.x/api/globals.html#performance
|
||||
* @since v16.0.0
|
||||
*/
|
||||
var performance: typeof globalThis extends {
|
||||
onmessage: any;
|
||||
performance: infer T;
|
||||
} ? T
|
||||
: typeof _performance;
|
||||
}
|
||||
}
|
||||
declare module "node:perf_hooks" {
|
||||
export * from "perf_hooks";
|
||||
}
|
||||
-2089
File diff suppressed because it is too large
Load Diff
-117
@@ -1,117 +0,0 @@
|
||||
/**
|
||||
* **The version of the punycode module bundled in Node.js is being deprecated. **In a future major version of Node.js this module will be removed. Users
|
||||
* currently depending on the `punycode` module should switch to using the
|
||||
* userland-provided [Punycode.js](https://github.com/bestiejs/punycode.js) module instead. For punycode-based URL
|
||||
* encoding, see `url.domainToASCII` or, more generally, the `WHATWG URL API`.
|
||||
*
|
||||
* The `punycode` module is a bundled version of the [Punycode.js](https://github.com/bestiejs/punycode.js) module. It
|
||||
* can be accessed using:
|
||||
*
|
||||
* ```js
|
||||
* import punycode from 'node:punycode';
|
||||
* ```
|
||||
*
|
||||
* [Punycode](https://tools.ietf.org/html/rfc3492) is a character encoding scheme defined by RFC 3492 that is
|
||||
* primarily intended for use in Internationalized Domain Names. Because host
|
||||
* names in URLs are limited to ASCII characters only, Domain Names that contain
|
||||
* non-ASCII characters must be converted into ASCII using the Punycode scheme.
|
||||
* For instance, the Japanese character that translates into the English word, `'example'` is `'例'`. The Internationalized Domain Name, `'例.com'` (equivalent
|
||||
* to `'example.com'`) is represented by Punycode as the ASCII string `'xn--fsq.com'`.
|
||||
*
|
||||
* The `punycode` module provides a simple implementation of the Punycode standard.
|
||||
*
|
||||
* The `punycode` module is a third-party dependency used by Node.js and
|
||||
* made available to developers as a convenience. Fixes or other modifications to
|
||||
* the module must be directed to the [Punycode.js](https://github.com/bestiejs/punycode.js) project.
|
||||
* @deprecated Since v7.0.0 - Deprecated
|
||||
* @see [source](https://github.com/nodejs/node/blob/v24.x/lib/punycode.js)
|
||||
*/
|
||||
declare module "punycode" {
|
||||
/**
|
||||
* The `punycode.decode()` method converts a [Punycode](https://tools.ietf.org/html/rfc3492) string of ASCII-only
|
||||
* characters to the equivalent string of Unicode codepoints.
|
||||
*
|
||||
* ```js
|
||||
* punycode.decode('maana-pta'); // 'mañana'
|
||||
* punycode.decode('--dqo34k'); // '☃-⌘'
|
||||
* ```
|
||||
* @since v0.5.1
|
||||
*/
|
||||
function decode(string: string): string;
|
||||
/**
|
||||
* The `punycode.encode()` method converts a string of Unicode codepoints to a [Punycode](https://tools.ietf.org/html/rfc3492) string of ASCII-only characters.
|
||||
*
|
||||
* ```js
|
||||
* punycode.encode('mañana'); // 'maana-pta'
|
||||
* punycode.encode('☃-⌘'); // '--dqo34k'
|
||||
* ```
|
||||
* @since v0.5.1
|
||||
*/
|
||||
function encode(string: string): string;
|
||||
/**
|
||||
* The `punycode.toUnicode()` method converts a string representing a domain name
|
||||
* containing [Punycode](https://tools.ietf.org/html/rfc3492) encoded characters into Unicode. Only the [Punycode](https://tools.ietf.org/html/rfc3492) encoded parts of the domain name are be
|
||||
* converted.
|
||||
*
|
||||
* ```js
|
||||
* // decode domain names
|
||||
* punycode.toUnicode('xn--maana-pta.com'); // 'mañana.com'
|
||||
* punycode.toUnicode('xn----dqo34k.com'); // '☃-⌘.com'
|
||||
* punycode.toUnicode('example.com'); // 'example.com'
|
||||
* ```
|
||||
* @since v0.6.1
|
||||
*/
|
||||
function toUnicode(domain: string): string;
|
||||
/**
|
||||
* The `punycode.toASCII()` method converts a Unicode string representing an
|
||||
* Internationalized Domain Name to [Punycode](https://tools.ietf.org/html/rfc3492). Only the non-ASCII parts of the
|
||||
* domain name will be converted. Calling `punycode.toASCII()` on a string that
|
||||
* already only contains ASCII characters will have no effect.
|
||||
*
|
||||
* ```js
|
||||
* // encode domain names
|
||||
* punycode.toASCII('mañana.com'); // 'xn--maana-pta.com'
|
||||
* punycode.toASCII('☃-⌘.com'); // 'xn----dqo34k.com'
|
||||
* punycode.toASCII('example.com'); // 'example.com'
|
||||
* ```
|
||||
* @since v0.6.1
|
||||
*/
|
||||
function toASCII(domain: string): string;
|
||||
/**
|
||||
* @deprecated since v7.0.0
|
||||
* The version of the punycode module bundled in Node.js is being deprecated.
|
||||
* In a future major version of Node.js this module will be removed.
|
||||
* Users currently depending on the punycode module should switch to using
|
||||
* the userland-provided Punycode.js module instead.
|
||||
*/
|
||||
const ucs2: ucs2;
|
||||
interface ucs2 {
|
||||
/**
|
||||
* @deprecated since v7.0.0
|
||||
* The version of the punycode module bundled in Node.js is being deprecated.
|
||||
* In a future major version of Node.js this module will be removed.
|
||||
* Users currently depending on the punycode module should switch to using
|
||||
* the userland-provided Punycode.js module instead.
|
||||
*/
|
||||
decode(string: string): number[];
|
||||
/**
|
||||
* @deprecated since v7.0.0
|
||||
* The version of the punycode module bundled in Node.js is being deprecated.
|
||||
* In a future major version of Node.js this module will be removed.
|
||||
* Users currently depending on the punycode module should switch to using
|
||||
* the userland-provided Punycode.js module instead.
|
||||
*/
|
||||
encode(codePoints: readonly number[]): string;
|
||||
}
|
||||
/**
|
||||
* @deprecated since v7.0.0
|
||||
* The version of the punycode module bundled in Node.js is being deprecated.
|
||||
* In a future major version of Node.js this module will be removed.
|
||||
* Users currently depending on the punycode module should switch to using
|
||||
* the userland-provided Punycode.js module instead.
|
||||
*/
|
||||
const version: string;
|
||||
}
|
||||
declare module "node:punycode" {
|
||||
export * from "punycode";
|
||||
}
|
||||
-152
@@ -1,152 +0,0 @@
|
||||
/**
|
||||
* The `node:querystring` module provides utilities for parsing and formatting URL
|
||||
* query strings. It can be accessed using:
|
||||
*
|
||||
* ```js
|
||||
* import querystring from 'node:querystring';
|
||||
* ```
|
||||
*
|
||||
* `querystring` is more performant than `URLSearchParams` but is not a
|
||||
* standardized API. Use `URLSearchParams` when performance is not critical or
|
||||
* when compatibility with browser code is desirable.
|
||||
* @see [source](https://github.com/nodejs/node/blob/v24.x/lib/querystring.js)
|
||||
*/
|
||||
declare module "querystring" {
|
||||
interface StringifyOptions {
|
||||
/**
|
||||
* The function to use when converting URL-unsafe characters to percent-encoding in the query string.
|
||||
* @default `querystring.escape()`
|
||||
*/
|
||||
encodeURIComponent?: ((str: string) => string) | undefined;
|
||||
}
|
||||
interface ParseOptions {
|
||||
/**
|
||||
* Specifies the maximum number of keys to parse. Specify `0` to remove key counting limitations.
|
||||
* @default 1000
|
||||
*/
|
||||
maxKeys?: number | undefined;
|
||||
/**
|
||||
* The function to use when decoding percent-encoded characters in the query string.
|
||||
* @default `querystring.unescape()`
|
||||
*/
|
||||
decodeURIComponent?: ((str: string) => string) | undefined;
|
||||
}
|
||||
interface ParsedUrlQuery extends NodeJS.Dict<string | string[]> {}
|
||||
interface ParsedUrlQueryInput extends
|
||||
NodeJS.Dict<
|
||||
| string
|
||||
| number
|
||||
| boolean
|
||||
| bigint
|
||||
| ReadonlyArray<string | number | boolean | bigint>
|
||||
| null
|
||||
>
|
||||
{}
|
||||
/**
|
||||
* The `querystring.stringify()` method produces a URL query string from a
|
||||
* given `obj` by iterating through the object's "own properties".
|
||||
*
|
||||
* It serializes the following types of values passed in `obj`: [string](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type) |
|
||||
* [number](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type) |
|
||||
* [bigint](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) |
|
||||
* [boolean](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type) |
|
||||
* [string\[\]](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#String_type) |
|
||||
* [number\[\]](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Number_type) |
|
||||
* [bigint\[\]](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/BigInt) |
|
||||
* [boolean\[\]](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Boolean_type) The numeric values must be finite. Any other input values will be coerced to
|
||||
* empty strings.
|
||||
*
|
||||
* ```js
|
||||
* querystring.stringify({ foo: 'bar', baz: ['qux', 'quux'], corge: '' });
|
||||
* // Returns 'foo=bar&baz=qux&baz=quux&corge='
|
||||
*
|
||||
* querystring.stringify({ foo: 'bar', baz: 'qux' }, ';', ':');
|
||||
* // Returns 'foo:bar;baz:qux'
|
||||
* ```
|
||||
*
|
||||
* By default, characters requiring percent-encoding within the query string will
|
||||
* be encoded as UTF-8\. If an alternative encoding is required, then an alternative `encodeURIComponent` option will need to be specified:
|
||||
*
|
||||
* ```js
|
||||
* // Assuming gbkEncodeURIComponent function already exists,
|
||||
*
|
||||
* querystring.stringify({ w: '中文', foo: 'bar' }, null, null,
|
||||
* { encodeURIComponent: gbkEncodeURIComponent });
|
||||
* ```
|
||||
* @since v0.1.25
|
||||
* @param obj The object to serialize into a URL query string
|
||||
* @param [sep='&'] The substring used to delimit key and value pairs in the query string.
|
||||
* @param [eq='='] . The substring used to delimit keys and values in the query string.
|
||||
*/
|
||||
function stringify(obj?: ParsedUrlQueryInput, sep?: string, eq?: string, options?: StringifyOptions): string;
|
||||
/**
|
||||
* The `querystring.parse()` method parses a URL query string (`str`) into a
|
||||
* collection of key and value pairs.
|
||||
*
|
||||
* For example, the query string `'foo=bar&abc=xyz&abc=123'` is parsed into:
|
||||
*
|
||||
* ```json
|
||||
* {
|
||||
* "foo": "bar",
|
||||
* "abc": ["xyz", "123"]
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* The object returned by the `querystring.parse()` method _does not_ prototypically inherit from the JavaScript `Object`. This means that typical `Object` methods such as `obj.toString()`,
|
||||
* `obj.hasOwnProperty()`, and others
|
||||
* are not defined and _will not work_.
|
||||
*
|
||||
* By default, percent-encoded characters within the query string will be assumed
|
||||
* to use UTF-8 encoding. If an alternative character encoding is used, then an
|
||||
* alternative `decodeURIComponent` option will need to be specified:
|
||||
*
|
||||
* ```js
|
||||
* // Assuming gbkDecodeURIComponent function already exists...
|
||||
*
|
||||
* querystring.parse('w=%D6%D0%CE%C4&foo=bar', null, null,
|
||||
* { decodeURIComponent: gbkDecodeURIComponent });
|
||||
* ```
|
||||
* @since v0.1.25
|
||||
* @param str The URL query string to parse
|
||||
* @param [sep='&'] The substring used to delimit key and value pairs in the query string.
|
||||
* @param [eq='='] The substring used to delimit keys and values in the query string.
|
||||
*/
|
||||
function parse(str: string, sep?: string, eq?: string, options?: ParseOptions): ParsedUrlQuery;
|
||||
/**
|
||||
* The querystring.encode() function is an alias for querystring.stringify().
|
||||
*/
|
||||
const encode: typeof stringify;
|
||||
/**
|
||||
* The querystring.decode() function is an alias for querystring.parse().
|
||||
*/
|
||||
const decode: typeof parse;
|
||||
/**
|
||||
* The `querystring.escape()` method performs URL percent-encoding on the given `str` in a manner that is optimized for the specific requirements of URL
|
||||
* query strings.
|
||||
*
|
||||
* The `querystring.escape()` method is used by `querystring.stringify()` and is
|
||||
* generally not expected to be used directly. It is exported primarily to allow
|
||||
* application code to provide a replacement percent-encoding implementation if
|
||||
* necessary by assigning `querystring.escape` to an alternative function.
|
||||
* @since v0.1.25
|
||||
*/
|
||||
function escape(str: string): string;
|
||||
/**
|
||||
* The `querystring.unescape()` method performs decoding of URL percent-encoded
|
||||
* characters on the given `str`.
|
||||
*
|
||||
* The `querystring.unescape()` method is used by `querystring.parse()` and is
|
||||
* generally not expected to be used directly. It is exported primarily to allow
|
||||
* application code to provide a replacement decoding implementation if
|
||||
* necessary by assigning `querystring.unescape` to an alternative function.
|
||||
*
|
||||
* By default, the `querystring.unescape()` method will attempt to use the
|
||||
* JavaScript built-in `decodeURIComponent()` method to decode. If that fails,
|
||||
* a safer equivalent that does not throw on malformed URLs will be used.
|
||||
* @since v0.1.25
|
||||
*/
|
||||
function unescape(str: string): string;
|
||||
}
|
||||
declare module "node:querystring" {
|
||||
export * from "querystring";
|
||||
}
|
||||
-594
@@ -1,594 +0,0 @@
|
||||
/**
|
||||
* The `node:readline` module provides an interface for reading data from a [Readable](https://nodejs.org/docs/latest-v24.x/api/stream.html#readable-streams) stream
|
||||
* (such as [`process.stdin`](https://nodejs.org/docs/latest-v24.x/api/process.html#processstdin)) one line at a time.
|
||||
*
|
||||
* To use the promise-based APIs:
|
||||
*
|
||||
* ```js
|
||||
* import * as readline from 'node:readline/promises';
|
||||
* ```
|
||||
*
|
||||
* To use the callback and sync APIs:
|
||||
*
|
||||
* ```js
|
||||
* import * as readline from 'node:readline';
|
||||
* ```
|
||||
*
|
||||
* The following simple example illustrates the basic use of the `node:readline` module.
|
||||
*
|
||||
* ```js
|
||||
* import * as readline from 'node:readline/promises';
|
||||
* import { stdin as input, stdout as output } from 'node:process';
|
||||
*
|
||||
* const rl = readline.createInterface({ input, output });
|
||||
*
|
||||
* const answer = await rl.question('What do you think of Node.js? ');
|
||||
*
|
||||
* console.log(`Thank you for your valuable feedback: ${answer}`);
|
||||
*
|
||||
* rl.close();
|
||||
* ```
|
||||
*
|
||||
* Once this code is invoked, the Node.js application will not terminate until the `readline.Interface` is closed because the interface waits for data to be
|
||||
* received on the `input` stream.
|
||||
* @see [source](https://github.com/nodejs/node/blob/v24.x/lib/readline.js)
|
||||
*/
|
||||
declare module "readline" {
|
||||
import { Abortable, EventEmitter } from "node:events";
|
||||
import * as promises from "node:readline/promises";
|
||||
export { promises };
|
||||
export interface Key {
|
||||
sequence?: string | undefined;
|
||||
name?: string | undefined;
|
||||
ctrl?: boolean | undefined;
|
||||
meta?: boolean | undefined;
|
||||
shift?: boolean | undefined;
|
||||
}
|
||||
/**
|
||||
* Instances of the `readline.Interface` class are constructed using the `readline.createInterface()` method. Every instance is associated with a
|
||||
* single `input` [Readable](https://nodejs.org/docs/latest-v24.x/api/stream.html#readable-streams) stream and a single `output` [Writable](https://nodejs.org/docs/latest-v24.x/api/stream.html#writable-streams) stream.
|
||||
* The `output` stream is used to print prompts for user input that arrives on,
|
||||
* and is read from, the `input` stream.
|
||||
* @since v0.1.104
|
||||
*/
|
||||
export class Interface extends EventEmitter implements Disposable {
|
||||
readonly terminal: boolean;
|
||||
/**
|
||||
* The current input data being processed by node.
|
||||
*
|
||||
* This can be used when collecting input from a TTY stream to retrieve the
|
||||
* current value that has been processed thus far, prior to the `line` event
|
||||
* being emitted. Once the `line` event has been emitted, this property will
|
||||
* be an empty string.
|
||||
*
|
||||
* Be aware that modifying the value during the instance runtime may have
|
||||
* unintended consequences if `rl.cursor` is not also controlled.
|
||||
*
|
||||
* **If not using a TTY stream for input, use the `'line'` event.**
|
||||
*
|
||||
* One possible use case would be as follows:
|
||||
*
|
||||
* ```js
|
||||
* const values = ['lorem ipsum', 'dolor sit amet'];
|
||||
* const rl = readline.createInterface(process.stdin);
|
||||
* const showResults = debounce(() => {
|
||||
* console.log(
|
||||
* '\n',
|
||||
* values.filter((val) => val.startsWith(rl.line)).join(' '),
|
||||
* );
|
||||
* }, 300);
|
||||
* process.stdin.on('keypress', (c, k) => {
|
||||
* showResults();
|
||||
* });
|
||||
* ```
|
||||
* @since v0.1.98
|
||||
*/
|
||||
readonly line: string;
|
||||
/**
|
||||
* The cursor position relative to `rl.line`.
|
||||
*
|
||||
* This will track where the current cursor lands in the input string, when
|
||||
* reading input from a TTY stream. The position of cursor determines the
|
||||
* portion of the input string that will be modified as input is processed,
|
||||
* as well as the column where the terminal caret will be rendered.
|
||||
* @since v0.1.98
|
||||
*/
|
||||
readonly cursor: number;
|
||||
/**
|
||||
* NOTE: According to the documentation:
|
||||
*
|
||||
* > Instances of the `readline.Interface` class are constructed using the
|
||||
* > `readline.createInterface()` method.
|
||||
*
|
||||
* @see https://nodejs.org/dist/latest-v24.x/docs/api/readline.html#class-interfaceconstructor
|
||||
*/
|
||||
protected constructor(
|
||||
input: NodeJS.ReadableStream,
|
||||
output?: NodeJS.WritableStream,
|
||||
completer?: Completer | AsyncCompleter,
|
||||
terminal?: boolean,
|
||||
);
|
||||
/**
|
||||
* NOTE: According to the documentation:
|
||||
*
|
||||
* > Instances of the `readline.Interface` class are constructed using the
|
||||
* > `readline.createInterface()` method.
|
||||
*
|
||||
* @see https://nodejs.org/dist/latest-v24.x/docs/api/readline.html#class-interfaceconstructor
|
||||
*/
|
||||
protected constructor(options: ReadLineOptions);
|
||||
/**
|
||||
* The `rl.getPrompt()` method returns the current prompt used by `rl.prompt()`.
|
||||
* @since v15.3.0, v14.17.0
|
||||
* @return the current prompt string
|
||||
*/
|
||||
getPrompt(): string;
|
||||
/**
|
||||
* The `rl.setPrompt()` method sets the prompt that will be written to `output` whenever `rl.prompt()` is called.
|
||||
* @since v0.1.98
|
||||
*/
|
||||
setPrompt(prompt: string): void;
|
||||
/**
|
||||
* The `rl.prompt()` method writes the `Interface` instances configured`prompt` to a new line in `output` in order to provide a user with a new
|
||||
* location at which to provide input.
|
||||
*
|
||||
* When called, `rl.prompt()` will resume the `input` stream if it has been
|
||||
* paused.
|
||||
*
|
||||
* If the `Interface` was created with `output` set to `null` or `undefined` the prompt is not written.
|
||||
* @since v0.1.98
|
||||
* @param preserveCursor If `true`, prevents the cursor placement from being reset to `0`.
|
||||
*/
|
||||
prompt(preserveCursor?: boolean): void;
|
||||
/**
|
||||
* The `rl.question()` method displays the `query` by writing it to the `output`,
|
||||
* waits for user input to be provided on `input`, then invokes the `callback` function passing the provided input as the first argument.
|
||||
*
|
||||
* When called, `rl.question()` will resume the `input` stream if it has been
|
||||
* paused.
|
||||
*
|
||||
* If the `Interface` was created with `output` set to `null` or `undefined` the `query` is not written.
|
||||
*
|
||||
* The `callback` function passed to `rl.question()` does not follow the typical
|
||||
* pattern of accepting an `Error` object or `null` as the first argument.
|
||||
* The `callback` is called with the provided answer as the only argument.
|
||||
*
|
||||
* An error will be thrown if calling `rl.question()` after `rl.close()`.
|
||||
*
|
||||
* Example usage:
|
||||
*
|
||||
* ```js
|
||||
* rl.question('What is your favorite food? ', (answer) => {
|
||||
* console.log(`Oh, so your favorite food is ${answer}`);
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* Using an `AbortController` to cancel a question.
|
||||
*
|
||||
* ```js
|
||||
* const ac = new AbortController();
|
||||
* const signal = ac.signal;
|
||||
*
|
||||
* rl.question('What is your favorite food? ', { signal }, (answer) => {
|
||||
* console.log(`Oh, so your favorite food is ${answer}`);
|
||||
* });
|
||||
*
|
||||
* signal.addEventListener('abort', () => {
|
||||
* console.log('The food question timed out');
|
||||
* }, { once: true });
|
||||
*
|
||||
* setTimeout(() => ac.abort(), 10000);
|
||||
* ```
|
||||
* @since v0.3.3
|
||||
* @param query A statement or query to write to `output`, prepended to the prompt.
|
||||
* @param callback A callback function that is invoked with the user's input in response to the `query`.
|
||||
*/
|
||||
question(query: string, callback: (answer: string) => void): void;
|
||||
question(query: string, options: Abortable, callback: (answer: string) => void): void;
|
||||
/**
|
||||
* The `rl.pause()` method pauses the `input` stream, allowing it to be resumed
|
||||
* later if necessary.
|
||||
*
|
||||
* Calling `rl.pause()` does not immediately pause other events (including `'line'`) from being emitted by the `Interface` instance.
|
||||
* @since v0.3.4
|
||||
*/
|
||||
pause(): this;
|
||||
/**
|
||||
* The `rl.resume()` method resumes the `input` stream if it has been paused.
|
||||
* @since v0.3.4
|
||||
*/
|
||||
resume(): this;
|
||||
/**
|
||||
* The `rl.close()` method closes the `Interface` instance and
|
||||
* relinquishes control over the `input` and `output` streams. When called,
|
||||
* the `'close'` event will be emitted.
|
||||
*
|
||||
* Calling `rl.close()` does not immediately stop other events (including `'line'`)
|
||||
* from being emitted by the `Interface` instance.
|
||||
* @since v0.1.98
|
||||
*/
|
||||
close(): void;
|
||||
/**
|
||||
* Alias for `rl.close()`.
|
||||
* @since v22.15.0
|
||||
*/
|
||||
[Symbol.dispose](): void;
|
||||
/**
|
||||
* The `rl.write()` method will write either `data` or a key sequence identified
|
||||
* by `key` to the `output`. The `key` argument is supported only if `output` is
|
||||
* a `TTY` text terminal. See `TTY keybindings` for a list of key
|
||||
* combinations.
|
||||
*
|
||||
* If `key` is specified, `data` is ignored.
|
||||
*
|
||||
* When called, `rl.write()` will resume the `input` stream if it has been
|
||||
* paused.
|
||||
*
|
||||
* If the `Interface` was created with `output` set to `null` or `undefined` the `data` and `key` are not written.
|
||||
*
|
||||
* ```js
|
||||
* rl.write('Delete this!');
|
||||
* // Simulate Ctrl+U to delete the line written previously
|
||||
* rl.write(null, { ctrl: true, name: 'u' });
|
||||
* ```
|
||||
*
|
||||
* The `rl.write()` method will write the data to the `readline` `Interface`'s `input` _as if it were provided by the user_.
|
||||
* @since v0.1.98
|
||||
*/
|
||||
write(data: string | Buffer, key?: Key): void;
|
||||
write(data: undefined | null | string | Buffer, key: Key): void;
|
||||
/**
|
||||
* Returns the real position of the cursor in relation to the input
|
||||
* prompt + string. Long input (wrapping) strings, as well as multiple
|
||||
* line prompts are included in the calculations.
|
||||
* @since v13.5.0, v12.16.0
|
||||
*/
|
||||
getCursorPos(): CursorPos;
|
||||
/**
|
||||
* events.EventEmitter
|
||||
* 1. close
|
||||
* 2. line
|
||||
* 3. pause
|
||||
* 4. resume
|
||||
* 5. SIGCONT
|
||||
* 6. SIGINT
|
||||
* 7. SIGTSTP
|
||||
* 8. history
|
||||
*/
|
||||
addListener(event: string, listener: (...args: any[]) => void): this;
|
||||
addListener(event: "close", listener: () => void): this;
|
||||
addListener(event: "line", listener: (input: string) => void): this;
|
||||
addListener(event: "pause", listener: () => void): this;
|
||||
addListener(event: "resume", listener: () => void): this;
|
||||
addListener(event: "SIGCONT", listener: () => void): this;
|
||||
addListener(event: "SIGINT", listener: () => void): this;
|
||||
addListener(event: "SIGTSTP", listener: () => void): this;
|
||||
addListener(event: "history", listener: (history: string[]) => void): this;
|
||||
emit(event: string | symbol, ...args: any[]): boolean;
|
||||
emit(event: "close"): boolean;
|
||||
emit(event: "line", input: string): boolean;
|
||||
emit(event: "pause"): boolean;
|
||||
emit(event: "resume"): boolean;
|
||||
emit(event: "SIGCONT"): boolean;
|
||||
emit(event: "SIGINT"): boolean;
|
||||
emit(event: "SIGTSTP"): boolean;
|
||||
emit(event: "history", history: string[]): boolean;
|
||||
on(event: string, listener: (...args: any[]) => void): this;
|
||||
on(event: "close", listener: () => void): this;
|
||||
on(event: "line", listener: (input: string) => void): this;
|
||||
on(event: "pause", listener: () => void): this;
|
||||
on(event: "resume", listener: () => void): this;
|
||||
on(event: "SIGCONT", listener: () => void): this;
|
||||
on(event: "SIGINT", listener: () => void): this;
|
||||
on(event: "SIGTSTP", listener: () => void): this;
|
||||
on(event: "history", listener: (history: string[]) => void): this;
|
||||
once(event: string, listener: (...args: any[]) => void): this;
|
||||
once(event: "close", listener: () => void): this;
|
||||
once(event: "line", listener: (input: string) => void): this;
|
||||
once(event: "pause", listener: () => void): this;
|
||||
once(event: "resume", listener: () => void): this;
|
||||
once(event: "SIGCONT", listener: () => void): this;
|
||||
once(event: "SIGINT", listener: () => void): this;
|
||||
once(event: "SIGTSTP", listener: () => void): this;
|
||||
once(event: "history", listener: (history: string[]) => void): this;
|
||||
prependListener(event: string, listener: (...args: any[]) => void): this;
|
||||
prependListener(event: "close", listener: () => void): this;
|
||||
prependListener(event: "line", listener: (input: string) => void): this;
|
||||
prependListener(event: "pause", listener: () => void): this;
|
||||
prependListener(event: "resume", listener: () => void): this;
|
||||
prependListener(event: "SIGCONT", listener: () => void): this;
|
||||
prependListener(event: "SIGINT", listener: () => void): this;
|
||||
prependListener(event: "SIGTSTP", listener: () => void): this;
|
||||
prependListener(event: "history", listener: (history: string[]) => void): this;
|
||||
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
|
||||
prependOnceListener(event: "close", listener: () => void): this;
|
||||
prependOnceListener(event: "line", listener: (input: string) => void): this;
|
||||
prependOnceListener(event: "pause", listener: () => void): this;
|
||||
prependOnceListener(event: "resume", listener: () => void): this;
|
||||
prependOnceListener(event: "SIGCONT", listener: () => void): this;
|
||||
prependOnceListener(event: "SIGINT", listener: () => void): this;
|
||||
prependOnceListener(event: "SIGTSTP", listener: () => void): this;
|
||||
prependOnceListener(event: "history", listener: (history: string[]) => void): this;
|
||||
[Symbol.asyncIterator](): NodeJS.AsyncIterator<string>;
|
||||
}
|
||||
export type ReadLine = Interface; // type forwarded for backwards compatibility
|
||||
export type Completer = (line: string) => CompleterResult;
|
||||
export type AsyncCompleter = (
|
||||
line: string,
|
||||
callback: (err?: null | Error, result?: CompleterResult) => void,
|
||||
) => void;
|
||||
export type CompleterResult = [string[], string];
|
||||
export interface ReadLineOptions {
|
||||
/**
|
||||
* The [`Readable`](https://nodejs.org/docs/latest-v24.x/api/stream.html#readable-streams) stream to listen to
|
||||
*/
|
||||
input: NodeJS.ReadableStream;
|
||||
/**
|
||||
* The [`Writable`](https://nodejs.org/docs/latest-v24.x/api/stream.html#writable-streams) stream to write readline data to.
|
||||
*/
|
||||
output?: NodeJS.WritableStream | undefined;
|
||||
/**
|
||||
* An optional function used for Tab autocompletion.
|
||||
*/
|
||||
completer?: Completer | AsyncCompleter | undefined;
|
||||
/**
|
||||
* `true` if the `input` and `output` streams should be treated like a TTY,
|
||||
* and have ANSI/VT100 escape codes written to it.
|
||||
* Default: checking `isTTY` on the `output` stream upon instantiation.
|
||||
*/
|
||||
terminal?: boolean | undefined;
|
||||
/**
|
||||
* Initial list of history lines.
|
||||
* This option makes sense only if `terminal` is set to `true` by the user or by an internal `output` check,
|
||||
* otherwise the history caching mechanism is not initialized at all.
|
||||
* @default []
|
||||
*/
|
||||
history?: string[] | undefined;
|
||||
/**
|
||||
* Maximum number of history lines retained.
|
||||
* To disable the history set this value to `0`.
|
||||
* This option makes sense only if `terminal` is set to `true` by the user or by an internal `output` check,
|
||||
* otherwise the history caching mechanism is not initialized at all.
|
||||
* @default 30
|
||||
*/
|
||||
historySize?: number | undefined;
|
||||
/**
|
||||
* If `true`, when a new input line added to the history list duplicates an older one,
|
||||
* this removes the older line from the list.
|
||||
* @default false
|
||||
*/
|
||||
removeHistoryDuplicates?: boolean | undefined;
|
||||
/**
|
||||
* The prompt string to use.
|
||||
* @default "> "
|
||||
*/
|
||||
prompt?: string | undefined;
|
||||
/**
|
||||
* If the delay between `\r` and `\n` exceeds `crlfDelay` milliseconds,
|
||||
* both `\r` and `\n` will be treated as separate end-of-line input.
|
||||
* `crlfDelay` will be coerced to a number no less than `100`.
|
||||
* It can be set to `Infinity`, in which case
|
||||
* `\r` followed by `\n` will always be considered a single newline
|
||||
* (which may be reasonable for [reading files](https://nodejs.org/docs/latest-v24.x/api/readline.html#example-read-file-stream-line-by-line) with `\r\n` line delimiter).
|
||||
* @default 100
|
||||
*/
|
||||
crlfDelay?: number | undefined;
|
||||
/**
|
||||
* The duration `readline` will wait for a character
|
||||
* (when reading an ambiguous key sequence in milliseconds
|
||||
* one that can both form a complete key sequence using the input read so far
|
||||
* and can take additional input to complete a longer key sequence).
|
||||
* @default 500
|
||||
*/
|
||||
escapeCodeTimeout?: number | undefined;
|
||||
/**
|
||||
* The number of spaces a tab is equal to (minimum 1).
|
||||
* @default 8
|
||||
*/
|
||||
tabSize?: number | undefined;
|
||||
/**
|
||||
* Allows closing the interface using an AbortSignal.
|
||||
* Aborting the signal will internally call `close` on the interface.
|
||||
*/
|
||||
signal?: AbortSignal | undefined;
|
||||
}
|
||||
/**
|
||||
* The `readline.createInterface()` method creates a new `readline.Interface` instance.
|
||||
*
|
||||
* ```js
|
||||
* import readline from 'node:readline';
|
||||
* const rl = readline.createInterface({
|
||||
* input: process.stdin,
|
||||
* output: process.stdout,
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* Once the `readline.Interface` instance is created, the most common case is to
|
||||
* listen for the `'line'` event:
|
||||
*
|
||||
* ```js
|
||||
* rl.on('line', (line) => {
|
||||
* console.log(`Received: ${line}`);
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* If `terminal` is `true` for this instance then the `output` stream will get
|
||||
* the best compatibility if it defines an `output.columns` property and emits
|
||||
* a `'resize'` event on the `output` if or when the columns ever change
|
||||
* (`process.stdout` does this automatically when it is a TTY).
|
||||
*
|
||||
* When creating a `readline.Interface` using `stdin` as input, the program
|
||||
* will not terminate until it receives an [EOF character](https://en.wikipedia.org/wiki/End-of-file#EOF_character). To exit without
|
||||
* waiting for user input, call `process.stdin.unref()`.
|
||||
* @since v0.1.98
|
||||
*/
|
||||
export function createInterface(
|
||||
input: NodeJS.ReadableStream,
|
||||
output?: NodeJS.WritableStream,
|
||||
completer?: Completer | AsyncCompleter,
|
||||
terminal?: boolean,
|
||||
): Interface;
|
||||
export function createInterface(options: ReadLineOptions): Interface;
|
||||
/**
|
||||
* The `readline.emitKeypressEvents()` method causes the given `Readable` stream to begin emitting `'keypress'` events corresponding to received input.
|
||||
*
|
||||
* Optionally, `interface` specifies a `readline.Interface` instance for which
|
||||
* autocompletion is disabled when copy-pasted input is detected.
|
||||
*
|
||||
* If the `stream` is a `TTY`, then it must be in raw mode.
|
||||
*
|
||||
* This is automatically called by any readline instance on its `input` if the `input` is a terminal. Closing the `readline` instance does not stop
|
||||
* the `input` from emitting `'keypress'` events.
|
||||
*
|
||||
* ```js
|
||||
* readline.emitKeypressEvents(process.stdin);
|
||||
* if (process.stdin.isTTY)
|
||||
* process.stdin.setRawMode(true);
|
||||
* ```
|
||||
*
|
||||
* ## Example: Tiny CLI
|
||||
*
|
||||
* The following example illustrates the use of `readline.Interface` class to
|
||||
* implement a small command-line interface:
|
||||
*
|
||||
* ```js
|
||||
* import readline from 'node:readline';
|
||||
* const rl = readline.createInterface({
|
||||
* input: process.stdin,
|
||||
* output: process.stdout,
|
||||
* prompt: 'OHAI> ',
|
||||
* });
|
||||
*
|
||||
* rl.prompt();
|
||||
*
|
||||
* rl.on('line', (line) => {
|
||||
* switch (line.trim()) {
|
||||
* case 'hello':
|
||||
* console.log('world!');
|
||||
* break;
|
||||
* default:
|
||||
* console.log(`Say what? I might have heard '${line.trim()}'`);
|
||||
* break;
|
||||
* }
|
||||
* rl.prompt();
|
||||
* }).on('close', () => {
|
||||
* console.log('Have a great day!');
|
||||
* process.exit(0);
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* ## Example: Read file stream line-by-Line
|
||||
*
|
||||
* A common use case for `readline` is to consume an input file one line at a
|
||||
* time. The easiest way to do so is leveraging the `fs.ReadStream` API as
|
||||
* well as a `for await...of` loop:
|
||||
*
|
||||
* ```js
|
||||
* import fs from 'node:fs';
|
||||
* import readline from 'node:readline';
|
||||
*
|
||||
* async function processLineByLine() {
|
||||
* const fileStream = fs.createReadStream('input.txt');
|
||||
*
|
||||
* const rl = readline.createInterface({
|
||||
* input: fileStream,
|
||||
* crlfDelay: Infinity,
|
||||
* });
|
||||
* // Note: we use the crlfDelay option to recognize all instances of CR LF
|
||||
* // ('\r\n') in input.txt as a single line break.
|
||||
*
|
||||
* for await (const line of rl) {
|
||||
* // Each line in input.txt will be successively available here as `line`.
|
||||
* console.log(`Line from file: ${line}`);
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* processLineByLine();
|
||||
* ```
|
||||
*
|
||||
* Alternatively, one could use the `'line'` event:
|
||||
*
|
||||
* ```js
|
||||
* import fs from 'node:fs';
|
||||
* import readline from 'node:readline';
|
||||
*
|
||||
* const rl = readline.createInterface({
|
||||
* input: fs.createReadStream('sample.txt'),
|
||||
* crlfDelay: Infinity,
|
||||
* });
|
||||
*
|
||||
* rl.on('line', (line) => {
|
||||
* console.log(`Line from file: ${line}`);
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* Currently, `for await...of` loop can be a bit slower. If `async` / `await` flow and speed are both essential, a mixed approach can be applied:
|
||||
*
|
||||
* ```js
|
||||
* import { once } from 'node:events';
|
||||
* import { createReadStream } from 'node:fs';
|
||||
* import { createInterface } from 'node:readline';
|
||||
*
|
||||
* (async function processLineByLine() {
|
||||
* try {
|
||||
* const rl = createInterface({
|
||||
* input: createReadStream('big-file.txt'),
|
||||
* crlfDelay: Infinity,
|
||||
* });
|
||||
*
|
||||
* rl.on('line', (line) => {
|
||||
* // Process the line.
|
||||
* });
|
||||
*
|
||||
* await once(rl, 'close');
|
||||
*
|
||||
* console.log('File processed.');
|
||||
* } catch (err) {
|
||||
* console.error(err);
|
||||
* }
|
||||
* })();
|
||||
* ```
|
||||
* @since v0.7.7
|
||||
*/
|
||||
export function emitKeypressEvents(stream: NodeJS.ReadableStream, readlineInterface?: Interface): void;
|
||||
export type Direction = -1 | 0 | 1;
|
||||
export interface CursorPos {
|
||||
rows: number;
|
||||
cols: number;
|
||||
}
|
||||
/**
|
||||
* The `readline.clearLine()` method clears current line of given [TTY](https://nodejs.org/docs/latest-v24.x/api/tty.html) stream
|
||||
* in a specified direction identified by `dir`.
|
||||
* @since v0.7.7
|
||||
* @param callback Invoked once the operation completes.
|
||||
* @return `false` if `stream` wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
|
||||
*/
|
||||
export function clearLine(stream: NodeJS.WritableStream, dir: Direction, callback?: () => void): boolean;
|
||||
/**
|
||||
* The `readline.clearScreenDown()` method clears the given [TTY](https://nodejs.org/docs/latest-v24.x/api/tty.html) stream from
|
||||
* the current position of the cursor down.
|
||||
* @since v0.7.7
|
||||
* @param callback Invoked once the operation completes.
|
||||
* @return `false` if `stream` wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
|
||||
*/
|
||||
export function clearScreenDown(stream: NodeJS.WritableStream, callback?: () => void): boolean;
|
||||
/**
|
||||
* The `readline.cursorTo()` method moves cursor to the specified position in a
|
||||
* given [TTY](https://nodejs.org/docs/latest-v24.x/api/tty.html) `stream`.
|
||||
* @since v0.7.7
|
||||
* @param callback Invoked once the operation completes.
|
||||
* @return `false` if `stream` wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
|
||||
*/
|
||||
export function cursorTo(stream: NodeJS.WritableStream, x: number, y?: number, callback?: () => void): boolean;
|
||||
/**
|
||||
* The `readline.moveCursor()` method moves the cursor _relative_ to its current
|
||||
* position in a given [TTY](https://nodejs.org/docs/latest-v24.x/api/tty.html) `stream`.
|
||||
* @since v0.7.7
|
||||
* @param callback Invoked once the operation completes.
|
||||
* @return `false` if `stream` wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
|
||||
*/
|
||||
export function moveCursor(stream: NodeJS.WritableStream, dx: number, dy: number, callback?: () => void): boolean;
|
||||
}
|
||||
declare module "node:readline" {
|
||||
export * from "readline";
|
||||
}
|
||||
@@ -1,438 +0,0 @@
|
||||
/**
|
||||
* The `node:repl` module provides a Read-Eval-Print-Loop (REPL) implementation
|
||||
* that is available both as a standalone program or includible in other
|
||||
* applications. It can be accessed using:
|
||||
*
|
||||
* ```js
|
||||
* import repl from 'node:repl';
|
||||
* ```
|
||||
* @see [source](https://github.com/nodejs/node/blob/v24.x/lib/repl.js)
|
||||
*/
|
||||
declare module "repl" {
|
||||
import { AsyncCompleter, Completer, Interface } from "node:readline";
|
||||
import { Context } from "node:vm";
|
||||
import { InspectOptions } from "node:util";
|
||||
interface ReplOptions {
|
||||
/**
|
||||
* The input prompt to display.
|
||||
* @default "> "
|
||||
*/
|
||||
prompt?: string | undefined;
|
||||
/**
|
||||
* The `Readable` stream from which REPL input will be read.
|
||||
* @default process.stdin
|
||||
*/
|
||||
input?: NodeJS.ReadableStream | undefined;
|
||||
/**
|
||||
* The `Writable` stream to which REPL output will be written.
|
||||
* @default process.stdout
|
||||
*/
|
||||
output?: NodeJS.WritableStream | undefined;
|
||||
/**
|
||||
* If `true`, specifies that the output should be treated as a TTY terminal, and have
|
||||
* ANSI/VT100 escape codes written to it.
|
||||
* Default: checking the value of the `isTTY` property on the output stream upon
|
||||
* instantiation.
|
||||
*/
|
||||
terminal?: boolean | undefined;
|
||||
/**
|
||||
* The function to be used when evaluating each given line of input.
|
||||
* **Default:** an async wrapper for the JavaScript `eval()` function. An `eval` function can
|
||||
* error with `repl.Recoverable` to indicate the input was incomplete and prompt for
|
||||
* additional lines. See the [custom evaluation functions](https://nodejs.org/dist/latest-v24.x/docs/api/repl.html#custom-evaluation-functions)
|
||||
* section for more details.
|
||||
*/
|
||||
eval?: REPLEval | undefined;
|
||||
/**
|
||||
* Defines if the repl prints output previews or not.
|
||||
* @default `true` Always `false` in case `terminal` is falsy.
|
||||
*/
|
||||
preview?: boolean | undefined;
|
||||
/**
|
||||
* If `true`, specifies that the default `writer` function should include ANSI color
|
||||
* styling to REPL output. If a custom `writer` function is provided then this has no
|
||||
* effect.
|
||||
* @default the REPL instance's `terminal` value
|
||||
*/
|
||||
useColors?: boolean | undefined;
|
||||
/**
|
||||
* If `true`, specifies that the default evaluation function will use the JavaScript
|
||||
* `global` as the context as opposed to creating a new separate context for the REPL
|
||||
* instance. The node CLI REPL sets this value to `true`.
|
||||
* @default false
|
||||
*/
|
||||
useGlobal?: boolean | undefined;
|
||||
/**
|
||||
* If `true`, specifies that the default writer will not output the return value of a
|
||||
* command if it evaluates to `undefined`.
|
||||
* @default false
|
||||
*/
|
||||
ignoreUndefined?: boolean | undefined;
|
||||
/**
|
||||
* The function to invoke to format the output of each command before writing to `output`.
|
||||
* @default a wrapper for `util.inspect`
|
||||
*
|
||||
* @see https://nodejs.org/dist/latest-v24.x/docs/api/repl.html#repl_customizing_repl_output
|
||||
*/
|
||||
writer?: REPLWriter | undefined;
|
||||
/**
|
||||
* An optional function used for custom Tab auto completion.
|
||||
*
|
||||
* @see https://nodejs.org/dist/latest-v24.x/docs/api/readline.html#readline_use_of_the_completer_function
|
||||
*/
|
||||
completer?: Completer | AsyncCompleter | undefined;
|
||||
/**
|
||||
* A flag that specifies whether the default evaluator executes all JavaScript commands in
|
||||
* strict mode or default (sloppy) mode.
|
||||
* Accepted values are:
|
||||
* - `repl.REPL_MODE_SLOPPY` - evaluates expressions in sloppy mode.
|
||||
* - `repl.REPL_MODE_STRICT` - evaluates expressions in strict mode. This is equivalent to
|
||||
* prefacing every repl statement with `'use strict'`.
|
||||
*/
|
||||
replMode?: typeof REPL_MODE_SLOPPY | typeof REPL_MODE_STRICT | undefined;
|
||||
/**
|
||||
* Stop evaluating the current piece of code when `SIGINT` is received, i.e. `Ctrl+C` is
|
||||
* pressed. This cannot be used together with a custom `eval` function.
|
||||
* @default false
|
||||
*/
|
||||
breakEvalOnSigint?: boolean | undefined;
|
||||
}
|
||||
type REPLEval = (
|
||||
this: REPLServer,
|
||||
evalCmd: string,
|
||||
context: Context,
|
||||
file: string,
|
||||
cb: (err: Error | null, result: any) => void,
|
||||
) => void;
|
||||
type REPLWriter = (this: REPLServer, obj: any) => string;
|
||||
/**
|
||||
* This is the default "writer" value, if none is passed in the REPL options,
|
||||
* and it can be overridden by custom print functions.
|
||||
*/
|
||||
const writer: REPLWriter & {
|
||||
options: InspectOptions;
|
||||
};
|
||||
type REPLCommandAction = (this: REPLServer, text: string) => void;
|
||||
interface REPLCommand {
|
||||
/**
|
||||
* Help text to be displayed when `.help` is entered.
|
||||
*/
|
||||
help?: string | undefined;
|
||||
/**
|
||||
* The function to execute, optionally accepting a single string argument.
|
||||
*/
|
||||
action: REPLCommandAction;
|
||||
}
|
||||
interface REPLServerSetupHistoryOptions {
|
||||
filePath?: string | undefined;
|
||||
size?: number | undefined;
|
||||
removeHistoryDuplicates?: boolean | undefined;
|
||||
onHistoryFileLoaded?: ((err: Error | null, repl: REPLServer) => void) | undefined;
|
||||
}
|
||||
/**
|
||||
* Instances of `repl.REPLServer` are created using the {@link start} method
|
||||
* or directly using the JavaScript `new` keyword.
|
||||
*
|
||||
* ```js
|
||||
* import repl from 'node:repl';
|
||||
*
|
||||
* const options = { useColors: true };
|
||||
*
|
||||
* const firstInstance = repl.start(options);
|
||||
* const secondInstance = new repl.REPLServer(options);
|
||||
* ```
|
||||
* @since v0.1.91
|
||||
*/
|
||||
class REPLServer extends Interface {
|
||||
/**
|
||||
* The `vm.Context` provided to the `eval` function to be used for JavaScript
|
||||
* evaluation.
|
||||
*/
|
||||
readonly context: Context;
|
||||
/**
|
||||
* @deprecated since v14.3.0 - Use `input` instead.
|
||||
*/
|
||||
readonly inputStream: NodeJS.ReadableStream;
|
||||
/**
|
||||
* @deprecated since v14.3.0 - Use `output` instead.
|
||||
*/
|
||||
readonly outputStream: NodeJS.WritableStream;
|
||||
/**
|
||||
* The `Readable` stream from which REPL input will be read.
|
||||
*/
|
||||
readonly input: NodeJS.ReadableStream;
|
||||
/**
|
||||
* The `Writable` stream to which REPL output will be written.
|
||||
*/
|
||||
readonly output: NodeJS.WritableStream;
|
||||
/**
|
||||
* The commands registered via `replServer.defineCommand()`.
|
||||
*/
|
||||
readonly commands: NodeJS.ReadOnlyDict<REPLCommand>;
|
||||
/**
|
||||
* A value indicating whether the REPL is currently in "editor mode".
|
||||
*
|
||||
* @see https://nodejs.org/dist/latest-v24.x/docs/api/repl.html#repl_commands_and_special_keys
|
||||
*/
|
||||
readonly editorMode: boolean;
|
||||
/**
|
||||
* A value indicating whether the `_` variable has been assigned.
|
||||
*
|
||||
* @see https://nodejs.org/dist/latest-v24.x/docs/api/repl.html#repl_assignment_of_the_underscore_variable
|
||||
*/
|
||||
readonly underscoreAssigned: boolean;
|
||||
/**
|
||||
* The last evaluation result from the REPL (assigned to the `_` variable inside of the REPL).
|
||||
*
|
||||
* @see https://nodejs.org/dist/latest-v24.x/docs/api/repl.html#repl_assignment_of_the_underscore_variable
|
||||
*/
|
||||
readonly last: any;
|
||||
/**
|
||||
* A value indicating whether the `_error` variable has been assigned.
|
||||
*
|
||||
* @since v9.8.0
|
||||
* @see https://nodejs.org/dist/latest-v24.x/docs/api/repl.html#repl_assignment_of_the_underscore_variable
|
||||
*/
|
||||
readonly underscoreErrAssigned: boolean;
|
||||
/**
|
||||
* The last error raised inside the REPL (assigned to the `_error` variable inside of the REPL).
|
||||
*
|
||||
* @since v9.8.0
|
||||
* @see https://nodejs.org/dist/latest-v24.x/docs/api/repl.html#repl_assignment_of_the_underscore_variable
|
||||
*/
|
||||
readonly lastError: any;
|
||||
/**
|
||||
* Specified in the REPL options, this is the function to be used when evaluating each
|
||||
* given line of input. If not specified in the REPL options, this is an async wrapper
|
||||
* for the JavaScript `eval()` function.
|
||||
*/
|
||||
readonly eval: REPLEval;
|
||||
/**
|
||||
* Specified in the REPL options, this is a value indicating whether the default
|
||||
* `writer` function should include ANSI color styling to REPL output.
|
||||
*/
|
||||
readonly useColors: boolean;
|
||||
/**
|
||||
* Specified in the REPL options, this is a value indicating whether the default `eval`
|
||||
* function will use the JavaScript `global` as the context as opposed to creating a new
|
||||
* separate context for the REPL instance.
|
||||
*/
|
||||
readonly useGlobal: boolean;
|
||||
/**
|
||||
* Specified in the REPL options, this is a value indicating whether the default `writer`
|
||||
* function should output the result of a command if it evaluates to `undefined`.
|
||||
*/
|
||||
readonly ignoreUndefined: boolean;
|
||||
/**
|
||||
* Specified in the REPL options, this is the function to invoke to format the output of
|
||||
* each command before writing to `outputStream`. If not specified in the REPL options,
|
||||
* this will be a wrapper for `util.inspect`.
|
||||
*/
|
||||
readonly writer: REPLWriter;
|
||||
/**
|
||||
* Specified in the REPL options, this is the function to use for custom Tab auto-completion.
|
||||
*/
|
||||
readonly completer: Completer | AsyncCompleter;
|
||||
/**
|
||||
* Specified in the REPL options, this is a flag that specifies whether the default `eval`
|
||||
* function should execute all JavaScript commands in strict mode or default (sloppy) mode.
|
||||
* Possible values are:
|
||||
* - `repl.REPL_MODE_SLOPPY` - evaluates expressions in sloppy mode.
|
||||
* - `repl.REPL_MODE_STRICT` - evaluates expressions in strict mode. This is equivalent to
|
||||
* prefacing every repl statement with `'use strict'`.
|
||||
*/
|
||||
readonly replMode: typeof REPL_MODE_SLOPPY | typeof REPL_MODE_STRICT;
|
||||
/**
|
||||
* NOTE: According to the documentation:
|
||||
*
|
||||
* > Instances of `repl.REPLServer` are created using the `repl.start()` method and
|
||||
* > _should not_ be created directly using the JavaScript `new` keyword.
|
||||
*
|
||||
* `REPLServer` cannot be subclassed due to implementation specifics in NodeJS.
|
||||
*
|
||||
* @see https://nodejs.org/dist/latest-v24.x/docs/api/repl.html#repl_class_replserver
|
||||
*/
|
||||
private constructor();
|
||||
/**
|
||||
* The `replServer.defineCommand()` method is used to add new `.`\-prefixed commands
|
||||
* to the REPL instance. Such commands are invoked by typing a `.` followed by the `keyword`. The `cmd` is either a `Function` or an `Object` with the following
|
||||
* properties:
|
||||
*
|
||||
* The following example shows two new commands added to the REPL instance:
|
||||
*
|
||||
* ```js
|
||||
* import repl from 'node:repl';
|
||||
*
|
||||
* const replServer = repl.start({ prompt: '> ' });
|
||||
* replServer.defineCommand('sayhello', {
|
||||
* help: 'Say hello',
|
||||
* action(name) {
|
||||
* this.clearBufferedCommand();
|
||||
* console.log(`Hello, ${name}!`);
|
||||
* this.displayPrompt();
|
||||
* },
|
||||
* });
|
||||
* replServer.defineCommand('saybye', function saybye() {
|
||||
* console.log('Goodbye!');
|
||||
* this.close();
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* The new commands can then be used from within the REPL instance:
|
||||
*
|
||||
* ```console
|
||||
* > .sayhello Node.js User
|
||||
* Hello, Node.js User!
|
||||
* > .saybye
|
||||
* Goodbye!
|
||||
* ```
|
||||
* @since v0.3.0
|
||||
* @param keyword The command keyword (_without_ a leading `.` character).
|
||||
* @param cmd The function to invoke when the command is processed.
|
||||
*/
|
||||
defineCommand(keyword: string, cmd: REPLCommandAction | REPLCommand): void;
|
||||
/**
|
||||
* The `replServer.displayPrompt()` method readies the REPL instance for input
|
||||
* from the user, printing the configured `prompt` to a new line in the `output` and resuming the `input` to accept new input.
|
||||
*
|
||||
* When multi-line input is being entered, a pipe `'|'` is printed rather than the
|
||||
* 'prompt'.
|
||||
*
|
||||
* When `preserveCursor` is `true`, the cursor placement will not be reset to `0`.
|
||||
*
|
||||
* The `replServer.displayPrompt` method is primarily intended to be called from
|
||||
* within the action function for commands registered using the `replServer.defineCommand()` method.
|
||||
* @since v0.1.91
|
||||
*/
|
||||
displayPrompt(preserveCursor?: boolean): void;
|
||||
/**
|
||||
* The `replServer.clearBufferedCommand()` method clears any command that has been
|
||||
* buffered but not yet executed. This method is primarily intended to be
|
||||
* called from within the action function for commands registered using the `replServer.defineCommand()` method.
|
||||
* @since v9.0.0
|
||||
*/
|
||||
clearBufferedCommand(): void;
|
||||
/**
|
||||
* Initializes a history log file for the REPL instance. When executing the
|
||||
* Node.js binary and using the command-line REPL, a history file is initialized
|
||||
* by default. However, this is not the case when creating a REPL
|
||||
* programmatically. Use this method to initialize a history log file when working
|
||||
* with REPL instances programmatically.
|
||||
* @since v11.10.0
|
||||
* @param historyPath the path to the history file
|
||||
* @param callback called when history writes are ready or upon error
|
||||
*/
|
||||
setupHistory(historyPath: string, callback: (err: Error | null, repl: this) => void): void;
|
||||
setupHistory(
|
||||
historyConfig?: REPLServerSetupHistoryOptions,
|
||||
callback?: (err: Error | null, repl: this) => void,
|
||||
): void;
|
||||
/**
|
||||
* events.EventEmitter
|
||||
* 1. close - inherited from `readline.Interface`
|
||||
* 2. line - inherited from `readline.Interface`
|
||||
* 3. pause - inherited from `readline.Interface`
|
||||
* 4. resume - inherited from `readline.Interface`
|
||||
* 5. SIGCONT - inherited from `readline.Interface`
|
||||
* 6. SIGINT - inherited from `readline.Interface`
|
||||
* 7. SIGTSTP - inherited from `readline.Interface`
|
||||
* 8. exit
|
||||
* 9. reset
|
||||
*/
|
||||
addListener(event: string, listener: (...args: any[]) => void): this;
|
||||
addListener(event: "close", listener: () => void): this;
|
||||
addListener(event: "line", listener: (input: string) => void): this;
|
||||
addListener(event: "pause", listener: () => void): this;
|
||||
addListener(event: "resume", listener: () => void): this;
|
||||
addListener(event: "SIGCONT", listener: () => void): this;
|
||||
addListener(event: "SIGINT", listener: () => void): this;
|
||||
addListener(event: "SIGTSTP", listener: () => void): this;
|
||||
addListener(event: "exit", listener: () => void): this;
|
||||
addListener(event: "reset", listener: (context: Context) => void): this;
|
||||
emit(event: string | symbol, ...args: any[]): boolean;
|
||||
emit(event: "close"): boolean;
|
||||
emit(event: "line", input: string): boolean;
|
||||
emit(event: "pause"): boolean;
|
||||
emit(event: "resume"): boolean;
|
||||
emit(event: "SIGCONT"): boolean;
|
||||
emit(event: "SIGINT"): boolean;
|
||||
emit(event: "SIGTSTP"): boolean;
|
||||
emit(event: "exit"): boolean;
|
||||
emit(event: "reset", context: Context): boolean;
|
||||
on(event: string, listener: (...args: any[]) => void): this;
|
||||
on(event: "close", listener: () => void): this;
|
||||
on(event: "line", listener: (input: string) => void): this;
|
||||
on(event: "pause", listener: () => void): this;
|
||||
on(event: "resume", listener: () => void): this;
|
||||
on(event: "SIGCONT", listener: () => void): this;
|
||||
on(event: "SIGINT", listener: () => void): this;
|
||||
on(event: "SIGTSTP", listener: () => void): this;
|
||||
on(event: "exit", listener: () => void): this;
|
||||
on(event: "reset", listener: (context: Context) => void): this;
|
||||
once(event: string, listener: (...args: any[]) => void): this;
|
||||
once(event: "close", listener: () => void): this;
|
||||
once(event: "line", listener: (input: string) => void): this;
|
||||
once(event: "pause", listener: () => void): this;
|
||||
once(event: "resume", listener: () => void): this;
|
||||
once(event: "SIGCONT", listener: () => void): this;
|
||||
once(event: "SIGINT", listener: () => void): this;
|
||||
once(event: "SIGTSTP", listener: () => void): this;
|
||||
once(event: "exit", listener: () => void): this;
|
||||
once(event: "reset", listener: (context: Context) => void): this;
|
||||
prependListener(event: string, listener: (...args: any[]) => void): this;
|
||||
prependListener(event: "close", listener: () => void): this;
|
||||
prependListener(event: "line", listener: (input: string) => void): this;
|
||||
prependListener(event: "pause", listener: () => void): this;
|
||||
prependListener(event: "resume", listener: () => void): this;
|
||||
prependListener(event: "SIGCONT", listener: () => void): this;
|
||||
prependListener(event: "SIGINT", listener: () => void): this;
|
||||
prependListener(event: "SIGTSTP", listener: () => void): this;
|
||||
prependListener(event: "exit", listener: () => void): this;
|
||||
prependListener(event: "reset", listener: (context: Context) => void): this;
|
||||
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
|
||||
prependOnceListener(event: "close", listener: () => void): this;
|
||||
prependOnceListener(event: "line", listener: (input: string) => void): this;
|
||||
prependOnceListener(event: "pause", listener: () => void): this;
|
||||
prependOnceListener(event: "resume", listener: () => void): this;
|
||||
prependOnceListener(event: "SIGCONT", listener: () => void): this;
|
||||
prependOnceListener(event: "SIGINT", listener: () => void): this;
|
||||
prependOnceListener(event: "SIGTSTP", listener: () => void): this;
|
||||
prependOnceListener(event: "exit", listener: () => void): this;
|
||||
prependOnceListener(event: "reset", listener: (context: Context) => void): this;
|
||||
}
|
||||
/**
|
||||
* A flag passed in the REPL options. Evaluates expressions in sloppy mode.
|
||||
*/
|
||||
const REPL_MODE_SLOPPY: unique symbol;
|
||||
/**
|
||||
* A flag passed in the REPL options. Evaluates expressions in strict mode.
|
||||
* This is equivalent to prefacing every repl statement with `'use strict'`.
|
||||
*/
|
||||
const REPL_MODE_STRICT: unique symbol;
|
||||
/**
|
||||
* The `repl.start()` method creates and starts a {@link REPLServer} instance.
|
||||
*
|
||||
* If `options` is a string, then it specifies the input prompt:
|
||||
*
|
||||
* ```js
|
||||
* import repl from 'node:repl';
|
||||
*
|
||||
* // a Unix style prompt
|
||||
* repl.start('$ ');
|
||||
* ```
|
||||
* @since v0.1.91
|
||||
*/
|
||||
function start(options?: string | ReplOptions): REPLServer;
|
||||
/**
|
||||
* Indicates a recoverable error that a `REPLServer` can use to support multi-line input.
|
||||
*
|
||||
* @see https://nodejs.org/dist/latest-v24.x/docs/api/repl.html#repl_recoverable_errors
|
||||
*/
|
||||
class Recoverable extends SyntaxError {
|
||||
err: Error;
|
||||
constructor(err: Error);
|
||||
}
|
||||
}
|
||||
declare module "node:repl" {
|
||||
export * from "repl";
|
||||
}
|
||||
@@ -1,153 +0,0 @@
|
||||
/**
|
||||
* This feature allows the distribution of a Node.js application conveniently to a
|
||||
* system that does not have Node.js installed.
|
||||
*
|
||||
* Node.js supports the creation of [single executable applications](https://github.com/nodejs/single-executable) by allowing
|
||||
* the injection of a blob prepared by Node.js, which can contain a bundled script,
|
||||
* into the `node` binary. During start up, the program checks if anything has been
|
||||
* injected. If the blob is found, it executes the script in the blob. Otherwise
|
||||
* Node.js operates as it normally does.
|
||||
*
|
||||
* The single executable application feature currently only supports running a
|
||||
* single embedded script using the `CommonJS` module system.
|
||||
*
|
||||
* Users can create a single executable application from their bundled script
|
||||
* with the `node` binary itself and any tool which can inject resources into the
|
||||
* binary.
|
||||
*
|
||||
* Here are the steps for creating a single executable application using one such
|
||||
* tool, [postject](https://github.com/nodejs/postject):
|
||||
*
|
||||
* 1. Create a JavaScript file:
|
||||
* ```bash
|
||||
* echo 'console.log(`Hello, ${process.argv[2]}!`);' > hello.js
|
||||
* ```
|
||||
* 2. Create a configuration file building a blob that can be injected into the
|
||||
* single executable application (see `Generating single executable preparation blobs` for details):
|
||||
* ```bash
|
||||
* echo '{ "main": "hello.js", "output": "sea-prep.blob" }' > sea-config.json
|
||||
* ```
|
||||
* 3. Generate the blob to be injected:
|
||||
* ```bash
|
||||
* node --experimental-sea-config sea-config.json
|
||||
* ```
|
||||
* 4. Create a copy of the `node` executable and name it according to your needs:
|
||||
* * On systems other than Windows:
|
||||
* ```bash
|
||||
* cp $(command -v node) hello
|
||||
* ```
|
||||
* * On Windows:
|
||||
* ```text
|
||||
* node -e "require('fs').copyFileSync(process.execPath, 'hello.exe')"
|
||||
* ```
|
||||
* The `.exe` extension is necessary.
|
||||
* 5. Remove the signature of the binary (macOS and Windows only):
|
||||
* * On macOS:
|
||||
* ```bash
|
||||
* codesign --remove-signature hello
|
||||
* ```
|
||||
* * On Windows (optional):
|
||||
* [signtool](https://learn.microsoft.com/en-us/windows/win32/seccrypto/signtool) can be used from the installed [Windows SDK](https://developer.microsoft.com/en-us/windows/downloads/windows-sdk/).
|
||||
* If this step is
|
||||
* skipped, ignore any signature-related warning from postject.
|
||||
* ```powershell
|
||||
* signtool remove /s hello.exe
|
||||
* ```
|
||||
* 6. Inject the blob into the copied binary by running `postject` with
|
||||
* the following options:
|
||||
* * `hello` / `hello.exe` \- The name of the copy of the `node` executable
|
||||
* created in step 4.
|
||||
* * `NODE_SEA_BLOB` \- The name of the resource / note / section in the binary
|
||||
* where the contents of the blob will be stored.
|
||||
* * `sea-prep.blob` \- The name of the blob created in step 1.
|
||||
* * `--sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2` \- The [fuse](https://www.electronjs.org/docs/latest/tutorial/fuses) used by the Node.js project to detect if a file has been
|
||||
* injected.
|
||||
* * `--macho-segment-name NODE_SEA` (only needed on macOS) - The name of the
|
||||
* segment in the binary where the contents of the blob will be
|
||||
* stored.
|
||||
* To summarize, here is the required command for each platform:
|
||||
* * On Linux:
|
||||
* ```bash
|
||||
* npx postject hello NODE_SEA_BLOB sea-prep.blob \
|
||||
* --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2
|
||||
* ```
|
||||
* * On Windows - PowerShell:
|
||||
* ```powershell
|
||||
* npx postject hello.exe NODE_SEA_BLOB sea-prep.blob `
|
||||
* --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2
|
||||
* ```
|
||||
* * On Windows - Command Prompt:
|
||||
* ```text
|
||||
* npx postject hello.exe NODE_SEA_BLOB sea-prep.blob ^
|
||||
* --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2
|
||||
* ```
|
||||
* * On macOS:
|
||||
* ```bash
|
||||
* npx postject hello NODE_SEA_BLOB sea-prep.blob \
|
||||
* --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 \
|
||||
* --macho-segment-name NODE_SEA
|
||||
* ```
|
||||
* 7. Sign the binary (macOS and Windows only):
|
||||
* * On macOS:
|
||||
* ```bash
|
||||
* codesign --sign - hello
|
||||
* ```
|
||||
* * On Windows (optional):
|
||||
* A certificate needs to be present for this to work. However, the unsigned
|
||||
* binary would still be runnable.
|
||||
* ```powershell
|
||||
* signtool sign /fd SHA256 hello.exe
|
||||
* ```
|
||||
* 8. Run the binary:
|
||||
* * On systems other than Windows
|
||||
* ```console
|
||||
* $ ./hello world
|
||||
* Hello, world!
|
||||
* ```
|
||||
* * On Windows
|
||||
* ```console
|
||||
* $ .\hello.exe world
|
||||
* Hello, world!
|
||||
* ```
|
||||
* @since v19.7.0, v18.16.0
|
||||
* @experimental
|
||||
* @see [source](https://github.com/nodejs/node/blob/v24.x/src/node_sea.cc)
|
||||
*/
|
||||
declare module "node:sea" {
|
||||
type AssetKey = string;
|
||||
/**
|
||||
* @since v20.12.0
|
||||
* @return Whether this script is running inside a single-executable application.
|
||||
*/
|
||||
function isSea(): boolean;
|
||||
/**
|
||||
* This method can be used to retrieve the assets configured to be bundled into the
|
||||
* single-executable application at build time.
|
||||
* An error is thrown when no matching asset can be found.
|
||||
* @since v20.12.0
|
||||
*/
|
||||
function getAsset(key: AssetKey): ArrayBuffer;
|
||||
function getAsset(key: AssetKey, encoding: string): string;
|
||||
/**
|
||||
* Similar to `sea.getAsset()`, but returns the result in a [`Blob`](https://developer.mozilla.org/en-US/docs/Web/API/Blob).
|
||||
* An error is thrown when no matching asset can be found.
|
||||
* @since v20.12.0
|
||||
*/
|
||||
function getAssetAsBlob(key: AssetKey, options?: {
|
||||
type: string;
|
||||
}): Blob;
|
||||
/**
|
||||
* This method can be used to retrieve the assets configured to be bundled into the
|
||||
* single-executable application at build time.
|
||||
* An error is thrown when no matching asset can be found.
|
||||
*
|
||||
* Unlike `sea.getRawAsset()` or `sea.getAssetAsBlob()`, this method does not
|
||||
* return a copy. Instead, it returns the raw asset bundled inside the executable.
|
||||
*
|
||||
* For now, users should avoid writing to the returned array buffer. If the
|
||||
* injected section is not marked as writable or not aligned properly,
|
||||
* writes to the returned array buffer is likely to result in a crash.
|
||||
* @since v20.12.0
|
||||
*/
|
||||
function getRawAsset(key: AssetKey): ArrayBuffer;
|
||||
}
|
||||
-687
@@ -1,687 +0,0 @@
|
||||
/**
|
||||
* The `node:sqlite` module facilitates working with SQLite databases.
|
||||
* To access it:
|
||||
*
|
||||
* ```js
|
||||
* import sqlite from 'node:sqlite';
|
||||
* ```
|
||||
*
|
||||
* This module is only available under the `node:` scheme. The following will not
|
||||
* work:
|
||||
*
|
||||
* ```js
|
||||
* import sqlite from 'sqlite';
|
||||
* ```
|
||||
*
|
||||
* The following example shows the basic usage of the `node:sqlite` module to open
|
||||
* an in-memory database, write data to the database, and then read the data back.
|
||||
*
|
||||
* ```js
|
||||
* import { DatabaseSync } from 'node:sqlite';
|
||||
* const database = new DatabaseSync(':memory:');
|
||||
*
|
||||
* // Execute SQL statements from strings.
|
||||
* database.exec(`
|
||||
* CREATE TABLE data(
|
||||
* key INTEGER PRIMARY KEY,
|
||||
* value TEXT
|
||||
* ) STRICT
|
||||
* `);
|
||||
* // Create a prepared statement to insert data into the database.
|
||||
* const insert = database.prepare('INSERT INTO data (key, value) VALUES (?, ?)');
|
||||
* // Execute the prepared statement with bound values.
|
||||
* insert.run(1, 'hello');
|
||||
* insert.run(2, 'world');
|
||||
* // Create a prepared statement to read data from the database.
|
||||
* const query = database.prepare('SELECT * FROM data ORDER BY key');
|
||||
* // Execute the prepared statement and log the result set.
|
||||
* console.log(query.all());
|
||||
* // Prints: [ { key: 1, value: 'hello' }, { key: 2, value: 'world' } ]
|
||||
* ```
|
||||
* @since v22.5.0
|
||||
* @experimental
|
||||
* @see [source](https://github.com/nodejs/node/blob/v24.x/lib/sqlite.js)
|
||||
*/
|
||||
declare module "node:sqlite" {
|
||||
type SQLInputValue = null | number | bigint | string | NodeJS.ArrayBufferView;
|
||||
type SQLOutputValue = null | number | bigint | string | Uint8Array;
|
||||
/** @deprecated Use `SQLInputValue` or `SQLOutputValue` instead. */
|
||||
type SupportedValueType = SQLOutputValue;
|
||||
interface DatabaseSyncOptions {
|
||||
/**
|
||||
* If `true`, the database is opened by the constructor. When
|
||||
* this value is `false`, the database must be opened via the `open()` method.
|
||||
* @since v22.5.0
|
||||
* @default true
|
||||
*/
|
||||
open?: boolean | undefined;
|
||||
/**
|
||||
* If `true`, foreign key constraints
|
||||
* are enabled. This is recommended but can be disabled for compatibility with
|
||||
* legacy database schemas. The enforcement of foreign key constraints can be
|
||||
* enabled and disabled after opening the database using
|
||||
* [`PRAGMA foreign_keys`](https://www.sqlite.org/pragma.html#pragma_foreign_keys).
|
||||
* @since v22.10.0
|
||||
* @default true
|
||||
*/
|
||||
enableForeignKeyConstraints?: boolean | undefined;
|
||||
/**
|
||||
* If `true`, SQLite will accept
|
||||
* [double-quoted string literals](https://www.sqlite.org/quirks.html#dblquote).
|
||||
* This is not recommended but can be
|
||||
* enabled for compatibility with legacy database schemas.
|
||||
* @since v22.10.0
|
||||
* @default false
|
||||
*/
|
||||
enableDoubleQuotedStringLiterals?: boolean | undefined;
|
||||
/**
|
||||
* If `true`, the database is opened in read-only mode.
|
||||
* If the database does not exist, opening it will fail.
|
||||
* @since v22.12.0
|
||||
* @default false
|
||||
*/
|
||||
readOnly?: boolean | undefined;
|
||||
/**
|
||||
* If `true`, the `loadExtension` SQL function
|
||||
* and the `loadExtension()` method are enabled.
|
||||
* You can call `enableLoadExtension(false)` later to disable this feature.
|
||||
* @since v22.13.0
|
||||
* @default false
|
||||
*/
|
||||
allowExtension?: boolean | undefined;
|
||||
/**
|
||||
* The [busy timeout](https://sqlite.org/c3ref/busy_timeout.html) in milliseconds. This is the maximum amount of
|
||||
* time that SQLite will wait for a database lock to be released before
|
||||
* returning an error.
|
||||
* @since v24.0.0
|
||||
* @default 0
|
||||
*/
|
||||
timeout?: number | undefined;
|
||||
}
|
||||
interface CreateSessionOptions {
|
||||
/**
|
||||
* A specific table to track changes for. By default, changes to all tables are tracked.
|
||||
* @since v22.12.0
|
||||
*/
|
||||
table?: string | undefined;
|
||||
/**
|
||||
* Name of the database to track. This is useful when multiple databases have been added using
|
||||
* [`ATTACH DATABASE`](https://www.sqlite.org/lang_attach.html).
|
||||
* @since v22.12.0
|
||||
* @default 'main'
|
||||
*/
|
||||
db?: string | undefined;
|
||||
}
|
||||
interface ApplyChangesetOptions {
|
||||
/**
|
||||
* Skip changes that, when targeted table name is supplied to this function, return a truthy value.
|
||||
* By default, all changes are attempted.
|
||||
* @since v22.12.0
|
||||
*/
|
||||
filter?: ((tableName: string) => boolean) | undefined;
|
||||
/**
|
||||
* A function that determines how to handle conflicts. The function receives one argument,
|
||||
* which can be one of the following values:
|
||||
*
|
||||
* * `SQLITE_CHANGESET_DATA`: A `DELETE` or `UPDATE` change does not contain the expected "before" values.
|
||||
* * `SQLITE_CHANGESET_NOTFOUND`: A row matching the primary key of the `DELETE` or `UPDATE` change does not exist.
|
||||
* * `SQLITE_CHANGESET_CONFLICT`: An `INSERT` change results in a duplicate primary key.
|
||||
* * `SQLITE_CHANGESET_FOREIGN_KEY`: Applying a change would result in a foreign key violation.
|
||||
* * `SQLITE_CHANGESET_CONSTRAINT`: Applying a change results in a `UNIQUE`, `CHECK`, or `NOT NULL` constraint
|
||||
* violation.
|
||||
*
|
||||
* The function should return one of the following values:
|
||||
*
|
||||
* * `SQLITE_CHANGESET_OMIT`: Omit conflicting changes.
|
||||
* * `SQLITE_CHANGESET_REPLACE`: Replace existing values with conflicting changes (only valid with
|
||||
`SQLITE_CHANGESET_DATA` or `SQLITE_CHANGESET_CONFLICT` conflicts).
|
||||
* * `SQLITE_CHANGESET_ABORT`: Abort on conflict and roll back the database.
|
||||
*
|
||||
* When an error is thrown in the conflict handler or when any other value is returned from the handler,
|
||||
* applying the changeset is aborted and the database is rolled back.
|
||||
*
|
||||
* **Default**: A function that returns `SQLITE_CHANGESET_ABORT`.
|
||||
* @since v22.12.0
|
||||
*/
|
||||
onConflict?: ((conflictType: number) => number) | undefined;
|
||||
}
|
||||
interface FunctionOptions {
|
||||
/**
|
||||
* If `true`, the [`SQLITE_DETERMINISTIC`](https://www.sqlite.org/c3ref/c_deterministic.html) flag is
|
||||
* set on the created function.
|
||||
* @default false
|
||||
*/
|
||||
deterministic?: boolean | undefined;
|
||||
/**
|
||||
* If `true`, the [`SQLITE_DIRECTONLY`](https://www.sqlite.org/c3ref/c_directonly.html) flag is set on
|
||||
* the created function.
|
||||
* @default false
|
||||
*/
|
||||
directOnly?: boolean | undefined;
|
||||
/**
|
||||
* If `true`, integer arguments to `function`
|
||||
* are converted to `BigInt`s. If `false`, integer arguments are passed as
|
||||
* JavaScript numbers.
|
||||
* @default false
|
||||
*/
|
||||
useBigIntArguments?: boolean | undefined;
|
||||
/**
|
||||
* If `true`, `function` may be invoked with any number of
|
||||
* arguments (between zero and
|
||||
* [`SQLITE_MAX_FUNCTION_ARG`](https://www.sqlite.org/limits.html#max_function_arg)). If `false`,
|
||||
* `function` must be invoked with exactly `function.length` arguments.
|
||||
* @default false
|
||||
*/
|
||||
varargs?: boolean | undefined;
|
||||
}
|
||||
interface AggregateOptions<T extends SQLInputValue = SQLInputValue> extends FunctionOptions {
|
||||
/**
|
||||
* The identity value for the aggregation function. This value is used when the aggregation
|
||||
* function is initialized. When a `Function` is passed the identity will be its return value.
|
||||
*/
|
||||
start: T | (() => T);
|
||||
/**
|
||||
* The function to call for each row in the aggregation. The
|
||||
* function receives the current state and the row value. The return value of
|
||||
* this function should be the new state.
|
||||
*/
|
||||
step: (accumulator: T, ...args: SQLOutputValue[]) => T;
|
||||
/**
|
||||
* The function to call to get the result of the
|
||||
* aggregation. The function receives the final state and should return the
|
||||
* result of the aggregation.
|
||||
*/
|
||||
result?: ((accumulator: T) => SQLInputValue) | undefined;
|
||||
/**
|
||||
* When this function is provided, the `aggregate` method will work as a window function.
|
||||
* The function receives the current state and the dropped row value. The return value of this function should be the
|
||||
* new state.
|
||||
*/
|
||||
inverse?: ((accumulator: T, ...args: SQLOutputValue[]) => T) | undefined;
|
||||
}
|
||||
/**
|
||||
* This class represents a single [connection](https://www.sqlite.org/c3ref/sqlite3.html) to a SQLite database. All APIs
|
||||
* exposed by this class execute synchronously.
|
||||
* @since v22.5.0
|
||||
*/
|
||||
class DatabaseSync implements Disposable {
|
||||
/**
|
||||
* Constructs a new `DatabaseSync` instance.
|
||||
* @param path The path of the database.
|
||||
* A SQLite database can be stored in a file or completely [in memory](https://www.sqlite.org/inmemorydb.html).
|
||||
* To use a file-backed database, the path should be a file path.
|
||||
* To use an in-memory database, the path should be the special name `':memory:'`.
|
||||
* @param options Configuration options for the database connection.
|
||||
*/
|
||||
constructor(path: string | Buffer | URL, options?: DatabaseSyncOptions);
|
||||
/**
|
||||
* Registers a new aggregate function with the SQLite database. This method is a wrapper around
|
||||
* [`sqlite3_create_window_function()`](https://www.sqlite.org/c3ref/create_function.html).
|
||||
*
|
||||
* When used as a window function, the `result` function will be called multiple times.
|
||||
*
|
||||
* ```js
|
||||
* import { DatabaseSync } from 'node:sqlite';
|
||||
*
|
||||
* const db = new DatabaseSync(':memory:');
|
||||
* db.exec(`
|
||||
* CREATE TABLE t3(x, y);
|
||||
* INSERT INTO t3 VALUES ('a', 4),
|
||||
* ('b', 5),
|
||||
* ('c', 3),
|
||||
* ('d', 8),
|
||||
* ('e', 1);
|
||||
* `);
|
||||
*
|
||||
* db.aggregate('sumint', {
|
||||
* start: 0,
|
||||
* step: (acc, value) => acc + value,
|
||||
* });
|
||||
*
|
||||
* db.prepare('SELECT sumint(y) as total FROM t3').get(); // { total: 21 }
|
||||
* ```
|
||||
* @since v24.0.0
|
||||
* @param name The name of the SQLite function to create.
|
||||
* @param options Function configuration settings.
|
||||
*/
|
||||
aggregate(name: string, options: AggregateOptions): void;
|
||||
aggregate<T extends SQLInputValue>(name: string, options: AggregateOptions<T>): void;
|
||||
/**
|
||||
* Closes the database connection. An exception is thrown if the database is not
|
||||
* open. This method is a wrapper around [`sqlite3_close_v2()`](https://www.sqlite.org/c3ref/close.html).
|
||||
* @since v22.5.0
|
||||
*/
|
||||
close(): void;
|
||||
/**
|
||||
* Loads a shared library into the database connection. This method is a wrapper
|
||||
* around [`sqlite3_load_extension()`](https://www.sqlite.org/c3ref/load_extension.html). It is required to enable the
|
||||
* `allowExtension` option when constructing the `DatabaseSync` instance.
|
||||
* @since v22.13.0
|
||||
* @param path The path to the shared library to load.
|
||||
*/
|
||||
loadExtension(path: string): void;
|
||||
/**
|
||||
* Enables or disables the `loadExtension` SQL function, and the `loadExtension()`
|
||||
* method. When `allowExtension` is `false` when constructing, you cannot enable
|
||||
* loading extensions for security reasons.
|
||||
* @since v22.13.0
|
||||
* @param allow Whether to allow loading extensions.
|
||||
*/
|
||||
enableLoadExtension(allow: boolean): void;
|
||||
/**
|
||||
* This method is a wrapper around [`sqlite3_db_filename()`](https://sqlite.org/c3ref/db_filename.html)
|
||||
* @since v24.0.0
|
||||
* @param dbName Name of the database. This can be `'main'` (the default primary database) or any other
|
||||
* database that has been added with [`ATTACH DATABASE`](https://www.sqlite.org/lang_attach.html) **Default:** `'main'`.
|
||||
* @returns The location of the database file. When using an in-memory database,
|
||||
* this method returns null.
|
||||
*/
|
||||
location(dbName?: string): string | null;
|
||||
/**
|
||||
* This method allows one or more SQL statements to be executed without returning
|
||||
* any results. This method is useful when executing SQL statements read from a
|
||||
* file. This method is a wrapper around [`sqlite3_exec()`](https://www.sqlite.org/c3ref/exec.html).
|
||||
* @since v22.5.0
|
||||
* @param sql A SQL string to execute.
|
||||
*/
|
||||
exec(sql: string): void;
|
||||
/**
|
||||
* This method is used to create SQLite user-defined functions. This method is a
|
||||
* wrapper around [`sqlite3_create_function_v2()`](https://www.sqlite.org/c3ref/create_function.html).
|
||||
* @since v22.13.0
|
||||
* @param name The name of the SQLite function to create.
|
||||
* @param options Optional configuration settings for the function.
|
||||
* @param func The JavaScript function to call when the SQLite
|
||||
* function is invoked. The return value of this function should be a valid
|
||||
* SQLite data type: see
|
||||
* [Type conversion between JavaScript and SQLite](https://nodejs.org/docs/latest-v24.x/api/sqlite.html#type-conversion-between-javascript-and-sqlite).
|
||||
* The result defaults to `NULL` if the return value is `undefined`.
|
||||
*/
|
||||
function(
|
||||
name: string,
|
||||
options: FunctionOptions,
|
||||
func: (...args: SQLOutputValue[]) => SQLInputValue,
|
||||
): void;
|
||||
function(name: string, func: (...args: SQLOutputValue[]) => SQLInputValue): void;
|
||||
/**
|
||||
* Whether the database is currently open or not.
|
||||
* @since v22.15.0
|
||||
*/
|
||||
readonly isOpen: boolean;
|
||||
/**
|
||||
* Whether the database is currently within a transaction. This method
|
||||
* is a wrapper around [`sqlite3_get_autocommit()`](https://sqlite.org/c3ref/get_autocommit.html).
|
||||
* @since v24.0.0
|
||||
*/
|
||||
readonly isTransaction: boolean;
|
||||
/**
|
||||
* Opens the database specified in the `path` argument of the `DatabaseSync`constructor. This method should only be used when the database is not opened via
|
||||
* the constructor. An exception is thrown if the database is already open.
|
||||
* @since v22.5.0
|
||||
*/
|
||||
open(): void;
|
||||
/**
|
||||
* Compiles a SQL statement into a [prepared statement](https://www.sqlite.org/c3ref/stmt.html). This method is a wrapper
|
||||
* around [`sqlite3_prepare_v2()`](https://www.sqlite.org/c3ref/prepare.html).
|
||||
* @since v22.5.0
|
||||
* @param sql A SQL string to compile to a prepared statement.
|
||||
* @return The prepared statement.
|
||||
*/
|
||||
prepare(sql: string): StatementSync;
|
||||
/**
|
||||
* Creates and attaches a session to the database. This method is a wrapper around
|
||||
* [`sqlite3session_create()`](https://www.sqlite.org/session/sqlite3session_create.html) and
|
||||
* [`sqlite3session_attach()`](https://www.sqlite.org/session/sqlite3session_attach.html).
|
||||
* @param options The configuration options for the session.
|
||||
* @returns A session handle.
|
||||
* @since v22.12.0
|
||||
*/
|
||||
createSession(options?: CreateSessionOptions): Session;
|
||||
/**
|
||||
* An exception is thrown if the database is not
|
||||
* open. This method is a wrapper around
|
||||
* [`sqlite3changeset_apply()`](https://www.sqlite.org/session/sqlite3changeset_apply.html).
|
||||
*
|
||||
* ```js
|
||||
* const sourceDb = new DatabaseSync(':memory:');
|
||||
* const targetDb = new DatabaseSync(':memory:');
|
||||
*
|
||||
* sourceDb.exec('CREATE TABLE data(key INTEGER PRIMARY KEY, value TEXT)');
|
||||
* targetDb.exec('CREATE TABLE data(key INTEGER PRIMARY KEY, value TEXT)');
|
||||
*
|
||||
* const session = sourceDb.createSession();
|
||||
*
|
||||
* const insert = sourceDb.prepare('INSERT INTO data (key, value) VALUES (?, ?)');
|
||||
* insert.run(1, 'hello');
|
||||
* insert.run(2, 'world');
|
||||
*
|
||||
* const changeset = session.changeset();
|
||||
* targetDb.applyChangeset(changeset);
|
||||
* // Now that the changeset has been applied, targetDb contains the same data as sourceDb.
|
||||
* ```
|
||||
* @param changeset A binary changeset or patchset.
|
||||
* @param options The configuration options for how the changes will be applied.
|
||||
* @returns Whether the changeset was applied successfully without being aborted.
|
||||
* @since v22.12.0
|
||||
*/
|
||||
applyChangeset(changeset: Uint8Array, options?: ApplyChangesetOptions): boolean;
|
||||
/**
|
||||
* Closes the database connection. If the database connection is already closed
|
||||
* then this is a no-op.
|
||||
* @since v22.15.0
|
||||
*/
|
||||
[Symbol.dispose](): void;
|
||||
}
|
||||
/**
|
||||
* @since v22.12.0
|
||||
*/
|
||||
interface Session {
|
||||
/**
|
||||
* Retrieves a changeset containing all changes since the changeset was created. Can be called multiple times.
|
||||
* An exception is thrown if the database or the session is not open. This method is a wrapper around
|
||||
* [`sqlite3session_changeset()`](https://www.sqlite.org/session/sqlite3session_changeset.html).
|
||||
* @returns Binary changeset that can be applied to other databases.
|
||||
* @since v22.12.0
|
||||
*/
|
||||
changeset(): Uint8Array;
|
||||
/**
|
||||
* Similar to the method above, but generates a more compact patchset. See
|
||||
* [Changesets and Patchsets](https://www.sqlite.org/sessionintro.html#changesets_and_patchsets)
|
||||
* in the documentation of SQLite. An exception is thrown if the database or the session is not open. This method is a
|
||||
* wrapper around
|
||||
* [`sqlite3session_patchset()`](https://www.sqlite.org/session/sqlite3session_patchset.html).
|
||||
* @returns Binary patchset that can be applied to other databases.
|
||||
* @since v22.12.0
|
||||
*/
|
||||
patchset(): Uint8Array;
|
||||
/**
|
||||
* Closes the session. An exception is thrown if the database or the session is not open. This method is a
|
||||
* wrapper around
|
||||
* [`sqlite3session_delete()`](https://www.sqlite.org/session/sqlite3session_delete.html).
|
||||
*/
|
||||
close(): void;
|
||||
}
|
||||
interface StatementColumnMetadata {
|
||||
/**
|
||||
* The unaliased name of the column in the origin
|
||||
* table, or `null` if the column is the result of an expression or subquery.
|
||||
* This property is the result of [`sqlite3_column_origin_name()`](https://www.sqlite.org/c3ref/column_database_name.html).
|
||||
*/
|
||||
column: string | null;
|
||||
/**
|
||||
* The unaliased name of the origin database, or
|
||||
* `null` if the column is the result of an expression or subquery. This
|
||||
* property is the result of [`sqlite3_column_database_name()`](https://www.sqlite.org/c3ref/column_database_name.html).
|
||||
*/
|
||||
database: string | null;
|
||||
/**
|
||||
* The name assigned to the column in the result set of a
|
||||
* `SELECT` statement. This property is the result of
|
||||
* [`sqlite3_column_name()`](https://www.sqlite.org/c3ref/column_name.html).
|
||||
*/
|
||||
name: string;
|
||||
/**
|
||||
* The unaliased name of the origin table, or `null` if
|
||||
* the column is the result of an expression or subquery. This property is the
|
||||
* result of [`sqlite3_column_table_name()`](https://www.sqlite.org/c3ref/column_database_name.html).
|
||||
*/
|
||||
table: string | null;
|
||||
/**
|
||||
* The declared data type of the column, or `null` if the
|
||||
* column is the result of an expression or subquery. This property is the
|
||||
* result of [`sqlite3_column_decltype()`](https://www.sqlite.org/c3ref/column_decltype.html).
|
||||
*/
|
||||
type: string | null;
|
||||
}
|
||||
interface StatementResultingChanges {
|
||||
/**
|
||||
* The number of rows modified, inserted, or deleted by the most recently completed `INSERT`, `UPDATE`, or `DELETE` statement.
|
||||
* This field is either a number or a `BigInt` depending on the prepared statement's configuration.
|
||||
* This property is the result of [`sqlite3_changes64()`](https://www.sqlite.org/c3ref/changes.html).
|
||||
*/
|
||||
changes: number | bigint;
|
||||
/**
|
||||
* The most recently inserted rowid.
|
||||
* This field is either a number or a `BigInt` depending on the prepared statement's configuration.
|
||||
* This property is the result of [`sqlite3_last_insert_rowid()`](https://www.sqlite.org/c3ref/last_insert_rowid.html).
|
||||
*/
|
||||
lastInsertRowid: number | bigint;
|
||||
}
|
||||
/**
|
||||
* This class represents a single [prepared statement](https://www.sqlite.org/c3ref/stmt.html). This class cannot be
|
||||
* instantiated via its constructor. Instead, instances are created via the`database.prepare()` method. All APIs exposed by this class execute
|
||||
* synchronously.
|
||||
*
|
||||
* A prepared statement is an efficient binary representation of the SQL used to
|
||||
* create it. Prepared statements are parameterizable, and can be invoked multiple
|
||||
* times with different bound values. Parameters also offer protection against [SQL injection](https://en.wikipedia.org/wiki/SQL_injection) attacks. For these reasons, prepared statements are
|
||||
* preferred
|
||||
* over hand-crafted SQL strings when handling user input.
|
||||
* @since v22.5.0
|
||||
*/
|
||||
class StatementSync {
|
||||
private constructor();
|
||||
/**
|
||||
* This method executes a prepared statement and returns all results as an array of
|
||||
* objects. If the prepared statement does not return any results, this method
|
||||
* returns an empty array. The prepared statement [parameters are bound](https://www.sqlite.org/c3ref/bind_blob.html) using
|
||||
* the values in `namedParameters` and `anonymousParameters`.
|
||||
* @since v22.5.0
|
||||
* @param namedParameters An optional object used to bind named parameters. The keys of this object are used to configure the mapping.
|
||||
* @param anonymousParameters Zero or more values to bind to anonymous parameters.
|
||||
* @return An array of objects. Each object corresponds to a row returned by executing the prepared statement. The keys and values of each object correspond to the column names and values of
|
||||
* the row.
|
||||
*/
|
||||
all(...anonymousParameters: SQLInputValue[]): Record<string, SQLOutputValue>[];
|
||||
all(
|
||||
namedParameters: Record<string, SQLInputValue>,
|
||||
...anonymousParameters: SQLInputValue[]
|
||||
): Record<string, SQLOutputValue>[];
|
||||
/**
|
||||
* This method is used to retrieve information about the columns returned by the
|
||||
* prepared statement.
|
||||
* @since v23.11.0
|
||||
* @returns An array of objects. Each object corresponds to a column
|
||||
* in the prepared statement, and contains the following properties:
|
||||
*/
|
||||
columns(): StatementColumnMetadata[];
|
||||
/**
|
||||
* The source SQL text of the prepared statement with parameter
|
||||
* placeholders replaced by the values that were used during the most recent
|
||||
* execution of this prepared statement. This property is a wrapper around
|
||||
* [`sqlite3_expanded_sql()`](https://www.sqlite.org/c3ref/expanded_sql.html).
|
||||
* @since v22.5.0
|
||||
*/
|
||||
readonly expandedSQL: string;
|
||||
/**
|
||||
* This method executes a prepared statement and returns the first result as an
|
||||
* object. If the prepared statement does not return any results, this method
|
||||
* returns `undefined`. The prepared statement [parameters are bound](https://www.sqlite.org/c3ref/bind_blob.html) using the
|
||||
* values in `namedParameters` and `anonymousParameters`.
|
||||
* @since v22.5.0
|
||||
* @param namedParameters An optional object used to bind named parameters. The keys of this object are used to configure the mapping.
|
||||
* @param anonymousParameters Zero or more values to bind to anonymous parameters.
|
||||
* @return An object corresponding to the first row returned by executing the prepared statement. The keys and values of the object correspond to the column names and values of the row. If no
|
||||
* rows were returned from the database then this method returns `undefined`.
|
||||
*/
|
||||
get(...anonymousParameters: SQLInputValue[]): Record<string, SQLOutputValue> | undefined;
|
||||
get(
|
||||
namedParameters: Record<string, SQLInputValue>,
|
||||
...anonymousParameters: SQLInputValue[]
|
||||
): Record<string, SQLOutputValue> | undefined;
|
||||
/**
|
||||
* This method executes a prepared statement and returns an iterator of
|
||||
* objects. If the prepared statement does not return any results, this method
|
||||
* returns an empty iterator. The prepared statement [parameters are bound](https://www.sqlite.org/c3ref/bind_blob.html) using
|
||||
* the values in `namedParameters` and `anonymousParameters`.
|
||||
* @since v22.13.0
|
||||
* @param namedParameters An optional object used to bind named parameters.
|
||||
* The keys of this object are used to configure the mapping.
|
||||
* @param anonymousParameters Zero or more values to bind to anonymous parameters.
|
||||
* @returns An iterable iterator of objects. Each object corresponds to a row
|
||||
* returned by executing the prepared statement. The keys and values of each
|
||||
* object correspond to the column names and values of the row.
|
||||
*/
|
||||
iterate(...anonymousParameters: SQLInputValue[]): NodeJS.Iterator<Record<string, SQLOutputValue>>;
|
||||
iterate(
|
||||
namedParameters: Record<string, SQLInputValue>,
|
||||
...anonymousParameters: SQLInputValue[]
|
||||
): NodeJS.Iterator<Record<string, SQLOutputValue>>;
|
||||
/**
|
||||
* This method executes a prepared statement and returns an object summarizing the
|
||||
* resulting changes. The prepared statement [parameters are bound](https://www.sqlite.org/c3ref/bind_blob.html) using the
|
||||
* values in `namedParameters` and `anonymousParameters`.
|
||||
* @since v22.5.0
|
||||
* @param namedParameters An optional object used to bind named parameters. The keys of this object are used to configure the mapping.
|
||||
* @param anonymousParameters Zero or more values to bind to anonymous parameters.
|
||||
*/
|
||||
run(...anonymousParameters: SQLInputValue[]): StatementResultingChanges;
|
||||
run(
|
||||
namedParameters: Record<string, SQLInputValue>,
|
||||
...anonymousParameters: SQLInputValue[]
|
||||
): StatementResultingChanges;
|
||||
/**
|
||||
* The names of SQLite parameters begin with a prefix character. By default,`node:sqlite` requires that this prefix character is present when binding
|
||||
* parameters. However, with the exception of dollar sign character, these
|
||||
* prefix characters also require extra quoting when used in object keys.
|
||||
*
|
||||
* To improve ergonomics, this method can be used to also allow bare named
|
||||
* parameters, which do not require the prefix character in JavaScript code. There
|
||||
* are several caveats to be aware of when enabling bare named parameters:
|
||||
*
|
||||
* * The prefix character is still required in SQL.
|
||||
* * The prefix character is still allowed in JavaScript. In fact, prefixed names
|
||||
* will have slightly better binding performance.
|
||||
* * Using ambiguous named parameters, such as `$k` and `@k`, in the same prepared
|
||||
* statement will result in an exception as it cannot be determined how to bind
|
||||
* a bare name.
|
||||
* @since v22.5.0
|
||||
* @param enabled Enables or disables support for binding named parameters without the prefix character.
|
||||
*/
|
||||
setAllowBareNamedParameters(enabled: boolean): void;
|
||||
/**
|
||||
* By default, if an unknown name is encountered while binding parameters, an
|
||||
* exception is thrown. This method allows unknown named parameters to be ignored.
|
||||
* @since v22.15.0
|
||||
* @param enabled Enables or disables support for unknown named parameters.
|
||||
*/
|
||||
setAllowUnknownNamedParameters(enabled: boolean): void;
|
||||
/**
|
||||
* When reading from the database, SQLite `INTEGER`s are mapped to JavaScript
|
||||
* numbers by default. However, SQLite `INTEGER`s can store values larger than
|
||||
* JavaScript numbers are capable of representing. In such cases, this method can
|
||||
* be used to read `INTEGER` data using JavaScript `BigInt`s. This method has no
|
||||
* impact on database write operations where numbers and `BigInt`s are both
|
||||
* supported at all times.
|
||||
* @since v22.5.0
|
||||
* @param enabled Enables or disables the use of `BigInt`s when reading `INTEGER` fields from the database.
|
||||
*/
|
||||
setReadBigInts(enabled: boolean): void;
|
||||
/**
|
||||
* The source SQL text of the prepared statement. This property is a
|
||||
* wrapper around [`sqlite3_sql()`](https://www.sqlite.org/c3ref/expanded_sql.html).
|
||||
* @since v22.5.0
|
||||
*/
|
||||
readonly sourceSQL: string;
|
||||
}
|
||||
interface BackupOptions {
|
||||
/**
|
||||
* Name of the source database. This can be `'main'` (the default primary database) or any other
|
||||
* database that have been added with [`ATTACH DATABASE`](https://www.sqlite.org/lang_attach.html)
|
||||
* @default 'main'
|
||||
*/
|
||||
source?: string | undefined;
|
||||
/**
|
||||
* Name of the target database. This can be `'main'` (the default primary database) or any other
|
||||
* database that have been added with [`ATTACH DATABASE`](https://www.sqlite.org/lang_attach.html)
|
||||
* @default 'main'
|
||||
*/
|
||||
target?: string | undefined;
|
||||
/**
|
||||
* Number of pages to be transmitted in each batch of the backup.
|
||||
* @default 100
|
||||
*/
|
||||
rate?: number | undefined;
|
||||
/**
|
||||
* Callback function that will be called with the number of pages copied and the total number of
|
||||
* pages.
|
||||
*/
|
||||
progress?: ((progressInfo: BackupProgressInfo) => void) | undefined;
|
||||
}
|
||||
interface BackupProgressInfo {
|
||||
totalPages: number;
|
||||
remainingPages: number;
|
||||
}
|
||||
/**
|
||||
* This method makes a database backup. This method abstracts the
|
||||
* [`sqlite3_backup_init()`](https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupinit),
|
||||
* [`sqlite3_backup_step()`](https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupstep)
|
||||
* and [`sqlite3_backup_finish()`](https://www.sqlite.org/c3ref/backup_finish.html#sqlite3backupfinish) functions.
|
||||
*
|
||||
* The backed-up database can be used normally during the backup process. Mutations coming from the same connection - same
|
||||
* `DatabaseSync` - object will be reflected in the backup right away. However, mutations from other connections will cause
|
||||
* the backup process to restart.
|
||||
*
|
||||
* ```js
|
||||
* import { backup, DatabaseSync } from 'node:sqlite';
|
||||
*
|
||||
* const sourceDb = new DatabaseSync('source.db');
|
||||
* const totalPagesTransferred = await backup(sourceDb, 'backup.db', {
|
||||
* rate: 1, // Copy one page at a time.
|
||||
* progress: ({ totalPages, remainingPages }) => {
|
||||
* console.log('Backup in progress', { totalPages, remainingPages });
|
||||
* },
|
||||
* });
|
||||
*
|
||||
* console.log('Backup completed', totalPagesTransferred);
|
||||
* ```
|
||||
* @since v23.8.0
|
||||
* @param sourceDb The database to backup. The source database must be open.
|
||||
* @param path The path where the backup will be created. If the file already exists,
|
||||
* the contents will be overwritten.
|
||||
* @param options Optional configuration for the backup. The
|
||||
* following properties are supported:
|
||||
* @returns A promise that resolves when the backup is completed and rejects if an error occurs.
|
||||
*/
|
||||
function backup(sourceDb: DatabaseSync, path: string | Buffer | URL, options?: BackupOptions): Promise<void>;
|
||||
/**
|
||||
* @since v22.13.0
|
||||
*/
|
||||
namespace constants {
|
||||
/**
|
||||
* The conflict handler is invoked with this constant when processing a DELETE or UPDATE change if a row with the required PRIMARY KEY fields is present in the database, but one or more other (non primary-key) fields modified by the update do not contain the expected "before" values.
|
||||
* @since v22.14.0
|
||||
*/
|
||||
const SQLITE_CHANGESET_DATA: number;
|
||||
/**
|
||||
* The conflict handler is invoked with this constant when processing a DELETE or UPDATE change if a row with the required PRIMARY KEY fields is not present in the database.
|
||||
* @since v22.14.0
|
||||
*/
|
||||
const SQLITE_CHANGESET_NOTFOUND: number;
|
||||
/**
|
||||
* This constant is passed to the conflict handler while processing an INSERT change if the operation would result in duplicate primary key values.
|
||||
* @since v22.14.0
|
||||
*/
|
||||
const SQLITE_CHANGESET_CONFLICT: number;
|
||||
/**
|
||||
* If foreign key handling is enabled, and applying a changeset leaves the database in a state containing foreign key violations, the conflict handler is invoked with this constant exactly once before the changeset is committed. If the conflict handler returns `SQLITE_CHANGESET_OMIT`, the changes, including those that caused the foreign key constraint violation, are committed. Or, if it returns `SQLITE_CHANGESET_ABORT`, the changeset is rolled back.
|
||||
* @since v22.14.0
|
||||
*/
|
||||
const SQLITE_CHANGESET_FOREIGN_KEY: number;
|
||||
/**
|
||||
* Conflicting changes are omitted.
|
||||
* @since v22.12.0
|
||||
*/
|
||||
const SQLITE_CHANGESET_OMIT: number;
|
||||
/**
|
||||
* Conflicting changes replace existing values. Note that this value can only be returned when the type of conflict is either `SQLITE_CHANGESET_DATA` or `SQLITE_CHANGESET_CONFLICT`.
|
||||
* @since v22.12.0
|
||||
*/
|
||||
const SQLITE_CHANGESET_REPLACE: number;
|
||||
/**
|
||||
* Abort when a change encounters a conflict and roll back database.
|
||||
* @since v22.12.0
|
||||
*/
|
||||
const SQLITE_CHANGESET_ABORT: number;
|
||||
}
|
||||
}
|
||||
-1668
File diff suppressed because it is too large
Load Diff
-67
@@ -1,67 +0,0 @@
|
||||
/**
|
||||
* The `node:string_decoder` module provides an API for decoding `Buffer` objects
|
||||
* into strings in a manner that preserves encoded multi-byte UTF-8 and UTF-16
|
||||
* characters. It can be accessed using:
|
||||
*
|
||||
* ```js
|
||||
* import { StringDecoder } from 'node:string_decoder';
|
||||
* ```
|
||||
*
|
||||
* The following example shows the basic use of the `StringDecoder` class.
|
||||
*
|
||||
* ```js
|
||||
* import { StringDecoder } from 'node:string_decoder';
|
||||
* const decoder = new StringDecoder('utf8');
|
||||
*
|
||||
* const cent = Buffer.from([0xC2, 0xA2]);
|
||||
* console.log(decoder.write(cent)); // Prints: ¢
|
||||
*
|
||||
* const euro = Buffer.from([0xE2, 0x82, 0xAC]);
|
||||
* console.log(decoder.write(euro)); // Prints: €
|
||||
* ```
|
||||
*
|
||||
* When a `Buffer` instance is written to the `StringDecoder` instance, an
|
||||
* internal buffer is used to ensure that the decoded string does not contain
|
||||
* any incomplete multibyte characters. These are held in the buffer until the
|
||||
* next call to `stringDecoder.write()` or until `stringDecoder.end()` is called.
|
||||
*
|
||||
* In the following example, the three UTF-8 encoded bytes of the European Euro
|
||||
* symbol (`€`) are written over three separate operations:
|
||||
*
|
||||
* ```js
|
||||
* import { StringDecoder } from 'node:string_decoder';
|
||||
* const decoder = new StringDecoder('utf8');
|
||||
*
|
||||
* decoder.write(Buffer.from([0xE2]));
|
||||
* decoder.write(Buffer.from([0x82]));
|
||||
* console.log(decoder.end(Buffer.from([0xAC]))); // Prints: €
|
||||
* ```
|
||||
* @see [source](https://github.com/nodejs/node/blob/v24.x/lib/string_decoder.js)
|
||||
*/
|
||||
declare module "string_decoder" {
|
||||
class StringDecoder {
|
||||
constructor(encoding?: BufferEncoding);
|
||||
/**
|
||||
* Returns a decoded string, ensuring that any incomplete multibyte characters at
|
||||
* the end of the `Buffer`, or `TypedArray`, or `DataView` are omitted from the
|
||||
* returned string and stored in an internal buffer for the next call to `stringDecoder.write()` or `stringDecoder.end()`.
|
||||
* @since v0.1.99
|
||||
* @param buffer The bytes to decode.
|
||||
*/
|
||||
write(buffer: string | Buffer | NodeJS.ArrayBufferView): string;
|
||||
/**
|
||||
* Returns any remaining input stored in the internal buffer as a string. Bytes
|
||||
* representing incomplete UTF-8 and UTF-16 characters will be replaced with
|
||||
* substitution characters appropriate for the character encoding.
|
||||
*
|
||||
* If the `buffer` argument is provided, one final call to `stringDecoder.write()` is performed before returning the remaining input.
|
||||
* After `end()` is called, the `stringDecoder` object can be reused for new input.
|
||||
* @since v0.9.3
|
||||
* @param buffer The bytes to decode.
|
||||
*/
|
||||
end(buffer?: string | Buffer | NodeJS.ArrayBufferView): string;
|
||||
}
|
||||
}
|
||||
declare module "node:string_decoder" {
|
||||
export * from "string_decoder";
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
-285
@@ -1,285 +0,0 @@
|
||||
/**
|
||||
* The `timer` module exposes a global API for scheduling functions to
|
||||
* be called at some future period of time. Because the timer functions are
|
||||
* globals, there is no need to import `node:timers` to use the API.
|
||||
*
|
||||
* The timer functions within Node.js implement a similar API as the timers API
|
||||
* provided by Web Browsers but use a different internal implementation that is
|
||||
* built around the Node.js [Event Loop](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#setimmediate-vs-settimeout).
|
||||
* @see [source](https://github.com/nodejs/node/blob/v24.x/lib/timers.js)
|
||||
*/
|
||||
declare module "timers" {
|
||||
import { Abortable } from "node:events";
|
||||
import * as promises from "node:timers/promises";
|
||||
export interface TimerOptions extends Abortable {
|
||||
/**
|
||||
* Set to `false` to indicate that the scheduled `Timeout`
|
||||
* should not require the Node.js event loop to remain active.
|
||||
* @default true
|
||||
*/
|
||||
ref?: boolean | undefined;
|
||||
}
|
||||
global {
|
||||
namespace NodeJS {
|
||||
/**
|
||||
* This object is created internally and is returned from `setImmediate()`. It
|
||||
* can be passed to `clearImmediate()` in order to cancel the scheduled
|
||||
* actions.
|
||||
*
|
||||
* By default, when an immediate is scheduled, the Node.js event loop will continue
|
||||
* running as long as the immediate is active. The `Immediate` object returned by
|
||||
* `setImmediate()` exports both `immediate.ref()` and `immediate.unref()`
|
||||
* functions that can be used to control this default behavior.
|
||||
*/
|
||||
interface Immediate extends RefCounted, Disposable {
|
||||
/**
|
||||
* If true, the `Immediate` object will keep the Node.js event loop active.
|
||||
* @since v11.0.0
|
||||
*/
|
||||
hasRef(): boolean;
|
||||
/**
|
||||
* When called, requests that the Node.js event loop _not_ exit so long as the
|
||||
* `Immediate` is active. Calling `immediate.ref()` multiple times will have no
|
||||
* effect.
|
||||
*
|
||||
* By default, all `Immediate` objects are "ref'ed", making it normally unnecessary
|
||||
* to call `immediate.ref()` unless `immediate.unref()` had been called previously.
|
||||
* @since v9.7.0
|
||||
* @returns a reference to `immediate`
|
||||
*/
|
||||
ref(): this;
|
||||
/**
|
||||
* When called, the active `Immediate` object will not require the Node.js event
|
||||
* loop to remain active. If there is no other activity keeping the event loop
|
||||
* running, the process may exit before the `Immediate` object's callback is
|
||||
* invoked. Calling `immediate.unref()` multiple times will have no effect.
|
||||
* @since v9.7.0
|
||||
* @returns a reference to `immediate`
|
||||
*/
|
||||
unref(): this;
|
||||
/**
|
||||
* Cancels the immediate. This is similar to calling `clearImmediate()`.
|
||||
* @since v20.5.0, v18.18.0
|
||||
*/
|
||||
[Symbol.dispose](): void;
|
||||
_onImmediate(...args: any[]): void;
|
||||
}
|
||||
// Legacy interface used in Node.js v9 and prior
|
||||
// TODO: remove in a future major version bump
|
||||
/** @deprecated Use `NodeJS.Timeout` instead. */
|
||||
interface Timer extends RefCounted {
|
||||
hasRef(): boolean;
|
||||
refresh(): this;
|
||||
[Symbol.toPrimitive](): number;
|
||||
}
|
||||
/**
|
||||
* This object is created internally and is returned from `setTimeout()` and
|
||||
* `setInterval()`. It can be passed to either `clearTimeout()` or
|
||||
* `clearInterval()` in order to cancel the scheduled actions.
|
||||
*
|
||||
* By default, when a timer is scheduled using either `setTimeout()` or
|
||||
* `setInterval()`, the Node.js event loop will continue running as long as the
|
||||
* timer is active. Each of the `Timeout` objects returned by these functions
|
||||
* export both `timeout.ref()` and `timeout.unref()` functions that can be used to
|
||||
* control this default behavior.
|
||||
*/
|
||||
interface Timeout extends RefCounted, Disposable, Timer {
|
||||
/**
|
||||
* Cancels the timeout.
|
||||
* @since v0.9.1
|
||||
* @legacy Use `clearTimeout()` instead.
|
||||
* @returns a reference to `timeout`
|
||||
*/
|
||||
close(): this;
|
||||
/**
|
||||
* If true, the `Timeout` object will keep the Node.js event loop active.
|
||||
* @since v11.0.0
|
||||
*/
|
||||
hasRef(): boolean;
|
||||
/**
|
||||
* When called, requests that the Node.js event loop _not_ exit so long as the
|
||||
* `Timeout` is active. Calling `timeout.ref()` multiple times will have no effect.
|
||||
*
|
||||
* By default, all `Timeout` objects are "ref'ed", making it normally unnecessary
|
||||
* to call `timeout.ref()` unless `timeout.unref()` had been called previously.
|
||||
* @since v0.9.1
|
||||
* @returns a reference to `timeout`
|
||||
*/
|
||||
ref(): this;
|
||||
/**
|
||||
* Sets the timer's start time to the current time, and reschedules the timer to
|
||||
* call its callback at the previously specified duration adjusted to the current
|
||||
* time. This is useful for refreshing a timer without allocating a new
|
||||
* JavaScript object.
|
||||
*
|
||||
* Using this on a timer that has already called its callback will reactivate the
|
||||
* timer.
|
||||
* @since v10.2.0
|
||||
* @returns a reference to `timeout`
|
||||
*/
|
||||
refresh(): this;
|
||||
/**
|
||||
* When called, the active `Timeout` object will not require the Node.js event loop
|
||||
* to remain active. If there is no other activity keeping the event loop running,
|
||||
* the process may exit before the `Timeout` object's callback is invoked. Calling
|
||||
* `timeout.unref()` multiple times will have no effect.
|
||||
* @since v0.9.1
|
||||
* @returns a reference to `timeout`
|
||||
*/
|
||||
unref(): this;
|
||||
/**
|
||||
* Coerce a `Timeout` to a primitive. The primitive can be used to
|
||||
* clear the `Timeout`. The primitive can only be used in the
|
||||
* same thread where the timeout was created. Therefore, to use it
|
||||
* across `worker_threads` it must first be passed to the correct
|
||||
* thread. This allows enhanced compatibility with browser
|
||||
* `setTimeout()` and `setInterval()` implementations.
|
||||
* @since v14.9.0, v12.19.0
|
||||
*/
|
||||
[Symbol.toPrimitive](): number;
|
||||
/**
|
||||
* Cancels the timeout.
|
||||
* @since v20.5.0, v18.18.0
|
||||
*/
|
||||
[Symbol.dispose](): void;
|
||||
_onTimeout(...args: any[]): void;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Schedules the "immediate" execution of the `callback` after I/O events'
|
||||
* callbacks.
|
||||
*
|
||||
* When multiple calls to `setImmediate()` are made, the `callback` functions are
|
||||
* queued for execution in the order in which they are created. The entire callback
|
||||
* queue is processed every event loop iteration. If an immediate timer is queued
|
||||
* from inside an executing callback, that timer will not be triggered until the
|
||||
* next event loop iteration.
|
||||
*
|
||||
* If `callback` is not a function, a `TypeError` will be thrown.
|
||||
*
|
||||
* This method has a custom variant for promises that is available using
|
||||
* `timersPromises.setImmediate()`.
|
||||
* @since v0.9.1
|
||||
* @param callback The function to call at the end of this turn of
|
||||
* the Node.js [Event Loop](https://nodejs.org/en/docs/guides/event-loop-timers-and-nexttick/#setimmediate-vs-settimeout)
|
||||
* @param args Optional arguments to pass when the `callback` is called.
|
||||
* @returns for use with `clearImmediate()`
|
||||
*/
|
||||
function setImmediate<TArgs extends any[]>(
|
||||
callback: (...args: TArgs) => void,
|
||||
...args: TArgs
|
||||
): NodeJS.Immediate;
|
||||
// Allow a single void-accepting argument to be optional in arguments lists.
|
||||
// Allows usage such as `new Promise(resolve => setTimeout(resolve, ms))` (#54258)
|
||||
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
||||
function setImmediate(callback: (_: void) => void): NodeJS.Immediate;
|
||||
namespace setImmediate {
|
||||
import __promisify__ = promises.setImmediate;
|
||||
export { __promisify__ };
|
||||
}
|
||||
/**
|
||||
* Schedules repeated execution of `callback` every `delay` milliseconds.
|
||||
*
|
||||
* When `delay` is larger than `2147483647` or less than `1` or `NaN`, the `delay`
|
||||
* will be set to `1`. Non-integer delays are truncated to an integer.
|
||||
*
|
||||
* If `callback` is not a function, a `TypeError` will be thrown.
|
||||
*
|
||||
* This method has a custom variant for promises that is available using
|
||||
* `timersPromises.setInterval()`.
|
||||
* @since v0.0.1
|
||||
* @param callback The function to call when the timer elapses.
|
||||
* @param delay The number of milliseconds to wait before calling the
|
||||
* `callback`. **Default:** `1`.
|
||||
* @param args Optional arguments to pass when the `callback` is called.
|
||||
* @returns for use with `clearInterval()`
|
||||
*/
|
||||
function setInterval<TArgs extends any[]>(
|
||||
callback: (...args: TArgs) => void,
|
||||
delay?: number,
|
||||
...args: TArgs
|
||||
): NodeJS.Timeout;
|
||||
// Allow a single void-accepting argument to be optional in arguments lists.
|
||||
// Allows usage such as `new Promise(resolve => setTimeout(resolve, ms))` (#54258)
|
||||
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
||||
function setInterval(callback: (_: void) => void, delay?: number): NodeJS.Timeout;
|
||||
/**
|
||||
* Schedules execution of a one-time `callback` after `delay` milliseconds.
|
||||
*
|
||||
* The `callback` will likely not be invoked in precisely `delay` milliseconds.
|
||||
* Node.js makes no guarantees about the exact timing of when callbacks will fire,
|
||||
* nor of their ordering. The callback will be called as close as possible to the
|
||||
* time specified.
|
||||
*
|
||||
* When `delay` is larger than `2147483647` or less than `1` or `NaN`, the `delay`
|
||||
* will be set to `1`. Non-integer delays are truncated to an integer.
|
||||
*
|
||||
* If `callback` is not a function, a `TypeError` will be thrown.
|
||||
*
|
||||
* This method has a custom variant for promises that is available using
|
||||
* `timersPromises.setTimeout()`.
|
||||
* @since v0.0.1
|
||||
* @param callback The function to call when the timer elapses.
|
||||
* @param delay The number of milliseconds to wait before calling the
|
||||
* `callback`. **Default:** `1`.
|
||||
* @param args Optional arguments to pass when the `callback` is called.
|
||||
* @returns for use with `clearTimeout()`
|
||||
*/
|
||||
function setTimeout<TArgs extends any[]>(
|
||||
callback: (...args: TArgs) => void,
|
||||
delay?: number,
|
||||
...args: TArgs
|
||||
): NodeJS.Timeout;
|
||||
// Allow a single void-accepting argument to be optional in arguments lists.
|
||||
// Allows usage such as `new Promise(resolve => setTimeout(resolve, ms))` (#54258)
|
||||
// eslint-disable-next-line @typescript-eslint/no-invalid-void-type
|
||||
function setTimeout(callback: (_: void) => void, delay?: number): NodeJS.Timeout;
|
||||
namespace setTimeout {
|
||||
import __promisify__ = promises.setTimeout;
|
||||
export { __promisify__ };
|
||||
}
|
||||
/**
|
||||
* Cancels an `Immediate` object created by `setImmediate()`.
|
||||
* @since v0.9.1
|
||||
* @param immediate An `Immediate` object as returned by `setImmediate()`.
|
||||
*/
|
||||
function clearImmediate(immediate: NodeJS.Immediate | undefined): void;
|
||||
/**
|
||||
* Cancels a `Timeout` object created by `setInterval()`.
|
||||
* @since v0.0.1
|
||||
* @param timeout A `Timeout` object as returned by `setInterval()`
|
||||
* or the primitive of the `Timeout` object as a string or a number.
|
||||
*/
|
||||
function clearInterval(timeout: NodeJS.Timeout | string | number | undefined): void;
|
||||
/**
|
||||
* Cancels a `Timeout` object created by `setTimeout()`.
|
||||
* @since v0.0.1
|
||||
* @param timeout A `Timeout` object as returned by `setTimeout()`
|
||||
* or the primitive of the `Timeout` object as a string or a number.
|
||||
*/
|
||||
function clearTimeout(timeout: NodeJS.Timeout | string | number | undefined): void;
|
||||
/**
|
||||
* The `queueMicrotask()` method queues a microtask to invoke `callback`. If
|
||||
* `callback` throws an exception, the `process` object `'uncaughtException'`
|
||||
* event will be emitted.
|
||||
*
|
||||
* The microtask queue is managed by V8 and may be used in a similar manner to
|
||||
* the `process.nextTick()` queue, which is managed by Node.js. The
|
||||
* `process.nextTick()` queue is always processed before the microtask queue
|
||||
* within each turn of the Node.js event loop.
|
||||
* @since v11.0.0
|
||||
* @param callback Function to be queued.
|
||||
*/
|
||||
function queueMicrotask(callback: () => void): void;
|
||||
}
|
||||
import clearImmediate = globalThis.clearImmediate;
|
||||
import clearInterval = globalThis.clearInterval;
|
||||
import clearTimeout = globalThis.clearTimeout;
|
||||
import setImmediate = globalThis.setImmediate;
|
||||
import setInterval = globalThis.setInterval;
|
||||
import setTimeout = globalThis.setTimeout;
|
||||
export { clearImmediate, clearInterval, clearTimeout, promises, setImmediate, setInterval, setTimeout };
|
||||
}
|
||||
declare module "node:timers" {
|
||||
export * from "timers";
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
-197
@@ -1,197 +0,0 @@
|
||||
/**
|
||||
* The `node:trace_events` module provides a mechanism to centralize tracing information
|
||||
* generated by V8, Node.js core, and userspace code.
|
||||
*
|
||||
* Tracing can be enabled with the `--trace-event-categories` command-line flag
|
||||
* or by using the `trace_events` module. The `--trace-event-categories` flag
|
||||
* accepts a list of comma-separated category names.
|
||||
*
|
||||
* The available categories are:
|
||||
*
|
||||
* * `node`: An empty placeholder.
|
||||
* * `node.async_hooks`: Enables capture of detailed [`async_hooks`](https://nodejs.org/docs/latest-v24.x/api/async_hooks.html) trace data.
|
||||
* The [`async_hooks`](https://nodejs.org/docs/latest-v24.x/api/async_hooks.html) events have a unique `asyncId` and a special `triggerId` `triggerAsyncId` property.
|
||||
* * `node.bootstrap`: Enables capture of Node.js bootstrap milestones.
|
||||
* * `node.console`: Enables capture of `console.time()` and `console.count()` output.
|
||||
* * `node.threadpoolwork.sync`: Enables capture of trace data for threadpool synchronous operations, such as `blob`, `zlib`, `crypto` and `node_api`.
|
||||
* * `node.threadpoolwork.async`: Enables capture of trace data for threadpool asynchronous operations, such as `blob`, `zlib`, `crypto` and `node_api`.
|
||||
* * `node.dns.native`: Enables capture of trace data for DNS queries.
|
||||
* * `node.net.native`: Enables capture of trace data for network.
|
||||
* * `node.environment`: Enables capture of Node.js Environment milestones.
|
||||
* * `node.fs.sync`: Enables capture of trace data for file system sync methods.
|
||||
* * `node.fs_dir.sync`: Enables capture of trace data for file system sync directory methods.
|
||||
* * `node.fs.async`: Enables capture of trace data for file system async methods.
|
||||
* * `node.fs_dir.async`: Enables capture of trace data for file system async directory methods.
|
||||
* * `node.perf`: Enables capture of [Performance API](https://nodejs.org/docs/latest-v24.x/api/perf_hooks.html) measurements.
|
||||
* * `node.perf.usertiming`: Enables capture of only Performance API User Timing
|
||||
* measures and marks.
|
||||
* * `node.perf.timerify`: Enables capture of only Performance API timerify
|
||||
* measurements.
|
||||
* * `node.promises.rejections`: Enables capture of trace data tracking the number
|
||||
* of unhandled Promise rejections and handled-after-rejections.
|
||||
* * `node.vm.script`: Enables capture of trace data for the `node:vm` module's `runInNewContext()`, `runInContext()`, and `runInThisContext()` methods.
|
||||
* * `v8`: The [V8](https://nodejs.org/docs/latest-v24.x/api/v8.html) events are GC, compiling, and execution related.
|
||||
* * `node.http`: Enables capture of trace data for http request / response.
|
||||
*
|
||||
* By default the `node`, `node.async_hooks`, and `v8` categories are enabled.
|
||||
*
|
||||
* ```bash
|
||||
* node --trace-event-categories v8,node,node.async_hooks server.js
|
||||
* ```
|
||||
*
|
||||
* Prior versions of Node.js required the use of the `--trace-events-enabled` flag to enable trace events. This requirement has been removed. However, the `--trace-events-enabled` flag _may_ still be
|
||||
* used and will enable the `node`, `node.async_hooks`, and `v8` trace event categories by default.
|
||||
*
|
||||
* ```bash
|
||||
* node --trace-events-enabled
|
||||
*
|
||||
* # is equivalent to
|
||||
*
|
||||
* node --trace-event-categories v8,node,node.async_hooks
|
||||
* ```
|
||||
*
|
||||
* Alternatively, trace events may be enabled using the `node:trace_events` module:
|
||||
*
|
||||
* ```js
|
||||
* import trace_events from 'node:trace_events';
|
||||
* const tracing = trace_events.createTracing({ categories: ['node.perf'] });
|
||||
* tracing.enable(); // Enable trace event capture for the 'node.perf' category
|
||||
*
|
||||
* // do work
|
||||
*
|
||||
* tracing.disable(); // Disable trace event capture for the 'node.perf' category
|
||||
* ```
|
||||
*
|
||||
* Running Node.js with tracing enabled will produce log files that can be opened
|
||||
* in the [`chrome://tracing`](https://www.chromium.org/developers/how-tos/trace-event-profiling-tool) tab of Chrome.
|
||||
*
|
||||
* The logging file is by default called `node_trace.${rotation}.log`, where `${rotation}` is an incrementing log-rotation id. The filepath pattern can
|
||||
* be specified with `--trace-event-file-pattern` that accepts a template
|
||||
* string that supports `${rotation}` and `${pid}`:
|
||||
*
|
||||
* ```bash
|
||||
* node --trace-event-categories v8 --trace-event-file-pattern '${pid}-${rotation}.log' server.js
|
||||
* ```
|
||||
*
|
||||
* To guarantee that the log file is properly generated after signal events like `SIGINT`, `SIGTERM`, or `SIGBREAK`, make sure to have the appropriate handlers
|
||||
* in your code, such as:
|
||||
*
|
||||
* ```js
|
||||
* process.on('SIGINT', function onSigint() {
|
||||
* console.info('Received SIGINT.');
|
||||
* process.exit(130); // Or applicable exit code depending on OS and signal
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* The tracing system uses the same time source
|
||||
* as the one used by `process.hrtime()`.
|
||||
* However the trace-event timestamps are expressed in microseconds,
|
||||
* unlike `process.hrtime()` which returns nanoseconds.
|
||||
*
|
||||
* The features from this module are not available in [`Worker`](https://nodejs.org/docs/latest-v24.x/api/worker_threads.html#class-worker) threads.
|
||||
* @experimental
|
||||
* @see [source](https://github.com/nodejs/node/blob/v24.x/lib/trace_events.js)
|
||||
*/
|
||||
declare module "trace_events" {
|
||||
/**
|
||||
* The `Tracing` object is used to enable or disable tracing for sets of
|
||||
* categories. Instances are created using the
|
||||
* `trace_events.createTracing()` method.
|
||||
*
|
||||
* When created, the `Tracing` object is disabled. Calling the
|
||||
* `tracing.enable()` method adds the categories to the set of enabled trace
|
||||
* event categories. Calling `tracing.disable()` will remove the categories
|
||||
* from the set of enabled trace event categories.
|
||||
*/
|
||||
interface Tracing {
|
||||
/**
|
||||
* A comma-separated list of the trace event categories covered by this
|
||||
* `Tracing` object.
|
||||
* @since v10.0.0
|
||||
*/
|
||||
readonly categories: string;
|
||||
/**
|
||||
* Disables this `Tracing` object.
|
||||
*
|
||||
* Only trace event categories _not_ covered by other enabled `Tracing`
|
||||
* objects and _not_ specified by the `--trace-event-categories` flag
|
||||
* will be disabled.
|
||||
*
|
||||
* ```js
|
||||
* import trace_events from 'node:trace_events';
|
||||
* const t1 = trace_events.createTracing({ categories: ['node', 'v8'] });
|
||||
* const t2 = trace_events.createTracing({ categories: ['node.perf', 'node'] });
|
||||
* t1.enable();
|
||||
* t2.enable();
|
||||
*
|
||||
* // Prints 'node,node.perf,v8'
|
||||
* console.log(trace_events.getEnabledCategories());
|
||||
*
|
||||
* t2.disable(); // Will only disable emission of the 'node.perf' category
|
||||
*
|
||||
* // Prints 'node,v8'
|
||||
* console.log(trace_events.getEnabledCategories());
|
||||
* ```
|
||||
* @since v10.0.0
|
||||
*/
|
||||
disable(): void;
|
||||
/**
|
||||
* Enables this `Tracing` object for the set of categories covered by
|
||||
* the `Tracing` object.
|
||||
* @since v10.0.0
|
||||
*/
|
||||
enable(): void;
|
||||
/**
|
||||
* `true` only if the `Tracing` object has been enabled.
|
||||
* @since v10.0.0
|
||||
*/
|
||||
readonly enabled: boolean;
|
||||
}
|
||||
interface CreateTracingOptions {
|
||||
/**
|
||||
* An array of trace category names. Values included in the array are
|
||||
* coerced to a string when possible. An error will be thrown if the
|
||||
* value cannot be coerced.
|
||||
*/
|
||||
categories: string[];
|
||||
}
|
||||
/**
|
||||
* Creates and returns a `Tracing` object for the given set of `categories`.
|
||||
*
|
||||
* ```js
|
||||
* import trace_events from 'node:trace_events';
|
||||
* const categories = ['node.perf', 'node.async_hooks'];
|
||||
* const tracing = trace_events.createTracing({ categories });
|
||||
* tracing.enable();
|
||||
* // do stuff
|
||||
* tracing.disable();
|
||||
* ```
|
||||
* @since v10.0.0
|
||||
*/
|
||||
function createTracing(options: CreateTracingOptions): Tracing;
|
||||
/**
|
||||
* Returns a comma-separated list of all currently-enabled trace event
|
||||
* categories. The current set of enabled trace event categories is determined
|
||||
* by the _union_ of all currently-enabled `Tracing` objects and any categories
|
||||
* enabled using the `--trace-event-categories` flag.
|
||||
*
|
||||
* Given the file `test.js` below, the command `node --trace-event-categories node.perf test.js` will print `'node.async_hooks,node.perf'` to the console.
|
||||
*
|
||||
* ```js
|
||||
* import trace_events from 'node:trace_events';
|
||||
* const t1 = trace_events.createTracing({ categories: ['node.async_hooks'] });
|
||||
* const t2 = trace_events.createTracing({ categories: ['node.perf'] });
|
||||
* const t3 = trace_events.createTracing({ categories: ['v8'] });
|
||||
*
|
||||
* t1.enable();
|
||||
* t2.enable();
|
||||
*
|
||||
* console.log(trace_events.getEnabledCategories());
|
||||
* ```
|
||||
* @since v10.0.0
|
||||
*/
|
||||
function getEnabledCategories(): string | undefined;
|
||||
}
|
||||
declare module "node:trace_events" {
|
||||
export * from "trace_events";
|
||||
}
|
||||
@@ -1,208 +0,0 @@
|
||||
/**
|
||||
* The `node:tty` module provides the `tty.ReadStream` and `tty.WriteStream` classes. In most cases, it will not be necessary or possible to use this module
|
||||
* directly. However, it can be accessed using:
|
||||
*
|
||||
* ```js
|
||||
* import tty from 'node:tty';
|
||||
* ```
|
||||
*
|
||||
* When Node.js detects that it is being run with a text terminal ("TTY")
|
||||
* attached, `process.stdin` will, by default, be initialized as an instance of `tty.ReadStream` and both `process.stdout` and `process.stderr` will, by
|
||||
* default, be instances of `tty.WriteStream`. The preferred method of determining
|
||||
* whether Node.js is being run within a TTY context is to check that the value of
|
||||
* the `process.stdout.isTTY` property is `true`:
|
||||
*
|
||||
* ```console
|
||||
* $ node -p -e "Boolean(process.stdout.isTTY)"
|
||||
* true
|
||||
* $ node -p -e "Boolean(process.stdout.isTTY)" | cat
|
||||
* false
|
||||
* ```
|
||||
*
|
||||
* In most cases, there should be little to no reason for an application to
|
||||
* manually create instances of the `tty.ReadStream` and `tty.WriteStream` classes.
|
||||
* @see [source](https://github.com/nodejs/node/blob/v24.x/lib/tty.js)
|
||||
*/
|
||||
declare module "tty" {
|
||||
import * as net from "node:net";
|
||||
/**
|
||||
* The `tty.isatty()` method returns `true` if the given `fd` is associated with
|
||||
* a TTY and `false` if it is not, including whenever `fd` is not a non-negative
|
||||
* integer.
|
||||
* @since v0.5.8
|
||||
* @param fd A numeric file descriptor
|
||||
*/
|
||||
function isatty(fd: number): boolean;
|
||||
/**
|
||||
* Represents the readable side of a TTY. In normal circumstances `process.stdin` will be the only `tty.ReadStream` instance in a Node.js
|
||||
* process and there should be no reason to create additional instances.
|
||||
* @since v0.5.8
|
||||
*/
|
||||
class ReadStream extends net.Socket {
|
||||
constructor(fd: number, options?: net.SocketConstructorOpts);
|
||||
/**
|
||||
* A `boolean` that is `true` if the TTY is currently configured to operate as a
|
||||
* raw device.
|
||||
*
|
||||
* This flag is always `false` when a process starts, even if the terminal is
|
||||
* operating in raw mode. Its value will change with subsequent calls to `setRawMode`.
|
||||
* @since v0.7.7
|
||||
*/
|
||||
isRaw: boolean;
|
||||
/**
|
||||
* Allows configuration of `tty.ReadStream` so that it operates as a raw device.
|
||||
*
|
||||
* When in raw mode, input is always available character-by-character, not
|
||||
* including modifiers. Additionally, all special processing of characters by the
|
||||
* terminal is disabled, including echoing input
|
||||
* characters. Ctrl+C will no longer cause a `SIGINT` when
|
||||
* in this mode.
|
||||
* @since v0.7.7
|
||||
* @param mode If `true`, configures the `tty.ReadStream` to operate as a raw device. If `false`, configures the `tty.ReadStream` to operate in its default mode. The `readStream.isRaw`
|
||||
* property will be set to the resulting mode.
|
||||
* @return The read stream instance.
|
||||
*/
|
||||
setRawMode(mode: boolean): this;
|
||||
/**
|
||||
* A `boolean` that is always `true` for `tty.ReadStream` instances.
|
||||
* @since v0.5.8
|
||||
*/
|
||||
isTTY: boolean;
|
||||
}
|
||||
/**
|
||||
* -1 - to the left from cursor
|
||||
* 0 - the entire line
|
||||
* 1 - to the right from cursor
|
||||
*/
|
||||
type Direction = -1 | 0 | 1;
|
||||
/**
|
||||
* Represents the writable side of a TTY. In normal circumstances, `process.stdout` and `process.stderr` will be the only`tty.WriteStream` instances created for a Node.js process and there
|
||||
* should be no reason to create additional instances.
|
||||
* @since v0.5.8
|
||||
*/
|
||||
class WriteStream extends net.Socket {
|
||||
constructor(fd: number);
|
||||
addListener(event: string, listener: (...args: any[]) => void): this;
|
||||
addListener(event: "resize", listener: () => void): this;
|
||||
emit(event: string | symbol, ...args: any[]): boolean;
|
||||
emit(event: "resize"): boolean;
|
||||
on(event: string, listener: (...args: any[]) => void): this;
|
||||
on(event: "resize", listener: () => void): this;
|
||||
once(event: string, listener: (...args: any[]) => void): this;
|
||||
once(event: "resize", listener: () => void): this;
|
||||
prependListener(event: string, listener: (...args: any[]) => void): this;
|
||||
prependListener(event: "resize", listener: () => void): this;
|
||||
prependOnceListener(event: string, listener: (...args: any[]) => void): this;
|
||||
prependOnceListener(event: "resize", listener: () => void): this;
|
||||
/**
|
||||
* `writeStream.clearLine()` clears the current line of this `WriteStream` in a
|
||||
* direction identified by `dir`.
|
||||
* @since v0.7.7
|
||||
* @param callback Invoked once the operation completes.
|
||||
* @return `false` if the stream wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
|
||||
*/
|
||||
clearLine(dir: Direction, callback?: () => void): boolean;
|
||||
/**
|
||||
* `writeStream.clearScreenDown()` clears this `WriteStream` from the current
|
||||
* cursor down.
|
||||
* @since v0.7.7
|
||||
* @param callback Invoked once the operation completes.
|
||||
* @return `false` if the stream wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
|
||||
*/
|
||||
clearScreenDown(callback?: () => void): boolean;
|
||||
/**
|
||||
* `writeStream.cursorTo()` moves this `WriteStream`'s cursor to the specified
|
||||
* position.
|
||||
* @since v0.7.7
|
||||
* @param callback Invoked once the operation completes.
|
||||
* @return `false` if the stream wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
|
||||
*/
|
||||
cursorTo(x: number, y?: number, callback?: () => void): boolean;
|
||||
cursorTo(x: number, callback: () => void): boolean;
|
||||
/**
|
||||
* `writeStream.moveCursor()` moves this `WriteStream`'s cursor _relative_ to its
|
||||
* current position.
|
||||
* @since v0.7.7
|
||||
* @param callback Invoked once the operation completes.
|
||||
* @return `false` if the stream wishes for the calling code to wait for the `'drain'` event to be emitted before continuing to write additional data; otherwise `true`.
|
||||
*/
|
||||
moveCursor(dx: number, dy: number, callback?: () => void): boolean;
|
||||
/**
|
||||
* Returns:
|
||||
*
|
||||
* * `1` for 2,
|
||||
* * `4` for 16,
|
||||
* * `8` for 256,
|
||||
* * `24` for 16,777,216 colors supported.
|
||||
*
|
||||
* Use this to determine what colors the terminal supports. Due to the nature of
|
||||
* colors in terminals it is possible to either have false positives or false
|
||||
* negatives. It depends on process information and the environment variables that
|
||||
* may lie about what terminal is used.
|
||||
* It is possible to pass in an `env` object to simulate the usage of a specific
|
||||
* terminal. This can be useful to check how specific environment settings behave.
|
||||
*
|
||||
* To enforce a specific color support, use one of the below environment settings.
|
||||
*
|
||||
* * 2 colors: `FORCE_COLOR = 0` (Disables colors)
|
||||
* * 16 colors: `FORCE_COLOR = 1`
|
||||
* * 256 colors: `FORCE_COLOR = 2`
|
||||
* * 16,777,216 colors: `FORCE_COLOR = 3`
|
||||
*
|
||||
* Disabling color support is also possible by using the `NO_COLOR` and `NODE_DISABLE_COLORS` environment variables.
|
||||
* @since v9.9.0
|
||||
* @param [env=process.env] An object containing the environment variables to check. This enables simulating the usage of a specific terminal.
|
||||
*/
|
||||
getColorDepth(env?: object): number;
|
||||
/**
|
||||
* Returns `true` if the `writeStream` supports at least as many colors as provided
|
||||
* in `count`. Minimum support is 2 (black and white).
|
||||
*
|
||||
* This has the same false positives and negatives as described in `writeStream.getColorDepth()`.
|
||||
*
|
||||
* ```js
|
||||
* process.stdout.hasColors();
|
||||
* // Returns true or false depending on if `stdout` supports at least 16 colors.
|
||||
* process.stdout.hasColors(256);
|
||||
* // Returns true or false depending on if `stdout` supports at least 256 colors.
|
||||
* process.stdout.hasColors({ TMUX: '1' });
|
||||
* // Returns true.
|
||||
* process.stdout.hasColors(2 ** 24, { TMUX: '1' });
|
||||
* // Returns false (the environment setting pretends to support 2 ** 8 colors).
|
||||
* ```
|
||||
* @since v11.13.0, v10.16.0
|
||||
* @param [count=16] The number of colors that are requested (minimum 2).
|
||||
* @param [env=process.env] An object containing the environment variables to check. This enables simulating the usage of a specific terminal.
|
||||
*/
|
||||
hasColors(count?: number): boolean;
|
||||
hasColors(env?: object): boolean;
|
||||
hasColors(count: number, env?: object): boolean;
|
||||
/**
|
||||
* `writeStream.getWindowSize()` returns the size of the TTY
|
||||
* corresponding to this `WriteStream`. The array is of the type `[numColumns, numRows]` where `numColumns` and `numRows` represent the number
|
||||
* of columns and rows in the corresponding TTY.
|
||||
* @since v0.7.7
|
||||
*/
|
||||
getWindowSize(): [number, number];
|
||||
/**
|
||||
* A `number` specifying the number of columns the TTY currently has. This property
|
||||
* is updated whenever the `'resize'` event is emitted.
|
||||
* @since v0.7.7
|
||||
*/
|
||||
columns: number;
|
||||
/**
|
||||
* A `number` specifying the number of rows the TTY currently has. This property
|
||||
* is updated whenever the `'resize'` event is emitted.
|
||||
* @since v0.7.7
|
||||
*/
|
||||
rows: number;
|
||||
/**
|
||||
* A `boolean` that is always `true`.
|
||||
* @since v0.5.8
|
||||
*/
|
||||
isTTY: boolean;
|
||||
}
|
||||
}
|
||||
declare module "node:tty" {
|
||||
export * from "tty";
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1,919 +0,0 @@
|
||||
/**
|
||||
* The `node:v8` module exposes APIs that are specific to the version of [V8](https://developers.google.com/v8/) built into the Node.js binary. It can be accessed using:
|
||||
*
|
||||
* ```js
|
||||
* import v8 from 'node:v8';
|
||||
* ```
|
||||
* @see [source](https://github.com/nodejs/node/blob/v24.x/lib/v8.js)
|
||||
*/
|
||||
declare module "v8" {
|
||||
import { Readable } from "node:stream";
|
||||
interface HeapSpaceInfo {
|
||||
space_name: string;
|
||||
space_size: number;
|
||||
space_used_size: number;
|
||||
space_available_size: number;
|
||||
physical_space_size: number;
|
||||
}
|
||||
// ** Signifies if the --zap_code_space option is enabled or not. 1 == enabled, 0 == disabled. */
|
||||
type DoesZapCodeSpaceFlag = 0 | 1;
|
||||
interface HeapInfo {
|
||||
total_heap_size: number;
|
||||
total_heap_size_executable: number;
|
||||
total_physical_size: number;
|
||||
total_available_size: number;
|
||||
used_heap_size: number;
|
||||
heap_size_limit: number;
|
||||
malloced_memory: number;
|
||||
peak_malloced_memory: number;
|
||||
does_zap_garbage: DoesZapCodeSpaceFlag;
|
||||
number_of_native_contexts: number;
|
||||
number_of_detached_contexts: number;
|
||||
total_global_handles_size: number;
|
||||
used_global_handles_size: number;
|
||||
external_memory: number;
|
||||
}
|
||||
interface HeapCodeStatistics {
|
||||
code_and_metadata_size: number;
|
||||
bytecode_and_metadata_size: number;
|
||||
external_script_source_size: number;
|
||||
}
|
||||
interface HeapSnapshotOptions {
|
||||
/**
|
||||
* If true, expose internals in the heap snapshot.
|
||||
* @default false
|
||||
*/
|
||||
exposeInternals?: boolean;
|
||||
/**
|
||||
* If true, expose numeric values in artificial fields.
|
||||
* @default false
|
||||
*/
|
||||
exposeNumericValues?: boolean;
|
||||
}
|
||||
/**
|
||||
* Returns an integer representing a version tag derived from the V8 version,
|
||||
* command-line flags, and detected CPU features. This is useful for determining
|
||||
* whether a `vm.Script` `cachedData` buffer is compatible with this instance
|
||||
* of V8.
|
||||
*
|
||||
* ```js
|
||||
* console.log(v8.cachedDataVersionTag()); // 3947234607
|
||||
* // The value returned by v8.cachedDataVersionTag() is derived from the V8
|
||||
* // version, command-line flags, and detected CPU features. Test that the value
|
||||
* // does indeed update when flags are toggled.
|
||||
* v8.setFlagsFromString('--allow_natives_syntax');
|
||||
* console.log(v8.cachedDataVersionTag()); // 183726201
|
||||
* ```
|
||||
* @since v8.0.0
|
||||
*/
|
||||
function cachedDataVersionTag(): number;
|
||||
/**
|
||||
* Returns an object with the following properties:
|
||||
*
|
||||
* `does_zap_garbage` is a 0/1 boolean, which signifies whether the `--zap_code_space` option is enabled or not. This makes V8 overwrite heap
|
||||
* garbage with a bit pattern. The RSS footprint (resident set size) gets bigger
|
||||
* because it continuously touches all heap pages and that makes them less likely
|
||||
* to get swapped out by the operating system.
|
||||
*
|
||||
* `number_of_native_contexts` The value of native\_context is the number of the
|
||||
* top-level contexts currently active. Increase of this number over time indicates
|
||||
* a memory leak.
|
||||
*
|
||||
* `number_of_detached_contexts` The value of detached\_context is the number
|
||||
* of contexts that were detached and not yet garbage collected. This number
|
||||
* being non-zero indicates a potential memory leak.
|
||||
*
|
||||
* `total_global_handles_size` The value of total\_global\_handles\_size is the
|
||||
* total memory size of V8 global handles.
|
||||
*
|
||||
* `used_global_handles_size` The value of used\_global\_handles\_size is the
|
||||
* used memory size of V8 global handles.
|
||||
*
|
||||
* `external_memory` The value of external\_memory is the memory size of array
|
||||
* buffers and external strings.
|
||||
*
|
||||
* ```js
|
||||
* {
|
||||
* total_heap_size: 7326976,
|
||||
* total_heap_size_executable: 4194304,
|
||||
* total_physical_size: 7326976,
|
||||
* total_available_size: 1152656,
|
||||
* used_heap_size: 3476208,
|
||||
* heap_size_limit: 1535115264,
|
||||
* malloced_memory: 16384,
|
||||
* peak_malloced_memory: 1127496,
|
||||
* does_zap_garbage: 0,
|
||||
* number_of_native_contexts: 1,
|
||||
* number_of_detached_contexts: 0,
|
||||
* total_global_handles_size: 8192,
|
||||
* used_global_handles_size: 3296,
|
||||
* external_memory: 318824
|
||||
* }
|
||||
* ```
|
||||
* @since v1.0.0
|
||||
*/
|
||||
function getHeapStatistics(): HeapInfo;
|
||||
/**
|
||||
* It returns an object with a structure similar to the
|
||||
* [`cppgc::HeapStatistics`](https://v8docs.nodesource.com/node-22.4/d7/d51/heap-statistics_8h_source.html)
|
||||
* object. See the [V8 documentation](https://v8docs.nodesource.com/node-22.4/df/d2f/structcppgc_1_1_heap_statistics.html)
|
||||
* for more information about the properties of the object.
|
||||
*
|
||||
* ```js
|
||||
* // Detailed
|
||||
* ({
|
||||
* committed_size_bytes: 131072,
|
||||
* resident_size_bytes: 131072,
|
||||
* used_size_bytes: 152,
|
||||
* space_statistics: [
|
||||
* {
|
||||
* name: 'NormalPageSpace0',
|
||||
* committed_size_bytes: 0,
|
||||
* resident_size_bytes: 0,
|
||||
* used_size_bytes: 0,
|
||||
* page_stats: [{}],
|
||||
* free_list_stats: {},
|
||||
* },
|
||||
* {
|
||||
* name: 'NormalPageSpace1',
|
||||
* committed_size_bytes: 131072,
|
||||
* resident_size_bytes: 131072,
|
||||
* used_size_bytes: 152,
|
||||
* page_stats: [{}],
|
||||
* free_list_stats: {},
|
||||
* },
|
||||
* {
|
||||
* name: 'NormalPageSpace2',
|
||||
* committed_size_bytes: 0,
|
||||
* resident_size_bytes: 0,
|
||||
* used_size_bytes: 0,
|
||||
* page_stats: [{}],
|
||||
* free_list_stats: {},
|
||||
* },
|
||||
* {
|
||||
* name: 'NormalPageSpace3',
|
||||
* committed_size_bytes: 0,
|
||||
* resident_size_bytes: 0,
|
||||
* used_size_bytes: 0,
|
||||
* page_stats: [{}],
|
||||
* free_list_stats: {},
|
||||
* },
|
||||
* {
|
||||
* name: 'LargePageSpace',
|
||||
* committed_size_bytes: 0,
|
||||
* resident_size_bytes: 0,
|
||||
* used_size_bytes: 0,
|
||||
* page_stats: [{}],
|
||||
* free_list_stats: {},
|
||||
* },
|
||||
* ],
|
||||
* type_names: [],
|
||||
* detail_level: 'detailed',
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* ```js
|
||||
* // Brief
|
||||
* ({
|
||||
* committed_size_bytes: 131072,
|
||||
* resident_size_bytes: 131072,
|
||||
* used_size_bytes: 128864,
|
||||
* space_statistics: [],
|
||||
* type_names: [],
|
||||
* detail_level: 'brief',
|
||||
* });
|
||||
* ```
|
||||
* @since v22.15.0
|
||||
* @param detailLevel **Default:** `'detailed'`. Specifies the level of detail in the returned statistics.
|
||||
* Accepted values are:
|
||||
* * `'brief'`: Brief statistics contain only the top-level
|
||||
* allocated and used
|
||||
* memory statistics for the entire heap.
|
||||
* * `'detailed'`: Detailed statistics also contain a break
|
||||
* down per space and page, as well as freelist statistics
|
||||
* and object type histograms.
|
||||
*/
|
||||
function getCppHeapStatistics(detailLevel?: "brief" | "detailed"): object;
|
||||
/**
|
||||
* Returns statistics about the V8 heap spaces, i.e. the segments which make up
|
||||
* the V8 heap. Neither the ordering of heap spaces, nor the availability of a
|
||||
* heap space can be guaranteed as the statistics are provided via the
|
||||
* V8 [`GetHeapSpaceStatistics`](https://v8docs.nodesource.com/node-13.2/d5/dda/classv8_1_1_isolate.html#ac673576f24fdc7a33378f8f57e1d13a4) function and may change from one V8 version to the
|
||||
* next.
|
||||
*
|
||||
* The value returned is an array of objects containing the following properties:
|
||||
*
|
||||
* ```json
|
||||
* [
|
||||
* {
|
||||
* "space_name": "new_space",
|
||||
* "space_size": 2063872,
|
||||
* "space_used_size": 951112,
|
||||
* "space_available_size": 80824,
|
||||
* "physical_space_size": 2063872
|
||||
* },
|
||||
* {
|
||||
* "space_name": "old_space",
|
||||
* "space_size": 3090560,
|
||||
* "space_used_size": 2493792,
|
||||
* "space_available_size": 0,
|
||||
* "physical_space_size": 3090560
|
||||
* },
|
||||
* {
|
||||
* "space_name": "code_space",
|
||||
* "space_size": 1260160,
|
||||
* "space_used_size": 644256,
|
||||
* "space_available_size": 960,
|
||||
* "physical_space_size": 1260160
|
||||
* },
|
||||
* {
|
||||
* "space_name": "map_space",
|
||||
* "space_size": 1094160,
|
||||
* "space_used_size": 201608,
|
||||
* "space_available_size": 0,
|
||||
* "physical_space_size": 1094160
|
||||
* },
|
||||
* {
|
||||
* "space_name": "large_object_space",
|
||||
* "space_size": 0,
|
||||
* "space_used_size": 0,
|
||||
* "space_available_size": 1490980608,
|
||||
* "physical_space_size": 0
|
||||
* }
|
||||
* ]
|
||||
* ```
|
||||
* @since v6.0.0
|
||||
*/
|
||||
function getHeapSpaceStatistics(): HeapSpaceInfo[];
|
||||
/**
|
||||
* The `v8.setFlagsFromString()` method can be used to programmatically set
|
||||
* V8 command-line flags. This method should be used with care. Changing settings
|
||||
* after the VM has started may result in unpredictable behavior, including
|
||||
* crashes and data loss; or it may simply do nothing.
|
||||
*
|
||||
* The V8 options available for a version of Node.js may be determined by running `node --v8-options`.
|
||||
*
|
||||
* Usage:
|
||||
*
|
||||
* ```js
|
||||
* // Print GC events to stdout for one minute.
|
||||
* import v8 from 'node:v8';
|
||||
* v8.setFlagsFromString('--trace_gc');
|
||||
* setTimeout(() => { v8.setFlagsFromString('--notrace_gc'); }, 60e3);
|
||||
* ```
|
||||
* @since v1.0.0
|
||||
*/
|
||||
function setFlagsFromString(flags: string): void;
|
||||
/**
|
||||
* This is similar to the [`queryObjects()` console API](https://developer.chrome.com/docs/devtools/console/utilities#queryObjects-function)
|
||||
* provided by the Chromium DevTools console. It can be used to search for objects that have the matching constructor on its prototype chain
|
||||
* in the heap after a full garbage collection, which can be useful for memory leak regression tests. To avoid surprising results, users should
|
||||
* avoid using this API on constructors whose implementation they don't control, or on constructors that can be invoked by other parties in the
|
||||
* application.
|
||||
*
|
||||
* To avoid accidental leaks, this API does not return raw references to the objects found. By default, it returns the count of the objects
|
||||
* found. If `options.format` is `'summary'`, it returns an array containing brief string representations for each object. The visibility provided
|
||||
* in this API is similar to what the heap snapshot provides, while users can save the cost of serialization and parsing and directly filter the
|
||||
* target objects during the search.
|
||||
*
|
||||
* Only objects created in the current execution context are included in the results.
|
||||
*
|
||||
* ```js
|
||||
* import { queryObjects } from 'node:v8';
|
||||
* class A { foo = 'bar'; }
|
||||
* console.log(queryObjects(A)); // 0
|
||||
* const a = new A();
|
||||
* console.log(queryObjects(A)); // 1
|
||||
* // [ "A { foo: 'bar' }" ]
|
||||
* console.log(queryObjects(A, { format: 'summary' }));
|
||||
*
|
||||
* class B extends A { bar = 'qux'; }
|
||||
* const b = new B();
|
||||
* console.log(queryObjects(B)); // 1
|
||||
* // [ "B { foo: 'bar', bar: 'qux' }" ]
|
||||
* console.log(queryObjects(B, { format: 'summary' }));
|
||||
*
|
||||
* // Note that, when there are child classes inheriting from a constructor,
|
||||
* // the constructor also shows up in the prototype chain of the child
|
||||
* // classes's prototoype, so the child classes's prototoype would also be
|
||||
* // included in the result.
|
||||
* console.log(queryObjects(A)); // 3
|
||||
* // [ "B { foo: 'bar', bar: 'qux' }", 'A {}', "A { foo: 'bar' }" ]
|
||||
* console.log(queryObjects(A, { format: 'summary' }));
|
||||
* ```
|
||||
* @param ctor The constructor that can be used to search on the prototype chain in order to filter target objects in the heap.
|
||||
* @since v20.13.0
|
||||
* @experimental
|
||||
*/
|
||||
function queryObjects(ctor: Function): number | string[];
|
||||
function queryObjects(ctor: Function, options: { format: "count" }): number;
|
||||
function queryObjects(ctor: Function, options: { format: "summary" }): string[];
|
||||
/**
|
||||
* Generates a snapshot of the current V8 heap and returns a Readable
|
||||
* Stream that may be used to read the JSON serialized representation.
|
||||
* This JSON stream format is intended to be used with tools such as
|
||||
* Chrome DevTools. The JSON schema is undocumented and specific to the
|
||||
* V8 engine. Therefore, the schema may change from one version of V8 to the next.
|
||||
*
|
||||
* Creating a heap snapshot requires memory about twice the size of the heap at
|
||||
* the time the snapshot is created. This results in the risk of OOM killers
|
||||
* terminating the process.
|
||||
*
|
||||
* Generating a snapshot is a synchronous operation which blocks the event loop
|
||||
* for a duration depending on the heap size.
|
||||
*
|
||||
* ```js
|
||||
* // Print heap snapshot to the console
|
||||
* import v8 from 'node:v8';
|
||||
* const stream = v8.getHeapSnapshot();
|
||||
* stream.pipe(process.stdout);
|
||||
* ```
|
||||
* @since v11.13.0
|
||||
* @return A Readable containing the V8 heap snapshot.
|
||||
*/
|
||||
function getHeapSnapshot(options?: HeapSnapshotOptions): Readable;
|
||||
/**
|
||||
* Generates a snapshot of the current V8 heap and writes it to a JSON
|
||||
* file. This file is intended to be used with tools such as Chrome
|
||||
* DevTools. The JSON schema is undocumented and specific to the V8
|
||||
* engine, and may change from one version of V8 to the next.
|
||||
*
|
||||
* A heap snapshot is specific to a single V8 isolate. When using `worker threads`, a heap snapshot generated from the main thread will
|
||||
* not contain any information about the workers, and vice versa.
|
||||
*
|
||||
* Creating a heap snapshot requires memory about twice the size of the heap at
|
||||
* the time the snapshot is created. This results in the risk of OOM killers
|
||||
* terminating the process.
|
||||
*
|
||||
* Generating a snapshot is a synchronous operation which blocks the event loop
|
||||
* for a duration depending on the heap size.
|
||||
*
|
||||
* ```js
|
||||
* import { writeHeapSnapshot } from 'node:v8';
|
||||
* import {
|
||||
* Worker,
|
||||
* isMainThread,
|
||||
* parentPort,
|
||||
* } from 'node:worker_threads';
|
||||
*
|
||||
* if (isMainThread) {
|
||||
* const worker = new Worker(__filename);
|
||||
*
|
||||
* worker.once('message', (filename) => {
|
||||
* console.log(`worker heapdump: ${filename}`);
|
||||
* // Now get a heapdump for the main thread.
|
||||
* console.log(`main thread heapdump: ${writeHeapSnapshot()}`);
|
||||
* });
|
||||
*
|
||||
* // Tell the worker to create a heapdump.
|
||||
* worker.postMessage('heapdump');
|
||||
* } else {
|
||||
* parentPort.once('message', (message) => {
|
||||
* if (message === 'heapdump') {
|
||||
* // Generate a heapdump for the worker
|
||||
* // and return the filename to the parent.
|
||||
* parentPort.postMessage(writeHeapSnapshot());
|
||||
* }
|
||||
* });
|
||||
* }
|
||||
* ```
|
||||
* @since v11.13.0
|
||||
* @param filename The file path where the V8 heap snapshot is to be saved. If not specified, a file name with the pattern `'Heap-${yyyymmdd}-${hhmmss}-${pid}-${thread_id}.heapsnapshot'` will be
|
||||
* generated, where `{pid}` will be the PID of the Node.js process, `{thread_id}` will be `0` when `writeHeapSnapshot()` is called from the main Node.js thread or the id of a
|
||||
* worker thread.
|
||||
* @return The filename where the snapshot was saved.
|
||||
*/
|
||||
function writeHeapSnapshot(filename?: string, options?: HeapSnapshotOptions): string;
|
||||
/**
|
||||
* Get statistics about code and its metadata in the heap, see
|
||||
* V8 [`GetHeapCodeAndMetadataStatistics`](https://v8docs.nodesource.com/node-13.2/d5/dda/classv8_1_1_isolate.html#a6079122af17612ef54ef3348ce170866) API. Returns an object with the
|
||||
* following properties:
|
||||
*
|
||||
* ```js
|
||||
* {
|
||||
* code_and_metadata_size: 212208,
|
||||
* bytecode_and_metadata_size: 161368,
|
||||
* external_script_source_size: 1410794,
|
||||
* cpu_profiler_metadata_size: 0,
|
||||
* }
|
||||
* ```
|
||||
* @since v12.8.0
|
||||
*/
|
||||
function getHeapCodeStatistics(): HeapCodeStatistics;
|
||||
/**
|
||||
* V8 only supports `Latin-1/ISO-8859-1` and `UTF16` as the underlying representation of a string.
|
||||
* If the `content` uses `Latin-1/ISO-8859-1` as the underlying representation, this function will return true;
|
||||
* otherwise, it returns false.
|
||||
*
|
||||
* If this method returns false, that does not mean that the string contains some characters not in `Latin-1/ISO-8859-1`.
|
||||
* Sometimes a `Latin-1` string may also be represented as `UTF16`.
|
||||
*
|
||||
* ```js
|
||||
* const { isStringOneByteRepresentation } = require('node:v8');
|
||||
*
|
||||
* const Encoding = {
|
||||
* latin1: 1,
|
||||
* utf16le: 2,
|
||||
* };
|
||||
* const buffer = Buffer.alloc(100);
|
||||
* function writeString(input) {
|
||||
* if (isStringOneByteRepresentation(input)) {
|
||||
* buffer.writeUint8(Encoding.latin1);
|
||||
* buffer.writeUint32LE(input.length, 1);
|
||||
* buffer.write(input, 5, 'latin1');
|
||||
* } else {
|
||||
* buffer.writeUint8(Encoding.utf16le);
|
||||
* buffer.writeUint32LE(input.length * 2, 1);
|
||||
* buffer.write(input, 5, 'utf16le');
|
||||
* }
|
||||
* }
|
||||
* writeString('hello');
|
||||
* writeString('你好');
|
||||
* ```
|
||||
* @since v23.10.0, v22.15.0
|
||||
*/
|
||||
function isStringOneByteRepresentation(content: string): boolean;
|
||||
/**
|
||||
* @since v8.0.0
|
||||
*/
|
||||
class Serializer {
|
||||
/**
|
||||
* Writes out a header, which includes the serialization format version.
|
||||
*/
|
||||
writeHeader(): void;
|
||||
/**
|
||||
* Serializes a JavaScript value and adds the serialized representation to the
|
||||
* internal buffer.
|
||||
*
|
||||
* This throws an error if `value` cannot be serialized.
|
||||
*/
|
||||
writeValue(val: any): boolean;
|
||||
/**
|
||||
* Returns the stored internal buffer. This serializer should not be used once
|
||||
* the buffer is released. Calling this method results in undefined behavior
|
||||
* if a previous write has failed.
|
||||
*/
|
||||
releaseBuffer(): Buffer;
|
||||
/**
|
||||
* Marks an `ArrayBuffer` as having its contents transferred out of band.
|
||||
* Pass the corresponding `ArrayBuffer` in the deserializing context to `deserializer.transferArrayBuffer()`.
|
||||
* @param id A 32-bit unsigned integer.
|
||||
* @param arrayBuffer An `ArrayBuffer` instance.
|
||||
*/
|
||||
transferArrayBuffer(id: number, arrayBuffer: ArrayBuffer): void;
|
||||
/**
|
||||
* Write a raw 32-bit unsigned integer.
|
||||
* For use inside of a custom `serializer._writeHostObject()`.
|
||||
*/
|
||||
writeUint32(value: number): void;
|
||||
/**
|
||||
* Write a raw 64-bit unsigned integer, split into high and low 32-bit parts.
|
||||
* For use inside of a custom `serializer._writeHostObject()`.
|
||||
*/
|
||||
writeUint64(hi: number, lo: number): void;
|
||||
/**
|
||||
* Write a JS `number` value.
|
||||
* For use inside of a custom `serializer._writeHostObject()`.
|
||||
*/
|
||||
writeDouble(value: number): void;
|
||||
/**
|
||||
* Write raw bytes into the serializer's internal buffer. The deserializer
|
||||
* will require a way to compute the length of the buffer.
|
||||
* For use inside of a custom `serializer._writeHostObject()`.
|
||||
*/
|
||||
writeRawBytes(buffer: NodeJS.TypedArray): void;
|
||||
}
|
||||
/**
|
||||
* A subclass of `Serializer` that serializes `TypedArray`(in particular `Buffer`) and `DataView` objects as host objects, and only
|
||||
* stores the part of their underlying `ArrayBuffer`s that they are referring to.
|
||||
* @since v8.0.0
|
||||
*/
|
||||
class DefaultSerializer extends Serializer {}
|
||||
/**
|
||||
* @since v8.0.0
|
||||
*/
|
||||
class Deserializer {
|
||||
constructor(data: NodeJS.TypedArray);
|
||||
/**
|
||||
* Reads and validates a header (including the format version).
|
||||
* May, for example, reject an invalid or unsupported wire format. In that case,
|
||||
* an `Error` is thrown.
|
||||
*/
|
||||
readHeader(): boolean;
|
||||
/**
|
||||
* Deserializes a JavaScript value from the buffer and returns it.
|
||||
*/
|
||||
readValue(): any;
|
||||
/**
|
||||
* Marks an `ArrayBuffer` as having its contents transferred out of band.
|
||||
* Pass the corresponding `ArrayBuffer` in the serializing context to `serializer.transferArrayBuffer()` (or return the `id` from `serializer._getSharedArrayBufferId()` in the case of
|
||||
* `SharedArrayBuffer`s).
|
||||
* @param id A 32-bit unsigned integer.
|
||||
* @param arrayBuffer An `ArrayBuffer` instance.
|
||||
*/
|
||||
transferArrayBuffer(id: number, arrayBuffer: ArrayBuffer): void;
|
||||
/**
|
||||
* Reads the underlying wire format version. Likely mostly to be useful to
|
||||
* legacy code reading old wire format versions. May not be called before `.readHeader()`.
|
||||
*/
|
||||
getWireFormatVersion(): number;
|
||||
/**
|
||||
* Read a raw 32-bit unsigned integer and return it.
|
||||
* For use inside of a custom `deserializer._readHostObject()`.
|
||||
*/
|
||||
readUint32(): number;
|
||||
/**
|
||||
* Read a raw 64-bit unsigned integer and return it as an array `[hi, lo]` with two 32-bit unsigned integer entries.
|
||||
* For use inside of a custom `deserializer._readHostObject()`.
|
||||
*/
|
||||
readUint64(): [number, number];
|
||||
/**
|
||||
* Read a JS `number` value.
|
||||
* For use inside of a custom `deserializer._readHostObject()`.
|
||||
*/
|
||||
readDouble(): number;
|
||||
/**
|
||||
* Read raw bytes from the deserializer's internal buffer. The `length` parameter
|
||||
* must correspond to the length of the buffer that was passed to `serializer.writeRawBytes()`.
|
||||
* For use inside of a custom `deserializer._readHostObject()`.
|
||||
*/
|
||||
readRawBytes(length: number): Buffer;
|
||||
}
|
||||
/**
|
||||
* A subclass of `Deserializer` corresponding to the format written by `DefaultSerializer`.
|
||||
* @since v8.0.0
|
||||
*/
|
||||
class DefaultDeserializer extends Deserializer {}
|
||||
/**
|
||||
* Uses a `DefaultSerializer` to serialize `value` into a buffer.
|
||||
*
|
||||
* `ERR_BUFFER_TOO_LARGE` will be thrown when trying to
|
||||
* serialize a huge object which requires buffer
|
||||
* larger than `buffer.constants.MAX_LENGTH`.
|
||||
* @since v8.0.0
|
||||
*/
|
||||
function serialize(value: any): Buffer;
|
||||
/**
|
||||
* Uses a `DefaultDeserializer` with default options to read a JS value
|
||||
* from a buffer.
|
||||
* @since v8.0.0
|
||||
* @param buffer A buffer returned by {@link serialize}.
|
||||
*/
|
||||
function deserialize(buffer: NodeJS.ArrayBufferView): any;
|
||||
/**
|
||||
* The `v8.takeCoverage()` method allows the user to write the coverage started by `NODE_V8_COVERAGE` to disk on demand. This method can be invoked multiple
|
||||
* times during the lifetime of the process. Each time the execution counter will
|
||||
* be reset and a new coverage report will be written to the directory specified
|
||||
* by `NODE_V8_COVERAGE`.
|
||||
*
|
||||
* When the process is about to exit, one last coverage will still be written to
|
||||
* disk unless {@link stopCoverage} is invoked before the process exits.
|
||||
* @since v15.1.0, v14.18.0, v12.22.0
|
||||
*/
|
||||
function takeCoverage(): void;
|
||||
/**
|
||||
* The `v8.stopCoverage()` method allows the user to stop the coverage collection
|
||||
* started by `NODE_V8_COVERAGE`, so that V8 can release the execution count
|
||||
* records and optimize code. This can be used in conjunction with {@link takeCoverage} if the user wants to collect the coverage on demand.
|
||||
* @since v15.1.0, v14.18.0, v12.22.0
|
||||
*/
|
||||
function stopCoverage(): void;
|
||||
/**
|
||||
* The API is a no-op if `--heapsnapshot-near-heap-limit` is already set from the command line or the API is called more than once.
|
||||
* `limit` must be a positive integer. See [`--heapsnapshot-near-heap-limit`](https://nodejs.org/docs/latest-v24.x/api/cli.html#--heapsnapshot-near-heap-limitmax_count) for more information.
|
||||
* @since v18.10.0, v16.18.0
|
||||
*/
|
||||
function setHeapSnapshotNearHeapLimit(limit: number): void;
|
||||
/**
|
||||
* This API collects GC data in current thread.
|
||||
* @since v19.6.0, v18.15.0
|
||||
*/
|
||||
class GCProfiler {
|
||||
/**
|
||||
* Start collecting GC data.
|
||||
* @since v19.6.0, v18.15.0
|
||||
*/
|
||||
start(): void;
|
||||
/**
|
||||
* Stop collecting GC data and return an object. The content of object
|
||||
* is as follows.
|
||||
*
|
||||
* ```json
|
||||
* {
|
||||
* "version": 1,
|
||||
* "startTime": 1674059033862,
|
||||
* "statistics": [
|
||||
* {
|
||||
* "gcType": "Scavenge",
|
||||
* "beforeGC": {
|
||||
* "heapStatistics": {
|
||||
* "totalHeapSize": 5005312,
|
||||
* "totalHeapSizeExecutable": 524288,
|
||||
* "totalPhysicalSize": 5226496,
|
||||
* "totalAvailableSize": 4341325216,
|
||||
* "totalGlobalHandlesSize": 8192,
|
||||
* "usedGlobalHandlesSize": 2112,
|
||||
* "usedHeapSize": 4883840,
|
||||
* "heapSizeLimit": 4345298944,
|
||||
* "mallocedMemory": 254128,
|
||||
* "externalMemory": 225138,
|
||||
* "peakMallocedMemory": 181760
|
||||
* },
|
||||
* "heapSpaceStatistics": [
|
||||
* {
|
||||
* "spaceName": "read_only_space",
|
||||
* "spaceSize": 0,
|
||||
* "spaceUsedSize": 0,
|
||||
* "spaceAvailableSize": 0,
|
||||
* "physicalSpaceSize": 0
|
||||
* }
|
||||
* ]
|
||||
* },
|
||||
* "cost": 1574.14,
|
||||
* "afterGC": {
|
||||
* "heapStatistics": {
|
||||
* "totalHeapSize": 6053888,
|
||||
* "totalHeapSizeExecutable": 524288,
|
||||
* "totalPhysicalSize": 5500928,
|
||||
* "totalAvailableSize": 4341101384,
|
||||
* "totalGlobalHandlesSize": 8192,
|
||||
* "usedGlobalHandlesSize": 2112,
|
||||
* "usedHeapSize": 4059096,
|
||||
* "heapSizeLimit": 4345298944,
|
||||
* "mallocedMemory": 254128,
|
||||
* "externalMemory": 225138,
|
||||
* "peakMallocedMemory": 181760
|
||||
* },
|
||||
* "heapSpaceStatistics": [
|
||||
* {
|
||||
* "spaceName": "read_only_space",
|
||||
* "spaceSize": 0,
|
||||
* "spaceUsedSize": 0,
|
||||
* "spaceAvailableSize": 0,
|
||||
* "physicalSpaceSize": 0
|
||||
* }
|
||||
* ]
|
||||
* }
|
||||
* }
|
||||
* ],
|
||||
* "endTime": 1674059036865
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* Here's an example.
|
||||
*
|
||||
* ```js
|
||||
* import { GCProfiler } from 'node:v8';
|
||||
* const profiler = new GCProfiler();
|
||||
* profiler.start();
|
||||
* setTimeout(() => {
|
||||
* console.log(profiler.stop());
|
||||
* }, 1000);
|
||||
* ```
|
||||
* @since v19.6.0, v18.15.0
|
||||
*/
|
||||
stop(): GCProfilerResult;
|
||||
}
|
||||
interface GCProfilerResult {
|
||||
version: number;
|
||||
startTime: number;
|
||||
endTime: number;
|
||||
statistics: Array<{
|
||||
gcType: string;
|
||||
cost: number;
|
||||
beforeGC: {
|
||||
heapStatistics: HeapStatistics;
|
||||
heapSpaceStatistics: HeapSpaceStatistics[];
|
||||
};
|
||||
afterGC: {
|
||||
heapStatistics: HeapStatistics;
|
||||
heapSpaceStatistics: HeapSpaceStatistics[];
|
||||
};
|
||||
}>;
|
||||
}
|
||||
interface HeapStatistics {
|
||||
totalHeapSize: number;
|
||||
totalHeapSizeExecutable: number;
|
||||
totalPhysicalSize: number;
|
||||
totalAvailableSize: number;
|
||||
totalGlobalHandlesSize: number;
|
||||
usedGlobalHandlesSize: number;
|
||||
usedHeapSize: number;
|
||||
heapSizeLimit: number;
|
||||
mallocedMemory: number;
|
||||
externalMemory: number;
|
||||
peakMallocedMemory: number;
|
||||
}
|
||||
interface HeapSpaceStatistics {
|
||||
spaceName: string;
|
||||
spaceSize: number;
|
||||
spaceUsedSize: number;
|
||||
spaceAvailableSize: number;
|
||||
physicalSpaceSize: number;
|
||||
}
|
||||
/**
|
||||
* Called when a promise is constructed. This does not mean that corresponding before/after events will occur, only that the possibility exists. This will
|
||||
* happen if a promise is created without ever getting a continuation.
|
||||
* @since v17.1.0, v16.14.0
|
||||
* @param promise The promise being created.
|
||||
* @param parent The promise continued from, if applicable.
|
||||
*/
|
||||
interface Init {
|
||||
(promise: Promise<unknown>, parent: Promise<unknown>): void;
|
||||
}
|
||||
/**
|
||||
* Called before a promise continuation executes. This can be in the form of `then()`, `catch()`, or `finally()` handlers or an await resuming.
|
||||
*
|
||||
* The before callback will be called 0 to N times. The before callback will typically be called 0 times if no continuation was ever made for the promise.
|
||||
* The before callback may be called many times in the case where many continuations have been made from the same promise.
|
||||
* @since v17.1.0, v16.14.0
|
||||
*/
|
||||
interface Before {
|
||||
(promise: Promise<unknown>): void;
|
||||
}
|
||||
/**
|
||||
* Called immediately after a promise continuation executes. This may be after a `then()`, `catch()`, or `finally()` handler or before an await after another await.
|
||||
* @since v17.1.0, v16.14.0
|
||||
*/
|
||||
interface After {
|
||||
(promise: Promise<unknown>): void;
|
||||
}
|
||||
/**
|
||||
* Called when the promise receives a resolution or rejection value. This may occur synchronously in the case of {@link Promise.resolve()} or
|
||||
* {@link Promise.reject()}.
|
||||
* @since v17.1.0, v16.14.0
|
||||
*/
|
||||
interface Settled {
|
||||
(promise: Promise<unknown>): void;
|
||||
}
|
||||
/**
|
||||
* Key events in the lifetime of a promise have been categorized into four areas: creation of a promise, before/after a continuation handler is called or
|
||||
* around an await, and when the promise resolves or rejects.
|
||||
*
|
||||
* Because promises are asynchronous resources whose lifecycle is tracked via the promise hooks mechanism, the `init()`, `before()`, `after()`, and
|
||||
* `settled()` callbacks must not be async functions as they create more promises which would produce an infinite loop.
|
||||
* @since v17.1.0, v16.14.0
|
||||
*/
|
||||
interface HookCallbacks {
|
||||
init?: Init;
|
||||
before?: Before;
|
||||
after?: After;
|
||||
settled?: Settled;
|
||||
}
|
||||
interface PromiseHooks {
|
||||
/**
|
||||
* The `init` hook must be a plain function. Providing an async function will throw as it would produce an infinite microtask loop.
|
||||
* @since v17.1.0, v16.14.0
|
||||
* @param init The {@link Init | `init` callback} to call when a promise is created.
|
||||
* @return Call to stop the hook.
|
||||
*/
|
||||
onInit: (init: Init) => Function;
|
||||
/**
|
||||
* The `settled` hook must be a plain function. Providing an async function will throw as it would produce an infinite microtask loop.
|
||||
* @since v17.1.0, v16.14.0
|
||||
* @param settled The {@link Settled | `settled` callback} to call when a promise is created.
|
||||
* @return Call to stop the hook.
|
||||
*/
|
||||
onSettled: (settled: Settled) => Function;
|
||||
/**
|
||||
* The `before` hook must be a plain function. Providing an async function will throw as it would produce an infinite microtask loop.
|
||||
* @since v17.1.0, v16.14.0
|
||||
* @param before The {@link Before | `before` callback} to call before a promise continuation executes.
|
||||
* @return Call to stop the hook.
|
||||
*/
|
||||
onBefore: (before: Before) => Function;
|
||||
/**
|
||||
* The `after` hook must be a plain function. Providing an async function will throw as it would produce an infinite microtask loop.
|
||||
* @since v17.1.0, v16.14.0
|
||||
* @param after The {@link After | `after` callback} to call after a promise continuation executes.
|
||||
* @return Call to stop the hook.
|
||||
*/
|
||||
onAfter: (after: After) => Function;
|
||||
/**
|
||||
* Registers functions to be called for different lifetime events of each promise.
|
||||
* The callbacks `init()`/`before()`/`after()`/`settled()` are called for the respective events during a promise's lifetime.
|
||||
* All callbacks are optional. For example, if only promise creation needs to be tracked, then only the init callback needs to be passed.
|
||||
* The hook callbacks must be plain functions. Providing async functions will throw as it would produce an infinite microtask loop.
|
||||
* @since v17.1.0, v16.14.0
|
||||
* @param callbacks The {@link HookCallbacks | Hook Callbacks} to register
|
||||
* @return Used for disabling hooks
|
||||
*/
|
||||
createHook: (callbacks: HookCallbacks) => Function;
|
||||
}
|
||||
/**
|
||||
* The `promiseHooks` interface can be used to track promise lifecycle events.
|
||||
* @since v17.1.0, v16.14.0
|
||||
*/
|
||||
const promiseHooks: PromiseHooks;
|
||||
type StartupSnapshotCallbackFn = (args: any) => any;
|
||||
/**
|
||||
* The `v8.startupSnapshot` interface can be used to add serialization and deserialization hooks for custom startup snapshots.
|
||||
*
|
||||
* ```bash
|
||||
* $ node --snapshot-blob snapshot.blob --build-snapshot entry.js
|
||||
* # This launches a process with the snapshot
|
||||
* $ node --snapshot-blob snapshot.blob
|
||||
* ```
|
||||
*
|
||||
* In the example above, `entry.js` can use methods from the `v8.startupSnapshot` interface to specify how to save information for custom objects
|
||||
* in the snapshot during serialization and how the information can be used to synchronize these objects during deserialization of the snapshot.
|
||||
* For example, if the `entry.js` contains the following script:
|
||||
*
|
||||
* ```js
|
||||
* 'use strict';
|
||||
*
|
||||
* import fs from 'node:fs';
|
||||
* import zlib from 'node:zlib';
|
||||
* import path from 'node:path';
|
||||
* import assert from 'node:assert';
|
||||
*
|
||||
* import v8 from 'node:v8';
|
||||
*
|
||||
* class BookShelf {
|
||||
* storage = new Map();
|
||||
*
|
||||
* // Reading a series of files from directory and store them into storage.
|
||||
* constructor(directory, books) {
|
||||
* for (const book of books) {
|
||||
* this.storage.set(book, fs.readFileSync(path.join(directory, book)));
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* static compressAll(shelf) {
|
||||
* for (const [ book, content ] of shelf.storage) {
|
||||
* shelf.storage.set(book, zlib.gzipSync(content));
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* static decompressAll(shelf) {
|
||||
* for (const [ book, content ] of shelf.storage) {
|
||||
* shelf.storage.set(book, zlib.gunzipSync(content));
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* // __dirname here is where the snapshot script is placed
|
||||
* // during snapshot building time.
|
||||
* const shelf = new BookShelf(__dirname, [
|
||||
* 'book1.en_US.txt',
|
||||
* 'book1.es_ES.txt',
|
||||
* 'book2.zh_CN.txt',
|
||||
* ]);
|
||||
*
|
||||
* assert(v8.startupSnapshot.isBuildingSnapshot());
|
||||
* // On snapshot serialization, compress the books to reduce size.
|
||||
* v8.startupSnapshot.addSerializeCallback(BookShelf.compressAll, shelf);
|
||||
* // On snapshot deserialization, decompress the books.
|
||||
* v8.startupSnapshot.addDeserializeCallback(BookShelf.decompressAll, shelf);
|
||||
* v8.startupSnapshot.setDeserializeMainFunction((shelf) => {
|
||||
* // process.env and process.argv are refreshed during snapshot
|
||||
* // deserialization.
|
||||
* const lang = process.env.BOOK_LANG || 'en_US';
|
||||
* const book = process.argv[1];
|
||||
* const name = `${book}.${lang}.txt`;
|
||||
* console.log(shelf.storage.get(name));
|
||||
* }, shelf);
|
||||
* ```
|
||||
*
|
||||
* The resulted binary will get print the data deserialized from the snapshot during start up, using the refreshed `process.env` and `process.argv` of the launched process:
|
||||
*
|
||||
* ```bash
|
||||
* $ BOOK_LANG=es_ES node --snapshot-blob snapshot.blob book1
|
||||
* # Prints content of book1.es_ES.txt deserialized from the snapshot.
|
||||
* ```
|
||||
*
|
||||
* Currently the application deserialized from a user-land snapshot cannot be snapshotted again, so these APIs are only available to applications that are not deserialized from a user-land snapshot.
|
||||
*
|
||||
* @since v18.6.0, v16.17.0
|
||||
*/
|
||||
namespace startupSnapshot {
|
||||
/**
|
||||
* Add a callback that will be called when the Node.js instance is about to get serialized into a snapshot and exit.
|
||||
* This can be used to release resources that should not or cannot be serialized or to convert user data into a form more suitable for serialization.
|
||||
* @since v18.6.0, v16.17.0
|
||||
*/
|
||||
function addSerializeCallback(callback: StartupSnapshotCallbackFn, data?: any): void;
|
||||
/**
|
||||
* Add a callback that will be called when the Node.js instance is deserialized from a snapshot.
|
||||
* The `callback` and the `data` (if provided) will be serialized into the snapshot, they can be used to re-initialize the state of the application or
|
||||
* to re-acquire resources that the application needs when the application is restarted from the snapshot.
|
||||
* @since v18.6.0, v16.17.0
|
||||
*/
|
||||
function addDeserializeCallback(callback: StartupSnapshotCallbackFn, data?: any): void;
|
||||
/**
|
||||
* This sets the entry point of the Node.js application when it is deserialized from a snapshot. This can be called only once in the snapshot building script.
|
||||
* If called, the deserialized application no longer needs an additional entry point script to start up and will simply invoke the callback along with the deserialized
|
||||
* data (if provided), otherwise an entry point script still needs to be provided to the deserialized application.
|
||||
* @since v18.6.0, v16.17.0
|
||||
*/
|
||||
function setDeserializeMainFunction(callback: StartupSnapshotCallbackFn, data?: any): void;
|
||||
/**
|
||||
* Returns true if the Node.js instance is run to build a snapshot.
|
||||
* @since v18.6.0, v16.17.0
|
||||
*/
|
||||
function isBuildingSnapshot(): boolean;
|
||||
}
|
||||
}
|
||||
declare module "node:v8" {
|
||||
export * from "v8";
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,181 +0,0 @@
|
||||
/**
|
||||
* **The `node:wasi` module does not currently provide the**
|
||||
* **comprehensive file system security properties provided by some WASI runtimes.**
|
||||
* **Full support for secure file system sandboxing may or may not be implemented in**
|
||||
* **future. In the mean time, do not rely on it to run untrusted code.**
|
||||
*
|
||||
* The WASI API provides an implementation of the [WebAssembly System Interface](https://wasi.dev/) specification. WASI gives WebAssembly applications access to the underlying
|
||||
* operating system via a collection of POSIX-like functions.
|
||||
*
|
||||
* ```js
|
||||
* import { readFile } from 'node:fs/promises';
|
||||
* import { WASI } from 'node:wasi';
|
||||
* import { argv, env } from 'node:process';
|
||||
*
|
||||
* const wasi = new WASI({
|
||||
* version: 'preview1',
|
||||
* args: argv,
|
||||
* env,
|
||||
* preopens: {
|
||||
* '/local': '/some/real/path/that/wasm/can/access',
|
||||
* },
|
||||
* });
|
||||
*
|
||||
* const wasm = await WebAssembly.compile(
|
||||
* await readFile(new URL('./demo.wasm', import.meta.url)),
|
||||
* );
|
||||
* const instance = await WebAssembly.instantiate(wasm, wasi.getImportObject());
|
||||
*
|
||||
* wasi.start(instance);
|
||||
* ```
|
||||
*
|
||||
* To run the above example, create a new WebAssembly text format file named `demo.wat`:
|
||||
*
|
||||
* ```text
|
||||
* (module
|
||||
* ;; Import the required fd_write WASI function which will write the given io vectors to stdout
|
||||
* ;; The function signature for fd_write is:
|
||||
* ;; (File Descriptor, *iovs, iovs_len, nwritten) -> Returns number of bytes written
|
||||
* (import "wasi_snapshot_preview1" "fd_write" (func $fd_write (param i32 i32 i32 i32) (result i32)))
|
||||
*
|
||||
* (memory 1)
|
||||
* (export "memory" (memory 0))
|
||||
*
|
||||
* ;; Write 'hello world\n' to memory at an offset of 8 bytes
|
||||
* ;; Note the trailing newline which is required for the text to appear
|
||||
* (data (i32.const 8) "hello world\n")
|
||||
*
|
||||
* (func $main (export "_start")
|
||||
* ;; Creating a new io vector within linear memory
|
||||
* (i32.store (i32.const 0) (i32.const 8)) ;; iov.iov_base - This is a pointer to the start of the 'hello world\n' string
|
||||
* (i32.store (i32.const 4) (i32.const 12)) ;; iov.iov_len - The length of the 'hello world\n' string
|
||||
*
|
||||
* (call $fd_write
|
||||
* (i32.const 1) ;; file_descriptor - 1 for stdout
|
||||
* (i32.const 0) ;; *iovs - The pointer to the iov array, which is stored at memory location 0
|
||||
* (i32.const 1) ;; iovs_len - We're printing 1 string stored in an iov - so one.
|
||||
* (i32.const 20) ;; nwritten - A place in memory to store the number of bytes written
|
||||
* )
|
||||
* drop ;; Discard the number of bytes written from the top of the stack
|
||||
* )
|
||||
* )
|
||||
* ```
|
||||
*
|
||||
* Use [wabt](https://github.com/WebAssembly/wabt) to compile `.wat` to `.wasm`
|
||||
*
|
||||
* ```bash
|
||||
* wat2wasm demo.wat
|
||||
* ```
|
||||
* @experimental
|
||||
* @see [source](https://github.com/nodejs/node/blob/v24.x/lib/wasi.js)
|
||||
*/
|
||||
declare module "wasi" {
|
||||
interface WASIOptions {
|
||||
/**
|
||||
* An array of strings that the WebAssembly application will
|
||||
* see as command line arguments. The first argument is the virtual path to the
|
||||
* WASI command itself.
|
||||
* @default []
|
||||
*/
|
||||
args?: string[] | undefined;
|
||||
/**
|
||||
* An object similar to `process.env` that the WebAssembly
|
||||
* application will see as its environment.
|
||||
* @default {}
|
||||
*/
|
||||
env?: object | undefined;
|
||||
/**
|
||||
* This object represents the WebAssembly application's
|
||||
* sandbox directory structure. The string keys of `preopens` are treated as
|
||||
* directories within the sandbox. The corresponding values in `preopens` are
|
||||
* the real paths to those directories on the host machine.
|
||||
*/
|
||||
preopens?: NodeJS.Dict<string> | undefined;
|
||||
/**
|
||||
* By default, when WASI applications call `__wasi_proc_exit()`
|
||||
* `wasi.start()` will return with the exit code specified rather than terminatng the process.
|
||||
* Setting this option to `false` will cause the Node.js process to exit with
|
||||
* the specified exit code instead.
|
||||
* @default true
|
||||
*/
|
||||
returnOnExit?: boolean | undefined;
|
||||
/**
|
||||
* The file descriptor used as standard input in the WebAssembly application.
|
||||
* @default 0
|
||||
*/
|
||||
stdin?: number | undefined;
|
||||
/**
|
||||
* The file descriptor used as standard output in the WebAssembly application.
|
||||
* @default 1
|
||||
*/
|
||||
stdout?: number | undefined;
|
||||
/**
|
||||
* The file descriptor used as standard error in the WebAssembly application.
|
||||
* @default 2
|
||||
*/
|
||||
stderr?: number | undefined;
|
||||
/**
|
||||
* The version of WASI requested.
|
||||
* Currently the only supported versions are `'unstable'` and `'preview1'`. This option is mandatory.
|
||||
* @since v19.8.0
|
||||
*/
|
||||
version: "unstable" | "preview1";
|
||||
}
|
||||
/**
|
||||
* The `WASI` class provides the WASI system call API and additional convenience
|
||||
* methods for working with WASI-based applications. Each `WASI` instance
|
||||
* represents a distinct environment.
|
||||
* @since v13.3.0, v12.16.0
|
||||
*/
|
||||
class WASI {
|
||||
constructor(options?: WASIOptions);
|
||||
/**
|
||||
* Return an import object that can be passed to `WebAssembly.instantiate()` if no other WASM imports are needed beyond those provided by WASI.
|
||||
*
|
||||
* If version `unstable` was passed into the constructor it will return:
|
||||
*
|
||||
* ```js
|
||||
* { wasi_unstable: wasi.wasiImport }
|
||||
* ```
|
||||
*
|
||||
* If version `preview1` was passed into the constructor or no version was specified it will return:
|
||||
*
|
||||
* ```js
|
||||
* { wasi_snapshot_preview1: wasi.wasiImport }
|
||||
* ```
|
||||
* @since v19.8.0
|
||||
*/
|
||||
getImportObject(): object;
|
||||
/**
|
||||
* Attempt to begin execution of `instance` as a WASI command by invoking its `_start()` export. If `instance` does not contain a `_start()` export, or if `instance` contains an `_initialize()`
|
||||
* export, then an exception is thrown.
|
||||
*
|
||||
* `start()` requires that `instance` exports a [`WebAssembly.Memory`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory) named `memory`. If
|
||||
* `instance` does not have a `memory` export an exception is thrown.
|
||||
*
|
||||
* If `start()` is called more than once, an exception is thrown.
|
||||
* @since v13.3.0, v12.16.0
|
||||
*/
|
||||
start(instance: object): number; // TODO: avoid DOM dependency until WASM moved to own lib.
|
||||
/**
|
||||
* Attempt to initialize `instance` as a WASI reactor by invoking its `_initialize()` export, if it is present. If `instance` contains a `_start()` export, then an exception is thrown.
|
||||
*
|
||||
* `initialize()` requires that `instance` exports a [`WebAssembly.Memory`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Memory) named `memory`.
|
||||
* If `instance` does not have a `memory` export an exception is thrown.
|
||||
*
|
||||
* If `initialize()` is called more than once, an exception is thrown.
|
||||
* @since v14.6.0, v12.19.0
|
||||
*/
|
||||
initialize(instance: object): void; // TODO: avoid DOM dependency until WASM moved to own lib.
|
||||
/**
|
||||
* `wasiImport` is an object that implements the WASI system call API. This object
|
||||
* should be passed as the `wasi_snapshot_preview1` import during the instantiation
|
||||
* of a [`WebAssembly.Instance`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Instance).
|
||||
* @since v13.3.0, v12.16.0
|
||||
*/
|
||||
readonly wasiImport: NodeJS.Dict<any>; // TODO: Narrow to DOM types
|
||||
}
|
||||
}
|
||||
declare module "node:wasi" {
|
||||
export * from "wasi";
|
||||
}
|
||||
-787
@@ -1,787 +0,0 @@
|
||||
/**
|
||||
* The `node:worker_threads` module enables the use of threads that execute
|
||||
* JavaScript in parallel. To access it:
|
||||
*
|
||||
* ```js
|
||||
* import worker from 'node:worker_threads';
|
||||
* ```
|
||||
*
|
||||
* Workers (threads) are useful for performing CPU-intensive JavaScript operations.
|
||||
* They do not help much with I/O-intensive work. The Node.js built-in
|
||||
* asynchronous I/O operations are more efficient than Workers can be.
|
||||
*
|
||||
* Unlike `child_process` or `cluster`, `worker_threads` can share memory. They do
|
||||
* so by transferring `ArrayBuffer` instances or sharing `SharedArrayBuffer` instances.
|
||||
*
|
||||
* ```js
|
||||
* import {
|
||||
* Worker,
|
||||
* isMainThread,
|
||||
* parentPort,
|
||||
* workerData,
|
||||
* } from 'node:worker_threads';
|
||||
*
|
||||
* if (!isMainThread) {
|
||||
* const { parse } = await import('some-js-parsing-library');
|
||||
* const script = workerData;
|
||||
* parentPort.postMessage(parse(script));
|
||||
* }
|
||||
*
|
||||
* export default function parseJSAsync(script) {
|
||||
* return new Promise((resolve, reject) => {
|
||||
* const worker = new Worker(new URL(import.meta.url), {
|
||||
* workerData: script,
|
||||
* });
|
||||
* worker.on('message', resolve);
|
||||
* worker.on('error', reject);
|
||||
* worker.on('exit', (code) => {
|
||||
* if (code !== 0)
|
||||
* reject(new Error(`Worker stopped with exit code ${code}`));
|
||||
* });
|
||||
* });
|
||||
* };
|
||||
* ```
|
||||
*
|
||||
* The above example spawns a Worker thread for each `parseJSAsync()` call. In
|
||||
* practice, use a pool of Workers for these kinds of tasks. Otherwise, the
|
||||
* overhead of creating Workers would likely exceed their benefit.
|
||||
*
|
||||
* When implementing a worker pool, use the `AsyncResource` API to inform
|
||||
* diagnostic tools (e.g. to provide asynchronous stack traces) about the
|
||||
* correlation between tasks and their outcomes. See `"Using AsyncResource for a Worker thread pool"` in the `async_hooks` documentation for an example implementation.
|
||||
*
|
||||
* Worker threads inherit non-process-specific options by default. Refer to `Worker constructor options` to know how to customize worker thread options,
|
||||
* specifically `argv` and `execArgv` options.
|
||||
* @see [source](https://github.com/nodejs/node/blob/v24.x/lib/worker_threads.js)
|
||||
*/
|
||||
declare module "worker_threads" {
|
||||
import { Context } from "node:vm";
|
||||
import { EventEmitter } from "node:events";
|
||||
import { EventLoopUtilityFunction } from "node:perf_hooks";
|
||||
import { FileHandle } from "node:fs/promises";
|
||||
import { Readable, Writable } from "node:stream";
|
||||
import { ReadableStream, TransformStream, WritableStream } from "node:stream/web";
|
||||
import { URL } from "node:url";
|
||||
import { HeapInfo } from "node:v8";
|
||||
const isInternalThread: boolean;
|
||||
const isMainThread: boolean;
|
||||
const parentPort: null | MessagePort;
|
||||
const resourceLimits: ResourceLimits;
|
||||
const SHARE_ENV: unique symbol;
|
||||
const threadId: number;
|
||||
const workerData: any;
|
||||
/**
|
||||
* Instances of the `worker.MessageChannel` class represent an asynchronous,
|
||||
* two-way communications channel.
|
||||
* The `MessageChannel` has no methods of its own. `new MessageChannel()` yields an object with `port1` and `port2` properties, which refer to linked `MessagePort` instances.
|
||||
*
|
||||
* ```js
|
||||
* import { MessageChannel } from 'node:worker_threads';
|
||||
*
|
||||
* const { port1, port2 } = new MessageChannel();
|
||||
* port1.on('message', (message) => console.log('received', message));
|
||||
* port2.postMessage({ foo: 'bar' });
|
||||
* // Prints: received { foo: 'bar' } from the `port1.on('message')` listener
|
||||
* ```
|
||||
* @since v10.5.0
|
||||
*/
|
||||
class MessageChannel {
|
||||
readonly port1: MessagePort;
|
||||
readonly port2: MessagePort;
|
||||
}
|
||||
interface WorkerPerformance {
|
||||
eventLoopUtilization: EventLoopUtilityFunction;
|
||||
}
|
||||
type Transferable =
|
||||
| ArrayBuffer
|
||||
| MessagePort
|
||||
| AbortSignal
|
||||
| FileHandle
|
||||
| ReadableStream
|
||||
| WritableStream
|
||||
| TransformStream;
|
||||
/** @deprecated Use `import { Transferable } from "node:worker_threads"` instead. */
|
||||
// TODO: remove in a future major @types/node version.
|
||||
type TransferListItem = Transferable;
|
||||
/**
|
||||
* Instances of the `worker.MessagePort` class represent one end of an
|
||||
* asynchronous, two-way communications channel. It can be used to transfer
|
||||
* structured data, memory regions and other `MessagePort`s between different `Worker`s.
|
||||
*
|
||||
* This implementation matches [browser `MessagePort`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort) s.
|
||||
* @since v10.5.0
|
||||
*/
|
||||
class MessagePort extends EventEmitter {
|
||||
/**
|
||||
* Disables further sending of messages on either side of the connection.
|
||||
* This method can be called when no further communication will happen over this `MessagePort`.
|
||||
*
|
||||
* The `'close' event` is emitted on both `MessagePort` instances that
|
||||
* are part of the channel.
|
||||
* @since v10.5.0
|
||||
*/
|
||||
close(): void;
|
||||
/**
|
||||
* Sends a JavaScript value to the receiving side of this channel. `value` is transferred in a way which is compatible with
|
||||
* the [HTML structured clone algorithm](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API/Structured_clone_algorithm).
|
||||
*
|
||||
* In particular, the significant differences to `JSON` are:
|
||||
*
|
||||
* * `value` may contain circular references.
|
||||
* * `value` may contain instances of builtin JS types such as `RegExp`s, `BigInt`s, `Map`s, `Set`s, etc.
|
||||
* * `value` may contain typed arrays, both using `ArrayBuffer`s
|
||||
* and `SharedArrayBuffer`s.
|
||||
* * `value` may contain [`WebAssembly.Module`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/WebAssembly/Module) instances.
|
||||
* * `value` may not contain native (C++-backed) objects other than:
|
||||
*
|
||||
* ```js
|
||||
* import { MessageChannel } from 'node:worker_threads';
|
||||
* const { port1, port2 } = new MessageChannel();
|
||||
*
|
||||
* port1.on('message', (message) => console.log(message));
|
||||
*
|
||||
* const circularData = {};
|
||||
* circularData.foo = circularData;
|
||||
* // Prints: { foo: [Circular] }
|
||||
* port2.postMessage(circularData);
|
||||
* ```
|
||||
*
|
||||
* `transferList` may be a list of [`ArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/ArrayBuffer), `MessagePort`, and `FileHandle` objects.
|
||||
* After transferring, they are not usable on the sending side of the channel
|
||||
* anymore (even if they are not contained in `value`). Unlike with `child processes`, transferring handles such as network sockets is currently
|
||||
* not supported.
|
||||
*
|
||||
* If `value` contains [`SharedArrayBuffer`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer) instances, those are accessible
|
||||
* from either thread. They cannot be listed in `transferList`.
|
||||
*
|
||||
* `value` may still contain `ArrayBuffer` instances that are not in `transferList`; in that case, the underlying memory is copied rather than moved.
|
||||
*
|
||||
* ```js
|
||||
* import { MessageChannel } from 'node:worker_threads';
|
||||
* const { port1, port2 } = new MessageChannel();
|
||||
*
|
||||
* port1.on('message', (message) => console.log(message));
|
||||
*
|
||||
* const uint8Array = new Uint8Array([ 1, 2, 3, 4 ]);
|
||||
* // This posts a copy of `uint8Array`:
|
||||
* port2.postMessage(uint8Array);
|
||||
* // This does not copy data, but renders `uint8Array` unusable:
|
||||
* port2.postMessage(uint8Array, [ uint8Array.buffer ]);
|
||||
*
|
||||
* // The memory for the `sharedUint8Array` is accessible from both the
|
||||
* // original and the copy received by `.on('message')`:
|
||||
* const sharedUint8Array = new Uint8Array(new SharedArrayBuffer(4));
|
||||
* port2.postMessage(sharedUint8Array);
|
||||
*
|
||||
* // This transfers a freshly created message port to the receiver.
|
||||
* // This can be used, for example, to create communication channels between
|
||||
* // multiple `Worker` threads that are children of the same parent thread.
|
||||
* const otherChannel = new MessageChannel();
|
||||
* port2.postMessage({ port: otherChannel.port1 }, [ otherChannel.port1 ]);
|
||||
* ```
|
||||
*
|
||||
* The message object is cloned immediately, and can be modified after
|
||||
* posting without having side effects.
|
||||
*
|
||||
* For more information on the serialization and deserialization mechanisms
|
||||
* behind this API, see the `serialization API of the node:v8 module`.
|
||||
* @since v10.5.0
|
||||
*/
|
||||
postMessage(value: any, transferList?: readonly Transferable[]): void;
|
||||
/**
|
||||
* If true, the `MessagePort` object will keep the Node.js event loop active.
|
||||
* @since v18.1.0, v16.17.0
|
||||
*/
|
||||
hasRef(): boolean;
|
||||
/**
|
||||
* Opposite of `unref()`. Calling `ref()` on a previously `unref()`ed port does _not_ let the program exit if it's the only active handle left (the default
|
||||
* behavior). If the port is `ref()`ed, calling `ref()` again has no effect.
|
||||
*
|
||||
* If listeners are attached or removed using `.on('message')`, the port
|
||||
* is `ref()`ed and `unref()`ed automatically depending on whether
|
||||
* listeners for the event exist.
|
||||
* @since v10.5.0
|
||||
*/
|
||||
ref(): void;
|
||||
/**
|
||||
* Calling `unref()` on a port allows the thread to exit if this is the only
|
||||
* active handle in the event system. If the port is already `unref()`ed calling `unref()` again has no effect.
|
||||
*
|
||||
* If listeners are attached or removed using `.on('message')`, the port is `ref()`ed and `unref()`ed automatically depending on whether
|
||||
* listeners for the event exist.
|
||||
* @since v10.5.0
|
||||
*/
|
||||
unref(): void;
|
||||
/**
|
||||
* Starts receiving messages on this `MessagePort`. When using this port
|
||||
* as an event emitter, this is called automatically once `'message'` listeners are attached.
|
||||
*
|
||||
* This method exists for parity with the Web `MessagePort` API. In Node.js,
|
||||
* it is only useful for ignoring messages when no event listener is present.
|
||||
* Node.js also diverges in its handling of `.onmessage`. Setting it
|
||||
* automatically calls `.start()`, but unsetting it lets messages queue up
|
||||
* until a new handler is set or the port is discarded.
|
||||
* @since v10.5.0
|
||||
*/
|
||||
start(): void;
|
||||
addListener(event: "close", listener: () => void): this;
|
||||
addListener(event: "message", listener: (value: any) => void): this;
|
||||
addListener(event: "messageerror", listener: (error: Error) => void): this;
|
||||
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||
emit(event: "close"): boolean;
|
||||
emit(event: "message", value: any): boolean;
|
||||
emit(event: "messageerror", error: Error): boolean;
|
||||
emit(event: string | symbol, ...args: any[]): boolean;
|
||||
on(event: "close", listener: () => void): this;
|
||||
on(event: "message", listener: (value: any) => void): this;
|
||||
on(event: "messageerror", listener: (error: Error) => void): this;
|
||||
on(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||
once(event: "close", listener: () => void): this;
|
||||
once(event: "message", listener: (value: any) => void): this;
|
||||
once(event: "messageerror", listener: (error: Error) => void): this;
|
||||
once(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||
prependListener(event: "close", listener: () => void): this;
|
||||
prependListener(event: "message", listener: (value: any) => void): this;
|
||||
prependListener(event: "messageerror", listener: (error: Error) => void): this;
|
||||
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||
prependOnceListener(event: "close", listener: () => void): this;
|
||||
prependOnceListener(event: "message", listener: (value: any) => void): this;
|
||||
prependOnceListener(event: "messageerror", listener: (error: Error) => void): this;
|
||||
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||
removeListener(event: "close", listener: () => void): this;
|
||||
removeListener(event: "message", listener: (value: any) => void): this;
|
||||
removeListener(event: "messageerror", listener: (error: Error) => void): this;
|
||||
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||
off(event: "close", listener: () => void): this;
|
||||
off(event: "message", listener: (value: any) => void): this;
|
||||
off(event: "messageerror", listener: (error: Error) => void): this;
|
||||
off(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||
addEventListener: EventTarget["addEventListener"];
|
||||
dispatchEvent: EventTarget["dispatchEvent"];
|
||||
removeEventListener: EventTarget["removeEventListener"];
|
||||
}
|
||||
interface WorkerOptions {
|
||||
/**
|
||||
* List of arguments which would be stringified and appended to
|
||||
* `process.argv` in the worker. This is mostly similar to the `workerData`
|
||||
* but the values will be available on the global `process.argv` as if they
|
||||
* were passed as CLI options to the script.
|
||||
*/
|
||||
argv?: any[] | undefined;
|
||||
env?: NodeJS.Dict<string> | typeof SHARE_ENV | undefined;
|
||||
eval?: boolean | undefined;
|
||||
workerData?: any;
|
||||
stdin?: boolean | undefined;
|
||||
stdout?: boolean | undefined;
|
||||
stderr?: boolean | undefined;
|
||||
execArgv?: string[] | undefined;
|
||||
resourceLimits?: ResourceLimits | undefined;
|
||||
/**
|
||||
* Additional data to send in the first worker message.
|
||||
*/
|
||||
transferList?: Transferable[] | undefined;
|
||||
/**
|
||||
* @default true
|
||||
*/
|
||||
trackUnmanagedFds?: boolean | undefined;
|
||||
/**
|
||||
* An optional `name` to be appended to the worker title
|
||||
* for debugging/identification purposes, making the final title as
|
||||
* `[worker ${id}] ${name}`.
|
||||
*/
|
||||
name?: string | undefined;
|
||||
}
|
||||
interface ResourceLimits {
|
||||
/**
|
||||
* The maximum size of a heap space for recently created objects.
|
||||
*/
|
||||
maxYoungGenerationSizeMb?: number | undefined;
|
||||
/**
|
||||
* The maximum size of the main heap in MB.
|
||||
*/
|
||||
maxOldGenerationSizeMb?: number | undefined;
|
||||
/**
|
||||
* The size of a pre-allocated memory range used for generated code.
|
||||
*/
|
||||
codeRangeSizeMb?: number | undefined;
|
||||
/**
|
||||
* The default maximum stack size for the thread. Small values may lead to unusable Worker instances.
|
||||
* @default 4
|
||||
*/
|
||||
stackSizeMb?: number | undefined;
|
||||
}
|
||||
/**
|
||||
* The `Worker` class represents an independent JavaScript execution thread.
|
||||
* Most Node.js APIs are available inside of it.
|
||||
*
|
||||
* Notable differences inside a Worker environment are:
|
||||
*
|
||||
* * The `process.stdin`, `process.stdout`, and `process.stderr` streams may be redirected by the parent thread.
|
||||
* * The `import { isMainThread } from 'node:worker_threads'` variable is set to `false`.
|
||||
* * The `import { parentPort } from 'node:worker_threads'` message port is available.
|
||||
* * `process.exit()` does not stop the whole program, just the single thread,
|
||||
* and `process.abort()` is not available.
|
||||
* * `process.chdir()` and `process` methods that set group or user ids
|
||||
* are not available.
|
||||
* * `process.env` is a copy of the parent thread's environment variables,
|
||||
* unless otherwise specified. Changes to one copy are not visible in other
|
||||
* threads, and are not visible to native add-ons (unless `worker.SHARE_ENV` is passed as the `env` option to the `Worker` constructor). On Windows, unlike the main thread, a copy of the
|
||||
* environment variables operates in a case-sensitive manner.
|
||||
* * `process.title` cannot be modified.
|
||||
* * Signals are not delivered through `process.on('...')`.
|
||||
* * Execution may stop at any point as a result of `worker.terminate()` being invoked.
|
||||
* * IPC channels from parent processes are not accessible.
|
||||
* * The `trace_events` module is not supported.
|
||||
* * Native add-ons can only be loaded from multiple threads if they fulfill `certain conditions`.
|
||||
*
|
||||
* Creating `Worker` instances inside of other `Worker`s is possible.
|
||||
*
|
||||
* Like [Web Workers](https://developer.mozilla.org/en-US/docs/Web/API/Web_Workers_API) and the `node:cluster module`, two-way communication
|
||||
* can be achieved through inter-thread message passing. Internally, a `Worker` has
|
||||
* a built-in pair of `MessagePort` s that are already associated with each
|
||||
* other when the `Worker` is created. While the `MessagePort` object on the parent
|
||||
* side is not directly exposed, its functionalities are exposed through `worker.postMessage()` and the `worker.on('message')` event
|
||||
* on the `Worker` object for the parent thread.
|
||||
*
|
||||
* To create custom messaging channels (which is encouraged over using the default
|
||||
* global channel because it facilitates separation of concerns), users can create
|
||||
* a `MessageChannel` object on either thread and pass one of the`MessagePort`s on that `MessageChannel` to the other thread through a
|
||||
* pre-existing channel, such as the global one.
|
||||
*
|
||||
* See `port.postMessage()` for more information on how messages are passed,
|
||||
* and what kind of JavaScript values can be successfully transported through
|
||||
* the thread barrier.
|
||||
*
|
||||
* ```js
|
||||
* import assert from 'node:assert';
|
||||
* import {
|
||||
* Worker, MessageChannel, MessagePort, isMainThread, parentPort,
|
||||
* } from 'node:worker_threads';
|
||||
* if (isMainThread) {
|
||||
* const worker = new Worker(__filename);
|
||||
* const subChannel = new MessageChannel();
|
||||
* worker.postMessage({ hereIsYourPort: subChannel.port1 }, [subChannel.port1]);
|
||||
* subChannel.port2.on('message', (value) => {
|
||||
* console.log('received:', value);
|
||||
* });
|
||||
* } else {
|
||||
* parentPort.once('message', (value) => {
|
||||
* assert(value.hereIsYourPort instanceof MessagePort);
|
||||
* value.hereIsYourPort.postMessage('the worker is sending this');
|
||||
* value.hereIsYourPort.close();
|
||||
* });
|
||||
* }
|
||||
* ```
|
||||
* @since v10.5.0
|
||||
*/
|
||||
class Worker extends EventEmitter {
|
||||
/**
|
||||
* If `stdin: true` was passed to the `Worker` constructor, this is a
|
||||
* writable stream. The data written to this stream will be made available in
|
||||
* the worker thread as `process.stdin`.
|
||||
* @since v10.5.0
|
||||
*/
|
||||
readonly stdin: Writable | null;
|
||||
/**
|
||||
* This is a readable stream which contains data written to `process.stdout` inside the worker thread. If `stdout: true` was not passed to the `Worker` constructor, then data is piped to the
|
||||
* parent thread's `process.stdout` stream.
|
||||
* @since v10.5.0
|
||||
*/
|
||||
readonly stdout: Readable;
|
||||
/**
|
||||
* This is a readable stream which contains data written to `process.stderr` inside the worker thread. If `stderr: true` was not passed to the `Worker` constructor, then data is piped to the
|
||||
* parent thread's `process.stderr` stream.
|
||||
* @since v10.5.0
|
||||
*/
|
||||
readonly stderr: Readable;
|
||||
/**
|
||||
* An integer identifier for the referenced thread. Inside the worker thread,
|
||||
* it is available as `import { threadId } from 'node:worker_threads'`.
|
||||
* This value is unique for each `Worker` instance inside a single process.
|
||||
* @since v10.5.0
|
||||
*/
|
||||
readonly threadId: number;
|
||||
/**
|
||||
* Provides the set of JS engine resource constraints for this Worker thread.
|
||||
* If the `resourceLimits` option was passed to the `Worker` constructor,
|
||||
* this matches its values.
|
||||
*
|
||||
* If the worker has stopped, the return value is an empty object.
|
||||
* @since v13.2.0, v12.16.0
|
||||
*/
|
||||
readonly resourceLimits?: ResourceLimits | undefined;
|
||||
/**
|
||||
* An object that can be used to query performance information from a worker
|
||||
* instance. Similar to `perf_hooks.performance`.
|
||||
* @since v15.1.0, v14.17.0, v12.22.0
|
||||
*/
|
||||
readonly performance: WorkerPerformance;
|
||||
/**
|
||||
* @param filename The path to the Worker’s main script or module.
|
||||
* Must be either an absolute path or a relative path (i.e. relative to the current working directory) starting with ./ or ../,
|
||||
* or a WHATWG URL object using file: protocol. If options.eval is true, this is a string containing JavaScript code rather than a path.
|
||||
*/
|
||||
constructor(filename: string | URL, options?: WorkerOptions);
|
||||
/**
|
||||
* Send a message to the worker that is received via `require('node:worker_threads').parentPort.on('message')`.
|
||||
* See `port.postMessage()` for more details.
|
||||
* @since v10.5.0
|
||||
*/
|
||||
postMessage(value: any, transferList?: readonly Transferable[]): void;
|
||||
/**
|
||||
* Sends a value to another worker, identified by its thread ID.
|
||||
* @param threadId The target thread ID. If the thread ID is invalid, a `ERR_WORKER_MESSAGING_FAILED` error will be thrown.
|
||||
* If the target thread ID is the current thread ID, a `ERR_WORKER_MESSAGING_SAME_THREAD` error will be thrown.
|
||||
* @param value The value to send.
|
||||
* @param transferList If one or more `MessagePort`-like objects are passed in value, a `transferList` is required for those items
|
||||
* or `ERR_MISSING_MESSAGE_PORT_IN_TRANSFER_LIST` is thrown. See `port.postMessage()` for more information.
|
||||
* @param timeout Time to wait for the message to be delivered in milliseconds. By default it's `undefined`, which means wait forever.
|
||||
* If the operation times out, a `ERR_WORKER_MESSAGING_TIMEOUT` error is thrown.
|
||||
* @since v22.5.0
|
||||
*/
|
||||
postMessageToThread(threadId: number, value: any, timeout?: number): Promise<void>;
|
||||
postMessageToThread(
|
||||
threadId: number,
|
||||
value: any,
|
||||
transferList: readonly Transferable[],
|
||||
timeout?: number,
|
||||
): Promise<void>;
|
||||
/**
|
||||
* Opposite of `unref()`, calling `ref()` on a previously `unref()`ed worker does _not_ let the program exit if it's the only active handle left (the default
|
||||
* behavior). If the worker is `ref()`ed, calling `ref()` again has
|
||||
* no effect.
|
||||
* @since v10.5.0
|
||||
*/
|
||||
ref(): void;
|
||||
/**
|
||||
* Calling `unref()` on a worker allows the thread to exit if this is the only
|
||||
* active handle in the event system. If the worker is already `unref()`ed calling `unref()` again has no effect.
|
||||
* @since v10.5.0
|
||||
*/
|
||||
unref(): void;
|
||||
/**
|
||||
* Stop all JavaScript execution in the worker thread as soon as possible.
|
||||
* Returns a Promise for the exit code that is fulfilled when the `'exit' event` is emitted.
|
||||
* @since v10.5.0
|
||||
*/
|
||||
terminate(): Promise<number>;
|
||||
/**
|
||||
* Returns a readable stream for a V8 snapshot of the current state of the Worker.
|
||||
* See `v8.getHeapSnapshot()` for more details.
|
||||
*
|
||||
* If the Worker thread is no longer running, which may occur before the `'exit' event` is emitted, the returned `Promise` is rejected
|
||||
* immediately with an `ERR_WORKER_NOT_RUNNING` error.
|
||||
* @since v13.9.0, v12.17.0
|
||||
* @return A promise for a Readable Stream containing a V8 heap snapshot
|
||||
*/
|
||||
getHeapSnapshot(): Promise<Readable>;
|
||||
/**
|
||||
* This method returns a `Promise` that will resolve to an object identical to `v8.getHeapStatistics()`,
|
||||
* or reject with an `ERR_WORKER_NOT_RUNNING` error if the worker is no longer running.
|
||||
* This methods allows the statistics to be observed from outside the actual thread.
|
||||
* @since v24.0.0
|
||||
*/
|
||||
getHeapStatistics(): Promise<HeapInfo>;
|
||||
/**
|
||||
* Calls `worker.terminate()` when the dispose scope is exited.
|
||||
*
|
||||
* ```js
|
||||
* async function example() {
|
||||
* await using worker = new Worker('for (;;) {}', { eval: true });
|
||||
* // Worker is automatically terminate when the scope is exited.
|
||||
* }
|
||||
* ```
|
||||
* @since v24.2.0
|
||||
*/
|
||||
[Symbol.asyncDispose](): Promise<void>;
|
||||
addListener(event: "error", listener: (err: Error) => void): this;
|
||||
addListener(event: "exit", listener: (exitCode: number) => void): this;
|
||||
addListener(event: "message", listener: (value: any) => void): this;
|
||||
addListener(event: "messageerror", listener: (error: Error) => void): this;
|
||||
addListener(event: "online", listener: () => void): this;
|
||||
addListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||
emit(event: "error", err: Error): boolean;
|
||||
emit(event: "exit", exitCode: number): boolean;
|
||||
emit(event: "message", value: any): boolean;
|
||||
emit(event: "messageerror", error: Error): boolean;
|
||||
emit(event: "online"): boolean;
|
||||
emit(event: string | symbol, ...args: any[]): boolean;
|
||||
on(event: "error", listener: (err: Error) => void): this;
|
||||
on(event: "exit", listener: (exitCode: number) => void): this;
|
||||
on(event: "message", listener: (value: any) => void): this;
|
||||
on(event: "messageerror", listener: (error: Error) => void): this;
|
||||
on(event: "online", listener: () => void): this;
|
||||
on(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||
once(event: "error", listener: (err: Error) => void): this;
|
||||
once(event: "exit", listener: (exitCode: number) => void): this;
|
||||
once(event: "message", listener: (value: any) => void): this;
|
||||
once(event: "messageerror", listener: (error: Error) => void): this;
|
||||
once(event: "online", listener: () => void): this;
|
||||
once(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||
prependListener(event: "error", listener: (err: Error) => void): this;
|
||||
prependListener(event: "exit", listener: (exitCode: number) => void): this;
|
||||
prependListener(event: "message", listener: (value: any) => void): this;
|
||||
prependListener(event: "messageerror", listener: (error: Error) => void): this;
|
||||
prependListener(event: "online", listener: () => void): this;
|
||||
prependListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||
prependOnceListener(event: "error", listener: (err: Error) => void): this;
|
||||
prependOnceListener(event: "exit", listener: (exitCode: number) => void): this;
|
||||
prependOnceListener(event: "message", listener: (value: any) => void): this;
|
||||
prependOnceListener(event: "messageerror", listener: (error: Error) => void): this;
|
||||
prependOnceListener(event: "online", listener: () => void): this;
|
||||
prependOnceListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||
removeListener(event: "error", listener: (err: Error) => void): this;
|
||||
removeListener(event: "exit", listener: (exitCode: number) => void): this;
|
||||
removeListener(event: "message", listener: (value: any) => void): this;
|
||||
removeListener(event: "messageerror", listener: (error: Error) => void): this;
|
||||
removeListener(event: "online", listener: () => void): this;
|
||||
removeListener(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||
off(event: "error", listener: (err: Error) => void): this;
|
||||
off(event: "exit", listener: (exitCode: number) => void): this;
|
||||
off(event: "message", listener: (value: any) => void): this;
|
||||
off(event: "messageerror", listener: (error: Error) => void): this;
|
||||
off(event: "online", listener: () => void): this;
|
||||
off(event: string | symbol, listener: (...args: any[]) => void): this;
|
||||
}
|
||||
interface BroadcastChannel extends NodeJS.RefCounted {}
|
||||
/**
|
||||
* Instances of `BroadcastChannel` allow asynchronous one-to-many communication
|
||||
* with all other `BroadcastChannel` instances bound to the same channel name.
|
||||
*
|
||||
* ```js
|
||||
* 'use strict';
|
||||
*
|
||||
* import {
|
||||
* isMainThread,
|
||||
* BroadcastChannel,
|
||||
* Worker,
|
||||
* } from 'node:worker_threads';
|
||||
*
|
||||
* const bc = new BroadcastChannel('hello');
|
||||
*
|
||||
* if (isMainThread) {
|
||||
* let c = 0;
|
||||
* bc.onmessage = (event) => {
|
||||
* console.log(event.data);
|
||||
* if (++c === 10) bc.close();
|
||||
* };
|
||||
* for (let n = 0; n < 10; n++)
|
||||
* new Worker(__filename);
|
||||
* } else {
|
||||
* bc.postMessage('hello from every worker');
|
||||
* bc.close();
|
||||
* }
|
||||
* ```
|
||||
* @since v15.4.0
|
||||
*/
|
||||
class BroadcastChannel {
|
||||
readonly name: string;
|
||||
/**
|
||||
* Invoked with a single \`MessageEvent\` argument when a message is received.
|
||||
* @since v15.4.0
|
||||
*/
|
||||
onmessage: (message: unknown) => void;
|
||||
/**
|
||||
* Invoked with a received message cannot be deserialized.
|
||||
* @since v15.4.0
|
||||
*/
|
||||
onmessageerror: (message: unknown) => void;
|
||||
constructor(name: string);
|
||||
/**
|
||||
* Closes the `BroadcastChannel` connection.
|
||||
* @since v15.4.0
|
||||
*/
|
||||
close(): void;
|
||||
/**
|
||||
* @since v15.4.0
|
||||
* @param message Any cloneable JavaScript value.
|
||||
*/
|
||||
postMessage(message: unknown): void;
|
||||
}
|
||||
/**
|
||||
* Mark an object as not transferable. If `object` occurs in the transfer list of
|
||||
* a `port.postMessage()` call, it is ignored.
|
||||
*
|
||||
* In particular, this makes sense for objects that can be cloned, rather than
|
||||
* transferred, and which are used by other objects on the sending side.
|
||||
* For example, Node.js marks the `ArrayBuffer`s it uses for its `Buffer pool` with this.
|
||||
*
|
||||
* This operation cannot be undone.
|
||||
*
|
||||
* ```js
|
||||
* import { MessageChannel, markAsUntransferable } from 'node:worker_threads';
|
||||
*
|
||||
* const pooledBuffer = new ArrayBuffer(8);
|
||||
* const typedArray1 = new Uint8Array(pooledBuffer);
|
||||
* const typedArray2 = new Float64Array(pooledBuffer);
|
||||
*
|
||||
* markAsUntransferable(pooledBuffer);
|
||||
*
|
||||
* const { port1 } = new MessageChannel();
|
||||
* port1.postMessage(typedArray1, [ typedArray1.buffer ]);
|
||||
*
|
||||
* // The following line prints the contents of typedArray1 -- it still owns
|
||||
* // its memory and has been cloned, not transferred. Without
|
||||
* // `markAsUntransferable()`, this would print an empty Uint8Array.
|
||||
* // typedArray2 is intact as well.
|
||||
* console.log(typedArray1);
|
||||
* console.log(typedArray2);
|
||||
* ```
|
||||
*
|
||||
* There is no equivalent to this API in browsers.
|
||||
* @since v14.5.0, v12.19.0
|
||||
*/
|
||||
function markAsUntransferable(object: object): void;
|
||||
/**
|
||||
* Check if an object is marked as not transferable with
|
||||
* {@link markAsUntransferable}.
|
||||
* @since v21.0.0
|
||||
*/
|
||||
function isMarkedAsUntransferable(object: object): boolean;
|
||||
/**
|
||||
* Mark an object as not cloneable. If `object` is used as `message` in
|
||||
* a `port.postMessage()` call, an error is thrown. This is a no-op if `object` is a
|
||||
* primitive value.
|
||||
*
|
||||
* This has no effect on `ArrayBuffer`, or any `Buffer` like objects.
|
||||
*
|
||||
* This operation cannot be undone.
|
||||
*
|
||||
* ```js
|
||||
* const { markAsUncloneable } = require('node:worker_threads');
|
||||
*
|
||||
* const anyObject = { foo: 'bar' };
|
||||
* markAsUncloneable(anyObject);
|
||||
* const { port1 } = new MessageChannel();
|
||||
* try {
|
||||
* // This will throw an error, because anyObject is not cloneable.
|
||||
* port1.postMessage(anyObject)
|
||||
* } catch (error) {
|
||||
* // error.name === 'DataCloneError'
|
||||
* }
|
||||
* ```
|
||||
*
|
||||
* There is no equivalent to this API in browsers.
|
||||
* @since v22.10.0
|
||||
*/
|
||||
function markAsUncloneable(object: object): void;
|
||||
/**
|
||||
* Transfer a `MessagePort` to a different `vm` Context. The original `port` object is rendered unusable, and the returned `MessagePort` instance
|
||||
* takes its place.
|
||||
*
|
||||
* The returned `MessagePort` is an object in the target context and
|
||||
* inherits from its global `Object` class. Objects passed to the [`port.onmessage()`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/onmessage) listener are also created in the
|
||||
* target context
|
||||
* and inherit from its global `Object` class.
|
||||
*
|
||||
* However, the created `MessagePort` no longer inherits from [`EventTarget`](https://developer.mozilla.org/en-US/docs/Web/API/EventTarget), and only
|
||||
* [`port.onmessage()`](https://developer.mozilla.org/en-US/docs/Web/API/MessagePort/onmessage) can be used to receive
|
||||
* events using it.
|
||||
* @since v11.13.0
|
||||
* @param port The message port to transfer.
|
||||
* @param contextifiedSandbox A `contextified` object as returned by the `vm.createContext()` method.
|
||||
*/
|
||||
function moveMessagePortToContext(port: MessagePort, contextifiedSandbox: Context): MessagePort;
|
||||
/**
|
||||
* Receive a single message from a given `MessagePort`. If no message is available,`undefined` is returned, otherwise an object with a single `message` property
|
||||
* that contains the message payload, corresponding to the oldest message in the `MessagePort`'s queue.
|
||||
*
|
||||
* ```js
|
||||
* import { MessageChannel, receiveMessageOnPort } from 'node:worker_threads';
|
||||
* const { port1, port2 } = new MessageChannel();
|
||||
* port1.postMessage({ hello: 'world' });
|
||||
*
|
||||
* console.log(receiveMessageOnPort(port2));
|
||||
* // Prints: { message: { hello: 'world' } }
|
||||
* console.log(receiveMessageOnPort(port2));
|
||||
* // Prints: undefined
|
||||
* ```
|
||||
*
|
||||
* When this function is used, no `'message'` event is emitted and the `onmessage` listener is not invoked.
|
||||
* @since v12.3.0
|
||||
*/
|
||||
function receiveMessageOnPort(port: MessagePort):
|
||||
| {
|
||||
message: any;
|
||||
}
|
||||
| undefined;
|
||||
type Serializable = string | object | number | boolean | bigint;
|
||||
/**
|
||||
* Within a worker thread, `worker.getEnvironmentData()` returns a clone
|
||||
* of data passed to the spawning thread's `worker.setEnvironmentData()`.
|
||||
* Every new `Worker` receives its own copy of the environment data
|
||||
* automatically.
|
||||
*
|
||||
* ```js
|
||||
* import {
|
||||
* Worker,
|
||||
* isMainThread,
|
||||
* setEnvironmentData,
|
||||
* getEnvironmentData,
|
||||
* } from 'node:worker_threads';
|
||||
*
|
||||
* if (isMainThread) {
|
||||
* setEnvironmentData('Hello', 'World!');
|
||||
* const worker = new Worker(__filename);
|
||||
* } else {
|
||||
* console.log(getEnvironmentData('Hello')); // Prints 'World!'.
|
||||
* }
|
||||
* ```
|
||||
* @since v15.12.0, v14.18.0
|
||||
* @param key Any arbitrary, cloneable JavaScript value that can be used as a {Map} key.
|
||||
*/
|
||||
function getEnvironmentData(key: Serializable): Serializable;
|
||||
/**
|
||||
* The `worker.setEnvironmentData()` API sets the content of `worker.getEnvironmentData()` in the current thread and all new `Worker` instances spawned from the current context.
|
||||
* @since v15.12.0, v14.18.0
|
||||
* @param key Any arbitrary, cloneable JavaScript value that can be used as a {Map} key.
|
||||
* @param value Any arbitrary, cloneable JavaScript value that will be cloned and passed automatically to all new `Worker` instances. If `value` is passed as `undefined`, any previously set value
|
||||
* for the `key` will be deleted.
|
||||
*/
|
||||
function setEnvironmentData(key: Serializable, value?: Serializable): void;
|
||||
|
||||
import {
|
||||
BroadcastChannel as _BroadcastChannel,
|
||||
MessageChannel as _MessageChannel,
|
||||
MessagePort as _MessagePort,
|
||||
} from "worker_threads";
|
||||
global {
|
||||
function structuredClone<T>(
|
||||
value: T,
|
||||
options?: { transfer?: Transferable[] },
|
||||
): T;
|
||||
/**
|
||||
* `BroadcastChannel` class is a global reference for `import { BroadcastChannel } from 'worker_threads'`
|
||||
* https://nodejs.org/api/globals.html#broadcastchannel
|
||||
* @since v18.0.0
|
||||
*/
|
||||
var BroadcastChannel: typeof globalThis extends {
|
||||
onmessage: any;
|
||||
BroadcastChannel: infer T;
|
||||
} ? T
|
||||
: typeof _BroadcastChannel;
|
||||
/**
|
||||
* `MessageChannel` class is a global reference for `import { MessageChannel } from 'worker_threads'`
|
||||
* https://nodejs.org/api/globals.html#messagechannel
|
||||
* @since v15.0.0
|
||||
*/
|
||||
var MessageChannel: typeof globalThis extends {
|
||||
onmessage: any;
|
||||
MessageChannel: infer T;
|
||||
} ? T
|
||||
: typeof _MessageChannel;
|
||||
/**
|
||||
* `MessagePort` class is a global reference for `import { MessagePort } from 'worker_threads'`
|
||||
* https://nodejs.org/api/globals.html#messageport
|
||||
* @since v15.0.0
|
||||
*/
|
||||
var MessagePort: typeof globalThis extends {
|
||||
onmessage: any;
|
||||
MessagePort: infer T;
|
||||
} ? T
|
||||
: typeof _MessagePort;
|
||||
}
|
||||
}
|
||||
declare module "node:worker_threads" {
|
||||
export * from "worker_threads";
|
||||
}
|
||||
@@ -1,674 +0,0 @@
|
||||
/**
|
||||
* The `node:zlib` module provides compression functionality implemented using
|
||||
* Gzip, Deflate/Inflate, and Brotli.
|
||||
*
|
||||
* To access it:
|
||||
*
|
||||
* ```js
|
||||
* import zlib from 'node:zlib';
|
||||
* ```
|
||||
*
|
||||
* Compression and decompression are built around the Node.js
|
||||
* [Streams API](https://nodejs.org/docs/latest-v24.x/api/stream.html).
|
||||
*
|
||||
* Compressing or decompressing a stream (such as a file) can be accomplished by
|
||||
* piping the source stream through a `zlib` `Transform` stream into a destination
|
||||
* stream:
|
||||
*
|
||||
* ```js
|
||||
* import { createGzip } from 'node:zlib';
|
||||
* import { pipeline } from 'node:stream';
|
||||
* import {
|
||||
* createReadStream,
|
||||
* createWriteStream,
|
||||
* } from 'node:fs';
|
||||
*
|
||||
* const gzip = createGzip();
|
||||
* const source = createReadStream('input.txt');
|
||||
* const destination = createWriteStream('input.txt.gz');
|
||||
*
|
||||
* pipeline(source, gzip, destination, (err) => {
|
||||
* if (err) {
|
||||
* console.error('An error occurred:', err);
|
||||
* process.exitCode = 1;
|
||||
* }
|
||||
* });
|
||||
*
|
||||
* // Or, Promisified
|
||||
*
|
||||
* import { promisify } from 'node:util';
|
||||
* const pipe = promisify(pipeline);
|
||||
*
|
||||
* async function do_gzip(input, output) {
|
||||
* const gzip = createGzip();
|
||||
* const source = createReadStream(input);
|
||||
* const destination = createWriteStream(output);
|
||||
* await pipe(source, gzip, destination);
|
||||
* }
|
||||
*
|
||||
* do_gzip('input.txt', 'input.txt.gz')
|
||||
* .catch((err) => {
|
||||
* console.error('An error occurred:', err);
|
||||
* process.exitCode = 1;
|
||||
* });
|
||||
* ```
|
||||
*
|
||||
* It is also possible to compress or decompress data in a single step:
|
||||
*
|
||||
* ```js
|
||||
* import { deflate, unzip } from 'node:zlib';
|
||||
*
|
||||
* const input = '.................................';
|
||||
* deflate(input, (err, buffer) => {
|
||||
* if (err) {
|
||||
* console.error('An error occurred:', err);
|
||||
* process.exitCode = 1;
|
||||
* }
|
||||
* console.log(buffer.toString('base64'));
|
||||
* });
|
||||
*
|
||||
* const buffer = Buffer.from('eJzT0yMAAGTvBe8=', 'base64');
|
||||
* unzip(buffer, (err, buffer) => {
|
||||
* if (err) {
|
||||
* console.error('An error occurred:', err);
|
||||
* process.exitCode = 1;
|
||||
* }
|
||||
* console.log(buffer.toString());
|
||||
* });
|
||||
*
|
||||
* // Or, Promisified
|
||||
*
|
||||
* import { promisify } from 'node:util';
|
||||
* const do_unzip = promisify(unzip);
|
||||
*
|
||||
* do_unzip(buffer)
|
||||
* .then((buf) => console.log(buf.toString()))
|
||||
* .catch((err) => {
|
||||
* console.error('An error occurred:', err);
|
||||
* process.exitCode = 1;
|
||||
* });
|
||||
* ```
|
||||
* @since v0.5.8
|
||||
* @see [source](https://github.com/nodejs/node/blob/v24.x/lib/zlib.js)
|
||||
*/
|
||||
declare module "zlib" {
|
||||
import * as stream from "node:stream";
|
||||
interface ZlibOptions {
|
||||
/**
|
||||
* @default constants.Z_NO_FLUSH
|
||||
*/
|
||||
flush?: number | undefined;
|
||||
/**
|
||||
* @default constants.Z_FINISH
|
||||
*/
|
||||
finishFlush?: number | undefined;
|
||||
/**
|
||||
* @default 16*1024
|
||||
*/
|
||||
chunkSize?: number | undefined;
|
||||
windowBits?: number | undefined;
|
||||
level?: number | undefined; // compression only
|
||||
memLevel?: number | undefined; // compression only
|
||||
strategy?: number | undefined; // compression only
|
||||
dictionary?: NodeJS.ArrayBufferView | ArrayBuffer | undefined; // deflate/inflate only, empty dictionary by default
|
||||
/**
|
||||
* If `true`, returns an object with `buffer` and `engine`.
|
||||
*/
|
||||
info?: boolean | undefined;
|
||||
/**
|
||||
* Limits output size when using convenience methods.
|
||||
* @default buffer.kMaxLength
|
||||
*/
|
||||
maxOutputLength?: number | undefined;
|
||||
}
|
||||
interface BrotliOptions {
|
||||
/**
|
||||
* @default constants.BROTLI_OPERATION_PROCESS
|
||||
*/
|
||||
flush?: number | undefined;
|
||||
/**
|
||||
* @default constants.BROTLI_OPERATION_FINISH
|
||||
*/
|
||||
finishFlush?: number | undefined;
|
||||
/**
|
||||
* @default 16*1024
|
||||
*/
|
||||
chunkSize?: number | undefined;
|
||||
params?:
|
||||
| {
|
||||
/**
|
||||
* Each key is a `constants.BROTLI_*` constant.
|
||||
*/
|
||||
[key: number]: boolean | number;
|
||||
}
|
||||
| undefined;
|
||||
/**
|
||||
* Limits output size when using [convenience methods](https://nodejs.org/docs/latest-v24.x/api/zlib.html#convenience-methods).
|
||||
* @default buffer.kMaxLength
|
||||
*/
|
||||
maxOutputLength?: number | undefined;
|
||||
/**
|
||||
* If `true`, returns an object with `buffer` and `engine`.
|
||||
*/
|
||||
info?: boolean | undefined;
|
||||
}
|
||||
interface ZstdOptions {
|
||||
/**
|
||||
* @default constants.ZSTD_e_continue
|
||||
*/
|
||||
flush?: number | undefined;
|
||||
/**
|
||||
* @default constants.ZSTD_e_end
|
||||
*/
|
||||
finishFlush?: number | undefined;
|
||||
/**
|
||||
* @default 16 * 1024
|
||||
*/
|
||||
chunkSize?: number | undefined;
|
||||
/**
|
||||
* Key-value object containing indexed
|
||||
* [Zstd parameters](https://nodejs.org/docs/latest-v24.x/api/zlib.html#zstd-constants).
|
||||
*/
|
||||
params?: { [key: number]: number | boolean } | undefined;
|
||||
/**
|
||||
* Limits output size when using
|
||||
* [convenience methods](https://nodejs.org/docs/latest-v24.x/api/zlib.html#convenience-methods).
|
||||
* @default buffer.kMaxLength
|
||||
*/
|
||||
maxOutputLength?: number | undefined;
|
||||
/**
|
||||
* If `true`, returns an object with `buffer` and `engine`.
|
||||
*/
|
||||
info?: boolean | undefined;
|
||||
}
|
||||
interface Zlib {
|
||||
readonly bytesWritten: number;
|
||||
shell?: boolean | string | undefined;
|
||||
close(callback?: () => void): void;
|
||||
flush(kind?: number, callback?: () => void): void;
|
||||
flush(callback?: () => void): void;
|
||||
}
|
||||
interface ZlibParams {
|
||||
params(level: number, strategy: number, callback: () => void): void;
|
||||
}
|
||||
interface ZlibReset {
|
||||
reset(): void;
|
||||
}
|
||||
interface BrotliCompress extends stream.Transform, Zlib {}
|
||||
interface BrotliDecompress extends stream.Transform, Zlib {}
|
||||
interface Gzip extends stream.Transform, Zlib {}
|
||||
interface Gunzip extends stream.Transform, Zlib {}
|
||||
interface Deflate extends stream.Transform, Zlib, ZlibReset, ZlibParams {}
|
||||
interface Inflate extends stream.Transform, Zlib, ZlibReset {}
|
||||
interface DeflateRaw extends stream.Transform, Zlib, ZlibReset, ZlibParams {}
|
||||
interface InflateRaw extends stream.Transform, Zlib, ZlibReset {}
|
||||
interface Unzip extends stream.Transform, Zlib {}
|
||||
/**
|
||||
* @since v22.15.0
|
||||
* @experimental
|
||||
*/
|
||||
interface ZstdCompress extends stream.Transform, Zlib {}
|
||||
/**
|
||||
* @since v22.15.0
|
||||
* @experimental
|
||||
*/
|
||||
interface ZstdDecompress extends stream.Transform, Zlib {}
|
||||
/**
|
||||
* Computes a 32-bit [Cyclic Redundancy Check](https://en.wikipedia.org/wiki/Cyclic_redundancy_check) checksum of `data`.
|
||||
* If `value` is specified, it is used as the starting value of the checksum, otherwise, 0 is used as the starting value.
|
||||
* @param data When `data` is a string, it will be encoded as UTF-8 before being used for computation.
|
||||
* @param value An optional starting value. It must be a 32-bit unsigned integer. @default 0
|
||||
* @returns A 32-bit unsigned integer containing the checksum.
|
||||
* @since v22.2.0
|
||||
*/
|
||||
function crc32(data: string | Buffer | NodeJS.ArrayBufferView, value?: number): number;
|
||||
/**
|
||||
* Creates and returns a new `BrotliCompress` object.
|
||||
* @since v11.7.0, v10.16.0
|
||||
*/
|
||||
function createBrotliCompress(options?: BrotliOptions): BrotliCompress;
|
||||
/**
|
||||
* Creates and returns a new `BrotliDecompress` object.
|
||||
* @since v11.7.0, v10.16.0
|
||||
*/
|
||||
function createBrotliDecompress(options?: BrotliOptions): BrotliDecompress;
|
||||
/**
|
||||
* Creates and returns a new `Gzip` object.
|
||||
* See `example`.
|
||||
* @since v0.5.8
|
||||
*/
|
||||
function createGzip(options?: ZlibOptions): Gzip;
|
||||
/**
|
||||
* Creates and returns a new `Gunzip` object.
|
||||
* @since v0.5.8
|
||||
*/
|
||||
function createGunzip(options?: ZlibOptions): Gunzip;
|
||||
/**
|
||||
* Creates and returns a new `Deflate` object.
|
||||
* @since v0.5.8
|
||||
*/
|
||||
function createDeflate(options?: ZlibOptions): Deflate;
|
||||
/**
|
||||
* Creates and returns a new `Inflate` object.
|
||||
* @since v0.5.8
|
||||
*/
|
||||
function createInflate(options?: ZlibOptions): Inflate;
|
||||
/**
|
||||
* Creates and returns a new `DeflateRaw` object.
|
||||
*
|
||||
* An upgrade of zlib from 1.2.8 to 1.2.11 changed behavior when `windowBits` is set to 8 for raw deflate streams. zlib would automatically set `windowBits` to 9 if was initially set to 8. Newer
|
||||
* versions of zlib will throw an exception,
|
||||
* so Node.js restored the original behavior of upgrading a value of 8 to 9,
|
||||
* since passing `windowBits = 9` to zlib actually results in a compressed stream
|
||||
* that effectively uses an 8-bit window only.
|
||||
* @since v0.5.8
|
||||
*/
|
||||
function createDeflateRaw(options?: ZlibOptions): DeflateRaw;
|
||||
/**
|
||||
* Creates and returns a new `InflateRaw` object.
|
||||
* @since v0.5.8
|
||||
*/
|
||||
function createInflateRaw(options?: ZlibOptions): InflateRaw;
|
||||
/**
|
||||
* Creates and returns a new `Unzip` object.
|
||||
* @since v0.5.8
|
||||
*/
|
||||
function createUnzip(options?: ZlibOptions): Unzip;
|
||||
/**
|
||||
* Creates and returns a new `ZstdCompress` object.
|
||||
* @since v22.15.0
|
||||
*/
|
||||
function createZstdCompress(options?: ZstdOptions): ZstdCompress;
|
||||
/**
|
||||
* Creates and returns a new `ZstdDecompress` object.
|
||||
* @since v22.15.0
|
||||
*/
|
||||
function createZstdDecompress(options?: ZstdOptions): ZstdDecompress;
|
||||
type InputType = string | ArrayBuffer | NodeJS.ArrayBufferView;
|
||||
type CompressCallback = (error: Error | null, result: Buffer) => void;
|
||||
/**
|
||||
* @since v11.7.0, v10.16.0
|
||||
*/
|
||||
function brotliCompress(buf: InputType, options: BrotliOptions, callback: CompressCallback): void;
|
||||
function brotliCompress(buf: InputType, callback: CompressCallback): void;
|
||||
namespace brotliCompress {
|
||||
function __promisify__(buffer: InputType, options?: BrotliOptions): Promise<Buffer>;
|
||||
}
|
||||
/**
|
||||
* Compress a chunk of data with `BrotliCompress`.
|
||||
* @since v11.7.0, v10.16.0
|
||||
*/
|
||||
function brotliCompressSync(buf: InputType, options?: BrotliOptions): Buffer;
|
||||
/**
|
||||
* @since v11.7.0, v10.16.0
|
||||
*/
|
||||
function brotliDecompress(buf: InputType, options: BrotliOptions, callback: CompressCallback): void;
|
||||
function brotliDecompress(buf: InputType, callback: CompressCallback): void;
|
||||
namespace brotliDecompress {
|
||||
function __promisify__(buffer: InputType, options?: BrotliOptions): Promise<Buffer>;
|
||||
}
|
||||
/**
|
||||
* Decompress a chunk of data with `BrotliDecompress`.
|
||||
* @since v11.7.0, v10.16.0
|
||||
*/
|
||||
function brotliDecompressSync(buf: InputType, options?: BrotliOptions): Buffer;
|
||||
/**
|
||||
* @since v0.6.0
|
||||
*/
|
||||
function deflate(buf: InputType, callback: CompressCallback): void;
|
||||
function deflate(buf: InputType, options: ZlibOptions, callback: CompressCallback): void;
|
||||
namespace deflate {
|
||||
function __promisify__(buffer: InputType, options?: ZlibOptions): Promise<Buffer>;
|
||||
}
|
||||
/**
|
||||
* Compress a chunk of data with `Deflate`.
|
||||
* @since v0.11.12
|
||||
*/
|
||||
function deflateSync(buf: InputType, options?: ZlibOptions): Buffer;
|
||||
/**
|
||||
* @since v0.6.0
|
||||
*/
|
||||
function deflateRaw(buf: InputType, callback: CompressCallback): void;
|
||||
function deflateRaw(buf: InputType, options: ZlibOptions, callback: CompressCallback): void;
|
||||
namespace deflateRaw {
|
||||
function __promisify__(buffer: InputType, options?: ZlibOptions): Promise<Buffer>;
|
||||
}
|
||||
/**
|
||||
* Compress a chunk of data with `DeflateRaw`.
|
||||
* @since v0.11.12
|
||||
*/
|
||||
function deflateRawSync(buf: InputType, options?: ZlibOptions): Buffer;
|
||||
/**
|
||||
* @since v0.6.0
|
||||
*/
|
||||
function gzip(buf: InputType, callback: CompressCallback): void;
|
||||
function gzip(buf: InputType, options: ZlibOptions, callback: CompressCallback): void;
|
||||
namespace gzip {
|
||||
function __promisify__(buffer: InputType, options?: ZlibOptions): Promise<Buffer>;
|
||||
}
|
||||
/**
|
||||
* Compress a chunk of data with `Gzip`.
|
||||
* @since v0.11.12
|
||||
*/
|
||||
function gzipSync(buf: InputType, options?: ZlibOptions): Buffer;
|
||||
/**
|
||||
* @since v0.6.0
|
||||
*/
|
||||
function gunzip(buf: InputType, callback: CompressCallback): void;
|
||||
function gunzip(buf: InputType, options: ZlibOptions, callback: CompressCallback): void;
|
||||
namespace gunzip {
|
||||
function __promisify__(buffer: InputType, options?: ZlibOptions): Promise<Buffer>;
|
||||
}
|
||||
/**
|
||||
* Decompress a chunk of data with `Gunzip`.
|
||||
* @since v0.11.12
|
||||
*/
|
||||
function gunzipSync(buf: InputType, options?: ZlibOptions): Buffer;
|
||||
/**
|
||||
* @since v0.6.0
|
||||
*/
|
||||
function inflate(buf: InputType, callback: CompressCallback): void;
|
||||
function inflate(buf: InputType, options: ZlibOptions, callback: CompressCallback): void;
|
||||
namespace inflate {
|
||||
function __promisify__(buffer: InputType, options?: ZlibOptions): Promise<Buffer>;
|
||||
}
|
||||
/**
|
||||
* Decompress a chunk of data with `Inflate`.
|
||||
* @since v0.11.12
|
||||
*/
|
||||
function inflateSync(buf: InputType, options?: ZlibOptions): Buffer;
|
||||
/**
|
||||
* @since v0.6.0
|
||||
*/
|
||||
function inflateRaw(buf: InputType, callback: CompressCallback): void;
|
||||
function inflateRaw(buf: InputType, options: ZlibOptions, callback: CompressCallback): void;
|
||||
namespace inflateRaw {
|
||||
function __promisify__(buffer: InputType, options?: ZlibOptions): Promise<Buffer>;
|
||||
}
|
||||
/**
|
||||
* Decompress a chunk of data with `InflateRaw`.
|
||||
* @since v0.11.12
|
||||
*/
|
||||
function inflateRawSync(buf: InputType, options?: ZlibOptions): Buffer;
|
||||
/**
|
||||
* @since v0.6.0
|
||||
*/
|
||||
function unzip(buf: InputType, callback: CompressCallback): void;
|
||||
function unzip(buf: InputType, options: ZlibOptions, callback: CompressCallback): void;
|
||||
namespace unzip {
|
||||
function __promisify__(buffer: InputType, options?: ZlibOptions): Promise<Buffer>;
|
||||
}
|
||||
/**
|
||||
* Decompress a chunk of data with `Unzip`.
|
||||
* @since v0.11.12
|
||||
*/
|
||||
function unzipSync(buf: InputType, options?: ZlibOptions): Buffer;
|
||||
/**
|
||||
* @since v22.15.0
|
||||
* @experimental
|
||||
*/
|
||||
function zstdCompress(buf: InputType, callback: CompressCallback): void;
|
||||
function zstdCompress(buf: InputType, options: ZstdOptions, callback: CompressCallback): void;
|
||||
namespace zstdCompress {
|
||||
function __promisify__(buffer: InputType, options?: ZstdOptions): Promise<Buffer>;
|
||||
}
|
||||
/**
|
||||
* Compress a chunk of data with `ZstdCompress`.
|
||||
* @since v22.15.0
|
||||
* @experimental
|
||||
*/
|
||||
function zstdCompressSync(buf: InputType, options?: ZstdOptions): Buffer;
|
||||
/**
|
||||
* @since v22.15.0
|
||||
* @experimental
|
||||
*/
|
||||
function zstdDecompress(buf: InputType, callback: CompressCallback): void;
|
||||
function zstdDecompress(buf: InputType, options: ZstdOptions, callback: CompressCallback): void;
|
||||
namespace zstdDecompress {
|
||||
function __promisify__(buffer: InputType, options?: ZstdOptions): Promise<Buffer>;
|
||||
}
|
||||
/**
|
||||
* Decompress a chunk of data with `ZstdDecompress`.
|
||||
* @since v22.15.0
|
||||
* @experimental
|
||||
*/
|
||||
function zstdDecompressSync(buf: InputType, options?: ZstdOptions): Buffer;
|
||||
namespace constants {
|
||||
const BROTLI_DECODE: number;
|
||||
const BROTLI_DECODER_ERROR_ALLOC_BLOCK_TYPE_TREES: number;
|
||||
const BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MAP: number;
|
||||
const BROTLI_DECODER_ERROR_ALLOC_CONTEXT_MODES: number;
|
||||
const BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_1: number;
|
||||
const BROTLI_DECODER_ERROR_ALLOC_RING_BUFFER_2: number;
|
||||
const BROTLI_DECODER_ERROR_ALLOC_TREE_GROUPS: number;
|
||||
const BROTLI_DECODER_ERROR_DICTIONARY_NOT_SET: number;
|
||||
const BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_1: number;
|
||||
const BROTLI_DECODER_ERROR_FORMAT_BLOCK_LENGTH_2: number;
|
||||
const BROTLI_DECODER_ERROR_FORMAT_CL_SPACE: number;
|
||||
const BROTLI_DECODER_ERROR_FORMAT_CONTEXT_MAP_REPEAT: number;
|
||||
const BROTLI_DECODER_ERROR_FORMAT_DICTIONARY: number;
|
||||
const BROTLI_DECODER_ERROR_FORMAT_DISTANCE: number;
|
||||
const BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_META_NIBBLE: number;
|
||||
const BROTLI_DECODER_ERROR_FORMAT_EXUBERANT_NIBBLE: number;
|
||||
const BROTLI_DECODER_ERROR_FORMAT_HUFFMAN_SPACE: number;
|
||||
const BROTLI_DECODER_ERROR_FORMAT_PADDING_1: number;
|
||||
const BROTLI_DECODER_ERROR_FORMAT_PADDING_2: number;
|
||||
const BROTLI_DECODER_ERROR_FORMAT_RESERVED: number;
|
||||
const BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_ALPHABET: number;
|
||||
const BROTLI_DECODER_ERROR_FORMAT_SIMPLE_HUFFMAN_SAME: number;
|
||||
const BROTLI_DECODER_ERROR_FORMAT_TRANSFORM: number;
|
||||
const BROTLI_DECODER_ERROR_FORMAT_WINDOW_BITS: number;
|
||||
const BROTLI_DECODER_ERROR_INVALID_ARGUMENTS: number;
|
||||
const BROTLI_DECODER_ERROR_UNREACHABLE: number;
|
||||
const BROTLI_DECODER_NEEDS_MORE_INPUT: number;
|
||||
const BROTLI_DECODER_NEEDS_MORE_OUTPUT: number;
|
||||
const BROTLI_DECODER_NO_ERROR: number;
|
||||
const BROTLI_DECODER_PARAM_DISABLE_RING_BUFFER_REALLOCATION: number;
|
||||
const BROTLI_DECODER_PARAM_LARGE_WINDOW: number;
|
||||
const BROTLI_DECODER_RESULT_ERROR: number;
|
||||
const BROTLI_DECODER_RESULT_NEEDS_MORE_INPUT: number;
|
||||
const BROTLI_DECODER_RESULT_NEEDS_MORE_OUTPUT: number;
|
||||
const BROTLI_DECODER_RESULT_SUCCESS: number;
|
||||
const BROTLI_DECODER_SUCCESS: number;
|
||||
const BROTLI_DEFAULT_MODE: number;
|
||||
const BROTLI_DEFAULT_QUALITY: number;
|
||||
const BROTLI_DEFAULT_WINDOW: number;
|
||||
const BROTLI_ENCODE: number;
|
||||
const BROTLI_LARGE_MAX_WINDOW_BITS: number;
|
||||
const BROTLI_MAX_INPUT_BLOCK_BITS: number;
|
||||
const BROTLI_MAX_QUALITY: number;
|
||||
const BROTLI_MAX_WINDOW_BITS: number;
|
||||
const BROTLI_MIN_INPUT_BLOCK_BITS: number;
|
||||
const BROTLI_MIN_QUALITY: number;
|
||||
const BROTLI_MIN_WINDOW_BITS: number;
|
||||
const BROTLI_MODE_FONT: number;
|
||||
const BROTLI_MODE_GENERIC: number;
|
||||
const BROTLI_MODE_TEXT: number;
|
||||
const BROTLI_OPERATION_EMIT_METADATA: number;
|
||||
const BROTLI_OPERATION_FINISH: number;
|
||||
const BROTLI_OPERATION_FLUSH: number;
|
||||
const BROTLI_OPERATION_PROCESS: number;
|
||||
const BROTLI_PARAM_DISABLE_LITERAL_CONTEXT_MODELING: number;
|
||||
const BROTLI_PARAM_LARGE_WINDOW: number;
|
||||
const BROTLI_PARAM_LGBLOCK: number;
|
||||
const BROTLI_PARAM_LGWIN: number;
|
||||
const BROTLI_PARAM_MODE: number;
|
||||
const BROTLI_PARAM_NDIRECT: number;
|
||||
const BROTLI_PARAM_NPOSTFIX: number;
|
||||
const BROTLI_PARAM_QUALITY: number;
|
||||
const BROTLI_PARAM_SIZE_HINT: number;
|
||||
const DEFLATE: number;
|
||||
const DEFLATERAW: number;
|
||||
const GUNZIP: number;
|
||||
const GZIP: number;
|
||||
const INFLATE: number;
|
||||
const INFLATERAW: number;
|
||||
const UNZIP: number;
|
||||
const ZLIB_VERNUM: number;
|
||||
const ZSTD_CLEVEL_DEFAULT: number;
|
||||
const ZSTD_COMPRESS: number;
|
||||
const ZSTD_DECOMPRESS: number;
|
||||
const ZSTD_btlazy2: number;
|
||||
const ZSTD_btopt: number;
|
||||
const ZSTD_btultra: number;
|
||||
const ZSTD_btultra2: number;
|
||||
const ZSTD_c_chainLog: number;
|
||||
const ZSTD_c_checksumFlag: number;
|
||||
const ZSTD_c_compressionLevel: number;
|
||||
const ZSTD_c_contentSizeFlag: number;
|
||||
const ZSTD_c_dictIDFlag: number;
|
||||
const ZSTD_c_enableLongDistanceMatching: number;
|
||||
const ZSTD_c_hashLog: number;
|
||||
const ZSTD_c_jobSize: number;
|
||||
const ZSTD_c_ldmBucketSizeLog: number;
|
||||
const ZSTD_c_ldmHashLog: number;
|
||||
const ZSTD_c_ldmHashRateLog: number;
|
||||
const ZSTD_c_ldmMinMatch: number;
|
||||
const ZSTD_c_minMatch: number;
|
||||
const ZSTD_c_nbWorkers: number;
|
||||
const ZSTD_c_overlapLog: number;
|
||||
const ZSTD_c_searchLog: number;
|
||||
const ZSTD_c_strategy: number;
|
||||
const ZSTD_c_targetLength: number;
|
||||
const ZSTD_c_windowLog: number;
|
||||
const ZSTD_d_windowLogMax: number;
|
||||
const ZSTD_dfast: number;
|
||||
const ZSTD_e_continue: number;
|
||||
const ZSTD_e_end: number;
|
||||
const ZSTD_e_flush: number;
|
||||
const ZSTD_error_GENERIC: number;
|
||||
const ZSTD_error_checksum_wrong: number;
|
||||
const ZSTD_error_corruption_detected: number;
|
||||
const ZSTD_error_dictionaryCreation_failed: number;
|
||||
const ZSTD_error_dictionary_corrupted: number;
|
||||
const ZSTD_error_dictionary_wrong: number;
|
||||
const ZSTD_error_dstBuffer_null: number;
|
||||
const ZSTD_error_dstSize_tooSmall: number;
|
||||
const ZSTD_error_frameParameter_unsupported: number;
|
||||
const ZSTD_error_frameParameter_windowTooLarge: number;
|
||||
const ZSTD_error_init_missing: number;
|
||||
const ZSTD_error_literals_headerWrong: number;
|
||||
const ZSTD_error_maxSymbolValue_tooLarge: number;
|
||||
const ZSTD_error_maxSymbolValue_tooSmall: number;
|
||||
const ZSTD_error_memory_allocation: number;
|
||||
const ZSTD_error_noForwardProgress_destFull: number;
|
||||
const ZSTD_error_noForwardProgress_inputEmpty: number;
|
||||
const ZSTD_error_no_error: number;
|
||||
const ZSTD_error_parameter_combination_unsupported: number;
|
||||
const ZSTD_error_parameter_outOfBound: number;
|
||||
const ZSTD_error_parameter_unsupported: number;
|
||||
const ZSTD_error_prefix_unknown: number;
|
||||
const ZSTD_error_srcSize_wrong: number;
|
||||
const ZSTD_error_stabilityCondition_notRespected: number;
|
||||
const ZSTD_error_stage_wrong: number;
|
||||
const ZSTD_error_tableLog_tooLarge: number;
|
||||
const ZSTD_error_version_unsupported: number;
|
||||
const ZSTD_error_workSpace_tooSmall: number;
|
||||
const ZSTD_fast: number;
|
||||
const ZSTD_greedy: number;
|
||||
const ZSTD_lazy: number;
|
||||
const ZSTD_lazy2: number;
|
||||
const Z_BEST_COMPRESSION: number;
|
||||
const Z_BEST_SPEED: number;
|
||||
const Z_BLOCK: number;
|
||||
const Z_BUF_ERROR: number;
|
||||
const Z_DATA_ERROR: number;
|
||||
const Z_DEFAULT_CHUNK: number;
|
||||
const Z_DEFAULT_COMPRESSION: number;
|
||||
const Z_DEFAULT_LEVEL: number;
|
||||
const Z_DEFAULT_MEMLEVEL: number;
|
||||
const Z_DEFAULT_STRATEGY: number;
|
||||
const Z_DEFAULT_WINDOWBITS: number;
|
||||
const Z_ERRNO: number;
|
||||
const Z_FILTERED: number;
|
||||
const Z_FINISH: number;
|
||||
const Z_FIXED: number;
|
||||
const Z_FULL_FLUSH: number;
|
||||
const Z_HUFFMAN_ONLY: number;
|
||||
const Z_MAX_CHUNK: number;
|
||||
const Z_MAX_LEVEL: number;
|
||||
const Z_MAX_MEMLEVEL: number;
|
||||
const Z_MAX_WINDOWBITS: number;
|
||||
const Z_MEM_ERROR: number;
|
||||
const Z_MIN_CHUNK: number;
|
||||
const Z_MIN_LEVEL: number;
|
||||
const Z_MIN_MEMLEVEL: number;
|
||||
const Z_MIN_WINDOWBITS: number;
|
||||
const Z_NEED_DICT: number;
|
||||
const Z_NO_COMPRESSION: number;
|
||||
const Z_NO_FLUSH: number;
|
||||
const Z_OK: number;
|
||||
const Z_PARTIAL_FLUSH: number;
|
||||
const Z_RLE: number;
|
||||
const Z_STREAM_END: number;
|
||||
const Z_STREAM_ERROR: number;
|
||||
const Z_SYNC_FLUSH: number;
|
||||
const Z_VERSION_ERROR: number;
|
||||
}
|
||||
// Allowed flush values.
|
||||
/** @deprecated Use `constants.Z_NO_FLUSH` */
|
||||
const Z_NO_FLUSH: number;
|
||||
/** @deprecated Use `constants.Z_PARTIAL_FLUSH` */
|
||||
const Z_PARTIAL_FLUSH: number;
|
||||
/** @deprecated Use `constants.Z_SYNC_FLUSH` */
|
||||
const Z_SYNC_FLUSH: number;
|
||||
/** @deprecated Use `constants.Z_FULL_FLUSH` */
|
||||
const Z_FULL_FLUSH: number;
|
||||
/** @deprecated Use `constants.Z_FINISH` */
|
||||
const Z_FINISH: number;
|
||||
/** @deprecated Use `constants.Z_BLOCK` */
|
||||
const Z_BLOCK: number;
|
||||
// Return codes for the compression/decompression functions.
|
||||
// Negative values are errors, positive values are used for special but normal events.
|
||||
/** @deprecated Use `constants.Z_OK` */
|
||||
const Z_OK: number;
|
||||
/** @deprecated Use `constants.Z_STREAM_END` */
|
||||
const Z_STREAM_END: number;
|
||||
/** @deprecated Use `constants.Z_NEED_DICT` */
|
||||
const Z_NEED_DICT: number;
|
||||
/** @deprecated Use `constants.Z_ERRNO` */
|
||||
const Z_ERRNO: number;
|
||||
/** @deprecated Use `constants.Z_STREAM_ERROR` */
|
||||
const Z_STREAM_ERROR: number;
|
||||
/** @deprecated Use `constants.Z_DATA_ERROR` */
|
||||
const Z_DATA_ERROR: number;
|
||||
/** @deprecated Use `constants.Z_MEM_ERROR` */
|
||||
const Z_MEM_ERROR: number;
|
||||
/** @deprecated Use `constants.Z_BUF_ERROR` */
|
||||
const Z_BUF_ERROR: number;
|
||||
/** @deprecated Use `constants.Z_VERSION_ERROR` */
|
||||
const Z_VERSION_ERROR: number;
|
||||
// Compression levels.
|
||||
/** @deprecated Use `constants.Z_NO_COMPRESSION` */
|
||||
const Z_NO_COMPRESSION: number;
|
||||
/** @deprecated Use `constants.Z_BEST_SPEED` */
|
||||
const Z_BEST_SPEED: number;
|
||||
/** @deprecated Use `constants.Z_BEST_COMPRESSION` */
|
||||
const Z_BEST_COMPRESSION: number;
|
||||
/** @deprecated Use `constants.Z_DEFAULT_COMPRESSION` */
|
||||
const Z_DEFAULT_COMPRESSION: number;
|
||||
// Compression strategy.
|
||||
/** @deprecated Use `constants.Z_FILTERED` */
|
||||
const Z_FILTERED: number;
|
||||
/** @deprecated Use `constants.Z_HUFFMAN_ONLY` */
|
||||
const Z_HUFFMAN_ONLY: number;
|
||||
/** @deprecated Use `constants.Z_RLE` */
|
||||
const Z_RLE: number;
|
||||
/** @deprecated Use `constants.Z_FIXED` */
|
||||
const Z_FIXED: number;
|
||||
/** @deprecated Use `constants.Z_DEFAULT_STRATEGY` */
|
||||
const Z_DEFAULT_STRATEGY: number;
|
||||
/** @deprecated */
|
||||
const Z_BINARY: number;
|
||||
/** @deprecated */
|
||||
const Z_TEXT: number;
|
||||
/** @deprecated */
|
||||
const Z_ASCII: number;
|
||||
/** @deprecated */
|
||||
const Z_UNKNOWN: number;
|
||||
/** @deprecated */
|
||||
const Z_DEFLATED: number;
|
||||
}
|
||||
declare module "node:zlib" {
|
||||
export * from "zlib";
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
export enum TaskStatus {
|
||||
ACTIVE = 0,
|
||||
START = 1,
|
||||
WAIT = 2,
|
||||
RELEASE = 3,
|
||||
PREEMPT = 4,
|
||||
TERMINATE = 5
|
||||
}
|
||||
|
||||
export interface TaskEvent {
|
||||
status: TaskStatus
|
||||
taskId: number
|
||||
coreId: number
|
||||
}
|
||||
|
||||
export enum IsrStatus {
|
||||
START = 0,
|
||||
STOP = 1
|
||||
}
|
||||
|
||||
export enum RunableStatus {
|
||||
INVOCATION = 0,
|
||||
TERMINATION = 1
|
||||
}
|
||||
|
||||
export enum TaskType {
|
||||
TASK = 0,
|
||||
ISR = 1,
|
||||
SPINLOCK = 2,
|
||||
RESOURCE = 3,
|
||||
HOOK = 4,
|
||||
SERVICE = 5,
|
||||
RUNABLE = 6,
|
||||
LINE = -1
|
||||
}
|
||||
|
||||
export enum SpinlockStatus {
|
||||
LOCKED = 0,
|
||||
UNLOCKED = 1
|
||||
}
|
||||
|
||||
export enum ResourceStatus {
|
||||
START = 0,
|
||||
STOP = 1
|
||||
}
|
||||
|
||||
export interface IsrEvent {
|
||||
status: IsrStatus
|
||||
isrId: number
|
||||
coreId: number
|
||||
}
|
||||
|
||||
export interface SpinlockEvent {
|
||||
status: SpinlockStatus
|
||||
spinlockId: number
|
||||
coreId: number
|
||||
}
|
||||
|
||||
export interface ResourceEvent {
|
||||
status: ResourceStatus
|
||||
resourceId: number
|
||||
coreId: number
|
||||
}
|
||||
|
||||
export interface HookEvent {
|
||||
hookParam: number
|
||||
hookType: number
|
||||
coreId: number
|
||||
}
|
||||
|
||||
export interface ServiceEvent {
|
||||
serviceParam: number
|
||||
serviceId: number
|
||||
coreId: number
|
||||
}
|
||||
|
||||
export interface LineEvent {
|
||||
from: string
|
||||
to: string
|
||||
coreId: number
|
||||
}
|
||||
|
||||
export const taskStatusRecord: Record<TaskStatus, string> = {
|
||||
[TaskStatus.ACTIVE]: 'Active',
|
||||
[TaskStatus.START]: 'Start',
|
||||
[TaskStatus.WAIT]: 'Wait',
|
||||
[TaskStatus.RELEASE]: 'Release',
|
||||
[TaskStatus.PREEMPT]: 'Preempt',
|
||||
[TaskStatus.TERMINATE]: 'Terminate'
|
||||
}
|
||||
|
||||
export const taskTypeRecord: Record<TaskType, string> = {
|
||||
[TaskType.TASK]: 'Task',
|
||||
[TaskType.ISR]: 'ISR',
|
||||
[TaskType.SPINLOCK]: 'Spinlock',
|
||||
[TaskType.RESOURCE]: 'Resource',
|
||||
[TaskType.HOOK]: 'Hook',
|
||||
[TaskType.SERVICE]: 'Service',
|
||||
[TaskType.LINE]: 'Line',
|
||||
[TaskType.RUNABLE]: 'Runable'
|
||||
}
|
||||
export const isrStatusRecord: Record<IsrStatus, string> = {
|
||||
[IsrStatus.START]: 'Start',
|
||||
[IsrStatus.STOP]: 'Stop'
|
||||
}
|
||||
|
||||
export const runableStatusRecord: Record<RunableStatus, string> = {
|
||||
[RunableStatus.INVOCATION]: 'Invocation',
|
||||
[RunableStatus.TERMINATION]: 'Termination'
|
||||
}
|
||||
|
||||
export function parseInfo(type: TaskType, status: number, br?: string): string {
|
||||
let str = ''
|
||||
switch (type) {
|
||||
case TaskType.TASK:
|
||||
str = `Task: ${taskStatusRecord[status as TaskStatus]}`
|
||||
break
|
||||
case TaskType.ISR:
|
||||
str = `ISR: ${isrStatusRecord[status as IsrStatus]}`
|
||||
break
|
||||
case TaskType.RUNABLE:
|
||||
str = `Runable: ${runableStatusRecord[status as RunableStatus]}`
|
||||
break
|
||||
default:
|
||||
return ''
|
||||
}
|
||||
if (br) {
|
||||
str += br
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
// Unified event structure to reduce computational overhead
|
||||
export interface OsEvent {
|
||||
database?: string
|
||||
index?: number
|
||||
type: TaskType
|
||||
id: number
|
||||
status: number
|
||||
coreId: number
|
||||
ts: number
|
||||
comment: string
|
||||
children?: Record<number, OsEvent[]>
|
||||
}
|
||||
-53
@@ -1,53 +0,0 @@
|
||||
/**
|
||||
* @category UDS
|
||||
*/
|
||||
declare class SecureAccessDll {
|
||||
_ref: any;
|
||||
constructor(dllPath: string);
|
||||
/**
|
||||
* Generates a key with extended options.
|
||||
*
|
||||
* @param ipSeedArray - A buffer containing the seed array, for c: = ipSeedArray + iSeedArraySize
|
||||
* @param iSecurityLevel - The security level to be used.
|
||||
* @param ipVariant - A buffer containing the variant. for c: = ipVariant, size decide by vendor self
|
||||
* @param ipOptions - A buffer containing the options. for c: = ipOptions, size decide by vendor self
|
||||
* @param key - A buffer containing the input key.for c: = iopKeyArray + iMaxKeyArraySize
|
||||
* @returns A buffer containing the generated key. Return is Buffer, for c: = iopKeyArray, length = oActualKeyArraySize
|
||||
* @throws Will throw an error if the key generation fails.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
*
|
||||
* const dllPath=path.join(__dirname,'GenerateKeyExOpt.dll')
|
||||
* const sa=new SecureAccessDll(dllPath)
|
||||
*
|
||||
* const seed=sa.GenerateKeyExOpt(Buffer.from([1,2,3,4,5]),1,Buffer.from([1,2,3,4,5]),Buffer.from([1,2,3,4,5]),Buffer.from([1,2,3,4,5]))
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
GenerateKeyExOpt(ipSeedArray: Buffer, iSecurityLevel: number, ipVariant: Buffer, ipOptions: Buffer, key: Buffer): Buffer;
|
||||
/**
|
||||
* Generates a key with extended options.
|
||||
*
|
||||
* @param ipSeedArray - A buffer containing the seed array, for c: = ipSeedArray + iSeedArraySize
|
||||
* @param iSecurityLevel - The security level to be used.
|
||||
* @param ipVariant - A buffer containing the variant. for c: = ipVariant, size decide by vendor self
|
||||
* @param key - A buffer containing the input key.for c: = ioKeyArray + iKeyArraySize
|
||||
* @returns A buffer containing the generated key. Return is Buffer, for c: = ioKeyArray, length = oSize
|
||||
* @throws Will throw an error if the key generation fails.
|
||||
*
|
||||
* @example
|
||||
* ```typescript
|
||||
*
|
||||
* const dllPath=path.join(__dirname,'GenerateKeyEx.dll')
|
||||
* const sa=new SecureAccessDll(dllPath)
|
||||
*
|
||||
*const seed=sa.GenerateKeyEx(Buffer.from([1,2,3,4,5]),1,Buffer.from([1,2,3,4,5]),Buffer.from([1,2,3,4,5]))
|
||||
* ```
|
||||
*
|
||||
*/
|
||||
GenerateKeyEx(ipSeedArray: Buffer, iSecurityLevel: number, ipVariant: Buffer, key: Buffer): Buffer;
|
||||
private loadDll;
|
||||
}
|
||||
|
||||
export { SecureAccessDll };
|
||||
@@ -1,51 +0,0 @@
|
||||
import type { CanVendor } from './can'
|
||||
|
||||
/**
|
||||
* A physical serial port enumerated from the host OS.
|
||||
* @category Serial
|
||||
*/
|
||||
export interface SerialDevice {
|
||||
/** Human readable label (friendly name, falls back to path) */
|
||||
label: string
|
||||
/** Unique id (serial port path) */
|
||||
id: string
|
||||
/** Port path passed to the serialport driver (e.g. 'COM3', '/dev/ttyUSB0') */
|
||||
handle: string
|
||||
/** Hardware serial number if reported by the OS */
|
||||
serialNumber?: string
|
||||
busy?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Configuration of a serial (UART) hardware device stored in the project.
|
||||
* @category Serial
|
||||
*/
|
||||
export interface SerialBaseInfo {
|
||||
id: string
|
||||
device: SerialDevice
|
||||
baudRate: number
|
||||
dataBits: 5 | 6 | 7 | 8
|
||||
stopBits: 1 | 1.5 | 2
|
||||
parity: 'none' | 'even' | 'odd' | 'mark' | 'space'
|
||||
vendor: CanVendor
|
||||
name: string
|
||||
}
|
||||
|
||||
/**
|
||||
* A serial frame (raw byte stream) sent (`OUT`) or received (`IN`) on a serial device.
|
||||
* @category Serial
|
||||
*/
|
||||
export interface SerialMessage {
|
||||
/** Direction relative to the host: `OUT` = host -> device, `IN` = device -> host */
|
||||
dir: 'OUT' | 'IN'
|
||||
/** Raw bytes */
|
||||
data: Buffer
|
||||
/** Timestamp relative to start, in microseconds */
|
||||
ts: number
|
||||
/** Device name */
|
||||
name: string
|
||||
/** Device id this frame belongs to */
|
||||
device: string
|
||||
/** uuid of the node that produced an `OUT` frame (used to suppress echo) */
|
||||
uuid?: string
|
||||
}
|
||||
@@ -1,209 +0,0 @@
|
||||
# vSomeIP Configuration Interfaces
|
||||
|
||||
This directory contains comprehensive TypeScript interfaces for vSomeIP 3.5.5 configuration, based on the official vSomeIP configuration documentation.
|
||||
|
||||
## File Structure
|
||||
|
||||
The configuration interfaces are split into multiple files for better organization and maintainability:
|
||||
|
||||
### Core Files
|
||||
|
||||
- **`index.ts`** - Main configuration interface and core sub-interfaces
|
||||
- **`payload-config.ts`** - Payload size and queue configuration
|
||||
- **`security-config.ts`** - Security and policy configuration
|
||||
- **`service-discovery-config.ts`** - Service discovery and tracing configuration
|
||||
- **`service-config.ts`** - Service, client, and internal service configuration
|
||||
- **`other-config.ts`** - Other configurations (watchdog, E2E, debounce, etc.)
|
||||
|
||||
### Main Interface
|
||||
|
||||
The main interface `SomeipConfig` combines all sub-interfaces to provide a comprehensive type-safe configuration:
|
||||
|
||||
```typescript
|
||||
import { SomeipConfig } from './index';
|
||||
|
||||
const config: SomeipConfig = {
|
||||
logging: {
|
||||
level: 'info',
|
||||
console: true
|
||||
},
|
||||
applications: [
|
||||
{
|
||||
name: 'my-app',
|
||||
id: '0x1234'
|
||||
}
|
||||
],
|
||||
// ... other configuration
|
||||
};
|
||||
```
|
||||
|
||||
## Key Features
|
||||
|
||||
### Complete Coverage
|
||||
- All configuration options from vSomeIP 3.5.5 documentation
|
||||
- Comprehensive TypeDoc comments for every property
|
||||
- Default value annotations with `@default` tags
|
||||
- Deprecated property annotations with `@deprecated` tags
|
||||
|
||||
### Type Safety
|
||||
- Proper TypeScript types for all configuration options
|
||||
- Union types for properties that accept multiple value types
|
||||
- Optional properties to match vSomeIP's flexible configuration
|
||||
- Complex nested structures properly typed
|
||||
|
||||
### Modular Design
|
||||
- Split into logical sub-interfaces for better organization
|
||||
- Easy to import specific configuration sections
|
||||
- Re-exported for convenience
|
||||
|
||||
## Configuration Sections
|
||||
|
||||
### Logging (`LoggingConfig`)
|
||||
- Console, file, and DLT logging
|
||||
- Log levels and statistics
|
||||
- Version logging configuration
|
||||
|
||||
### Routing (`RoutingConfig`)
|
||||
- Host and guest routing setup
|
||||
- TCP communication configuration
|
||||
- Legacy routing credentials
|
||||
|
||||
### Applications (`ApplicationConfig`)
|
||||
- Application definitions and IDs
|
||||
- Thread management and dispatching
|
||||
- Plugin configuration
|
||||
|
||||
### Network (`NetworkConfig`)
|
||||
- Diagnosis address and mask
|
||||
- Unicast and netmask settings
|
||||
- Device binding
|
||||
|
||||
### Security (`SecurityConfig`)
|
||||
- UNIX credentials authentication
|
||||
- Security policies and rules
|
||||
- Container policy extensions
|
||||
- Security update whitelist
|
||||
|
||||
### Service Discovery (`ServiceDiscoveryConfig`)
|
||||
- Multicast and port configuration
|
||||
- TTL and timing settings
|
||||
- Debouncing configuration
|
||||
|
||||
### Tracing (`TracingConfig`)
|
||||
- DLT integration
|
||||
- Channel and filter configuration
|
||||
- Message tracing options
|
||||
|
||||
### Services (`ServiceConfig`)
|
||||
- Service and instance definitions
|
||||
- Events and eventgroups
|
||||
- Reliable/unreliable communication
|
||||
- SOME/IP-TP configuration
|
||||
- nPDU debounce times
|
||||
|
||||
### Clients (`ClientConfig`)
|
||||
- Port configuration and mappings
|
||||
- Reliable/unreliable port ranges
|
||||
- Remote service port configuration
|
||||
|
||||
### Other Configurations
|
||||
- **Watchdog** (`WatchdogConfig`) - Health monitoring
|
||||
- **E2E Protection** (`E2EConfig`) - End-to-end security
|
||||
- **Debounce** (`DebounceConfig`) - Event filtering
|
||||
- **Acceptances** (`AcceptanceConfig`) - Port security
|
||||
- **Partitions** (`PartitionConfig`) - Service grouping
|
||||
|
||||
## Usage Examples
|
||||
|
||||
### Basic Configuration
|
||||
```typescript
|
||||
import { SomeipConfig } from './index';
|
||||
|
||||
const basicConfig: SomeipConfig = {
|
||||
logging: {
|
||||
level: 'info',
|
||||
console: true
|
||||
},
|
||||
applications: [
|
||||
{
|
||||
name: 'service-app',
|
||||
id: '0x1234'
|
||||
}
|
||||
],
|
||||
services: [
|
||||
{
|
||||
service: '0x1000',
|
||||
instance: '0x0001',
|
||||
reliable: {
|
||||
port: 30501
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
### Security Configuration
|
||||
```typescript
|
||||
import { SecurityConfig } from './security-config';
|
||||
|
||||
const securityConfig: SecurityConfig = {
|
||||
check_credentials: true,
|
||||
allow_remote_clients: false,
|
||||
policies: [
|
||||
{
|
||||
credentials: {
|
||||
uid: 1000,
|
||||
gid: 1000
|
||||
},
|
||||
allow: {
|
||||
requests: [
|
||||
{
|
||||
service: '0x1000',
|
||||
instances: [
|
||||
{
|
||||
ids: ['0x0001'],
|
||||
methods: ['0x0001']
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
```
|
||||
|
||||
### Service Discovery Configuration
|
||||
```typescript
|
||||
import { ServiceDiscoveryConfig } from './service-discovery-config';
|
||||
|
||||
const sdConfig: ServiceDiscoveryConfig = {
|
||||
enable: true,
|
||||
multicast: '224.224.224.0',
|
||||
port: 30490,
|
||||
protocol: 'udp',
|
||||
ttl: '0xFFFFFF'
|
||||
};
|
||||
```
|
||||
|
||||
## Environment Variables
|
||||
|
||||
The following environment variables are supported by vSomeIP but are not part of the configuration interface:
|
||||
|
||||
- `VSOMEIP_APPLICATION_NAME` - Application name
|
||||
- `VSOMEIP_CONFIGURATION` - Configuration file path
|
||||
- `VSOMEIP_CONFIGURATION_<application>` - Application-specific configuration
|
||||
- `VSOMEIP_MANDATORY_CONFIGURATION_FILES` - Mandatory configuration files
|
||||
- `VSOMEIP_CLIENTSIDELOGGING` - Client-side logging
|
||||
- `VSOMEIP_CONFIGURATION_MODULE` - Configuration module (TBD)
|
||||
- `VSOMEIP_E2E_PROTECTION_MODULE` - E2E protection module (TBD)
|
||||
- `VSOMEIP_LOAD_PLUGINS` - Plugin loading (TBD)
|
||||
|
||||
## Version Compatibility
|
||||
|
||||
These interfaces are based on vSomeIP 3.5.5 configuration documentation. For other versions, please refer to the corresponding documentation.
|
||||
|
||||
## References
|
||||
|
||||
- [vSomeIP Configuration Documentation](https://github.com/GENIVI/vsomeip/wiki/vsomeip-in-10-minutes#configuration)
|
||||
- [vSomeIP GitHub Repository](https://github.com/GENIVI/vsomeip)
|
||||
@@ -1,731 +0,0 @@
|
||||
/**
|
||||
* vSomeIP Configuration Interfaces
|
||||
*
|
||||
* This module contains comprehensive TypeScript interfaces for vSomeIP 3.5.5 configuration.
|
||||
* The main interface is split into multiple sub-interfaces for better organization and maintainability.
|
||||
*
|
||||
* @see {@link https://github.com/GENIVI/vsomeip/wiki/vsomeip-in-10-minutes#configuration}
|
||||
*/
|
||||
|
||||
// Import all sub-interfaces
|
||||
import type {
|
||||
GlobalPayloadConfig,
|
||||
GlobalQueueConfig,
|
||||
TcpRestartConfig,
|
||||
FilePermissionsConfig
|
||||
} from './payload-config'
|
||||
|
||||
import type { SecurityConfig } from './security-config'
|
||||
|
||||
import type { ServiceDiscoveryConfig, TracingConfig } from './service-discovery-config'
|
||||
|
||||
import type {
|
||||
ServiceConfig,
|
||||
ServiceEvent,
|
||||
ServiceEventgroup,
|
||||
InternalServiceConfig,
|
||||
ClientConfig
|
||||
} from './service-config'
|
||||
|
||||
import type {
|
||||
WatchdogConfig,
|
||||
LocalClientsKeepaliveConfig,
|
||||
SelectiveBroadcastsConfig,
|
||||
E2EConfig,
|
||||
DebounceConfig,
|
||||
AcceptanceConfig,
|
||||
SecureServiceConfig,
|
||||
PartitionConfig,
|
||||
SuppressMissingEventLogConfig,
|
||||
NpduDefaultTimingsConfig
|
||||
} from './other-config'
|
||||
|
||||
/**
|
||||
* Logging configuration for vSomeIP
|
||||
* Used to configure the log messages of vSomeIP
|
||||
*/
|
||||
export interface LoggingConfig {
|
||||
/**
|
||||
* Specifies whether logging via console is enabled
|
||||
* @default true
|
||||
*/
|
||||
console?: boolean
|
||||
|
||||
/**
|
||||
* File logging configuration
|
||||
*/
|
||||
file?: {
|
||||
/**
|
||||
* Specifies whether a log file should be created
|
||||
* @default false
|
||||
*/
|
||||
enable?: boolean
|
||||
|
||||
/**
|
||||
* The absolute path of the log file
|
||||
* @default "/tmp/vsomeip.log"
|
||||
*/
|
||||
path?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies whether Diagnostic Log and Trace (DLT) is enabled
|
||||
* @default false
|
||||
*/
|
||||
dlt?: boolean
|
||||
|
||||
/**
|
||||
* Specifies the log level
|
||||
* @default "info"
|
||||
*/
|
||||
level?: 'trace' | 'debug' | 'info' | 'warning' | 'error' | 'fatal'
|
||||
|
||||
/**
|
||||
* Configures logging of the vsomeip version
|
||||
*/
|
||||
version?: {
|
||||
/**
|
||||
* Enable or disable cyclic logging of vsomeip version
|
||||
* @default true
|
||||
*/
|
||||
enable?: boolean
|
||||
|
||||
/**
|
||||
* Configures interval in seconds to log the vsomeip version
|
||||
* @default 10
|
||||
*/
|
||||
interval?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures interval in seconds in which the routing manager logs its used memory.
|
||||
* Setting a value greater than zero enables the logging.
|
||||
* @default 0
|
||||
*/
|
||||
memory_log_interval?: number
|
||||
|
||||
/**
|
||||
* Configures interval in seconds in which the routing manager logs its internal status.
|
||||
* Setting a value greater than zero enables the logging.
|
||||
* @default 0
|
||||
*/
|
||||
status_log_interval?: number
|
||||
|
||||
/**
|
||||
* Statistics logging configuration
|
||||
*/
|
||||
statistics?: {
|
||||
/**
|
||||
* How often to report statistics data (received messages/events) in ms.
|
||||
* The minimum possible interval is 1000, for configured values below, 1000 will be used.
|
||||
* @default 10000
|
||||
*/
|
||||
interval?: number
|
||||
|
||||
/**
|
||||
* Minimum frequency of reported events
|
||||
* @default 50
|
||||
*/
|
||||
'min-frequency'?: number
|
||||
|
||||
/**
|
||||
* Maximum number of different messages that are reported
|
||||
* @default 50
|
||||
*/
|
||||
'max-messages'?: number
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Routing host configuration
|
||||
*/
|
||||
export interface RoutingHost {
|
||||
/**
|
||||
* Name of the application that hosts the routing component
|
||||
*/
|
||||
name: string
|
||||
|
||||
/**
|
||||
* User identifier of the process that runs the routing component.
|
||||
* Must be specified if credential checks are enabled by check_credentials set to true.
|
||||
*/
|
||||
uid?: number
|
||||
|
||||
/**
|
||||
* Group identifier of the process that runs the routing component.
|
||||
* Must be specified if credential checks are enabled by check_credentials set to true.
|
||||
*/
|
||||
gid?: number
|
||||
|
||||
/**
|
||||
* The unicast address that shall be used by the routing manager,
|
||||
* if the internal communication shall be done by using TCP connections.
|
||||
*/
|
||||
unicast?: string
|
||||
|
||||
/**
|
||||
* The port that shall be used by the routing manager,
|
||||
* if the internal communication shall be done by using TCP connections.
|
||||
*/
|
||||
port?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Routing guest configuration
|
||||
*/
|
||||
export interface RoutingGuest {
|
||||
/**
|
||||
* The unicast address that shall be used by the applications to connect to the routing manager.
|
||||
* If not set, the unicast address of the host entry is used.
|
||||
*/
|
||||
unicast?: string
|
||||
|
||||
/**
|
||||
* A set of port ranges that shall be used to connect to the routing manager per user identifier/group identifier.
|
||||
* Either specify uid, gid and ranges, or only a set of port ranges.
|
||||
* If uid and gid are not explicitly specified, they default to any.
|
||||
* Each client application requires two ports, one for receiving messages from other applications
|
||||
* and one to send messages to other applications.
|
||||
*/
|
||||
ports?: Array<{
|
||||
/**
|
||||
* User identifier
|
||||
*/
|
||||
uid?: number
|
||||
|
||||
/**
|
||||
* Group identifier
|
||||
*/
|
||||
gid?: number
|
||||
|
||||
/**
|
||||
* Set of port ranges. Each entry consists of a first, last pair that determines
|
||||
* the first and the last port of a port range.
|
||||
*/
|
||||
ranges?: Array<{
|
||||
/**
|
||||
* First port of a port range
|
||||
*/
|
||||
first: number
|
||||
|
||||
/**
|
||||
* Last port of a port range
|
||||
*/
|
||||
last: number
|
||||
}>
|
||||
|
||||
/**
|
||||
* First port of a port range (legacy format)
|
||||
*/
|
||||
first?: number
|
||||
|
||||
/**
|
||||
* Last port of a port range (legacy format)
|
||||
*/
|
||||
last?: number
|
||||
}>
|
||||
}
|
||||
|
||||
/**
|
||||
* Routing configuration
|
||||
* Specifies the properties of the routing. Either a string that specifies the application
|
||||
* that hosts the routing component or a structure that specifies all properties of the routing.
|
||||
* If the routing is not specified, the first started application will host the routing component.
|
||||
*/
|
||||
export interface RoutingConfig {
|
||||
/**
|
||||
* Properties of the routing manager
|
||||
*/
|
||||
host?: RoutingHost
|
||||
|
||||
/**
|
||||
* Properties of all applications that do not host the routing component,
|
||||
* if the internal communication shall be done using TCP connections.
|
||||
*/
|
||||
guests?: RoutingGuest
|
||||
}
|
||||
|
||||
/**
|
||||
* The UID / GID of the application acting as routing manager.
|
||||
* @deprecated Use routing.host.uid and routing.host.gid instead
|
||||
* Must be specified if credentials checks are enabled using check_credentials set to true
|
||||
* in order to successfully check the routing managers credentials passed on connect
|
||||
*/
|
||||
export interface RoutingCredentials {
|
||||
/**
|
||||
* The routing managers UID
|
||||
*/
|
||||
uid: number
|
||||
|
||||
/**
|
||||
* The routing managers GID
|
||||
*/
|
||||
gid: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Application plugin configuration
|
||||
*/
|
||||
export interface ApplicationPlugin {
|
||||
/**
|
||||
* The name of the plug-in
|
||||
*/
|
||||
name: string
|
||||
|
||||
/**
|
||||
* The plug-in type. An application plug-in extends the functionality on application level.
|
||||
* It gets informed by vsomeip over the basic application states (INIT/START/STOP) and can,
|
||||
* based on these notifications, access the standard "application"-API via the runtime.
|
||||
*/
|
||||
type: 'application_plugin'
|
||||
|
||||
/**
|
||||
* Generic way to define configuration data for plugins
|
||||
*/
|
||||
additional?: Record<string, any>
|
||||
}
|
||||
|
||||
/**
|
||||
* Application configuration
|
||||
*/
|
||||
export interface ApplicationConfig {
|
||||
/**
|
||||
* The id of the application. Usually its high byte is equal to the diagnosis address.
|
||||
* In this case the low byte must be different from zero. Thus, if the diagnosis address is 0x63,
|
||||
* valid values range from 0x6301 until 0x63FF. It is also possible to use id values with
|
||||
* a high byte different from the diagnosis address.
|
||||
*/
|
||||
id: string
|
||||
|
||||
/**
|
||||
* The maximum number of threads that shall be used to execute the application callbacks
|
||||
* @default 10
|
||||
*/
|
||||
max_dispatchers?: number
|
||||
|
||||
/**
|
||||
* The maximum time in ms that an application callback may consume before the callback
|
||||
* is considered to be blocked (and an additional thread is used to execute pending callbacks
|
||||
* if max_dispatchers is configured greater than 0)
|
||||
* @default 100
|
||||
*/
|
||||
max_dispatch_time?: number
|
||||
|
||||
/**
|
||||
* The maximum time in seconds that an application will wait for a detached dispatcher
|
||||
* thread to finish executing
|
||||
* @default 5
|
||||
*/
|
||||
max_detached_thread_wait_time?: number
|
||||
|
||||
/**
|
||||
* The number of internal threads to process messages and events within an application.
|
||||
* Valid values are 1-255
|
||||
* @default 2
|
||||
*/
|
||||
threads?: number
|
||||
|
||||
/**
|
||||
* The nice level for internal threads processing messages and events. POSIX/Linux only.
|
||||
* For actual values refer to nice() documentation
|
||||
* @default 0
|
||||
*/
|
||||
io_thread_nice?: number
|
||||
|
||||
/**
|
||||
* Specifies a debounce-time interval in ms in which request-service messages are sent
|
||||
* to the routing manager. If an application requests many services in short same time
|
||||
* the load of sent messages to the routing manager and furthermore the replies from
|
||||
* the routing manager (which contains the routing info for the requested service if available)
|
||||
* can be heavily reduced
|
||||
*/
|
||||
request_debounce_time?: number
|
||||
|
||||
/**
|
||||
* Contains the plug-ins that should be loaded to extend the functionality of vsomeip
|
||||
*/
|
||||
plugins?: ApplicationPlugin[]
|
||||
|
||||
/**
|
||||
* Client/Application specific configuration of debouncing
|
||||
*/
|
||||
debounce?: any
|
||||
|
||||
/**
|
||||
* Configures the session handling. Mostly used for E2E use cases when the application
|
||||
* handles the CRC calculation over the SOME/IP header by themself, and need the ability
|
||||
* to switch off the session handling as otherwise their calculated checksum does not
|
||||
* match reality after vsomeip inserts the session identifier
|
||||
* @default true
|
||||
*/
|
||||
has_session_handling?: boolean
|
||||
|
||||
/**
|
||||
* If set to a positive value, it enables the io_context object's event processing
|
||||
* run_for implementation to run the loop based on duration instead of running it
|
||||
* until the work queue has work to be done
|
||||
* @default 0
|
||||
*/
|
||||
event_loop_periodicity?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Network configuration
|
||||
*/
|
||||
export interface NetworkConfig {
|
||||
/**
|
||||
* Network identifier used to support multiple routing managers on one host.
|
||||
* This setting changes the name of the unix domain sockets in /tmp/.
|
||||
* @default "vsomeip"
|
||||
*/
|
||||
network?: string
|
||||
|
||||
/**
|
||||
* The diagnosis address (byte) that will be used to build client identifiers.
|
||||
* The diagnosis address is assigned to the most significant byte in all client identifiers
|
||||
* if not specified otherwise (for example through a predefined client ID)
|
||||
* @default 0x01
|
||||
*/
|
||||
diagnosis?: string
|
||||
|
||||
/**
|
||||
* The diagnosis mask (2 byte) is used to control the maximum amount of allowed
|
||||
* concurrent vsomeip clients on an ECU and the start value of the client IDs.
|
||||
* @default 0xFF00
|
||||
*/
|
||||
diagnosis_mask?: string
|
||||
|
||||
/**
|
||||
* The IP address of the host system
|
||||
*/
|
||||
unicast?: string
|
||||
|
||||
/**
|
||||
* The netmask to specify the subnet of the host system
|
||||
*/
|
||||
netmask?: string
|
||||
|
||||
/**
|
||||
* If specified, IP endpoints will be bound to this device
|
||||
*/
|
||||
device?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatching configuration
|
||||
* Define default settings for the maximum number of (additional) dispatchers
|
||||
* and the maximum dispatch time. These default values are overwritten by
|
||||
* application specific definitions.
|
||||
*/
|
||||
export interface DispatchingConfig {
|
||||
/**
|
||||
* The maximum number of threads that shall be used to execute the application callbacks
|
||||
* @default 10
|
||||
*/
|
||||
max_dispatchers?: number
|
||||
|
||||
/**
|
||||
* The maximum time in ms that an application callback may consume before the callback
|
||||
* is considered to be blocked (and an additional thread is used to execute pending
|
||||
* callbacks if max_dispatchers is configured greater than 0)
|
||||
* @default 100
|
||||
*/
|
||||
max_dispatch_time?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Main vSomeIP Configuration Interface
|
||||
*
|
||||
* This interface represents the complete configuration structure for vSomeIP 3.5.5.
|
||||
* It combines all sub-interfaces to provide a comprehensive type-safe configuration.
|
||||
*
|
||||
* @see {@link https://github.com/GENIVI/vsomeip/wiki/vsomeip-in-10-minutes#configuration}
|
||||
*/
|
||||
export interface SomeipConfig
|
||||
extends GlobalPayloadConfig,
|
||||
GlobalQueueConfig,
|
||||
TcpRestartConfig,
|
||||
FilePermissionsConfig {
|
||||
/**
|
||||
* Logging configuration for vSomeIP
|
||||
* Used to configure the log messages of vSomeIP
|
||||
*/
|
||||
logging?: LoggingConfig
|
||||
|
||||
/**
|
||||
* Routing configuration
|
||||
* Specifies the properties of the routing. Either a string that specifies the application
|
||||
* that hosts the routing component or a structure that specifies all properties of the routing.
|
||||
* If the routing is not specified, the first started application will host the routing component.
|
||||
*/
|
||||
routing?: string | RoutingConfig
|
||||
|
||||
/**
|
||||
* The UID / GID of the application acting as routing manager.
|
||||
* @deprecated Use routing.host.uid and routing.host.gid instead
|
||||
* Must be specified if credentials checks are enabled using check_credentials set to true
|
||||
* in order to successfully check the routing managers credentials passed on connect
|
||||
*/
|
||||
'routing-credentials'?: RoutingCredentials
|
||||
|
||||
/**
|
||||
* Contains the applications of the host system that use this config file
|
||||
*/
|
||||
applications?: ApplicationConfig[]
|
||||
|
||||
/**
|
||||
* Network configuration
|
||||
*/
|
||||
network?: NetworkConfig
|
||||
|
||||
/**
|
||||
* Configures the time in milliseconds local clients wait for acknowledgement
|
||||
* of their deregistration from the routing manager during shutdown
|
||||
* @default 5000
|
||||
*/
|
||||
shutdown_timeout?: number
|
||||
|
||||
/**
|
||||
* Define default settings for the maximum number of (additional) dispatchers
|
||||
* and the maximum dispatch time. These default values are overwritten by
|
||||
* application specific definitions.
|
||||
*/
|
||||
dispatching?: DispatchingConfig
|
||||
|
||||
/**
|
||||
* Security configuration based on UNIX credentials.
|
||||
* If activated every local connection is authenticated during connect using
|
||||
* the standard UNIX credential passing mechanism.
|
||||
*/
|
||||
security?: SecurityConfig
|
||||
|
||||
/**
|
||||
* Tracing configuration for the Trace Connector
|
||||
* Used to forward the internal messages that are sent over the Unix Domain Sockets (UDS) to DLT.
|
||||
*/
|
||||
tracing?: TracingConfig
|
||||
|
||||
/**
|
||||
* Specifies the size of the socket receive buffer (SO_RCVBUF) used for UDP client
|
||||
* and server endpoints in bytes. Requires CAP_NET_ADMIN to be successful.
|
||||
* @default 1703936
|
||||
*/
|
||||
'udp-receive-buffer-size'?: number
|
||||
|
||||
/**
|
||||
* Contains settings related to the Service Discovery of the host application
|
||||
*/
|
||||
'service-discovery'?: ServiceDiscoveryConfig
|
||||
|
||||
/**
|
||||
* Global nPDU default timings configuration
|
||||
* The nPDU feature can be used to reduce network load as it enables the vsomeip stack
|
||||
* to combine multiple vsomeip messages in one single ethernet frame.
|
||||
*/
|
||||
'npdu-default-timings'?: NpduDefaultTimingsConfig
|
||||
|
||||
/**
|
||||
* Contains the services of the service provider
|
||||
*/
|
||||
services?: ServiceConfig[]
|
||||
|
||||
/**
|
||||
* Specifies service/instance ranges for pure internal service-instances.
|
||||
* This information is used by vsomeip to avoid sending Find-Service messages
|
||||
* via the Service-Discovery when a client is requesting a not available service-instance.
|
||||
* Its can either be done on service/instance level or on service level only which
|
||||
* then includes all instance from 0x0000-0xffff.
|
||||
*/
|
||||
internal_services?: InternalServiceConfig[]
|
||||
|
||||
/**
|
||||
* The client-side ports that shall be used to connect to a specific service.
|
||||
* For each service, an array of ports to be used for reliable/unreliable communication
|
||||
* can be specified. vsomeip will take the first free port of the list. If no free port
|
||||
* can be found, the connection will fail. If vsomeip is asked to connect to a service
|
||||
* instance without specified port(s), the port will be selected by the system. This
|
||||
* implies that the user has to ensure that the ports configured here do not overlap
|
||||
* with the ports automatically selected by the IP stack.
|
||||
*/
|
||||
clients?: ClientConfig[]
|
||||
|
||||
/**
|
||||
* The Watchdog sends periodically pings to all known local clients. If a client
|
||||
* isn't responding within a configured time/amount of pongs the watchdog deregisters
|
||||
* this application/client. If not configured the watchdog isn't activated.
|
||||
*/
|
||||
watchdog?: WatchdogConfig
|
||||
|
||||
/**
|
||||
* The Local Clients Keepalive option activates the sending of periodic ping messages
|
||||
* from the routing manager clients to the routing host. The routing manager host shall
|
||||
* reply to the ping with a pong. The idea is to have a simpler alternetive to the
|
||||
* TCP_KEEPALIVE, particularly for systems where this option can not be configured.
|
||||
*/
|
||||
'local-clients-keepalive'?: LocalClientsKeepaliveConfig
|
||||
|
||||
/**
|
||||
* This nodes allow to add a list of IP addresses on which CAPI-Selective-Broadcasts
|
||||
* feature is supported. If not specified the feature can't be used and the subscription
|
||||
* behavior of the stack is same as with normal events.
|
||||
*/
|
||||
supports_selective_broadcasts?: SelectiveBroadcastsConfig[]
|
||||
|
||||
/**
|
||||
* Used to configure the E2E protection for the specified events
|
||||
*/
|
||||
e2e?: E2EConfig
|
||||
|
||||
/**
|
||||
* Events/fields sent by external devices will be forwarded to the applications
|
||||
* only if a configurable function evaluates to true. The function checks whether
|
||||
* the event/field payload has changed and whether a specified interval has been
|
||||
* elapsed since the last forwarding.
|
||||
*/
|
||||
debounce?: DebounceConfig[]
|
||||
|
||||
/**
|
||||
* Service requests done by an application can be debounced to be more efficient
|
||||
* if many services are requested simultaneously (e.g. at startup). This configuration
|
||||
* variable specified the maximum request debounce time in milliseconds.
|
||||
* @default 10
|
||||
*/
|
||||
request_debounce_time?: number
|
||||
|
||||
/**
|
||||
* Can be used to modify the assignment of ports to the unsecure, optional and secure ranges.
|
||||
*/
|
||||
acceptances?: AcceptanceConfig[]
|
||||
|
||||
/**
|
||||
* List of service instances that are only accepted, if being offered on a secure port.
|
||||
*/
|
||||
'secure-services'?: SecureServiceConfig[]
|
||||
|
||||
/**
|
||||
* Allows to group service instances that are offered on the same port into partitions.
|
||||
* For each partition, a separate client port will be used. The goal is to enable faster
|
||||
* processing of specific events if a single server port is used to offer many services
|
||||
* that send many messages, especially at startup.
|
||||
*/
|
||||
partitions?: PartitionConfig[][]
|
||||
|
||||
/**
|
||||
* Used to filter the log message "deliver_notification: Event [1234.5678.80f3]
|
||||
* is not registered. The message is dropped." that occurs whenever vSomeIP
|
||||
* receives an event without having a corresponding object being registered.
|
||||
*/
|
||||
suppress_missing_event_logs?: SuppressMissingEventLogConfig[]
|
||||
}
|
||||
|
||||
export interface SomeipInfo {
|
||||
id: string
|
||||
name: string
|
||||
services: ServiceConfig[]
|
||||
device: string
|
||||
application: ApplicationConfig
|
||||
serviceDiscovery: ServiceDiscoveryConfig
|
||||
}
|
||||
|
||||
export enum SomeipMessageType {
|
||||
REQUEST = 0,
|
||||
REQUEST_NO_RETURN = 1,
|
||||
NOTIFICATION = 2,
|
||||
RESPONSE = 0x80,
|
||||
REQUEST_ACK = 0x40,
|
||||
NOTIFICATION_ACK = 0x42,
|
||||
ERROR = 0x81,
|
||||
RESPONSE_ACK = 0xc0,
|
||||
ERROR_ACK = 0xc1,
|
||||
UNKNOWN = 255
|
||||
}
|
||||
|
||||
export interface SomeipMessage {
|
||||
uuid?: string
|
||||
service: number
|
||||
instance: number
|
||||
method: number
|
||||
client: number
|
||||
session: number
|
||||
payload: Buffer
|
||||
messageType: SomeipMessageType
|
||||
returnCode: number
|
||||
protocolVersion: number
|
||||
interfaceVersion: number
|
||||
ts: number
|
||||
reliable?: boolean
|
||||
sending: boolean
|
||||
protocol?: string
|
||||
ip?: string
|
||||
port?: number
|
||||
database?: string
|
||||
device?: string
|
||||
}
|
||||
|
||||
export interface VsomeipAvailabilityInfo {
|
||||
service: number
|
||||
instance: number
|
||||
available: boolean
|
||||
}
|
||||
|
||||
export interface VsomeipSubscriptionInfo {
|
||||
client: number
|
||||
uid: number
|
||||
gid: number
|
||||
subscribed: boolean
|
||||
}
|
||||
|
||||
export interface VsomeipSubscriptionStatusInfo {
|
||||
service: number
|
||||
instance: number
|
||||
eventgroup: number
|
||||
event: number
|
||||
status: number
|
||||
}
|
||||
|
||||
export const SomeipMessageTypeMap: Record<SomeipMessageType, string> = {
|
||||
[SomeipMessageType.REQUEST]: 'Request',
|
||||
[SomeipMessageType.REQUEST_NO_RETURN]: 'Request No Return',
|
||||
[SomeipMessageType.NOTIFICATION]: 'Notification',
|
||||
[SomeipMessageType.RESPONSE]: 'Response',
|
||||
[SomeipMessageType.REQUEST_ACK]: 'Request Ack',
|
||||
[SomeipMessageType.NOTIFICATION_ACK]: 'Notification Ack',
|
||||
[SomeipMessageType.ERROR]: 'Error',
|
||||
[SomeipMessageType.RESPONSE_ACK]: 'Response Ack',
|
||||
[SomeipMessageType.ERROR_ACK]: 'Error Ack',
|
||||
[SomeipMessageType.UNKNOWN]: 'Unknown'
|
||||
}
|
||||
|
||||
/** vSomeIP event_type_e (application::request_event) — matches vsomeip enumeration_types.hpp */
|
||||
export const VsomeipEventType = {
|
||||
ET_EVENT: 0,
|
||||
ET_SELECTIVE_EVENT: 1,
|
||||
ET_FIELD: 2,
|
||||
ET_UNKNOWN: 255
|
||||
} as const
|
||||
|
||||
// Re-export imported sub-interfaces for convenience
|
||||
export type {
|
||||
GlobalPayloadConfig,
|
||||
GlobalQueueConfig,
|
||||
TcpRestartConfig,
|
||||
FilePermissionsConfig,
|
||||
SecurityConfig,
|
||||
ServiceDiscoveryConfig,
|
||||
TracingConfig,
|
||||
ServiceConfig,
|
||||
ServiceEvent,
|
||||
ServiceEventgroup,
|
||||
InternalServiceConfig,
|
||||
ClientConfig,
|
||||
WatchdogConfig,
|
||||
LocalClientsKeepaliveConfig,
|
||||
SelectiveBroadcastsConfig,
|
||||
E2EConfig,
|
||||
DebounceConfig,
|
||||
AcceptanceConfig,
|
||||
SecureServiceConfig,
|
||||
PartitionConfig,
|
||||
SuppressMissingEventLogConfig,
|
||||
NpduDefaultTimingsConfig
|
||||
}
|
||||
-415
@@ -1,415 +0,0 @@
|
||||
/**
|
||||
* Other Configuration Interfaces
|
||||
*/
|
||||
|
||||
/**
|
||||
* Watchdog configuration
|
||||
* The Watchdog sends periodically pings to all known local clients. If a client
|
||||
* isn't responding within a configured time/amount of pongs the watchdog deregisters
|
||||
* this application/client. If not configured the watchdog isn't activated.
|
||||
*/
|
||||
export interface WatchdogConfig {
|
||||
/**
|
||||
* Specifies whether the watchdog is enabled or disabled
|
||||
* @default false
|
||||
*/
|
||||
enable?: boolean
|
||||
|
||||
/**
|
||||
* Specifies the timeout in ms the watchdog gets activated if a ping isn't
|
||||
* answered with a pong by a local client within that time. (valid values: 2 - 2^32)
|
||||
* @default 5000
|
||||
*/
|
||||
timeout?: number
|
||||
|
||||
/**
|
||||
* Specifies the amount of allowed missing pongs. (valid values: 1 - 2^32)
|
||||
* @default 3
|
||||
*/
|
||||
allowed_missing_pongs?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Local clients keepalive configuration
|
||||
* The Local Clients Keepalive option activates the sending of periodic ping messages
|
||||
* from the routing manager clients to the routing host. The routing manager host shall
|
||||
* reply to the ping with a pong. The idea is to have a simpler alternetive to the
|
||||
* TCP_KEEPALIVE, particularly for systems where this option can not be configured.
|
||||
*/
|
||||
export interface LocalClientsKeepaliveConfig {
|
||||
/**
|
||||
* Specifies whether the Local Clients Keepalive is enabled or disabled
|
||||
* @default false
|
||||
*/
|
||||
enable?: boolean
|
||||
|
||||
/**
|
||||
* Specifies the time in ms the Local Clients Keepalive messages are sent
|
||||
* @default 5000
|
||||
*/
|
||||
time?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Selective broadcasts support configuration
|
||||
* This nodes allow to add a list of IP addresses on which CAPI-Selective-Broadcasts
|
||||
* feature is supported. If not specified the feature can't be used and the subscription
|
||||
* behavior of the stack is same as with normal events.
|
||||
*/
|
||||
export interface SelectiveBroadcastsConfig {
|
||||
/**
|
||||
* Specifies an IP-Address (in IPv4 or IPv6 notation) on which the "selective"-feature is supported.
|
||||
* Multiple addresses can be configured.
|
||||
*/
|
||||
address: string
|
||||
}
|
||||
|
||||
/**
|
||||
* E2E protection configuration
|
||||
* Used to configure the E2E protection for the specified events
|
||||
*/
|
||||
export interface E2EConfig {
|
||||
/**
|
||||
* Specifies if E2E protection should be enabled or disabled. Use true to enable.
|
||||
*/
|
||||
e2e_enabled: boolean
|
||||
|
||||
/**
|
||||
* Specify the protected events
|
||||
*/
|
||||
protected: Array<{
|
||||
/**
|
||||
* Specifies the service ID
|
||||
*/
|
||||
service_id: string
|
||||
|
||||
/**
|
||||
* Specifies the event ID to be protected
|
||||
*/
|
||||
event_id: string
|
||||
|
||||
/**
|
||||
* Specifies if it should protect (send) or check (receive) the messages, or both.
|
||||
* Possible values are protector, checker and both, respectively.
|
||||
*/
|
||||
variant: 'protector' | 'checker' | 'both'
|
||||
|
||||
/**
|
||||
* Specify the E2E profile to be used. Valid values are CRC8 for Profile 01,
|
||||
* P04 for Profile 04, P07 for Profile 07 and CRC32 for the Custom Profile with ethernet CRC.
|
||||
*/
|
||||
profile: 'CRC8' | 'P04' | 'P07' | 'CRC32'
|
||||
|
||||
/**
|
||||
* Specifies the offset of the CRC in bytes
|
||||
*/
|
||||
crc_offset: number
|
||||
|
||||
/**
|
||||
* Specifies a system wide unique 16 bit numerical identifier (Profile 01)
|
||||
*/
|
||||
data_id?: number
|
||||
|
||||
/**
|
||||
* Specifies the length of all data in bits (Profile 01)
|
||||
*/
|
||||
data_length?: number
|
||||
|
||||
/**
|
||||
* Specifies the offset of the counter in bits (Profile 01)
|
||||
* @default 8
|
||||
*/
|
||||
counter_offset?: number
|
||||
|
||||
/**
|
||||
* Specifies the offset of the dataID nibble (Profile 01)
|
||||
* @default 12
|
||||
*/
|
||||
data_id_nibble_offset?: number
|
||||
|
||||
/**
|
||||
* Specifies the dataID mode (valid values are 0, 1, 2 and 3) (Profile 01).
|
||||
* It impacts which part of the dataID is used in CRC calculation and if any
|
||||
* port of the dataID is sent in the E2E Header.
|
||||
*/
|
||||
data_id_mode?: 0 | 1 | 2 | 3
|
||||
|
||||
/**
|
||||
* Specifies the minimum length of the data in bits (Profile 04/07)
|
||||
* @default 0
|
||||
*/
|
||||
min_data_length?: number
|
||||
|
||||
/**
|
||||
* Specifies the maximum length of the data in bits (Profile 04/07)
|
||||
* @default 0xFFFF for Profile 04, 0xFFFFFFFF for Profile 07
|
||||
*/
|
||||
max_data_length?: number
|
||||
|
||||
/**
|
||||
* Specifies the maximum allowed difference between the counter value of the
|
||||
* current message and the previous valid message (Profile 04/07)
|
||||
* @default 0xFFFF for Profile 04, 0xFFFFFFFF for Profile 07
|
||||
*/
|
||||
max_delta_counter?: number
|
||||
}>
|
||||
}
|
||||
|
||||
/**
|
||||
* Debounce event configuration
|
||||
*/
|
||||
export interface DebounceEvent {
|
||||
/**
|
||||
* Event ID
|
||||
*/
|
||||
event: string
|
||||
|
||||
/**
|
||||
* Specifies whether the event is forwarded on payload change or not
|
||||
* @default false
|
||||
*/
|
||||
on_change?: boolean
|
||||
|
||||
/**
|
||||
* Array of payload indexes with given bit mask (optional) to be ignored
|
||||
* in payload change evaluation. Instead of specifying an index / bitmask pair,
|
||||
* one can only define the payload index which shall be ignored in the evaluation.
|
||||
*/
|
||||
ignore?: Array<
|
||||
| {
|
||||
/**
|
||||
* Payload index to be checked with given bitmask
|
||||
*/
|
||||
index: number
|
||||
|
||||
/**
|
||||
* 1 Byte bitmask applied to byte at given payload index.
|
||||
* Example mask: 0x0f ignores payload changes in low nibble of the byte at given index.
|
||||
*/
|
||||
mask?: number
|
||||
}
|
||||
| number
|
||||
>
|
||||
|
||||
/**
|
||||
* Specifies if the event shall be debounced based on elapsed time interval.
|
||||
* (valid values: time in ms, never)
|
||||
* @default "never"
|
||||
*/
|
||||
interval?: number | 'never'
|
||||
|
||||
/**
|
||||
* Specifies if interval timer is reset when payload change was detected
|
||||
* @default false
|
||||
*/
|
||||
on_change_resets_interval?: boolean
|
||||
|
||||
/**
|
||||
* Specifies if last message should be sent after interval timeout
|
||||
* @default false
|
||||
*/
|
||||
send_current_value_after?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Debounce configuration
|
||||
* Events/fields sent by external devices will be forwarded to the applications
|
||||
* only if a configurable function evaluates to true. The function checks whether
|
||||
* the event/field payload has changed and whether a specified interval has been
|
||||
* elapsed since the last forwarding.
|
||||
*/
|
||||
export interface DebounceConfig {
|
||||
/**
|
||||
* Service ID which hosts the events to be debounced
|
||||
*/
|
||||
service: string
|
||||
|
||||
/**
|
||||
* Instance ID which hosts the events to be debounced
|
||||
*/
|
||||
instance: string
|
||||
|
||||
/**
|
||||
* Array of events which shall be debounced based on the following configuration options
|
||||
*/
|
||||
events: DebounceEvent[]
|
||||
}
|
||||
|
||||
/**
|
||||
* Acceptance configuration
|
||||
* Can be used to modify the assignment of ports to the unsecure, optional and secure ranges.
|
||||
*/
|
||||
export interface AcceptanceConfig {
|
||||
/**
|
||||
* The IP Address of the device where the ports should be modified
|
||||
*/
|
||||
address: string
|
||||
|
||||
/**
|
||||
* Either a single path to an activation file or a list of pathes to activation files.
|
||||
* The existence of an activation file switches on the filter mechanism for the specified address.
|
||||
*/
|
||||
path: string | string[]
|
||||
|
||||
/**
|
||||
* Type of ports to modify. Possible values are reliable and unreliable.
|
||||
*/
|
||||
reliable?: Array<{
|
||||
/**
|
||||
* Adds that port to the secure port group
|
||||
*/
|
||||
port?: number
|
||||
|
||||
/**
|
||||
* Group of ports starting at first, to add as a secure port
|
||||
*/
|
||||
first?: number
|
||||
|
||||
/**
|
||||
* Group of ports ending at last, to add as a secure port
|
||||
*/
|
||||
last?: number
|
||||
|
||||
/**
|
||||
* Used to specify the type of ports to remove from secure ports group.
|
||||
* Possible values are optional and secure.
|
||||
* - optional, removes the following ports from the secure port range:
|
||||
* - Closed(30491, 30499)
|
||||
* - Closed(30898, 30998)
|
||||
* - Closed(30501, 30599)
|
||||
* - secure, removes the following ports from the secure port range:
|
||||
* - Closed(32491, 32499)
|
||||
* - Closed(32898, 32998)
|
||||
* - Closed(32501, 32599)
|
||||
*/
|
||||
type?: 'optional' | 'secure'
|
||||
}>
|
||||
|
||||
/**
|
||||
* Type of ports to modify. Possible values are reliable and unreliable.
|
||||
*/
|
||||
unreliable?: Array<{
|
||||
/**
|
||||
* Adds that port to the secure port group
|
||||
*/
|
||||
port?: number
|
||||
|
||||
/**
|
||||
* Group of ports starting at first, to add as a secure port
|
||||
*/
|
||||
first?: number
|
||||
|
||||
/**
|
||||
* Group of ports ending at last, to add as a secure port
|
||||
*/
|
||||
last?: number
|
||||
|
||||
/**
|
||||
* Used to specify the type of ports to remove from secure ports group.
|
||||
* Possible values are optional and secure.
|
||||
* - optional, removes the following ports from the secure port range:
|
||||
* - Closed(30491, 30499)
|
||||
* - Closed(30898, 30998)
|
||||
* - Closed(30501, 30599)
|
||||
* - secure, removes the following ports from the secure port range:
|
||||
* - Closed(32491, 32499)
|
||||
* - Closed(32898, 32998)
|
||||
* - Closed(32501, 32599)
|
||||
*/
|
||||
type?: 'optional' | 'secure'
|
||||
}>
|
||||
}
|
||||
|
||||
/**
|
||||
* Secure service configuration
|
||||
* List of service instances that are only accepted, if being offered on a secure port.
|
||||
*/
|
||||
export interface SecureServiceConfig {
|
||||
/**
|
||||
* The id of the service
|
||||
*/
|
||||
service: string
|
||||
|
||||
/**
|
||||
* The id of the instance
|
||||
*/
|
||||
instance: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Partition configuration
|
||||
* Allows to group service instances that are offered on the same port into partitions.
|
||||
* For each partition, a separate client port will be used. The goal is to enable faster
|
||||
* processing of specific events if a single server port is used to offer many services
|
||||
* that send many messages, especially at startup.
|
||||
*/
|
||||
export interface PartitionConfig {
|
||||
/**
|
||||
* The id of the service
|
||||
*/
|
||||
service: string
|
||||
|
||||
/**
|
||||
* The id of the instance
|
||||
*/
|
||||
instance: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Suppress missing event log configuration
|
||||
* Used to filter the log message "deliver_notification: Event [1234.5678.80f3]
|
||||
* is not registered. The message is dropped." that occurs whenever vSomeIP
|
||||
* receives an event without having a corresponding object being registered.
|
||||
*/
|
||||
export interface SuppressMissingEventLogConfig {
|
||||
/**
|
||||
* Service ID of event to be filtered. Possible values: hex, dec, any.
|
||||
*/
|
||||
service: string
|
||||
|
||||
/**
|
||||
* Instance ID of event to be filtered. Possible values: hex, dec, any.
|
||||
*/
|
||||
instance: string
|
||||
|
||||
/**
|
||||
* Array of events to be filtered. Possible values:
|
||||
* - Single hex, dec value.
|
||||
* - Multiple hex, dec values.
|
||||
* - Range based hex, dec values.
|
||||
* - If no events is provided, then it's assumed all events are to be ignored.
|
||||
*/
|
||||
events?: Array<string | { first: string; last: string }>
|
||||
}
|
||||
|
||||
/**
|
||||
* nPDU default timings configuration
|
||||
* Global nPDU default timings configuration
|
||||
* The nPDU feature can be used to reduce network load as it enables the vsomeip stack
|
||||
* to combine multiple vsomeip messages in one single ethernet frame.
|
||||
*/
|
||||
export interface NpduDefaultTimingsConfig {
|
||||
/**
|
||||
* Default debounce time for requests in milliseconds
|
||||
* @default 2
|
||||
*/
|
||||
'debounce-time-request'?: number
|
||||
|
||||
/**
|
||||
* Default debounce time for responses in milliseconds
|
||||
* @default 2
|
||||
*/
|
||||
'debounce-time-response'?: number
|
||||
|
||||
/**
|
||||
* Default maximum retention time for requests in milliseconds
|
||||
* @default 5
|
||||
*/
|
||||
'max-retention-time-request'?: number
|
||||
|
||||
/**
|
||||
* Default maximum retention time for responses in milliseconds
|
||||
* @default 5
|
||||
*/
|
||||
'max-retention-time-response'?: number
|
||||
}
|
||||
-178
@@ -1,178 +0,0 @@
|
||||
/**
|
||||
* Payload and Queue Size Configuration Interfaces
|
||||
*/
|
||||
|
||||
/**
|
||||
* Payload size configuration for specific IP and port
|
||||
*/
|
||||
export interface PayloadSizeConfig {
|
||||
/**
|
||||
* IP Address of:
|
||||
* - On client side: the IP of the remote service for which the payload size should be limited.
|
||||
* - On service side: the IP of the offered service for which the payload size for receiving
|
||||
* and sending should be limited.
|
||||
*/
|
||||
unicast: string
|
||||
|
||||
/**
|
||||
* Array which holds pairs of port and payload size statements
|
||||
*/
|
||||
ports: Array<{
|
||||
/**
|
||||
* The ports regarding:
|
||||
* - On client side: the port of the remote service for which the payload size should be limited.
|
||||
* - On service side: the port of the offered service for which the payload size for receiving
|
||||
* and sending should be limited.
|
||||
*/
|
||||
port: string
|
||||
|
||||
/**
|
||||
* The payload regarding:
|
||||
* - On client side: the payload size limit in bytes of a message sent to the remote service
|
||||
* hosted on beforehand specified IP and port.
|
||||
* - On service side: the payload size limit in bytes of messages received and sent by the
|
||||
* service offered on previously specified IP and port. If multiple services are hosted
|
||||
* on the same port they all share the limit specified.
|
||||
*/
|
||||
'max-payload-size': string
|
||||
}>
|
||||
}
|
||||
|
||||
/**
|
||||
* Endpoint queue size configuration for specific IP and port
|
||||
*/
|
||||
export interface EndpointQueueConfig {
|
||||
/**
|
||||
* - On client side: The IP of the remote service for which the queue size of sent requests should be limited.
|
||||
* - On service side: The IP of the offered service for which the queue size for sent responses should be limited.
|
||||
* This IP address is therefore identical to the IP address specified via unicast setting on top level of the json file.
|
||||
*/
|
||||
unicast: string
|
||||
|
||||
/**
|
||||
* Array which holds pairs of port and queue size statements
|
||||
*/
|
||||
ports: Array<{
|
||||
/**
|
||||
* - On client side: the port of the remote service for which the queue size of sent requests should be limited.
|
||||
* - On service side: the port of the offered service for which the queue size for send responses should be limited.
|
||||
*/
|
||||
port: string
|
||||
|
||||
/**
|
||||
* - On client side: the queue size limit in bytes of messages sent to the remote service
|
||||
* hosted on beforehand specified IP and port.
|
||||
* - On service side: the queue size limit in bytes for responses sent by the service
|
||||
* offered on previously specified IP and port. If multiple services are hosted on
|
||||
* the same port they all share the limit specified.
|
||||
*/
|
||||
'queue-size-limit': string
|
||||
}>
|
||||
}
|
||||
|
||||
/**
|
||||
* Global payload size configuration
|
||||
*/
|
||||
export interface GlobalPayloadConfig {
|
||||
/**
|
||||
* Array to limit the maximum allowed payload sizes per IP and port.
|
||||
* If not specified otherwise the allowed payload sizes are unlimited.
|
||||
* The settings in this array only affect communication over TCP.
|
||||
* To limit the local payload size max-payload-size-local can be used.
|
||||
*/
|
||||
'payload-sizes'?: PayloadSizeConfig[]
|
||||
|
||||
/**
|
||||
* The maximum allowed payload size for node internal communication in bytes.
|
||||
* By default the payload size for node internal communication is unlimited.
|
||||
* It can be limited via this setting.
|
||||
*/
|
||||
'max-payload-size-local'?: string
|
||||
|
||||
/**
|
||||
* The maximum allowed payload size for TCP communication in bytes.
|
||||
* By default the payload size for TCP communication is unlimited.
|
||||
* It can be limited via this setting.
|
||||
*/
|
||||
'max-payload-size-reliable'?: string
|
||||
|
||||
/**
|
||||
* The maximum allowed payload size for UDP communication via SOME/IP-TP in bytes.
|
||||
* By default the payload size for UDP via SOME/IP-TP communication is unlimited.
|
||||
* It can be limited via this setting. This setting only applies for SOME/IP-TP enabled
|
||||
* methods/events/fields (otherwise the UDP default of 1400 bytes applies).
|
||||
*/
|
||||
'max-payload-size-unreliable'?: string
|
||||
|
||||
/**
|
||||
* The number of processed messages which are half the size or smaller than the allocated
|
||||
* buffer used to process them before the memory for the buffer is released and starts
|
||||
* to grow dynamically again. This setting can be useful in scenarios where only a small
|
||||
* number of the overall messages are a lot bigger then the rest and the memory allocated
|
||||
* to process them should be released in a timely manner. If the value is set to zero
|
||||
* the buffer sizes aren't reset and are as big as the biggest processed message.
|
||||
* @default 5
|
||||
*/
|
||||
'buffer-shrink-threshold'?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Global endpoint queue configuration
|
||||
*/
|
||||
export interface GlobalQueueConfig {
|
||||
/**
|
||||
* Array to limit the maximum allowed size in bytes of cached outgoing messages per IP and port
|
||||
* (message queue size per endpoint). If not specified otherwise the allowed queue size is unlimited.
|
||||
* The settings in this array only affect external communication.
|
||||
* To limit the local queue size endpoint-queue-limit-local can be used.
|
||||
*/
|
||||
'endpoint-queue-limits'?: EndpointQueueConfig[]
|
||||
|
||||
/**
|
||||
* Setting to limit the maximum allowed size in bytes of cached outgoing messages
|
||||
* for external communication (message queue size per endpoint). By default the queue
|
||||
* size for external communication is unlimited. It can be limited via this setting.
|
||||
* Settings done in the endpoint-queue-limits array override this setting.
|
||||
*/
|
||||
'endpoint-queue-limit-external'?: string
|
||||
|
||||
/**
|
||||
* Setting to limit the maximum allowed size in bytes of cached outgoing messages
|
||||
* for local communication (message queue size per endpoint). By default the queue
|
||||
* size for node internal communication is unlimited. It can be limited via this setting.
|
||||
*/
|
||||
'endpoint-queue-limit-local'?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* TCP restart configuration
|
||||
*/
|
||||
export interface TcpRestartConfig {
|
||||
/**
|
||||
* Setting to limit the number of TCP client endpoint restart aborts due to unfinished TCP handshake.
|
||||
* After the limit is reached, a forced restart of the TCP client endpoint is done if the
|
||||
* connection attempt is still pending.
|
||||
* @default 5
|
||||
*/
|
||||
'tcp-restart-aborts-max'?: number
|
||||
|
||||
/**
|
||||
* Setting to define the maximum time until the TCP client endpoint connection attempt
|
||||
* should be finished. If tcp-connect-time-max is elapsed, the TCP client endpoint is
|
||||
* forcefully restarted if the connection attempt is still pending.
|
||||
* @default 5000
|
||||
*/
|
||||
'tcp-connect-time-max'?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* File permissions configuration
|
||||
*/
|
||||
export interface FilePermissionsConfig {
|
||||
/**
|
||||
* If UDS is used, this configures the user file-creation mode mask (umask)
|
||||
* for the permissions of the sockets
|
||||
* @default 0666
|
||||
*/
|
||||
'permissions-uds'?: string
|
||||
}
|
||||
-229
@@ -1,229 +0,0 @@
|
||||
/**
|
||||
* Security Configuration Interfaces
|
||||
*/
|
||||
|
||||
/**
|
||||
* Security credentials configuration
|
||||
*/
|
||||
export interface SecurityCredentials {
|
||||
/**
|
||||
* Specifies the LINUX User ID of the client application as decimal number.
|
||||
* As a wildcard "any" can be used.
|
||||
*/
|
||||
uid?: number | 'any'
|
||||
|
||||
/**
|
||||
* Specifies the LINUX Group ID of the client application as decimal number.
|
||||
* As a wildcard "any" can be used.
|
||||
*/
|
||||
gid?: number | 'any'
|
||||
|
||||
/**
|
||||
* Specifies whether the LINUX user and group ids are allowed or denied for the policy.
|
||||
*/
|
||||
allow?: {
|
||||
/**
|
||||
* Specifies a list of LINUX user ids. These may either be specified as decimal
|
||||
* numbers or as ranges. Ranges are specified by the first and the last valid id.
|
||||
*/
|
||||
uid?: Array<number | { first: number; last: number }>
|
||||
|
||||
/**
|
||||
* Specifies a list of LINUX group ids. These may either be specified as decimal
|
||||
* numbers or as ranges. Ranges are specified by the first and the last valid id.
|
||||
*/
|
||||
gid?: Array<number | { first: number; last: number }>
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies whether the LINUX user and group ids are allowed or denied for the policy.
|
||||
*/
|
||||
deny?: {
|
||||
/**
|
||||
* Specifies a list of LINUX user ids. These may either be specified as decimal
|
||||
* numbers or as ranges. Ranges are specified by the first and the last valid id.
|
||||
*/
|
||||
uid?: Array<number | { first: number; last: number }>
|
||||
|
||||
/**
|
||||
* Specifies a list of LINUX group ids. These may either be specified as decimal
|
||||
* numbers or as ranges. Ranges are specified by the first and the last valid id.
|
||||
*/
|
||||
gid?: Array<number | { first: number; last: number }>
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Security request/offer configuration
|
||||
*/
|
||||
export interface SecurityRequestOffer {
|
||||
/**
|
||||
* Specifies a service for the requests/offers
|
||||
*/
|
||||
service: string
|
||||
|
||||
/**
|
||||
* Specifies a instance for the requests/offers. As a wildcard "any" can be used which
|
||||
* means a range from instance ID 0x01 to 0xFFFF which also implies a method
|
||||
* ID range from 0x01 to 0xFFFF.
|
||||
* @deprecated Use instances instead
|
||||
*/
|
||||
instance?: string
|
||||
|
||||
/**
|
||||
* Specifies a set of instance ID and method ID range pairs which are allowed/denied
|
||||
* to communicate with. If the ids tag below is not used to specify allowed/denied
|
||||
* requests on method ID level one can also only specify a a set of instance
|
||||
* ID ranges which are allowed to be requested analogous to the allowed offers section.
|
||||
* If no method IDs are specified, the allowed methods are by default a range
|
||||
* from 0x01 to 0xFFFF.
|
||||
*/
|
||||
instances?: Array<{
|
||||
/**
|
||||
* Specifies a set of instance ID ranges which are allowed/denied to communicate with.
|
||||
* It is also possible to specify a single instance ID as array element without
|
||||
* giving an upper / lower range bound. As a wildcard "any" can be used which
|
||||
* means a range from instance ID 0x01 to 0xFFFF.
|
||||
*/
|
||||
ids?: Array<string | { first: string; last: string }>
|
||||
|
||||
/**
|
||||
* Specifies a set of method ID ranges which are allowed/denied to communicate with.
|
||||
* It is also possible to specify a single method ID as array element without
|
||||
* giving an upper / lower range bound. As a wildcard "any" can be used which
|
||||
* means a range from method ID 0x01 to 0xFFFF.
|
||||
*/
|
||||
methods?: Array<string | { first: string; last: string }>
|
||||
}>
|
||||
}
|
||||
|
||||
/**
|
||||
* Security allow/deny configuration
|
||||
*/
|
||||
export interface SecurityAllowDeny {
|
||||
/**
|
||||
* Specifies a set of service instance pairs which the above client application
|
||||
* using the credentials above is allowed/denied to communicate with.
|
||||
*/
|
||||
requests?: SecurityRequestOffer[]
|
||||
|
||||
/**
|
||||
* Specifies a set of service instance pairs which are allowed/denied to be offered
|
||||
* by the client application using the credentials above.
|
||||
*/
|
||||
offers?: Array<{
|
||||
/**
|
||||
* Specifies a service for the offers
|
||||
*/
|
||||
service: string
|
||||
|
||||
/**
|
||||
* Specifies a instance for the offers. As a wildcard "any" can be used which
|
||||
* means a range from instance ID 0x01 to 0xFFFF.
|
||||
* @deprecated Use instances instead
|
||||
*/
|
||||
instance?: string
|
||||
|
||||
/**
|
||||
* Specifies a set of instance ID ranges which are allowed/denied to be offered by
|
||||
* the client application using the credentials above. It is also possible to
|
||||
* specify a single instance ID as array element without giving an upper /
|
||||
* lower range bound. As a wildcard "any" can be used which means a range
|
||||
* from instance ID 0x01 to 0xFFFF.
|
||||
*/
|
||||
instances?: Array<string | { first: string; last: string }>
|
||||
}>
|
||||
}
|
||||
|
||||
/**
|
||||
* Security policy configuration
|
||||
*/
|
||||
export interface SecurityPolicy {
|
||||
/**
|
||||
* Specifies the credentials for which a security policy will be applied.
|
||||
* If check_credentials is set to true the credentials of a local application
|
||||
* needs to be specified correctly to ensure local socket authentication can succeed.
|
||||
*/
|
||||
credentials?: SecurityCredentials
|
||||
|
||||
/**
|
||||
* This tag specifies either allow or deny depending on white or blacklisting is needed.
|
||||
* Specifying allow and deny entries in one policy is therefore not allowed.
|
||||
*/
|
||||
allow?: SecurityAllowDeny
|
||||
|
||||
/**
|
||||
* This tag specifies either allow or deny depending on white or blacklisting is needed.
|
||||
* Specifying allow and deny entries in one policy is therefore not allowed.
|
||||
*/
|
||||
deny?: SecurityAllowDeny
|
||||
}
|
||||
|
||||
/**
|
||||
* Security configuration based on UNIX credentials.
|
||||
* If activated every local connection is authenticated during connect using
|
||||
* the standard UNIX credential passing mechanism.
|
||||
*/
|
||||
export interface SecurityConfig {
|
||||
/**
|
||||
* Specifies whether security checks are active or not. This includes credentials
|
||||
* checks on connect as well as all policies checks configured in follow.
|
||||
* @default false
|
||||
*/
|
||||
check_credentials?: boolean
|
||||
|
||||
/**
|
||||
* Specifies whether incoming remote requests / subscriptions are allowed to be sent
|
||||
* to a local proxy / client. If not specified, all remote requests / subscriptions
|
||||
* are allowed to be received by default.
|
||||
* @default true
|
||||
*/
|
||||
allow_remote_clients?: boolean
|
||||
|
||||
/**
|
||||
* Specifies the security policies. Each policy at least needs to specify allow or deny.
|
||||
*/
|
||||
policies?: SecurityPolicy[]
|
||||
|
||||
/**
|
||||
* Container policy extensions configuration
|
||||
* Specifies the additional configuration folders to be loaded for each container hostname / filesystem path pair.
|
||||
*/
|
||||
container_policy_extensions?: Array<{
|
||||
/**
|
||||
* Specifies the linux hostname
|
||||
*/
|
||||
container: string
|
||||
|
||||
/**
|
||||
* Specifies a filesystem path (relative to vsomeip_policy_extensions.json or absolute)
|
||||
* which contains $UID_$GID subfolders that hold a vsomeip_security.json file.
|
||||
* NOTE: ($UID / $GID is the UID /GID of the vsomeip client application to which
|
||||
* a client from hostname defined with container connects to.
|
||||
*/
|
||||
path: string
|
||||
}>
|
||||
|
||||
/**
|
||||
* Security update whitelist configuration
|
||||
* @deprecated TBD - This feature is still under development
|
||||
*/
|
||||
'security-update-whitelist'?: {
|
||||
/**
|
||||
* Range of possible uids to use. Possible values are any, or range based using the tags first and last.
|
||||
* The range based possible values are dec/hex values or min/max respectively.
|
||||
*/
|
||||
uids?: 'any' | { first: string | number; last: string | number }
|
||||
|
||||
/**
|
||||
* Range of possible services to use. Possible values are any, or range based using the tags first and last.
|
||||
* The range based possible values are dec/hex values or min/max respectively.
|
||||
*/
|
||||
services?: 'any' | { first: string | number; last: string | number }
|
||||
|
||||
/**
|
||||
* Enables or disables the whitelist. Possible values are true or false.
|
||||
*/
|
||||
'check-whitelist'?: boolean
|
||||
}
|
||||
}
|
||||
-423
@@ -1,423 +0,0 @@
|
||||
/**
|
||||
* Service Configuration Interfaces
|
||||
*/
|
||||
|
||||
/**
|
||||
* Service event configuration
|
||||
*/
|
||||
export interface ServiceEvent {
|
||||
/**
|
||||
* The id of the event
|
||||
*/
|
||||
event: string
|
||||
|
||||
/**
|
||||
* Specifies whether the event is of type field. A field is a combination
|
||||
* of getter, setter and notification event. It contains at least a getter,
|
||||
* a setter, or a notifier. The notifier sends an event message that transports
|
||||
* the current value of a field on change.
|
||||
*/
|
||||
is_field?: boolean | string
|
||||
|
||||
/**
|
||||
* Specifies whether the communication is reliable respectively whether the
|
||||
* event is sent with the TCP protocol. If the value is false the UDP protocol will be used.
|
||||
*/
|
||||
is_reliable?: boolean | string
|
||||
|
||||
/**
|
||||
* Period between periodic event sends (milliseconds).
|
||||
*/
|
||||
cycle?: number
|
||||
|
||||
/**
|
||||
* Defines if the updates are sent right away if the event value changes
|
||||
* @default true
|
||||
*/
|
||||
update_on_change?: boolean
|
||||
|
||||
/**
|
||||
* When the update_on_change is set to true, and this parameter is also true,
|
||||
* the defined cycle is reset when the event value changes.
|
||||
* @default false
|
||||
*/
|
||||
change_resets_cycle?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Service eventgroup configuration
|
||||
*/
|
||||
export interface ServiceEventgroup {
|
||||
/**
|
||||
* The id of the event group
|
||||
*/
|
||||
eventgroup: string
|
||||
|
||||
/**
|
||||
* Specifies the multicast that is used to publish the eventgroup
|
||||
*/
|
||||
multicast?: {
|
||||
/**
|
||||
* The multicast address
|
||||
*/
|
||||
address: string
|
||||
|
||||
/**
|
||||
* The multicast port
|
||||
*/
|
||||
port: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Contains the ids of the appropriate events
|
||||
*/
|
||||
events: string[]
|
||||
|
||||
/**
|
||||
* Specifies when to use multicast and when to use unicast to send a notification event.
|
||||
* Must be set to a non-negative number. If it is set to zero, all events of the eventgroup
|
||||
* will be sent by unicast. Otherwise, the events will be sent by unicast as long as the
|
||||
* number of subscribers is lower than the threshold and by multicast if the number of
|
||||
* subscribers is greater or equal. This means, a threshold of 1 will lead to all events
|
||||
* being sent by multicast.
|
||||
* @default 0
|
||||
*/
|
||||
threshold?: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Service reliable configuration
|
||||
*/
|
||||
export interface ServiceReliable {
|
||||
/**
|
||||
* The port of the TCP endpoint
|
||||
*/
|
||||
port: number
|
||||
|
||||
/**
|
||||
* Specifies whether magic cookies are enabled
|
||||
* @default false
|
||||
*/
|
||||
'enable-magic-cookies'?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Service debounce times configuration
|
||||
*/
|
||||
export interface ServiceDebounceTimes {
|
||||
/**
|
||||
* Requests configuration
|
||||
*/
|
||||
requests?: Record<
|
||||
string,
|
||||
{
|
||||
/**
|
||||
* Minimal time between sending a message to the same method of a remote service
|
||||
* over the same connection (src/dst address + src/dst port).
|
||||
*/
|
||||
'debounce-time': number
|
||||
|
||||
/**
|
||||
* The maximum time which a message to the same method of a remote service over
|
||||
* the same connection (src/dst address + src/dst port) is allowed to be buffered
|
||||
* on sender side.
|
||||
*/
|
||||
'maximum-retention-time': number
|
||||
}
|
||||
>
|
||||
|
||||
/**
|
||||
* Responses configuration
|
||||
*/
|
||||
responses?: Record<
|
||||
string,
|
||||
{
|
||||
/**
|
||||
* Minimal time between sending a message to the same method of a remote service
|
||||
* over the same connection (src/dst address + src/dst port).
|
||||
*/
|
||||
'debounce-time': number
|
||||
|
||||
/**
|
||||
* The maximum time which a message to the same method of a remote service over
|
||||
* the same connection (src/dst address + src/dst port) is allowed to be buffered
|
||||
* on sender side.
|
||||
*/
|
||||
'maximum-retention-time': number
|
||||
}
|
||||
>
|
||||
}
|
||||
|
||||
/**
|
||||
* SOME/IP-TP configuration
|
||||
*/
|
||||
export interface SomeipTpConfig {
|
||||
/**
|
||||
* Contains the IDs for responses, fields and events which are sent from the node
|
||||
* to a remote client which can be segmented via SOME/IP-TP if they exceed the
|
||||
* maximum message size for UDP communication. If an ID isn't listed here the
|
||||
* message will otherwise be dropped if the maximum message size is exceeded.
|
||||
*/
|
||||
'service-to-client'?: Array<
|
||||
| string
|
||||
| {
|
||||
/**
|
||||
* Configures the method id to use
|
||||
*/
|
||||
method: string
|
||||
|
||||
/**
|
||||
* New UDP payload in bytes, value must be a multiple of 16
|
||||
*/
|
||||
'max-segment-length': number
|
||||
|
||||
/**
|
||||
* Lower limit used between sending of two segments of the same SOME/IP-TP message.
|
||||
* Default for the separation time is 0, no matter whether a message is SOME/IP-TP or not.
|
||||
* For separation time 0, message sending is no different from what it was before.
|
||||
* @default 0
|
||||
*/
|
||||
'separation-time'?: number
|
||||
}
|
||||
>
|
||||
|
||||
/**
|
||||
* Contains the IDs for requests, which are sent from the node to a remote service
|
||||
* which can be segmented via SOME/IP-TP if they exceed the maximum message size
|
||||
* for UDP communication. If an ID isn't listed here the message will otherwise
|
||||
* be dropped if the maximum message size is exceeded. Please note that the unicast
|
||||
* key has to be set to the remote IP address of the offering node for this setting
|
||||
* to take effect.
|
||||
*/
|
||||
'client-to-service'?: Array<
|
||||
| string
|
||||
| {
|
||||
/**
|
||||
* Configures the method id to use
|
||||
*/
|
||||
method: string
|
||||
|
||||
/**
|
||||
* New UDP payload in bytes, value must be a multiple of 16
|
||||
*/
|
||||
'max-segment-length': number
|
||||
|
||||
/**
|
||||
* Lower limit used between sending of two segments of the same SOME/IP-TP message.
|
||||
* Default for the separation time is 0, no matter whether a message is SOME/IP-TP or not.
|
||||
* For separation time 0, message sending is no different from what it was before.
|
||||
* @default 0
|
||||
*/
|
||||
'separation-time'?: number
|
||||
}
|
||||
>
|
||||
}
|
||||
|
||||
/**
|
||||
* Service configuration
|
||||
* Contains the services of the service provider
|
||||
*/
|
||||
export interface ServiceConfig {
|
||||
/**
|
||||
* The id of the service
|
||||
*/
|
||||
service: string
|
||||
|
||||
/**
|
||||
* The id of the service instance
|
||||
*/
|
||||
instance: string
|
||||
|
||||
/**
|
||||
* The protocol that is used to implement the service instance.
|
||||
* The default value is someip. If a different setting is provided,
|
||||
* vsomeip does not open the specified port (server side) or does not
|
||||
* connect to the specified port (client side). Thus, this option can
|
||||
* be used to let the service discovery announce a service that is
|
||||
* externally implemented.
|
||||
* @default "someip"
|
||||
*/
|
||||
protocol?: string
|
||||
|
||||
/**
|
||||
* The unicast that hosts the service instance. The unicast address is needed
|
||||
* if external service instances shall be used, but service discovery is disabled.
|
||||
* In this case, the provided unicast address is used to access the service instance.
|
||||
*/
|
||||
unicast?: string
|
||||
|
||||
/**
|
||||
* Specifies that the communication with the service is reliable respectively
|
||||
* the TCP protocol is used for communication.
|
||||
*/
|
||||
reliable?: ServiceReliable
|
||||
|
||||
/**
|
||||
* Specifies that the communication with the service is unreliable respectively
|
||||
* the UDP protocol is used for communication (valid values: the port of the UDP endpoint).
|
||||
*/
|
||||
unreliable?: number
|
||||
|
||||
/**
|
||||
* Contains the events of the service
|
||||
*/
|
||||
events?: ServiceEvent[]
|
||||
|
||||
/**
|
||||
* Events can be grouped together into on event group. For a client it is thus
|
||||
* possible to subscribe for an event group and to receive the appropriate events within the group.
|
||||
*/
|
||||
eventgroups?: ServiceEventgroup[]
|
||||
|
||||
/**
|
||||
* Used to configure the nPDU feature. This is described in detail in SOME/IP nPDU Default Timings.
|
||||
*/
|
||||
'debounce-times'?: ServiceDebounceTimes
|
||||
|
||||
/**
|
||||
* Used to configure the SOME/IP-TP feature. With SOME/IP Transport Protocol (TP)
|
||||
* it is possible to transport messages which exceed the UDP payload size limit of 1400 byte.
|
||||
* If enabled the message is segmented and send in multiple UDP datagrams.
|
||||
*/
|
||||
'someip-tp'?: SomeipTpConfig
|
||||
}
|
||||
|
||||
/**
|
||||
* Internal service configuration
|
||||
* Specifies service/instance ranges for pure internal service-instances.
|
||||
* This information is used by vsomeip to avoid sending Find-Service messages
|
||||
* via the Service-Discovery when a client is requesting a not available service-instance.
|
||||
* Its can either be done on service/instance level or on service level only which
|
||||
* then includes all instance from 0x0000-0xffff.
|
||||
*/
|
||||
export interface InternalServiceConfig {
|
||||
/**
|
||||
* The lowest entry of the internal service range
|
||||
*/
|
||||
first:
|
||||
| string
|
||||
| {
|
||||
/**
|
||||
* The lowest Service-ID in hex of the internal service range
|
||||
*/
|
||||
service: string
|
||||
|
||||
/**
|
||||
* The lowest Instance-ID in hex of a internal service-instance range.
|
||||
* If not specified the lowest Instance-ID is 0x0000.
|
||||
*/
|
||||
instance?: string
|
||||
}
|
||||
|
||||
/**
|
||||
* The highest entry of the internal service range
|
||||
*/
|
||||
last:
|
||||
| string
|
||||
| {
|
||||
/**
|
||||
* The highest Service-ID in hex of a internal service range
|
||||
*/
|
||||
service: string
|
||||
|
||||
/**
|
||||
* The highest Instance-ID in hex of a internal service-instance range.
|
||||
* If not specified the highest Instance-ID is 0xFFFF.
|
||||
*/
|
||||
instance?: string
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Client configuration
|
||||
* The client-side ports that shall be used to connect to a specific service.
|
||||
* For each service, an array of ports to be used for reliable/unreliable communication
|
||||
* can be specified. vsomeip will take the first free port of the list. If no free port
|
||||
* can be found, the connection will fail. If vsomeip is asked to connect to a service
|
||||
* instance without specified port(s), the port will be selected by the system. This
|
||||
* implies that the user has to ensure that the ports configured here do not overlap
|
||||
* with the ports automatically selected by the IP stack.
|
||||
*/
|
||||
export interface ClientConfig {
|
||||
/**
|
||||
* Specify the service the port configuration shall be applied to
|
||||
*/
|
||||
service: string
|
||||
|
||||
/**
|
||||
* Specify the instance the port configuration shall be applied to
|
||||
*/
|
||||
instance: string
|
||||
|
||||
/**
|
||||
* The list of client ports to be used for reliable (TCP) communication
|
||||
* to the given service instance. Ports can be specified in dec or hex format.
|
||||
*/
|
||||
reliable?: number[]
|
||||
|
||||
/**
|
||||
* The list of client ports to be used for unreliable (UDP) communication
|
||||
* to the given service instance. Ports can be specified in dec or hex format.
|
||||
*/
|
||||
unreliable?: number[]
|
||||
|
||||
/**
|
||||
* Specifies a range of reliable remote service ports
|
||||
*/
|
||||
reliable_remote_ports?: {
|
||||
/**
|
||||
* Lower bound of the port range
|
||||
*/
|
||||
first: number
|
||||
|
||||
/**
|
||||
* Upper bound of the port range
|
||||
*/
|
||||
last: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies a range of unreliable remote service ports
|
||||
*/
|
||||
unreliable_remote_ports?: {
|
||||
/**
|
||||
* Lower bound of the port range
|
||||
*/
|
||||
first: number
|
||||
|
||||
/**
|
||||
* Upper bound of the port range
|
||||
*/
|
||||
last: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the range of reliable client ports to be mapped to the reliable_remote_ports range
|
||||
*/
|
||||
reliable_client_ports?: {
|
||||
/**
|
||||
* Lower bound of the port range
|
||||
*/
|
||||
first: number
|
||||
|
||||
/**
|
||||
* Upper bound of the port range
|
||||
*/
|
||||
last: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the range of unreliable client ports to be mapped to the unreliable_remote_ports range
|
||||
*/
|
||||
unreliable_client_ports?: {
|
||||
/**
|
||||
* Lower bound of the port range
|
||||
*/
|
||||
first: number
|
||||
|
||||
/**
|
||||
* Upper bound of the port range
|
||||
*/
|
||||
last: number
|
||||
}
|
||||
}
|
||||
-277
@@ -1,277 +0,0 @@
|
||||
/**
|
||||
* Service Discovery and Tracing Configuration Interfaces
|
||||
*/
|
||||
|
||||
/**
|
||||
* TTL factor configuration for offers
|
||||
*/
|
||||
export interface TtlFactorOffer {
|
||||
/**
|
||||
* The id of the service
|
||||
*/
|
||||
service: string
|
||||
|
||||
/**
|
||||
* The id of the service instance
|
||||
*/
|
||||
instance: string
|
||||
|
||||
/**
|
||||
* TTL correction factor
|
||||
*/
|
||||
ttl_factor: number
|
||||
}
|
||||
|
||||
/**
|
||||
* TTL factor configuration for subscriptions
|
||||
*/
|
||||
export interface TtlFactorSubscription {
|
||||
/**
|
||||
* The id of the service
|
||||
*/
|
||||
service: string
|
||||
|
||||
/**
|
||||
* The id of the service instance
|
||||
*/
|
||||
instance: string
|
||||
|
||||
/**
|
||||
* TTL correction factor
|
||||
*/
|
||||
ttl_factor: number
|
||||
}
|
||||
|
||||
/**
|
||||
* Service discovery configuration
|
||||
* Contains settings related to the Service Discovery of the host application
|
||||
*/
|
||||
export interface ServiceDiscoveryConfig {
|
||||
/**
|
||||
* Specifies whether the Service Discovery is enabled
|
||||
* @default true
|
||||
*/
|
||||
enable?: boolean
|
||||
|
||||
/**
|
||||
* Specifies the initial Service Discovery state after startup
|
||||
* @default "unknown"
|
||||
*/
|
||||
initial_state?: 'unknown' | 'suspended' | 'resumed'
|
||||
|
||||
/**
|
||||
* The multicast address which the messages of the Service Discovery will be sent to
|
||||
* @default "224.224.224.0"
|
||||
*/
|
||||
multicast?: string
|
||||
|
||||
/**
|
||||
* The port of the Service Discovery
|
||||
* @default 30490
|
||||
*/
|
||||
port?: number
|
||||
|
||||
/**
|
||||
* The protocol that is used for sending the Service Discovery messages
|
||||
* @default "udp"
|
||||
*/
|
||||
protocol?: 'tcp' | 'udp'
|
||||
|
||||
/**
|
||||
* Minimum delay before first offer message
|
||||
* @default 0
|
||||
*/
|
||||
initial_delay_min?: number
|
||||
|
||||
/**
|
||||
* Maximum delay before first offer message
|
||||
* @default 3000
|
||||
*/
|
||||
initial_delay_max?: number
|
||||
|
||||
/**
|
||||
* Base delay sending offer messages within the repetition phase
|
||||
* @default 10
|
||||
*/
|
||||
repetitions_base_delay?: number
|
||||
|
||||
/**
|
||||
* Maximum number of repetitions for provided services within the repetition phase
|
||||
* @default 3
|
||||
*/
|
||||
repetitions_max?: number
|
||||
|
||||
/**
|
||||
* Lifetime of entries for provided services as well as consumed services and eventgroups
|
||||
* @default 0xFFFFFF
|
||||
*/
|
||||
ttl?: string
|
||||
|
||||
/**
|
||||
* Array which holds correction factors for incoming remote offers. If a value greater
|
||||
* than one is specified for a service instance, the TTL field of the corresponding
|
||||
* service entry will be multiplied with the specified factor.
|
||||
*/
|
||||
ttl_factor_offers?: TtlFactorOffer[]
|
||||
|
||||
/**
|
||||
* Array which holds correction factors for incoming remote subscriptions. If a value
|
||||
* greater than one is specified for a service instance, the TTL field of the corresponding
|
||||
* eventgroup entry will be multiplied with the specified factor.
|
||||
*/
|
||||
ttl_factor_subscriptions?: TtlFactorSubscription[]
|
||||
|
||||
/**
|
||||
* Cycle of the OfferService messages in the main phase
|
||||
* @default 1000
|
||||
*/
|
||||
cyclic_offer_delay?: number
|
||||
|
||||
/**
|
||||
* Minimum delay of a unicast message to a multicast message for provided services and eventgroups
|
||||
* @default 2000
|
||||
*/
|
||||
request_response_delay?: number
|
||||
|
||||
/**
|
||||
* Time which the stack collects new service offers before they enter the repetition phase.
|
||||
* This can be used to reduce the number of sent messages during startup.
|
||||
* @default 500
|
||||
*/
|
||||
offer_debounce_time?: number
|
||||
|
||||
/**
|
||||
* Time which the stack collects non local service requests before sending find messages
|
||||
* @default 500
|
||||
*/
|
||||
find_debounce_time?: number
|
||||
|
||||
/**
|
||||
* Maximum possible number of different remote subscribers. Additional remote subscribers
|
||||
* will not be acknowledged.
|
||||
* @default 3
|
||||
*/
|
||||
max_remote_subscribers?: number
|
||||
|
||||
/**
|
||||
* Number of initial debounces using find_initial_debounce_time. This can be used to
|
||||
* modify the number of sent messages during initial part of startup (valid values: 0 - 2^8-1)
|
||||
* @default 0
|
||||
*/
|
||||
find_initial_debounce_reps?: number
|
||||
|
||||
/**
|
||||
* Time which the stack collects new service requests before they enter the repetition phase.
|
||||
* This can be used to modify the number of sent messages during initial part of startup
|
||||
* @default 200
|
||||
*/
|
||||
find_initial_debounce_time?: number
|
||||
|
||||
/**
|
||||
* Enables the tracking of the route state on_net_interface_or_route_state_changed
|
||||
* @default true
|
||||
*/
|
||||
wait_route_netlink_notification?: boolean
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracing channel configuration
|
||||
*/
|
||||
export interface TracingChannel {
|
||||
/**
|
||||
* The name of the channel
|
||||
*/
|
||||
name: string
|
||||
|
||||
/**
|
||||
* The id of the channel
|
||||
*/
|
||||
id: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracing filter match configuration
|
||||
*/
|
||||
export interface TracingFilterMatch {
|
||||
/**
|
||||
* Service ID
|
||||
*/
|
||||
service: string
|
||||
|
||||
/**
|
||||
* Instance ID
|
||||
*/
|
||||
instance: string
|
||||
|
||||
/**
|
||||
* Method ID
|
||||
*/
|
||||
method: string
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracing filter configuration
|
||||
*/
|
||||
export interface TracingFilter {
|
||||
/**
|
||||
* The id of the channel over that the filtered messages are forwarded to DLT.
|
||||
* If no channel is specified the default channel (TC) is used. If you want to
|
||||
* use a filter in several different channels, you can provide an array of channel ids.
|
||||
*/
|
||||
channel?: string | string[]
|
||||
|
||||
/**
|
||||
* Specification of the criteria to include/exclude a message into/from the trace.
|
||||
* You can either specify lists (array) or ranges of matching elements. A list may
|
||||
* contain single identifiers which match all messages from/to all instances of the
|
||||
* corresponding service or tuples consisting of service, instance and method-identifier.
|
||||
* 'any' may be used as a wildcard for matching all services, instances or methods.
|
||||
* A range is specified by two tuples "from" and "to", each consisting of service-,
|
||||
* instance-and method-identifier. All messages with service-, instance-and method-identifiers
|
||||
* that are greater than or equal to "from" and less than or equal to "to" are matched.
|
||||
*/
|
||||
matches?: TracingFilterMatch[]
|
||||
|
||||
/**
|
||||
* Specifies the filter type. The default value is positive.
|
||||
* - A positive filter is used and a message matches one of the filter rules,
|
||||
* the message will be traced/forwarded to DLT.
|
||||
* - A negative filter messages can be excluded. So when a message matches one
|
||||
* of the filter rules, the message will not be traced/forwarded to DLT.
|
||||
* - A header-only filter is a positive filter that does not trace the message payload.
|
||||
* @default "positive"
|
||||
*/
|
||||
type?: 'positive' | 'negative' | 'header-only'
|
||||
}
|
||||
|
||||
/**
|
||||
* Tracing configuration for the Trace Connector
|
||||
* Used to forward the internal messages that are sent over the Unix Domain Sockets (UDS) to DLT.
|
||||
*/
|
||||
export interface TracingConfig {
|
||||
/**
|
||||
* Specifies whether the tracing of the SOME/IP messages is enabled.
|
||||
* If tracing is enabled, the messages will be forwarded to DLT by the Trace Connector.
|
||||
* @default false
|
||||
*/
|
||||
enable?: boolean
|
||||
|
||||
/**
|
||||
* Specifies whether the tracing of the SOME/IP service discovery messages is enabled.
|
||||
* @default false
|
||||
*/
|
||||
sd_enable?: boolean
|
||||
|
||||
/**
|
||||
* Contains the channels to DLT. You can set up multiple channels to DLT over that
|
||||
* you can forward the messages.
|
||||
*/
|
||||
channels?: TracingChannel[]
|
||||
|
||||
/**
|
||||
* Contains the filters that are applied on the messages. You can apply filters
|
||||
* respectively filter rules on the messages with specific criteria and expressions.
|
||||
* So only the filtered messages are forwarded to DLT.
|
||||
*/
|
||||
filters?: TracingFilter[]
|
||||
}
|
||||
-1743
File diff suppressed because it is too large
Load Diff
@@ -1,618 +0,0 @@
|
||||
import { VarItem } from 'src/preload/data'
|
||||
import { UdsDevice } from './uds'
|
||||
import { TesterInfo } from './tester'
|
||||
import type { ORTIFile } from 'src/renderer/src/database/ortiParse'
|
||||
import { IsrStatus, ResourceStatus, TaskStatus, TaskType } from './osEvent'
|
||||
|
||||
interface Item {
|
||||
type: 'string' | 'number'
|
||||
min?: number
|
||||
max?: number
|
||||
unit?: string
|
||||
desc?: string
|
||||
enum?: { name: string; value: number }[]
|
||||
}
|
||||
export const MonitorVar: VarItem[] = [
|
||||
{
|
||||
type: 'system',
|
||||
id: 'EventLoopDelay.min',
|
||||
name: `EventLoopDelayMin`,
|
||||
parentId: 'EventLoopDelay',
|
||||
desc: 'Minimum event loop delay - lower values indicate better performance',
|
||||
value: {
|
||||
type: 'number',
|
||||
initValue: 0,
|
||||
unit: 'ms'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'system',
|
||||
id: 'EventLoopDelay.max',
|
||||
name: `EventLoopDelayMax`,
|
||||
desc: 'Maximum event loop delay - higher values indicate potential performance issues',
|
||||
parentId: 'EventLoopDelay',
|
||||
value: {
|
||||
type: 'number',
|
||||
initValue: 0,
|
||||
unit: 'ms'
|
||||
}
|
||||
},
|
||||
{
|
||||
type: 'system',
|
||||
id: 'EventLoopDelay.avg',
|
||||
name: `EventLoopDelayAvg`,
|
||||
desc: 'Average event loop delay - a good balance between performance and stability',
|
||||
parentId: 'EventLoopDelay',
|
||||
value: {
|
||||
type: 'number',
|
||||
initValue: 0,
|
||||
unit: 'ms'
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
export function getAllSysVar(
|
||||
devices: Record<string, UdsDevice>,
|
||||
testers: Record<string, TesterInfo>,
|
||||
orti: Record<string, ORTIFile>
|
||||
): Record<string, VarItem> {
|
||||
const list: Record<string, VarItem> = {
|
||||
Statistics: {
|
||||
type: 'system',
|
||||
id: 'Statistics',
|
||||
name: `Statistics`
|
||||
},
|
||||
OsTrace: {
|
||||
type: 'system',
|
||||
id: 'OsTrace',
|
||||
name: `OsTrace`
|
||||
}
|
||||
}
|
||||
|
||||
for (const device of Object.values(devices)) {
|
||||
const buslist: Record<string, { min: number; max?: number; unit?: string }> = {
|
||||
BusLoad: {
|
||||
min: 0,
|
||||
max: 100,
|
||||
unit: '%'
|
||||
},
|
||||
BusLoadMin: {
|
||||
min: 0,
|
||||
max: 100,
|
||||
unit: '%'
|
||||
},
|
||||
BusLoadMax: {
|
||||
min: 0,
|
||||
max: 100,
|
||||
unit: '%'
|
||||
},
|
||||
BusLoadAvg: {
|
||||
min: 0,
|
||||
max: 100,
|
||||
unit: '%'
|
||||
},
|
||||
FrameSentFreq: {
|
||||
min: 0,
|
||||
max: 100,
|
||||
unit: 'f/s'
|
||||
},
|
||||
FrameRecvFreq: {
|
||||
min: 0,
|
||||
max: 100,
|
||||
unit: 'f/s'
|
||||
},
|
||||
FrameFreq: {
|
||||
min: 0,
|
||||
max: 100,
|
||||
unit: 'f/s'
|
||||
},
|
||||
SentCnt: {
|
||||
min: 0
|
||||
},
|
||||
RecvCnt: {
|
||||
min: 0
|
||||
}
|
||||
}
|
||||
|
||||
if (device.type === 'can' && device.canDevice) {
|
||||
list[`Statistics.${device.canDevice.id}`] = {
|
||||
type: 'system',
|
||||
id: `Statistics.${device.canDevice.id}`,
|
||||
name: device.canDevice.name,
|
||||
parentId: 'Statistics'
|
||||
}
|
||||
for (const key of Object.keys(buslist)) {
|
||||
const item = buslist[key as keyof typeof buslist]
|
||||
|
||||
list[`Statistics.${device.canDevice.id}.${key}`] = {
|
||||
type: 'system',
|
||||
id: `Statistics.${device.canDevice.id}.${key}`,
|
||||
name: `${key}`,
|
||||
parentId: `Statistics.${device.canDevice.id}`,
|
||||
value: {
|
||||
type: 'number',
|
||||
initValue: 0,
|
||||
min: item.min,
|
||||
max: item.max,
|
||||
unit: item.unit
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const tester of Object.values(testers)) {
|
||||
list[`Statistics.${tester.id}`] = {
|
||||
type: 'system',
|
||||
id: `Statistics.${tester.id}`,
|
||||
name: tester.name,
|
||||
parentId: 'Statistics',
|
||||
desc: 'UDS Tester'
|
||||
}
|
||||
if (tester.seqList.length > 0) {
|
||||
for (const [index, seq] of tester.seqList.entries()) {
|
||||
list[`Statistics.${tester.id}.${index}`] = {
|
||||
type: 'system',
|
||||
id: `Statistics.${tester.id}.${index}`,
|
||||
name: `Seq #${index}`,
|
||||
parentId: `Statistics.${tester.id}`,
|
||||
value: {
|
||||
type: 'number',
|
||||
initValue: 0,
|
||||
min: 0,
|
||||
max: 100,
|
||||
unit: '%'
|
||||
},
|
||||
desc: `UDS sequence download progress`
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (const item of Object.values(orti)) {
|
||||
const Ortilist: Record<string, Item> = {
|
||||
DelayTimeMin: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
unit: 'us',
|
||||
desc: '任务激活成功(Start)到任务运行(Runninng)的最小时间'
|
||||
},
|
||||
DelayTimeMax: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
unit: 'us',
|
||||
desc: '任务激活成功(Start)到任务运行(Runninng)的最大时间'
|
||||
},
|
||||
DelayTimeAvg: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
unit: 'us',
|
||||
desc: '任务激活成功(Start)到任务运行(Runninng)的平均时间'
|
||||
},
|
||||
ActivationIntervalMin: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
unit: 'us',
|
||||
desc: '任务激活间隔最小时间'
|
||||
},
|
||||
ActivationIntervalMax: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
unit: 'us',
|
||||
desc: '任务激活间隔最大时间'
|
||||
},
|
||||
ActivationIntervalAvg: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
unit: 'us',
|
||||
desc: '任务激活间隔平均时间'
|
||||
},
|
||||
ExecutionTimeMin: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
unit: 'us',
|
||||
desc: '任务执行时间最小时间'
|
||||
},
|
||||
ExecutionTimeMax: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
unit: 'us',
|
||||
desc: '任务执行时间最大时间'
|
||||
},
|
||||
ExecutionTimeAvg: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
unit: 'us',
|
||||
desc: '任务执行时间平均时间'
|
||||
},
|
||||
StartCount: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
desc: '任务开始次数'
|
||||
},
|
||||
Status: {
|
||||
type: 'number',
|
||||
desc: 'Task当前状态',
|
||||
max: 5,
|
||||
min: 0,
|
||||
enum: [
|
||||
{ name: 'Active', value: TaskStatus.ACTIVE },
|
||||
{ name: 'Start', value: TaskStatus.START },
|
||||
{ name: 'Wait', value: TaskStatus.WAIT },
|
||||
{ name: 'Release', value: TaskStatus.RELEASE },
|
||||
{ name: 'Preempt', value: TaskStatus.PREEMPT },
|
||||
{ name: 'Terminate', value: TaskStatus.TERMINATE }
|
||||
]
|
||||
},
|
||||
ActiveCount: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
desc: '任务激活次数'
|
||||
},
|
||||
TaskLost: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
max: 100,
|
||||
unit: '%',
|
||||
desc: '(Task被激活次数-Task运行次数)/Task被激活次数'
|
||||
},
|
||||
JitterMax: {
|
||||
type: 'number',
|
||||
unit: '%',
|
||||
desc: '最大Jitter值(当前激活间隔-理论激活间隔)/理论激活间隔,基于绝对值比较'
|
||||
},
|
||||
JitterMin: {
|
||||
type: 'number',
|
||||
unit: '%',
|
||||
desc: '最小Jitter值(当前激活间隔-理论激活间隔)/理论激活间隔,基于绝对值比较'
|
||||
},
|
||||
Jitter: {
|
||||
type: 'number',
|
||||
unit: '%',
|
||||
desc: '当前Jitter值(当前激活间隔-理论激活间隔)/理论激活间隔'
|
||||
}
|
||||
}
|
||||
|
||||
const ISRList: Record<string, Item> = {
|
||||
ExecutionTimeMin: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
unit: 'us',
|
||||
desc: 'ISR执行时间最小时间'
|
||||
},
|
||||
ExecutionTimeMax: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
unit: 'us',
|
||||
desc: 'ISR执行时间最大时间'
|
||||
},
|
||||
ExecutionTimeAvg: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
unit: 'us',
|
||||
desc: 'ISR执行时间平均时间'
|
||||
},
|
||||
RunCount: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
desc: 'ISR运行次数'
|
||||
},
|
||||
Status: {
|
||||
type: 'number',
|
||||
desc: 'ISR当前状态',
|
||||
max: 1,
|
||||
min: 0,
|
||||
enum: [
|
||||
{ name: 'Start', value: IsrStatus.START },
|
||||
{ name: 'Stop', value: IsrStatus.STOP }
|
||||
]
|
||||
},
|
||||
CallIntervalMin: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
unit: 'us',
|
||||
desc: 'ISR调用间隔最小时间'
|
||||
},
|
||||
CallIntervalMax: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
unit: 'us',
|
||||
desc: 'ISR调用间隔最大时间'
|
||||
},
|
||||
CallIntervalAvg: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
unit: 'us',
|
||||
desc: 'ISR调用间隔平均时间'
|
||||
}
|
||||
}
|
||||
|
||||
const ResourceList: Record<string, Item> = {
|
||||
Status: {
|
||||
type: 'number',
|
||||
desc: 'Resource当前状态',
|
||||
max: 1,
|
||||
min: 0,
|
||||
enum: [
|
||||
{ name: 'Start', value: ResourceStatus.START },
|
||||
{ name: 'Stop', value: ResourceStatus.STOP }
|
||||
]
|
||||
},
|
||||
AcquireCount: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
desc: 'Resource获取次数'
|
||||
},
|
||||
ReleaseCount: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
desc: 'Resource释放次数'
|
||||
}
|
||||
}
|
||||
|
||||
const ServiceList: Record<string, Item> = {
|
||||
Count: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
desc: 'Service调用次数'
|
||||
},
|
||||
LastStatus: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
desc: 'Service最后状态'
|
||||
}
|
||||
}
|
||||
|
||||
const HookList: Record<string, Item> = {
|
||||
Count: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
desc: 'Hook触发次数'
|
||||
},
|
||||
LastStatus: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
desc: 'Hook最后状态参数'
|
||||
},
|
||||
LastTriggerTime: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
unit: 'us',
|
||||
desc: 'Hook最后一次触发相对时间'
|
||||
}
|
||||
}
|
||||
list[`OsTrace.${item.id}`] = {
|
||||
type: 'system',
|
||||
id: `OsTrace.${item.id}`,
|
||||
name: item.name,
|
||||
parentId: 'OsTrace'
|
||||
}
|
||||
let coreNum = 0
|
||||
list[`OsTrace.${item.id}.Task`] = {
|
||||
type: 'system',
|
||||
id: `OsTrace.${item.id}.Task`,
|
||||
name: `Task`,
|
||||
parentId: `OsTrace.${item.id}`
|
||||
}
|
||||
list[`OsTrace.${item.id}.ISR`] = {
|
||||
type: 'system',
|
||||
id: `OsTrace.${item.id}.ISR`,
|
||||
name: `ISR`,
|
||||
parentId: `OsTrace.${item.id}`
|
||||
}
|
||||
|
||||
for (const core of item.coreConfigs) {
|
||||
coreNum = Math.max(coreNum, core.coreId + 1)
|
||||
if (core.type == TaskType.TASK) {
|
||||
list[`OsTrace.${item.id}.Task.${core.type}_${core.id}_${core.coreId}`] = {
|
||||
type: 'system',
|
||||
id: `OsTrace.${item.id}.Task.${core.type}_${core.id}_${core.coreId}`,
|
||||
name: core.name,
|
||||
parentId: `OsTrace.${item.id}.Task`
|
||||
}
|
||||
for (const key of Object.keys(Ortilist)) {
|
||||
const vitem = Ortilist[key as keyof typeof Ortilist]
|
||||
const vkey = `OsTrace.${item.id}.Task.${core.type}_${core.id}_${core.coreId}.${key}`
|
||||
list[vkey] = {
|
||||
type: 'system',
|
||||
id: vkey,
|
||||
name: `${key}`,
|
||||
parentId: `OsTrace.${item.id}.Task.${core.type}_${core.id}_${core.coreId}`,
|
||||
value: {
|
||||
type: vitem.type,
|
||||
min: vitem.min,
|
||||
max: vitem.max,
|
||||
unit: vitem.unit,
|
||||
enum: vitem.enum
|
||||
},
|
||||
desc: vitem.desc
|
||||
}
|
||||
}
|
||||
} else if (core.type == TaskType.ISR) {
|
||||
list[`OsTrace.${item.id}.ISR.${core.type}_${core.id}_${core.coreId}`] = {
|
||||
type: 'system',
|
||||
id: `OsTrace.${item.id}.ISR.${core.type}_${core.id}_${core.coreId}`,
|
||||
name: core.name,
|
||||
parentId: `OsTrace.${item.id}.ISR`
|
||||
}
|
||||
for (const key of Object.keys(ISRList)) {
|
||||
const vitem = ISRList[key as keyof typeof ISRList]
|
||||
const vkey = `OsTrace.${item.id}.ISR.${core.type}_${core.id}_${core.coreId}.${key}`
|
||||
list[vkey] = {
|
||||
type: 'system',
|
||||
id: vkey,
|
||||
name: `${key}`,
|
||||
parentId: `OsTrace.${item.id}.ISR.${core.type}_${core.id}_${core.coreId}`,
|
||||
value: {
|
||||
type: vitem.type,
|
||||
min: vitem.min,
|
||||
max: vitem.max,
|
||||
unit: vitem.unit,
|
||||
enum: vitem.enum
|
||||
},
|
||||
desc: vitem.desc
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
list[`OsTrace.${item.id}.Resource`] = {
|
||||
type: 'system',
|
||||
id: `OsTrace.${item.id}.Resource`,
|
||||
name: `Resource`,
|
||||
parentId: `OsTrace.${item.id}`
|
||||
}
|
||||
|
||||
// Process Resource configs
|
||||
for (const resource of item.resourceConfigs || []) {
|
||||
const resourceKey = `OsTrace.${item.id}.Resource.${TaskType.RESOURCE}_${resource.id}_${resource.coreId}`
|
||||
list[resourceKey] = {
|
||||
type: 'system',
|
||||
id: resourceKey,
|
||||
name: resource.name,
|
||||
parentId: `OsTrace.${item.id}.Resource`
|
||||
}
|
||||
for (const key of Object.keys(ResourceList)) {
|
||||
const vitem = ResourceList[key as keyof typeof ResourceList]
|
||||
const vkey = `OsTrace.${item.id}.Resource.${resourceKey}.${key}`
|
||||
list[vkey] = {
|
||||
type: 'system',
|
||||
id: vkey,
|
||||
name: `${key}`,
|
||||
parentId: resourceKey,
|
||||
value: {
|
||||
type: vitem.type,
|
||||
min: vitem.min,
|
||||
max: vitem.max,
|
||||
unit: vitem.unit,
|
||||
enum: vitem.enum
|
||||
},
|
||||
desc: vitem.desc
|
||||
}
|
||||
}
|
||||
}
|
||||
list[`OsTrace.${item.id}.Service`] = {
|
||||
type: 'system',
|
||||
id: `OsTrace.${item.id}.Service`,
|
||||
name: `Service`,
|
||||
parentId: `OsTrace.${item.id}`
|
||||
}
|
||||
|
||||
// Process Service configs
|
||||
for (const service of item.serviceConfigs || []) {
|
||||
const serviceKey = `OsTrace.${item.id}.Service.${TaskType.SERVICE}_${service.id}_0`
|
||||
list[serviceKey] = {
|
||||
type: 'system',
|
||||
id: serviceKey,
|
||||
name: service.name,
|
||||
parentId: `OsTrace.${item.id}.Service`
|
||||
}
|
||||
for (const key of Object.keys(ServiceList)) {
|
||||
const vitem = ServiceList[key as keyof typeof ServiceList]
|
||||
const vkey = `OsTrace.${item.id}.Service.${serviceKey}.${key}`
|
||||
list[vkey] = {
|
||||
type: 'system',
|
||||
id: vkey,
|
||||
name: `${key}`,
|
||||
parentId: serviceKey,
|
||||
value: {
|
||||
type: vitem.type,
|
||||
min: vitem.min,
|
||||
max: vitem.max,
|
||||
unit: vitem.unit,
|
||||
enum: vitem.enum
|
||||
},
|
||||
desc: vitem.desc
|
||||
}
|
||||
}
|
||||
}
|
||||
list[`OsTrace.${item.id}.Hook`] = {
|
||||
type: 'system',
|
||||
id: `OsTrace.${item.id}.Hook`,
|
||||
name: `Hook`,
|
||||
parentId: `OsTrace.${item.id}`
|
||||
}
|
||||
// Process Hook configs
|
||||
for (const hook of item.hostConfigs || []) {
|
||||
const hookKey = `OsTrace.${item.id}.Hook.${TaskType.HOOK}_${hook.id}_0`
|
||||
list[hookKey] = {
|
||||
type: 'system',
|
||||
id: hookKey,
|
||||
name: hook.name,
|
||||
parentId: `OsTrace.${item.id}.Hook`
|
||||
}
|
||||
for (const key of Object.keys(HookList)) {
|
||||
const vitem = HookList[key as keyof typeof HookList]
|
||||
const vkey = `OsTrace.${item.id}.Hook.${hookKey}.${key}`
|
||||
list[vkey] = {
|
||||
type: 'system',
|
||||
id: vkey,
|
||||
name: `${key}`,
|
||||
parentId: hookKey,
|
||||
value: {
|
||||
type: vitem.type,
|
||||
min: vitem.min,
|
||||
max: vitem.max,
|
||||
unit: vitem.unit,
|
||||
enum: vitem.enum
|
||||
},
|
||||
desc: vitem.desc
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (let i = 0; i < coreNum; i++) {
|
||||
list[`OsTrace.${item.id}.Core${i}`] = {
|
||||
type: 'system',
|
||||
id: `OsTrace.${item.id}.Core${i}`,
|
||||
name: `Core${i}`,
|
||||
parentId: `OsTrace.${item.id}`
|
||||
}
|
||||
const coreList: Record<
|
||||
string,
|
||||
{ type: 'string' | 'number'; min?: number; max?: number; unit?: string; desc?: string }
|
||||
> = {
|
||||
LoadPercent: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
max: 100,
|
||||
unit: '%',
|
||||
desc: 'Core负载百分比'
|
||||
},
|
||||
TotalTime: {
|
||||
type: 'number',
|
||||
min: 0,
|
||||
unit: 'ms',
|
||||
desc: 'Core总时间'
|
||||
}
|
||||
}
|
||||
for (const key of Object.keys(coreList)) {
|
||||
const vitem = coreList[key as keyof typeof coreList]
|
||||
const vkey = `OsTrace.${item.id}.Core${i}.${key}`
|
||||
list[vkey] = {
|
||||
type: 'system',
|
||||
id: vkey,
|
||||
name: `${key}`,
|
||||
parentId: `OsTrace.${item.id}.Core${i}`,
|
||||
value: {
|
||||
type: vitem.type,
|
||||
min: vitem.min,
|
||||
max: vitem.max,
|
||||
unit: vitem.unit
|
||||
},
|
||||
desc: vitem.desc
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//monitor var
|
||||
list[`EventLoopDelay`] = {
|
||||
type: 'system',
|
||||
id: 'EventLoopDelay',
|
||||
name: `EventLoopDelay`
|
||||
}
|
||||
for (const item of MonitorVar) {
|
||||
list[item.id] = item
|
||||
}
|
||||
return list
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user