7 Commits

Author SHA1 Message Date
dee5e1cb9e Fixed incorrect path hash parsing 2026-03-10 18:54:53 +01:00
e388a55575 Updated README 2026-03-10 18:44:56 +01:00
c52ec1dc43 Updated package name to include org 2026-03-10 18:39:32 +01:00
9b2d4d1096 Version 1.1.1 2026-03-10 18:22:04 +01:00
fae58c223b Export everything from types 2026-03-10 18:21:32 +01:00
7e5a8c74a5 Move tests to their own folder 2026-03-10 18:13:01 +01:00
df09c952de Move tests to their own folder 2026-03-10 18:12:42 +01:00
9 changed files with 79 additions and 32 deletions

View File

@@ -2,18 +2,54 @@
TypeScript library for MeshCore protocol utilities. TypeScript library for MeshCore protocol utilities.
Quick start ## Packet parsing
1. Install dev dependencies: Using the library to decode MeshCore packets:
```bash ```ts
npm install --save-dev typescript tsup import { Packet } from '@hamradio/meshcore';
const raw = new Uint8Array(Buffer.from("050AA50E2CB0336DB67BBF78928A3BB9BF7A8B677C83B6EC0716F9DD10002A06", "hex"));
const packet = Packet.fromBytes(raw);
console.log(packet);
/*
_Packet {
header: 5,
transport: undefined,
pathLength: 10,
path: Uint8Array(10) [
165, 14, 44, 176,
51, 109, 182, 123,
191, 120
],
payload: Uint8Array(20) [
146, 138, 59, 185, 191, 122,
139, 103, 124, 131, 182, 236,
7, 22, 249, 221, 16, 0,
42, 6
],
routeType: 1,
payloadVersion: 0,
payloadType: 1,
pathHashCount: 10,
pathHashSize: 1,
pathHashBytes: 10,
pathHashes: [
'a5', '0e', '2c',
'b0', '33', '6d',
'b6', '7b', 'bf',
'78'
]
}
*/
``` ```
2. Build the library: ## Identities
```bash The package supports:
npm run build - `Identity` for public key management.
``` - `LocalIdentity` for private key management.
- `Contact` for managing named identities.
3. Use the build output from the `dist/` folder or publish to npm. - `Group` for managing groups.
- `KeyManager` for managing all of the above and handling decryption.

View File

@@ -1,6 +1,6 @@
{ {
"name": "meshcore", "name": "@hamradio/meshcore",
"version": "1.1.0", "version": "1.1.3",
"description": "MeshCore protocol support for Typescript", "description": "MeshCore protocol support for Typescript",
"keywords": [ "keywords": [
"MeshCore", "MeshCore",
@@ -9,7 +9,7 @@
], ],
"repository": { "repository": {
"type": "git", "type": "git",
"url": "git+https://git.maze.io/ham/meshcore.js" "url": "https://git.maze.io/ham/meshcore.js"
}, },
"license": "MIT", "license": "MIT",
"author": "Wijnand Modderman-Lenstra", "author": "Wijnand Modderman-Lenstra",

View File

@@ -1,9 +1,20 @@
export * from './identity'; export * from './identity';
export * from './identity.types'; import * as identityTypes from './identity.types';
export type * from './identity.types'; import type * as identityTypesTypes from './identity.types';
export * from './crypto'; export * from './crypto';
export type * from './crypto.types'; import * as cryptoTypes from './crypto.types';
import type * as cryptoTypesTypes from './crypto.types';
export * from './packet'; export * from './packet';
export type * from './packet.types'; import * as packetTypes from './packet.types';
import type * as packetTypesTypes from './packet.types';
export type {
identityTypes,
identityTypesTypes,
cryptoTypes,
cryptoTypesTypes,
packetTypes,
packetTypesTypes
};

View File

@@ -52,13 +52,13 @@ export class Packet implements IPacket {
this.payloadVersion = (header >> 6) & 0x03; this.payloadVersion = (header >> 6) & 0x03;
this.payloadType = (header >> 2) & 0x0f; this.payloadType = (header >> 2) & 0x0f;
this.pathHashCount = (pathLength >> 6) + 1; this.pathHashSize = (pathLength >> 6) + 1;
this.pathHashSize = pathLength & 0x3f; this.pathHashCount = pathLength & 0x3f;
this.pathHashBytes = this.pathHashCount * this.pathHashSize; this.pathHashBytes = this.pathHashCount * this.pathHashSize;
this.pathHashes = []; this.pathHashes = [];
for (let i = 0; i < this.pathHashCount; i++) { for (let i = 0; i < this.pathHashBytes; i += this.pathHashSize) {
const hashBytes = this.path.slice(i * this.pathHashSize, (i + 1) * this.pathHashSize); const hashBytes = this.path.slice(i, i + this.pathHashSize);
const hashHex = bytesToHex(hashBytes); const hashHex = bytesToHex(hashBytes);
this.pathHashes.push(hashHex); this.pathHashes.push(hashHex);
} }

View File

@@ -1,6 +1,6 @@
import { describe, it, expect } from 'vitest'; import { describe, it, expect } from 'vitest';
import { PublicKey, PrivateKey, SharedSecret, StaticSecret } from './crypto'; import { PublicKey, PrivateKey, SharedSecret, StaticSecret } from '../src/crypto';
import { bytesToHex, hexToBytes } from './parser'; import { bytesToHex, hexToBytes } from '../src/parser';
const randomBytes = (len: number) => Uint8Array.from({ length: len }, () => Math.floor(Math.random() * 256)); const randomBytes = (len: number) => Uint8Array.from({ length: len }, () => Math.floor(Math.random() * 256));

View File

@@ -1,8 +1,8 @@
import { describe, it, expect, beforeEach } from 'vitest'; import { describe, it, expect, beforeEach } from 'vitest';
import { Identity, LocalIdentity, Contact, Group, Contacts, parseNodeHash } from './identity'; import { Identity, LocalIdentity, Contact, Group, Contacts, parseNodeHash } from '../src/identity';
import { PrivateKey, PublicKey, SharedSecret } from './crypto'; import { PrivateKey, PublicKey, SharedSecret } from '../src/crypto';
import { DecryptedGroupText, DecryptedGroupData } from './packet.types'; import { DecryptedGroupText, DecryptedGroupData } from '../src/packet.types';
import { bytesToHex } from './parser'; import { bytesToHex } from '../src/parser';
function randomBytes(len: number) { function randomBytes(len: number) {
return Uint8Array.from({ length: len }, () => Math.floor(Math.random() * 256)); return Uint8Array.from({ length: len }, () => Math.floor(Math.random() * 256));

View File

@@ -1,7 +1,7 @@
import { describe, expect, test } from 'vitest'; import { describe, expect, test } from 'vitest';
import { Packet } from './packet'; import { Packet } from '../src/packet';
import { PayloadType, RouteType, NodeType, TracePayload, AdvertPayload, RequestPayload, TextPayload, ResponsePayload, RawCustomPayload, AnonReqPayload } from './packet.types'; import { PayloadType, RouteType, NodeType, TracePayload, AdvertPayload, RequestPayload, TextPayload, ResponsePayload, RawCustomPayload, AnonReqPayload } from '../src/packet.types';
import { hexToBytes, bytesToHex } from './parser'; import { hexToBytes, bytesToHex } from '../src/parser';
describe('Packet.fromBytes', () => { describe('Packet.fromBytes', () => {
test('frame 1: len=122 type=5 payload_len=99', () => { test('frame 1: len=122 type=5 payload_len=99', () => {

View File

@@ -1,5 +1,5 @@
import { describe, it, expect } from 'vitest'; import { describe, it, expect } from 'vitest';
import { base64ToBytes, hexToBytes, BufferReader, BufferWriter } from './parser'; import { base64ToBytes, hexToBytes, BufferReader, BufferWriter } from '../src/parser';
describe('base64ToBytes', () => { describe('base64ToBytes', () => {
it('decodes a simple base64 string', () => { it('decodes a simple base64 string', () => {

View File

@@ -14,6 +14,6 @@
"isolatedModules": true, "isolatedModules": true,
"forceConsistentCasingInFileNames": true "forceConsistentCasingInFileNames": true
}, },
"include": ["src"], "include": ["src", "test/crypto.test.ts", "test/identity.test.ts", "test/packet.test.ts", "test/parser.test.ts"],
"exclude": ["node_modules", "dist", "test"] "exclude": ["node_modules", "dist", "test"]
} }