{"_id":"@aircast-one/mavlink","_rev":"2-d32d4e92c2b2a3d6e75b61da55a65e30","name":"@aircast-one/mavlink","dist-tags":{"latest":"3.1.0"},"versions":{"3.0.0":{"name":"@aircast-one/mavlink","version":"3.0.0","keywords":["aircast","mavlink","typescript","code-generation","drone","autopilot"],"author":{"name":"Aircast MAVLink"},"license":"MIT","_id":"@aircast-one/mavlink@3.0.0","maintainers":[{"name":"pavliha","email":"kostyk.pavel.09@gmail.com"}],"homepage":"https://github.com/pavliha/aircast-mavlink#readme","bugs":{"url":"https://github.com/pavliha/aircast-mavlink/issues"},"dist":{"shasum":"883683784639e063b7d933720df7630fc73dc695","tarball":"https://registry.npmjs.org/@aircast-one/mavlink/-/mavlink-3.0.0.tgz","fileCount":842,"integrity":"sha512-l8MCRBZJX58jUOJgf1B3uVNxlua4blkyaWNke9FS7h2Bk0WicoS8lnbZCz97Q/gdvZ1bliMtn4pkNJUgS5SRiA==","signatures":[{"sig":"MEUCIBpf563ZLs3iSxz01b9Dllde3f46UQOvsj2Biv5XX7cXAiEA+CbNssEHa5prMK6CwQEAXVOFnauWz5ZrosysiCkmTOo=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":1225216},"type":"module","engines":{"node":">=18.0.0"},"exports":{"./core/types":{"types":"./dist/core/types.d.ts"},"./dialects/common":{"types":"./dist/dialects/common/index.d.ts","import":"./dist/dialects/common/index.js"},"./dialects/minimal":{"types":"./dist/dialects/minimal/index.d.ts","import":"./dist/dialects/minimal/index.js"},"./dialects/standard":{"types":"./dist/dialects/standard/index.d.ts","import":"./dist/dialects/standard/index.js"},"./dialects/common/full":{"types":"./dist/dialects/common/full.d.ts","import":"./dist/dialects/common/full.js"},"./dialects/minimal/full":{"types":"./dist/dialects/minimal/full.d.ts","import":"./dist/dialects/minimal/full.js"},"./dialects/ardupilotmega":{"types":"./dist/dialects/ardupilotmega/index.d.ts","import":"./dist/dialects/ardupilotmega/index.js"},"./dialects/common/parser":{"types":"./dist/dialects/common/parser.d.ts","import":"./dist/dialects/common/parser.js"},"./dialects/standard/full":{"types":"./dist/dialects/standard/full.d.ts","import":"./dist/dialects/standard/full.js"},"./dialects/minimal/parser":{"types":"./dist/dialects/minimal/parser.d.ts","import":"./dist/dialects/minimal/parser.js"},"./dialects/common/messages":{"types":"./dist/dialects/common/messages.d.ts","import":"./dist/dialects/common/messages.js"},"./dialects/standard/parser":{"types":"./dist/dialects/standard/parser.d.ts","import":"./dist/dialects/standard/parser.js"},"./dialects/minimal/messages":{"types":"./dist/dialects/minimal/messages.d.ts","import":"./dist/dialects/minimal/messages.js"},"./dialects/standard/messages":{"types":"./dist/dialects/standard/messages.d.ts","import":"./dist/dialects/standard/messages.js"},"./dialects/ardupilotmega/full":{"types":"./dist/dialects/ardupilotmega/full.d.ts","import":"./dist/dialects/ardupilotmega/full.js"},"./dialects/common/constants/*":{"types":"./dist/dialects/common/constants/*.d.ts","import":"./dist/dialects/common/constants/*.js"},"./dialects/minimal/constants/*":{"types":"./dist/dialects/minimal/constants/*.d.ts","import":"./dist/dialects/minimal/constants/*.js"},"./dialects/ardupilotmega/parser":{"types":"./dist/dialects/ardupilotmega/parser.d.ts","import":"./dist/dialects/ardupilotmega/parser.js"},"./dialects/standard/constants/*":{"types":"./dist/dialects/standard/constants/*.d.ts","import":"./dist/dialects/standard/constants/*.js"},"./dialects/ardupilotmega/messages":{"types":"./dist/dialects/ardupilotmega/messages.d.ts","import":"./dist/dialects/ardupilotmega/messages.js"},"./dialects/ardupilotmega/constants/*":{"types":"./dist/dialects/ardupilotmega/constants/*.d.ts","import":"./dist/dialects/ardupilotmega/constants/*.js"}},"scripts":{"dev":"bun src/cli.ts","lint":"eslint src/**/*.ts","test":"jest","build":"npm run clean && npm run generate && npm run build:bundle","clean":"rm -rf dist src/generated","start":"node dist/cli.js","format":"prettier --write \"src/**/*.{ts,tsx,js,jsx,json}\"","gen:all":"npm run gen:common && npm run gen:ardupilotmega && npm run gen:minimal && npm run gen:standard","gen:url":"echo https://raw.githubusercontent.com/mavlink/mavlink/$(node -p \"require('./package.json').mavlinkCommit\")/message_definitions/v1.0","prepare":"lefthook install","gen:test":"bun src/cli.ts generate -i $(npm run --silent gen:url)/test.xml -o ./src/generated/dialects/test","generate":"npm run gen:all","lint:fix":"eslint src/**/*.ts --fix","typecheck":"tsc --noEmit","gen:common":"bun src/cli.ts generate -i $(npm run --silent gen:url)/common.xml -o ./src/generated/dialects/common","gen:minimal":"bun src/cli.ts generate -i $(npm run --silent gen:url)/minimal.xml -o ./src/generated/dialects/minimal","build:bundle":"rollup -c && tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src --target ES2020 --moduleResolution node --esModuleInterop --resolveJsonModule --skipLibCheck src/core/types.ts src/core/crc.ts src/core/codec.ts src/core/frame.ts src/core/parser.ts src/core/stream-buffer.ts src/core/message-registry.ts src/core/message-serializer.ts src/core/index.ts","format:check":"prettier --check \"src/**/*.{ts,tsx,js,jsx,json}\"","gen:standard":"bun src/cli.ts generate -i $(npm run --silent gen:url)/standard.xml -o ./src/generated/dialects/standard","gen:paparazzi":"bun src/cli.ts generate -i $(npm run --silent gen:url)/paparazzi.xml -o ./src/generated/dialects/paparazzi","release:major":"npm version major && git push origin master --tags && gh release create v$(node -p \"require('./package.json').version\") --title \"v$(node -p \"require('./package.json').version\")\" --generate-notes","release:minor":"npm version minor && git push origin master --tags && gh release create v$(node -p \"require('./package.json').version\") --title \"v$(node -p \"require('./package.json').version\")\" --generate-notes","release:patch":"npm version patch && git push origin master --tags && gh release create v$(node -p \"require('./package.json').version\") --title \"v$(node -p \"require('./package.json').version\")\" --generate-notes","test:coverage":"jest --coverage --collectCoverageFrom=\"src/**/*.ts\" --collectCoverageFrom=\"!src/generated/**/*\"","gen:ardupilotmega":"bun src/cli.ts generate -i $(npm run --silent gen:url)/ardupilotmega.xml -o ./src/generated/dialects/ardupilotmega","gen:python_array_test":"bun src/cli.ts generate -i $(npm run --silent gen:url)/python_array_test.xml -o ./src/generated/dialects/python_array_test"},"_npmUser":{"name":"pavliha","email":"kostyk.pavel.09@gmail.com"},"repository":{"url":"git+https://github.com/pavliha/aircast-mavlink.git","type":"git"},"_npmVersion":"10.9.2","description":"TypeScript type generator for MAVLink dialects","directories":{},"sideEffects":["./dist/dialects/*/full.js"],"_nodeVersion":"22.17.0","mavlinkCommit":"6dac9679ded48f96a44aab4c56958755b1d8638a","publishConfig":{"access":"public"},"_hasShrinkwrap":false,"devDependencies":{"glob":"^10.3.10","jest":"^29.7.0","tslib":"^2.6.2","eslint":"^8.55.0","rollup":"^4.9.6","xml2js":"^0.6.2","ts-jest":"^29.4.0","lefthook":"^2.0.13","prettier":"^3.6.2","commander":"^11.1.0","handlebars":"^4.7.8","typescript":"5.3.3","@types/jest":"^30.0.0","@types/node":"^20.19.7","node-mavlink":"^2.1.0","@types/xml2js":"^0.4.14","rollup-plugin-dts":"^6.1.0","@rollup/plugin-terser":"^0.4.4","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.3","@rollup/plugin-typescript":"^11.1.6","@typescript-eslint/parser":"^6.21.0","@rollup/plugin-node-resolve":"^15.2.3","@typescript-eslint/eslint-plugin":"^6.21.0"},"_npmOperationalInternal":{"tmp":"tmp/mavlink_3.0.0_1778908686414_0.045169708203041115","host":"s3://npm-registry-packages-npm-production"}},"3.1.0":{"name":"@aircast-one/mavlink","version":"3.1.0","description":"TypeScript type generator for MAVLink dialects","type":"module","exports":{".":{"types":"./dist/core/types.d.ts"},"./common":{"types":"./dist/dialects/common/full.d.ts","import":"./dist/dialects/common/full.js"},"./common/parser":{"types":"./dist/dialects/common/parser.d.ts","import":"./dist/dialects/common/parser.js"},"./common/messages":{"types":"./dist/dialects/common/messages.d.ts","import":"./dist/dialects/common/messages.js"},"./common/constants/*":{"types":"./dist/dialects/common/constants/*.d.ts","import":"./dist/dialects/common/constants/*.js"},"./minimal":{"types":"./dist/dialects/minimal/full.d.ts","import":"./dist/dialects/minimal/full.js"},"./minimal/parser":{"types":"./dist/dialects/minimal/parser.d.ts","import":"./dist/dialects/minimal/parser.js"},"./minimal/messages":{"types":"./dist/dialects/minimal/messages.d.ts","import":"./dist/dialects/minimal/messages.js"},"./minimal/constants/*":{"types":"./dist/dialects/minimal/constants/*.d.ts","import":"./dist/dialects/minimal/constants/*.js"},"./ardupilotmega":{"types":"./dist/dialects/ardupilotmega/full.d.ts","import":"./dist/dialects/ardupilotmega/full.js"},"./ardupilotmega/parser":{"types":"./dist/dialects/ardupilotmega/parser.d.ts","import":"./dist/dialects/ardupilotmega/parser.js"},"./ardupilotmega/messages":{"types":"./dist/dialects/ardupilotmega/messages.d.ts","import":"./dist/dialects/ardupilotmega/messages.js"},"./ardupilotmega/constants/*":{"types":"./dist/dialects/ardupilotmega/constants/*.d.ts","import":"./dist/dialects/ardupilotmega/constants/*.js"},"./standard":{"types":"./dist/dialects/standard/full.d.ts","import":"./dist/dialects/standard/full.js"},"./standard/parser":{"types":"./dist/dialects/standard/parser.d.ts","import":"./dist/dialects/standard/parser.js"},"./standard/messages":{"types":"./dist/dialects/standard/messages.d.ts","import":"./dist/dialects/standard/messages.js"},"./standard/constants/*":{"types":"./dist/dialects/standard/constants/*.d.ts","import":"./dist/dialects/standard/constants/*.js"}},"sideEffects":["./dist/dialects/*/full.js"],"mavlinkCommit":"6dac9679ded48f96a44aab4c56958755b1d8638a","scripts":{"build":"npm run clean && npm run generate && npm run build:bundle","build:bundle":"rollup -c && tsc --declaration --emitDeclarationOnly --outDir dist --rootDir src --target ES2020 --moduleResolution node --esModuleInterop --resolveJsonModule --skipLibCheck src/core/types.ts src/core/crc.ts src/core/codec.ts src/core/frame.ts src/core/parser.ts src/core/stream-buffer.ts src/core/message-registry.ts src/core/message-serializer.ts src/core/index.ts","generate":"npm run gen:all","start":"node dist/cli.js","dev":"bun src/cli.ts","test":"jest","test:coverage":"jest --coverage --collectCoverageFrom=\"src/**/*.ts\" --collectCoverageFrom=\"!src/generated/**/*\"","typecheck":"tsc --noEmit","lint":"eslint src/**/*.ts","lint:fix":"eslint src/**/*.ts --fix","format":"prettier --write \"src/**/*.{ts,tsx,js,jsx,json}\"","format:check":"prettier --check \"src/**/*.{ts,tsx,js,jsx,json}\"","clean":"rm -rf dist src/generated","gen:url":"echo https://raw.githubusercontent.com/mavlink/mavlink/$(node -p \"require('./package.json').mavlinkCommit\")/message_definitions/v1.0","gen:common":"bun src/cli.ts generate -i $(npm run --silent gen:url)/common.xml -o ./src/generated/dialects/common","gen:ardupilotmega":"bun src/cli.ts generate -i $(npm run --silent gen:url)/ardupilotmega.xml -o ./src/generated/dialects/ardupilotmega","gen:minimal":"bun src/cli.ts generate -i $(npm run --silent gen:url)/minimal.xml -o ./src/generated/dialects/minimal","gen:test":"bun src/cli.ts generate -i $(npm run --silent gen:url)/test.xml -o ./src/generated/dialects/test","gen:paparazzi":"bun src/cli.ts generate -i $(npm run --silent gen:url)/paparazzi.xml -o ./src/generated/dialects/paparazzi","gen:python_array_test":"bun src/cli.ts generate -i $(npm run --silent gen:url)/python_array_test.xml -o ./src/generated/dialects/python_array_test","gen:standard":"bun src/cli.ts generate -i $(npm run --silent gen:url)/standard.xml -o ./src/generated/dialects/standard","gen:all":"npm run gen:common && npm run gen:ardupilotmega && npm run gen:minimal && npm run gen:standard","release:patch":"npm version patch && git push origin master --tags && gh release create v$(node -p \"require('./package.json').version\") --title \"v$(node -p \"require('./package.json').version\")\" --generate-notes","release:minor":"npm version minor && git push origin master --tags && gh release create v$(node -p \"require('./package.json').version\") --title \"v$(node -p \"require('./package.json').version\")\" --generate-notes","release:major":"npm version major && git push origin master --tags && gh release create v$(node -p \"require('./package.json').version\") --title \"v$(node -p \"require('./package.json').version\")\" --generate-notes","prepare":"lefthook install"},"keywords":["aircast","mavlink","typescript","code-generation","drone","autopilot"],"author":{"name":"Aircast MAVLink"},"license":"MIT","repository":{"type":"git","url":"git+https://github.com/pavliha/aircast-mavlink.git"},"bugs":{"url":"https://github.com/pavliha/aircast-mavlink/issues"},"homepage":"https://github.com/pavliha/aircast-mavlink#readme","publishConfig":{"access":"public"},"devDependencies":{"@rollup/plugin-node-resolve":"^15.2.3","@rollup/plugin-terser":"^0.4.4","@rollup/plugin-typescript":"^11.1.6","@types/jest":"^30.0.0","@types/node":"^20.19.7","@types/xml2js":"^0.4.14","@typescript-eslint/eslint-plugin":"^6.21.0","@typescript-eslint/parser":"^6.21.0","commander":"^11.1.0","eslint":"^8.55.0","eslint-config-prettier":"^10.1.8","eslint-plugin-prettier":"^5.5.3","glob":"^10.3.10","handlebars":"^4.7.8","jest":"^29.7.0","lefthook":"^2.0.13","node-mavlink":"^2.1.0","prettier":"^3.6.2","rollup":"^4.9.6","rollup-plugin-dts":"^6.1.0","ts-jest":"^29.4.0","tslib":"^2.6.2","typescript":"5.3.3","xml2js":"^0.6.2"},"engines":{"node":">=18.0.0"},"dependencies":{"@aircast-one/mavlink":"^3.0.0"},"_id":"@aircast-one/mavlink@3.1.0","_nodeVersion":"22.17.0","_npmVersion":"10.9.2","dist":{"integrity":"sha512-vBrx/MDOggDJzgx/GyIkefgFXbQe9M7dMX+ZC47vT6Zonz1NVTRFoEVBg5YeMLZWOW1vSHlVDTpuwxGwumwQNA==","shasum":"6c9b08be0d71b47ebd6e798654e9cde5b913ca68","tarball":"https://registry.npmjs.org/@aircast-one/mavlink/-/mavlink-3.1.0.tgz","fileCount":842,"unpackedSize":1224429,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIQCSAbvWFE+mAc2JYlsxcqds2EIywUgDjOw++nIEBmn4VwIgEz5JU98dG2LEIVVE7IwqWoxkBI0gUKsYKUpewes1OTI="}]},"_npmUser":{"name":"pavliha","email":"kostyk.pavel.09@gmail.com"},"directories":{},"maintainers":[{"name":"pavliha","email":"kostyk.pavel.09@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/mavlink_3.1.0_1779571028696_0.9972447206112947"},"_hasShrinkwrap":false}},"time":{"created":"2026-05-16T05:18:06.307Z","modified":"2026-05-23T21:17:09.022Z","3.0.0":"2026-05-16T05:18:06.597Z","3.1.0":"2026-05-23T21:17:08.907Z"},"bugs":{"url":"https://github.com/pavliha/aircast-mavlink/issues"},"author":{"name":"Aircast MAVLink"},"license":"MIT","homepage":"https://github.com/pavliha/aircast-mavlink#readme","keywords":["aircast","mavlink","typescript","code-generation","drone","autopilot"],"repository":{"type":"git","url":"git+https://github.com/pavliha/aircast-mavlink.git"},"description":"TypeScript type generator for MAVLink dialects","maintainers":[{"name":"pavliha","email":"kostyk.pavel.09@gmail.com"}],"readme":"# @aircast-one/mavlink\n\nType-safe MAVLink library for TypeScript. Parses and serializes MAVLink v1/v2 messages with full type narrowing — no manual casts needed. Works in browsers, Web Workers, and Node.js.\n\nGenerated from official [MAVLink XML definitions](https://github.com/mavlink/mavlink/tree/master/message_definitions/v1.0).\n\n## Features\n\n- **Type-safe parsing** — discriminated unions narrow `payload` when you switch on `message_name`\n- **Type-safe serialization** — per-message `serialize` functions with typed payloads\n- **Tree-shakeable** — import only the constants and messages you need\n- **MAVLink v1 & v2** — automatic protocol detection, CRC validation, extension field handling\n- **Browser-first** — designed for Web Workers, no Node.js dependencies at runtime\n- **4 built-in dialects** — Common, ArduPilotMega, Minimal, Standard\n\n## Installation\n\n```bash\nnpm install @aircast-one/mavlink\n```\n\nRequires Node.js >= 18.0.0 (uses native `fetch` for code generation).\n\n## Quick Start\n\n### Parsing\n\n```typescript\nimport { ArdupilotmegaParser } from '@aircast-one/mavlink/ardupilotmega'\nimport type { ArdupilotmegaMessage } from '@aircast-one/mavlink/ardupilotmega/messages'\n\nconst parser = new ArdupilotmegaParser()\n\n// parseBytes handles buffering, frame sync, CRC validation\nconst messages = parser.parseBytes(rawBytes) as ArdupilotmegaMessage[]\n\nfor (const msg of messages) {\n  switch (msg.message_name) {\n    case 'HEARTBEAT':\n      // payload is auto-narrowed to MessageHeartbeat\n      console.log('Type:', msg.payload.type)\n      console.log('Autopilot:', msg.payload.autopilot)\n      break\n\n    case 'GPS_RAW_INT':\n      // payload is auto-narrowed to MessageGpsRawInt\n      console.log('Lat:', msg.payload.lat / 1e7)\n      console.log('Lon:', msg.payload.lon / 1e7)\n      break\n\n    case 'ATTITUDE':\n      console.log('Roll:', msg.payload.roll)\n      break\n  }\n}\n```\n\n### Serializing (type-safe per-message functions)\n\nEach message has a generated `serialize` function with a fully typed payload:\n\n```typescript\nimport { serializeCommandLong } from '@aircast-one/mavlink/ardupilotmega/messages'\n\nconst bytes = serializeCommandLong(\n  {\n    target_system: 1,\n    target_component: 1,\n    command: 400, // MAV_CMD_COMPONENT_ARM_DISARM\n    confirmation: 0,\n    param1: 1, // arm\n    param2: 0,\n    param3: 0,\n    param4: 0,\n    param5: 0,\n    param6: 0,\n    param7: 0,\n  },\n  { system_id: 255, component_id: 190, sequence: 0 }\n)\n```\n\n### Serializing (generic serializer)\n\nFor dynamic message names, use the dialect serializer:\n\n```typescript\nimport { ArdupilotmegaSerializer } from '@aircast-one/mavlink/ardupilotmega'\n\nconst serializer = new ArdupilotmegaSerializer()\n\nconst bytes = serializer.serialize(\n  'HEARTBEAT',\n  {\n    type: 6,\n    autopilot: 8,\n    base_mode: 81,\n    custom_mode: 0,\n    system_status: 4,\n    mavlink_version: 3,\n  },\n  { system_id: 255, component_id: 190, sequence: 0 }\n)\n```\n\n### Selective serializer (tree-shakeable)\n\nRegister only the messages you send — skip the full dialect bundle:\n\n```typescript\nimport { ArdupilotmegaSerializer } from '@aircast-one/mavlink/ardupilotmega/parser'\nimport { CommandLongDefinition } from '@aircast-one/mavlink/ardupilotmega/messages/command-long'\nimport { HeartbeatDefinition } from '@aircast-one/mavlink/ardupilotmega/messages/heartbeat'\n\nconst serializer = new ArdupilotmegaSerializer([CommandLongDefinition, HeartbeatDefinition])\n```\n\n### Constants\n\nConstants are tree-shakeable — import only what you need:\n\n```typescript\nimport {\n  MAV_CMD_COMPONENT_ARM_DISARM,\n  MAV_CMD_NAV_TAKEOFF,\n} from '@aircast-one/mavlink/ardupilotmega/constants/mav-cmd'\n\nimport type { MAV_CMD } from '@aircast-one/mavlink/ardupilotmega/constants/mav-cmd'\n```\n\n### Web Worker\n\n```typescript\n// worker.ts\nimport { ArdupilotmegaParser } from '@aircast-one/mavlink/ardupilotmega'\nimport type { ArdupilotmegaMessage } from '@aircast-one/mavlink/ardupilotmega/messages'\n\nconst parser = new ArdupilotmegaParser()\n\nself.onmessage = (event) => {\n  const messages = parser.parseBytes(event.data) as ArdupilotmegaMessage[]\n\n  for (const msg of messages) {\n    self.postMessage(msg)\n  }\n}\n```\n\n## Available Dialects\n\n| Dialect       | Parser                | Serializer                | Messages               |\n| ------------- | --------------------- | ------------------------- | ---------------------- |\n| Common        | `CommonParser`        | `CommonSerializer`        | `CommonMessage`        |\n| ArduPilotMega | `ArdupilotmegaParser` | `ArdupilotmegaSerializer` | `ArdupilotmegaMessage` |\n| Minimal       | `MinimalParser`       | `MinimalSerializer`       | `MinimalMessage`       |\n| Standard      | `StandardParser`      | `StandardSerializer`      | `StandardMessage`      |\n\nAll are imported from `@aircast-one/mavlink/<dialect>/full`.\n\n## API Reference\n\n### Parser\n\n```typescript\nclass DialectParser {\n  parseBytes(data: Uint8Array): ParsedMAVLinkMessage[]\n  decode(frame: MAVLinkFrame): ParsedMAVLinkMessage\n  resetBuffer(): void\n  getDialectName(): string\n}\n```\n\n`parseBytes` handles buffering, frame synchronization, protocol detection (v1/v2), CRC validation, and payload decoding. Feed it raw bytes from any transport — WebSocket, WebRTC data channel, TCP, serial — and get back fully decoded messages.\n\n### Serializer\n\n```typescript\nclass DialectSerializer {\n  constructor(definitions?: MessageDefinition[])\n  serialize(\n    messageName: string,\n    payload: Record<string, unknown>,\n    options: SerializeOptions\n  ): Uint8Array\n}\n\ninterface SerializeOptions {\n  system_id: number\n  component_id: number\n  sequence: number\n  protocol_version?: 1 | 2 // auto-detected from message ID if omitted\n}\n```\n\nPass specific `MessageDefinition` arrays to the constructor for selective registration (smaller bundles). Omit to use all definitions registered by the `/full` import.\n\n### Per-Message Serialize Functions\n\nEach message module exports a type-safe serialize function:\n\n```typescript\nfunction serializeHeartbeat(payload: MessageHeartbeat, options: SerializeOptions): Uint8Array\nfunction serializeCommandLong(payload: MessageCommandLong, options: SerializeOptions): Uint8Array\n// ... one per message in the dialect\n```\n\nImport from `@aircast-one/mavlink/<dialect>/messages`.\n\n### Generated Types\n\n```typescript\n// Discriminated union — TypeScript narrows payload via message_name\ntype ArdupilotmegaMessage =\n  | { message_name: 'HEARTBEAT'; payload: MessageHeartbeat; /* ...base fields */ }\n  | { message_name: 'GPS_RAW_INT'; payload: MessageGpsRawInt; /* ...base fields */ }\n  | { message_name: 'ATTITUDE'; payload: MessageAttitude; /* ...base fields */ }\n  // ... all messages in dialect\n\n// Message name literal union — for autocomplete and exhaustive checks\ntype ArdupilotmegaMessageName = 'HEARTBEAT' | 'GPS_RAW_INT' | 'ATTITUDE' | ...;\n\n// Lookup map — get payload type from message name\ninterface MessageTypeMap {\n  HEARTBEAT: MessageHeartbeat;\n  GPS_RAW_INT: MessageGpsRawInt;\n  // ...\n}\n```\n\n### ParsedMAVLinkMessage (base type)\n\n```typescript\ninterface ParsedMAVLinkMessage {\n  timestamp: number\n  system_id: number\n  component_id: number\n  message_id: number\n  message_name: string\n  sequence: number\n  payload: Record<string, unknown>\n  protocol_version: 1 | 2\n  checksum: number\n  crc_ok: boolean\n  signature?: Uint8Array\n  dialect?: string\n}\n```\n\nCast to the dialect's message type for full type narrowing:\n\n```typescript\nconst messages = parser.parseBytes(data) as ArdupilotmegaMessage[]\n```\n\n## Import Patterns\n\n```\n@aircast-one/mavlink\n├── (root)                        # import type { ParsedMAVLinkMessage } from '@aircast-one/mavlink'\n├── <dialect>                     # Parser + Serializer (all messages registered)\n├── <dialect>/parser              # Parser + Serializer (register manually)\n├── <dialect>/messages            # Message types + serialize functions + unions\n└── <dialect>/constants/<enum>    # Individual enum constants (tree-shakeable)\n```\n\nDialects: `ardupilotmega`, `common`, `minimal`, `standard`\n\n## Code Generation\n\nGenerate TypeScript types from any MAVLink XML dialect:\n\n```bash\n# From URL\nbun src/cli.ts generate \\\n  -i https://raw.githubusercontent.com/mavlink/mavlink/master/message_definitions/v1.0/common.xml \\\n  -o ./src/generated/dialects/common\n\n# From local file\nbun src/cli.ts generate -i ./my-dialect.xml -o ./types\n\n# Batch generate multiple dialects\nbun src/cli.ts batch -d \"common,minimal,ardupilotmega\" -o ./mavlink-types\n\n# List available upstream dialects\nbun src/cli.ts list\n```\n\n### CLI Options\n\n| Command    | Flag               | Description                                   |\n| ---------- | ------------------ | --------------------------------------------- |\n| `generate` | `-i <path>`        | Input XML file or URL (required)              |\n|            | `-o <path>`        | Output directory (default: `./types`)         |\n|            | `-n <name>`        | Dialect name (auto-detected from filename)    |\n|            | `-f <format>`      | `single` or `separate` (default: `separate`)  |\n|            | `--no-enums`       | Skip enum generation                          |\n|            | `--no-type-guards` | Skip type guard generation                    |\n| `batch`    | `-o <path>`        | Output directory (default: `./mavlink-types`) |\n|            | `-d <dialects>`    | Comma-separated dialect names                 |\n|            | `--package`        | Generate `package.json` and `tsconfig.json`   |\n\n### Programmatic Usage\n\n```typescript\nimport { generateTypesFromXML } from '@aircast-one/mavlink'\n\nconst files = await generateTypesFromXML(xmlContent, {\n  dialectName: 'my-dialect',\n  outputFormat: 'separate',\n  includeEnums: true,\n  includeTypeGuards: true,\n})\n// files: { 'types.ts': '...', 'parser.ts': '...', ... }\n```\n\n## Architecture\n\n```\nXML Dialect Definition\n        │\n        ▼\n   Code Generator ──► Per-message modules (definition + interface + serialize fn)\n        │              Per-constant modules (type union + const values)\n        │              Parser class (extends DialectParser)\n        │              Serializer class (standalone, lazy registration)\n        │              Discriminated union type\n        │              Message name literal union\n        ▼\n  Runtime (browser/Node.js)\n        │\n   ┌────┴────┐\n   │ Parser  │  Raw bytes → ParsedMAVLinkMessage[]\n   │         │  - StreamBuffer handles partial frames\n   │         │  - Frame parser detects v1/v2 magic bytes\n   │         │  - CRC validation with computed CRC_EXTRA\n   │         │  - Payload decoding with wire-order field sorting\n   └─────────┘\n   ┌─────────┐\n   │Serializer│  Message name + payload + options → Uint8Array\n   │         │  - Encodes payload with field defaults\n   │         │  - Creates v1/v2 frame with CRC\n   │         │  - Protocol version auto-detected from message ID\n   └─────────┘\n```\n\n## Limitations\n\n- **MAVLink v2 signing** — the parser reads v2 signatures but does not validate them. The serializer does not create signed frames. Use transport-layer encryption (DTLS/TLS) for security.\n- **CRC_EXTRA** — computed from XML definitions at generation time. Custom dialects must be generated with the CLI to get correct CRC values.\n- **Pinned MAVLink version** — built-in dialects are generated from a pinned upstream commit (`mavlinkCommit` in package.json). Update the commit SHA and regenerate to pick up new messages.\n\n## Development\n\n```bash\n# Install dependencies\nnpm install\n\n# Generate dialects from MAVLink XML\nnpm run generate\n\n# Build the package\nnpm run build\n\n# Run tests\nnpm test\n\n# Type-check\nnpm run typecheck\n```\n\n## License\n\nMIT\n","readmeFilename":"README.md"}