klv-ts 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1 @@
1
+ MIT
package/README.md ADDED
@@ -0,0 +1,30 @@
1
+ # klv-ts
2
+
3
+ A modern TypeScript parser for SMPTE 336M KLV packets.
4
+
5
+ ## Features
6
+
7
+ - Generic SMPTE 336M parser
8
+ - Browser support
9
+ - Node.js support
10
+ - Zero dependencies
11
+ - Tree-shakeable
12
+ - TypeScript first
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install klv-ts
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ ```ts
23
+ import { KlvParser } from "klv-ts";
24
+
25
+ const parser = new KlvParser();
26
+
27
+ const packet = parser.parse(bytes);
28
+
29
+ console.log(packet.length);
30
+ ```
package/dist/index.cjs ADDED
@@ -0,0 +1,103 @@
1
+ 'use strict';
2
+
3
+ // src/parser/ByteReader.ts
4
+ var ByteReader = class {
5
+ data;
6
+ offset = 0;
7
+ constructor(data) {
8
+ this.data = data;
9
+ }
10
+ get position() {
11
+ return this.offset;
12
+ }
13
+ get remaining() {
14
+ return this.data.length - this.offset;
15
+ }
16
+ hasRemaining(length = 1) {
17
+ return this.remaining >= length;
18
+ }
19
+ readByte() {
20
+ if (!this.hasRemaining()) {
21
+ throw new Error("Unexpected end of buffer.");
22
+ }
23
+ return this.data[this.offset++];
24
+ }
25
+ readBytes(length) {
26
+ if (!this.hasRemaining(length)) {
27
+ throw new Error("Unexpected end of buffer.");
28
+ }
29
+ const bytes = this.data.slice(this.offset, this.offset + length);
30
+ this.offset += length;
31
+ return bytes;
32
+ }
33
+ skip(length) {
34
+ if (!this.hasRemaining(length)) {
35
+ throw new Error("Unexpected end of buffer.");
36
+ }
37
+ this.offset += length;
38
+ }
39
+ };
40
+
41
+ // src/parser/BerReader.ts
42
+ var BerReader = class {
43
+ static readLength(reader) {
44
+ const first = reader.readByte();
45
+ if ((first & 128) === 0) {
46
+ return first;
47
+ }
48
+ const octets = first & 127;
49
+ if (octets === 0) {
50
+ throw new Error("Indefinite BER lengths are not supported.");
51
+ }
52
+ let length = 0;
53
+ for (let i = 0; i < octets; i++) {
54
+ length = length << 8 | reader.readByte();
55
+ }
56
+ return length;
57
+ }
58
+ };
59
+
60
+ // src/parser/UniversalKey.ts
61
+ var UniversalKey = class _UniversalKey {
62
+ constructor(bytes) {
63
+ this.bytes = bytes;
64
+ if (bytes.length !== _UniversalKey.LENGTH) {
65
+ throw new Error("Universal Key must contain 16 bytes.");
66
+ }
67
+ }
68
+ bytes;
69
+ static LENGTH = 16;
70
+ isSmpte() {
71
+ return this.bytes[0] === 6 && this.bytes[1] === 14 && this.bytes[2] === 43 && this.bytes[3] === 52;
72
+ }
73
+ equals(other) {
74
+ return this.bytes.every((v, i) => v === other.bytes[i]);
75
+ }
76
+ toHex(separator = "") {
77
+ return Array.from(this.bytes).map((b) => b.toString(16).padStart(2, "0")).join(separator);
78
+ }
79
+ };
80
+
81
+ // src/parser/KlvParser.ts
82
+ var KlvParser = class {
83
+ parse(data) {
84
+ const reader = new ByteReader(data);
85
+ const keyBytes = reader.readBytes(UniversalKey.LENGTH);
86
+ const key = new UniversalKey(keyBytes);
87
+ const length = BerReader.readLength(reader);
88
+ const value = reader.readBytes(length);
89
+ return {
90
+ key,
91
+ length,
92
+ value,
93
+ raw: data
94
+ };
95
+ }
96
+ };
97
+
98
+ exports.BerReader = BerReader;
99
+ exports.ByteReader = ByteReader;
100
+ exports.KlvParser = KlvParser;
101
+ exports.UniversalKey = UniversalKey;
102
+ //# sourceMappingURL=index.cjs.map
103
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/parser/ByteReader.ts","../src/parser/BerReader.ts","../src/parser/UniversalKey.ts","../src/parser/KlvParser.ts"],"names":[],"mappings":"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","file":"index.cjs","sourcesContent":["export class ByteReader {\r\n\r\n private readonly data: Uint8Array;\r\n private offset = 0;\r\n\r\n constructor(data: Uint8Array) {\r\n this.data = data;\r\n }\r\n\r\n get position(): number {\r\n return this.offset;\r\n }\r\n\r\n get remaining(): number {\r\n return this.data.length - this.offset;\r\n }\r\n\r\n hasRemaining(length = 1): boolean {\r\n return this.remaining >= length;\r\n }\r\n\r\n readByte(): number {\r\n if (!this.hasRemaining()) {\r\n throw new Error(\"Unexpected end of buffer.\");\r\n }\r\n\r\n return this.data[this.offset++];\r\n }\r\n\r\n readBytes(length: number): Uint8Array {\r\n if (!this.hasRemaining(length)) {\r\n throw new Error(\"Unexpected end of buffer.\");\r\n }\r\n\r\n const bytes = this.data.slice(this.offset, this.offset + length);\r\n this.offset += length;\r\n\r\n return bytes;\r\n }\r\n\r\n skip(length: number): void {\r\n if (!this.hasRemaining(length)) {\r\n throw new Error(\"Unexpected end of buffer.\");\r\n }\r\n\r\n this.offset += length;\r\n }\r\n}","import { ByteReader } from \"./ByteReader\";\r\n\r\nexport class BerReader {\r\n\r\n static readLength(reader: ByteReader): number {\r\n\r\n const first = reader.readByte();\r\n\r\n // Short form\r\n if ((first & 0x80) === 0) {\r\n return first;\r\n }\r\n\r\n const octets = first & 0x7F;\r\n\r\n if (octets === 0) {\r\n throw new Error(\"Indefinite BER lengths are not supported.\");\r\n }\r\n\r\n let length = 0;\r\n\r\n for (let i = 0; i < octets; i++) {\r\n length = (length << 8) | reader.readByte();\r\n }\r\n\r\n return length;\r\n }\r\n\r\n}","export class UniversalKey {\r\n\r\n static readonly LENGTH = 16;\r\n\r\n constructor(\r\n public readonly bytes: Uint8Array\r\n ) {\r\n\r\n if (bytes.length !== UniversalKey.LENGTH) {\r\n throw new Error(\"Universal Key must contain 16 bytes.\");\r\n }\r\n\r\n }\r\n\r\n isSmpte(): boolean {\r\n\r\n return (\r\n this.bytes[0] === 0x06 &&\r\n this.bytes[1] === 0x0E &&\r\n this.bytes[2] === 0x2B &&\r\n this.bytes[3] === 0x34\r\n );\r\n\r\n }\r\n\r\n equals(other: UniversalKey): boolean {\r\n\r\n return this.bytes.every((v, i) => v === other.bytes[i]);\r\n\r\n }\r\n\r\n toHex(separator = \"\"): string {\r\n\r\n return Array.from(this.bytes)\r\n .map(b => b.toString(16).padStart(2, \"0\"))\r\n .join(separator);\r\n\r\n }\r\n\r\n}","import { KlvPacket } from \"../packet/KlvPacket\";\r\nimport { BerReader } from \"./BerReader\";\r\nimport { ByteReader } from \"./ByteReader\";\r\nimport { UniversalKey } from \"./UniversalKey\";\r\n\r\nexport class KlvParser {\r\n\r\n parse(data: Uint8Array): KlvPacket {\r\n\r\n const reader = new ByteReader(data);\r\n\r\n const keyBytes = reader.readBytes(UniversalKey.LENGTH);\r\n\r\n const key = new UniversalKey(keyBytes);\r\n\r\n const length = BerReader.readLength(reader);\r\n\r\n const value = reader.readBytes(length);\r\n\r\n return {\r\n\r\n key,\r\n\r\n length,\r\n\r\n value,\r\n\r\n raw: data\r\n\r\n };\r\n\r\n }\r\n\r\n}"]}
@@ -0,0 +1,37 @@
1
+ declare class UniversalKey {
2
+ readonly bytes: Uint8Array;
3
+ static readonly LENGTH = 16;
4
+ constructor(bytes: Uint8Array);
5
+ isSmpte(): boolean;
6
+ equals(other: UniversalKey): boolean;
7
+ toHex(separator?: string): string;
8
+ }
9
+
10
+ interface KlvPacket {
11
+ key: UniversalKey;
12
+ length: number;
13
+ value: Uint8Array;
14
+ raw: Uint8Array;
15
+ }
16
+
17
+ declare class ByteReader {
18
+ private readonly data;
19
+ private offset;
20
+ constructor(data: Uint8Array);
21
+ get position(): number;
22
+ get remaining(): number;
23
+ hasRemaining(length?: number): boolean;
24
+ readByte(): number;
25
+ readBytes(length: number): Uint8Array;
26
+ skip(length: number): void;
27
+ }
28
+
29
+ declare class BerReader {
30
+ static readLength(reader: ByteReader): number;
31
+ }
32
+
33
+ declare class KlvParser {
34
+ parse(data: Uint8Array): KlvPacket;
35
+ }
36
+
37
+ export { BerReader, ByteReader, type KlvPacket, KlvParser, UniversalKey };
@@ -0,0 +1,37 @@
1
+ declare class UniversalKey {
2
+ readonly bytes: Uint8Array;
3
+ static readonly LENGTH = 16;
4
+ constructor(bytes: Uint8Array);
5
+ isSmpte(): boolean;
6
+ equals(other: UniversalKey): boolean;
7
+ toHex(separator?: string): string;
8
+ }
9
+
10
+ interface KlvPacket {
11
+ key: UniversalKey;
12
+ length: number;
13
+ value: Uint8Array;
14
+ raw: Uint8Array;
15
+ }
16
+
17
+ declare class ByteReader {
18
+ private readonly data;
19
+ private offset;
20
+ constructor(data: Uint8Array);
21
+ get position(): number;
22
+ get remaining(): number;
23
+ hasRemaining(length?: number): boolean;
24
+ readByte(): number;
25
+ readBytes(length: number): Uint8Array;
26
+ skip(length: number): void;
27
+ }
28
+
29
+ declare class BerReader {
30
+ static readLength(reader: ByteReader): number;
31
+ }
32
+
33
+ declare class KlvParser {
34
+ parse(data: Uint8Array): KlvPacket;
35
+ }
36
+
37
+ export { BerReader, ByteReader, type KlvPacket, KlvParser, UniversalKey };
package/dist/index.js ADDED
@@ -0,0 +1,98 @@
1
+ // src/parser/ByteReader.ts
2
+ var ByteReader = class {
3
+ data;
4
+ offset = 0;
5
+ constructor(data) {
6
+ this.data = data;
7
+ }
8
+ get position() {
9
+ return this.offset;
10
+ }
11
+ get remaining() {
12
+ return this.data.length - this.offset;
13
+ }
14
+ hasRemaining(length = 1) {
15
+ return this.remaining >= length;
16
+ }
17
+ readByte() {
18
+ if (!this.hasRemaining()) {
19
+ throw new Error("Unexpected end of buffer.");
20
+ }
21
+ return this.data[this.offset++];
22
+ }
23
+ readBytes(length) {
24
+ if (!this.hasRemaining(length)) {
25
+ throw new Error("Unexpected end of buffer.");
26
+ }
27
+ const bytes = this.data.slice(this.offset, this.offset + length);
28
+ this.offset += length;
29
+ return bytes;
30
+ }
31
+ skip(length) {
32
+ if (!this.hasRemaining(length)) {
33
+ throw new Error("Unexpected end of buffer.");
34
+ }
35
+ this.offset += length;
36
+ }
37
+ };
38
+
39
+ // src/parser/BerReader.ts
40
+ var BerReader = class {
41
+ static readLength(reader) {
42
+ const first = reader.readByte();
43
+ if ((first & 128) === 0) {
44
+ return first;
45
+ }
46
+ const octets = first & 127;
47
+ if (octets === 0) {
48
+ throw new Error("Indefinite BER lengths are not supported.");
49
+ }
50
+ let length = 0;
51
+ for (let i = 0; i < octets; i++) {
52
+ length = length << 8 | reader.readByte();
53
+ }
54
+ return length;
55
+ }
56
+ };
57
+
58
+ // src/parser/UniversalKey.ts
59
+ var UniversalKey = class _UniversalKey {
60
+ constructor(bytes) {
61
+ this.bytes = bytes;
62
+ if (bytes.length !== _UniversalKey.LENGTH) {
63
+ throw new Error("Universal Key must contain 16 bytes.");
64
+ }
65
+ }
66
+ bytes;
67
+ static LENGTH = 16;
68
+ isSmpte() {
69
+ return this.bytes[0] === 6 && this.bytes[1] === 14 && this.bytes[2] === 43 && this.bytes[3] === 52;
70
+ }
71
+ equals(other) {
72
+ return this.bytes.every((v, i) => v === other.bytes[i]);
73
+ }
74
+ toHex(separator = "") {
75
+ return Array.from(this.bytes).map((b) => b.toString(16).padStart(2, "0")).join(separator);
76
+ }
77
+ };
78
+
79
+ // src/parser/KlvParser.ts
80
+ var KlvParser = class {
81
+ parse(data) {
82
+ const reader = new ByteReader(data);
83
+ const keyBytes = reader.readBytes(UniversalKey.LENGTH);
84
+ const key = new UniversalKey(keyBytes);
85
+ const length = BerReader.readLength(reader);
86
+ const value = reader.readBytes(length);
87
+ return {
88
+ key,
89
+ length,
90
+ value,
91
+ raw: data
92
+ };
93
+ }
94
+ };
95
+
96
+ export { BerReader, ByteReader, KlvParser, UniversalKey };
97
+ //# sourceMappingURL=index.js.map
98
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/parser/ByteReader.ts","../src/parser/BerReader.ts","../src/parser/UniversalKey.ts","../src/parser/KlvParser.ts"],"names":[],"mappings":";AAAO,IAAM,aAAN,MAAiB;AAAA,EAEH,IAAA;AAAA,EACT,MAAA,GAAS,CAAA;AAAA,EAEjB,YAAY,IAAA,EAAkB;AAC1B,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AAAA,EAChB;AAAA,EAEA,IAAI,QAAA,GAAmB;AACnB,IAAA,OAAO,IAAA,CAAK,MAAA;AAAA,EAChB;AAAA,EAEA,IAAI,SAAA,GAAoB;AACpB,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,MAAA,GAAS,IAAA,CAAK,MAAA;AAAA,EACnC;AAAA,EAEA,YAAA,CAAa,SAAS,CAAA,EAAY;AAC9B,IAAA,OAAO,KAAK,SAAA,IAAa,MAAA;AAAA,EAC7B;AAAA,EAEA,QAAA,GAAmB;AACf,IAAA,IAAI,CAAC,IAAA,CAAK,YAAA,EAAa,EAAG;AACtB,MAAA,MAAM,IAAI,MAAM,2BAA2B,CAAA;AAAA,IAC/C;AAEA,IAAA,OAAO,IAAA,CAAK,IAAA,CAAK,IAAA,CAAK,MAAA,EAAQ,CAAA;AAAA,EAClC;AAAA,EAEA,UAAU,MAAA,EAA4B;AAClC,IAAA,IAAI,CAAC,IAAA,CAAK,YAAA,CAAa,MAAM,CAAA,EAAG;AAC5B,MAAA,MAAM,IAAI,MAAM,2BAA2B,CAAA;AAAA,IAC/C;AAEA,IAAA,MAAM,KAAA,GAAQ,KAAK,IAAA,CAAK,KAAA,CAAM,KAAK,MAAA,EAAQ,IAAA,CAAK,SAAS,MAAM,CAAA;AAC/D,IAAA,IAAA,CAAK,MAAA,IAAU,MAAA;AAEf,IAAA,OAAO,KAAA;AAAA,EACX;AAAA,EAEA,KAAK,MAAA,EAAsB;AACvB,IAAA,IAAI,CAAC,IAAA,CAAK,YAAA,CAAa,MAAM,CAAA,EAAG;AAC5B,MAAA,MAAM,IAAI,MAAM,2BAA2B,CAAA;AAAA,IAC/C;AAEA,IAAA,IAAA,CAAK,MAAA,IAAU,MAAA;AAAA,EACnB;AACJ;;;AC7CO,IAAM,YAAN,MAAgB;AAAA,EAEnB,OAAO,WAAW,MAAA,EAA4B;AAE1C,IAAA,MAAM,KAAA,GAAQ,OAAO,QAAA,EAAS;AAG9B,IAAA,IAAA,CAAK,KAAA,GAAQ,SAAU,CAAA,EAAG;AACtB,MAAA,OAAO,KAAA;AAAA,IACX;AAEA,IAAA,MAAM,SAAS,KAAA,GAAQ,GAAA;AAEvB,IAAA,IAAI,WAAW,CAAA,EAAG;AACd,MAAA,MAAM,IAAI,MAAM,2CAA2C,CAAA;AAAA,IAC/D;AAEA,IAAA,IAAI,MAAA,GAAS,CAAA;AAEb,IAAA,KAAA,IAAS,CAAA,GAAI,CAAA,EAAG,CAAA,GAAI,MAAA,EAAQ,CAAA,EAAA,EAAK;AAC7B,MAAA,MAAA,GAAU,MAAA,IAAU,CAAA,GAAK,MAAA,CAAO,QAAA,EAAS;AAAA,IAC7C;AAEA,IAAA,OAAO,MAAA;AAAA,EACX;AAEJ;;;AC5BO,IAAM,YAAA,GAAN,MAAM,aAAA,CAAa;AAAA,EAItB,YACoB,KAAA,EAClB;AADkB,IAAA,IAAA,CAAA,KAAA,GAAA,KAAA;AAGhB,IAAA,IAAI,KAAA,CAAM,MAAA,KAAW,aAAA,CAAa,MAAA,EAAQ;AACtC,MAAA,MAAM,IAAI,MAAM,sCAAsC,CAAA;AAAA,IAC1D;AAAA,EAEJ;AAAA,EAPoB,KAAA;AAAA,EAHpB,OAAgB,MAAA,GAAS,EAAA;AAAA,EAYzB,OAAA,GAAmB;AAEf,IAAA,OACI,KAAK,KAAA,CAAM,CAAC,MAAM,CAAA,IAClB,IAAA,CAAK,MAAM,CAAC,CAAA,KAAM,EAAA,IAClB,IAAA,CAAK,MAAM,CAAC,CAAA,KAAM,MAClB,IAAA,CAAK,KAAA,CAAM,CAAC,CAAA,KAAM,EAAA;AAAA,EAG1B;AAAA,EAEA,OAAO,KAAA,EAA8B;AAEjC,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,KAAA,CAAM,CAAC,CAAA,EAAG,MAAM,CAAA,KAAM,KAAA,CAAM,KAAA,CAAM,CAAC,CAAC,CAAA;AAAA,EAE1D;AAAA,EAEA,KAAA,CAAM,YAAY,EAAA,EAAY;AAE1B,IAAA,OAAO,MAAM,IAAA,CAAK,IAAA,CAAK,KAAK,CAAA,CACvB,IAAI,CAAA,CAAA,KAAK,CAAA,CAAE,QAAA,CAAS,EAAE,EAAE,QAAA,CAAS,CAAA,EAAG,GAAG,CAAC,CAAA,CACxC,KAAK,SAAS,CAAA;AAAA,EAEvB;AAEJ;;;AClCO,IAAM,YAAN,MAAgB;AAAA,EAEnB,MAAM,IAAA,EAA6B;AAE/B,IAAA,MAAM,MAAA,GAAS,IAAI,UAAA,CAAW,IAAI,CAAA;AAElC,IAAA,MAAM,QAAA,GAAW,MAAA,CAAO,SAAA,CAAU,YAAA,CAAa,MAAM,CAAA;AAErD,IAAA,MAAM,GAAA,GAAM,IAAI,YAAA,CAAa,QAAQ,CAAA;AAErC,IAAA,MAAM,MAAA,GAAS,SAAA,CAAU,UAAA,CAAW,MAAM,CAAA;AAE1C,IAAA,MAAM,KAAA,GAAQ,MAAA,CAAO,SAAA,CAAU,MAAM,CAAA;AAErC,IAAA,OAAO;AAAA,MAEH,GAAA;AAAA,MAEA,MAAA;AAAA,MAEA,KAAA;AAAA,MAEA,GAAA,EAAK;AAAA,KAET;AAAA,EAEJ;AAEJ","file":"index.js","sourcesContent":["export class ByteReader {\r\n\r\n private readonly data: Uint8Array;\r\n private offset = 0;\r\n\r\n constructor(data: Uint8Array) {\r\n this.data = data;\r\n }\r\n\r\n get position(): number {\r\n return this.offset;\r\n }\r\n\r\n get remaining(): number {\r\n return this.data.length - this.offset;\r\n }\r\n\r\n hasRemaining(length = 1): boolean {\r\n return this.remaining >= length;\r\n }\r\n\r\n readByte(): number {\r\n if (!this.hasRemaining()) {\r\n throw new Error(\"Unexpected end of buffer.\");\r\n }\r\n\r\n return this.data[this.offset++];\r\n }\r\n\r\n readBytes(length: number): Uint8Array {\r\n if (!this.hasRemaining(length)) {\r\n throw new Error(\"Unexpected end of buffer.\");\r\n }\r\n\r\n const bytes = this.data.slice(this.offset, this.offset + length);\r\n this.offset += length;\r\n\r\n return bytes;\r\n }\r\n\r\n skip(length: number): void {\r\n if (!this.hasRemaining(length)) {\r\n throw new Error(\"Unexpected end of buffer.\");\r\n }\r\n\r\n this.offset += length;\r\n }\r\n}","import { ByteReader } from \"./ByteReader\";\r\n\r\nexport class BerReader {\r\n\r\n static readLength(reader: ByteReader): number {\r\n\r\n const first = reader.readByte();\r\n\r\n // Short form\r\n if ((first & 0x80) === 0) {\r\n return first;\r\n }\r\n\r\n const octets = first & 0x7F;\r\n\r\n if (octets === 0) {\r\n throw new Error(\"Indefinite BER lengths are not supported.\");\r\n }\r\n\r\n let length = 0;\r\n\r\n for (let i = 0; i < octets; i++) {\r\n length = (length << 8) | reader.readByte();\r\n }\r\n\r\n return length;\r\n }\r\n\r\n}","export class UniversalKey {\r\n\r\n static readonly LENGTH = 16;\r\n\r\n constructor(\r\n public readonly bytes: Uint8Array\r\n ) {\r\n\r\n if (bytes.length !== UniversalKey.LENGTH) {\r\n throw new Error(\"Universal Key must contain 16 bytes.\");\r\n }\r\n\r\n }\r\n\r\n isSmpte(): boolean {\r\n\r\n return (\r\n this.bytes[0] === 0x06 &&\r\n this.bytes[1] === 0x0E &&\r\n this.bytes[2] === 0x2B &&\r\n this.bytes[3] === 0x34\r\n );\r\n\r\n }\r\n\r\n equals(other: UniversalKey): boolean {\r\n\r\n return this.bytes.every((v, i) => v === other.bytes[i]);\r\n\r\n }\r\n\r\n toHex(separator = \"\"): string {\r\n\r\n return Array.from(this.bytes)\r\n .map(b => b.toString(16).padStart(2, \"0\"))\r\n .join(separator);\r\n\r\n }\r\n\r\n}","import { KlvPacket } from \"../packet/KlvPacket\";\r\nimport { BerReader } from \"./BerReader\";\r\nimport { ByteReader } from \"./ByteReader\";\r\nimport { UniversalKey } from \"./UniversalKey\";\r\n\r\nexport class KlvParser {\r\n\r\n parse(data: Uint8Array): KlvPacket {\r\n\r\n const reader = new ByteReader(data);\r\n\r\n const keyBytes = reader.readBytes(UniversalKey.LENGTH);\r\n\r\n const key = new UniversalKey(keyBytes);\r\n\r\n const length = BerReader.readLength(reader);\r\n\r\n const value = reader.readBytes(length);\r\n\r\n return {\r\n\r\n key,\r\n\r\n length,\r\n\r\n value,\r\n\r\n raw: data\r\n\r\n };\r\n\r\n }\r\n\r\n}"]}
package/package.json ADDED
@@ -0,0 +1,47 @@
1
+ {
2
+ "name": "klv-ts",
3
+ "version": "0.1.0",
4
+ "description": "Generic SMPTE 336M KLV parser for JavaScript and TypeScript",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "module": "./dist/index.js",
9
+ "types": "./dist/index.d.ts",
10
+ "exports": {
11
+ ".": {
12
+ "types": "./dist/index.d.ts",
13
+ "import": "./dist/index.js"
14
+ }
15
+ },
16
+ "files": [
17
+ "dist"
18
+ ],
19
+ "scripts": {
20
+ "build": "tsup",
21
+ "dev": "tsup --watch",
22
+ "test": "vitest run",
23
+ "test:watch": "vitest",
24
+ "lint": "tsc --noEmit",
25
+ "prepublishOnly": "pnpm build && pnpm test"
26
+ },
27
+ "keywords": [
28
+ "klv",
29
+ "misb",
30
+ "mpegts",
31
+ "smpte",
32
+ "metadata",
33
+ "video",
34
+ "uas"
35
+ ],
36
+ "repository": {
37
+ "type": "git",
38
+ "url": "https://github.com/JuankAnacona/klv-ts.git"
39
+ },
40
+ "dependencies": {
41
+ "tsup": "^8.5.1",
42
+ "vitest": "^4.1.10"
43
+ },
44
+ "devDependencies": {
45
+ "typescript": "5.9.2"
46
+ }
47
+ }