webserial-flasher 1.0.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.
Files changed (103) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +97 -0
  3. package/dist/autoDetect.d.ts +24 -0
  4. package/dist/autoDetect.d.ts.map +1 -0
  5. package/dist/autoDetect.js +66 -0
  6. package/dist/autoDetect.js.map +1 -0
  7. package/dist/boards/database.d.ts +17 -0
  8. package/dist/boards/database.d.ts.map +1 -0
  9. package/dist/boards/database.js +957 -0
  10. package/dist/boards/database.js.map +1 -0
  11. package/dist/core/constants.d.ts +44 -0
  12. package/dist/core/constants.d.ts.map +1 -0
  13. package/dist/core/constants.js +56 -0
  14. package/dist/core/constants.js.map +1 -0
  15. package/dist/core/errors.d.ts +45 -0
  16. package/dist/core/errors.d.ts.map +1 -0
  17. package/dist/core/errors.js +92 -0
  18. package/dist/core/errors.js.map +1 -0
  19. package/dist/core/types.d.ts +138 -0
  20. package/dist/core/types.d.ts.map +1 -0
  21. package/dist/core/types.js +3 -0
  22. package/dist/core/types.js.map +1 -0
  23. package/dist/index.d.ts +24 -0
  24. package/dist/index.d.ts.map +1 -0
  25. package/dist/index.js +25 -0
  26. package/dist/index.js.map +1 -0
  27. package/dist/protocol/avr109/programmer.d.ts +78 -0
  28. package/dist/protocol/avr109/programmer.d.ts.map +1 -0
  29. package/dist/protocol/avr109/programmer.js +324 -0
  30. package/dist/protocol/avr109/programmer.js.map +1 -0
  31. package/dist/protocol/hexParser.d.ts +12 -0
  32. package/dist/protocol/hexParser.d.ts.map +1 -0
  33. package/dist/protocol/hexParser.js +133 -0
  34. package/dist/protocol/hexParser.js.map +1 -0
  35. package/dist/protocol/picoboot/constants.d.ts +65 -0
  36. package/dist/protocol/picoboot/constants.d.ts.map +1 -0
  37. package/dist/protocol/picoboot/constants.js +80 -0
  38. package/dist/protocol/picoboot/constants.js.map +1 -0
  39. package/dist/protocol/picoboot/programmer.d.ts +73 -0
  40. package/dist/protocol/picoboot/programmer.d.ts.map +1 -0
  41. package/dist/protocol/picoboot/programmer.js +278 -0
  42. package/dist/protocol/picoboot/programmer.js.map +1 -0
  43. package/dist/protocol/picoboot/uf2.d.ts +51 -0
  44. package/dist/protocol/picoboot/uf2.d.ts.map +1 -0
  45. package/dist/protocol/picoboot/uf2.js +119 -0
  46. package/dist/protocol/picoboot/uf2.js.map +1 -0
  47. package/dist/protocol/receiveData.d.ts +3 -0
  48. package/dist/protocol/receiveData.d.ts.map +1 -0
  49. package/dist/protocol/receiveData.js +72 -0
  50. package/dist/protocol/receiveData.js.map +1 -0
  51. package/dist/protocol/sendCommand.d.ts +14 -0
  52. package/dist/protocol/sendCommand.d.ts.map +1 -0
  53. package/dist/protocol/sendCommand.js +48 -0
  54. package/dist/protocol/sendCommand.js.map +1 -0
  55. package/dist/protocol/stk500v2/constants.d.ts +57 -0
  56. package/dist/protocol/stk500v2/constants.d.ts.map +1 -0
  57. package/dist/protocol/stk500v2/constants.js +62 -0
  58. package/dist/protocol/stk500v2/constants.js.map +1 -0
  59. package/dist/protocol/stk500v2/frame.d.ts +14 -0
  60. package/dist/protocol/stk500v2/frame.d.ts.map +1 -0
  61. package/dist/protocol/stk500v2/frame.js +116 -0
  62. package/dist/protocol/stk500v2/frame.js.map +1 -0
  63. package/dist/protocol/stk500v2/programmer.d.ts +92 -0
  64. package/dist/protocol/stk500v2/programmer.d.ts.map +1 -0
  65. package/dist/protocol/stk500v2/programmer.js +482 -0
  66. package/dist/protocol/stk500v2/programmer.js.map +1 -0
  67. package/dist/protocol/updi/constants.d.ts +107 -0
  68. package/dist/protocol/updi/constants.d.ts.map +1 -0
  69. package/dist/protocol/updi/constants.js +130 -0
  70. package/dist/protocol/updi/constants.js.map +1 -0
  71. package/dist/protocol/updi/link.d.ts +82 -0
  72. package/dist/protocol/updi/link.d.ts.map +1 -0
  73. package/dist/protocol/updi/link.js +241 -0
  74. package/dist/protocol/updi/link.js.map +1 -0
  75. package/dist/protocol/updi/programmer.d.ts +89 -0
  76. package/dist/protocol/updi/programmer.d.ts.map +1 -0
  77. package/dist/protocol/updi/programmer.js +359 -0
  78. package/dist/protocol/updi/programmer.js.map +1 -0
  79. package/dist/stk500.d.ts +101 -0
  80. package/dist/stk500.d.ts.map +1 -0
  81. package/dist/stk500.js +426 -0
  82. package/dist/stk500.js.map +1 -0
  83. package/dist/transport/IPicobootTransport.d.ts +25 -0
  84. package/dist/transport/IPicobootTransport.d.ts.map +1 -0
  85. package/dist/transport/IPicobootTransport.js +10 -0
  86. package/dist/transport/IPicobootTransport.js.map +1 -0
  87. package/dist/transport/ITransport.d.ts +33 -0
  88. package/dist/transport/ITransport.d.ts.map +1 -0
  89. package/dist/transport/ITransport.js +4 -0
  90. package/dist/transport/ITransport.js.map +1 -0
  91. package/dist/transport/NodeSerialTransport.d.ts +35 -0
  92. package/dist/transport/NodeSerialTransport.d.ts.map +1 -0
  93. package/dist/transport/NodeSerialTransport.js +102 -0
  94. package/dist/transport/NodeSerialTransport.js.map +1 -0
  95. package/dist/transport/NodeUSBTransport.d.ts +24 -0
  96. package/dist/transport/NodeUSBTransport.d.ts.map +1 -0
  97. package/dist/transport/NodeUSBTransport.js +146 -0
  98. package/dist/transport/NodeUSBTransport.js.map +1 -0
  99. package/dist/transport/WebSerialTransport.d.ts +63 -0
  100. package/dist/transport/WebSerialTransport.d.ts.map +1 -0
  101. package/dist/transport/WebSerialTransport.js +159 -0
  102. package/dist/transport/WebSerialTransport.js.map +1 -0
  103. package/package.json +79 -0
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2024 Sebastian Barrenechea
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,97 @@
1
+ # webserial-flasher
2
+
3
+ A modern, ESM-compatible, TypeScript implementation of the STK500v1 protocol for programming Arduino boards directly from Node.js or the browser.
4
+
5
+ ## Features
6
+
7
+ - Full JavaScript/TypeScript implementation of the STK500v1 programmer
8
+ - ESM (ECMAScript Modules) compatible
9
+ - Can be used in Node.js or browser environments
10
+ - No dependency on avrdude or the Arduino IDE
11
+ - TypeScript support for improved developer experience
12
+ - **Built-in Intel HEX parsing** (no need for external parsing libraries)
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install webserial-flasher
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ Here's a basic example of how to use webserial-flasher to program an Arduino:
23
+
24
+ ```typescript
25
+ import { SerialPort } from "serialport";
26
+ import fs from "fs/promises";
27
+ import STK500, { type Board } from "webserial-flasher";
28
+
29
+ const board: Board = {
30
+ name: "Arduino Uno",
31
+ baudRate: 115200,
32
+ signature: new Uint8Array([0x1e, 0x95, 0x0f]),
33
+ pageSize: 128,
34
+ timeout: 400,
35
+ };
36
+
37
+ async function upload(path: string) {
38
+ let serialPort;
39
+ try {
40
+ const hexData = await fs.readFile("path/to/your/sketch.hex");
41
+ serialPort = new SerialPort({ path, baudRate: board.baudRate });
42
+ const stk = new STK500(serialPort, board);
43
+ await stk.bootload(hexData);
44
+ console.log("Programming successful!");
45
+ } catch (error) {
46
+ console.error("Programming failed:", error);
47
+ } finally {
48
+ if (serialPort) {
49
+ await serialPort.close();
50
+ }
51
+ }
52
+ }
53
+
54
+ upload("/dev/ttyACM0"); // Replace with your Arduino's serial port
55
+ ```
56
+
57
+ ## Examples
58
+
59
+ For more detailed examples, please check the `examples` folder in the repository. It contains several TypeScript files demonstrating how to use webserial-flasher with different Arduino boards:
60
+
61
+ - `avr4809.ts`: Example for AVR4809 based boards
62
+ - `diecimila-duemilanove168.ts`: Example for Arduino Diecimila and Duemilanove (ATmega168)
63
+ - `duemilanove328.ts`: Example for Arduino Duemilanove (ATmega328)
64
+ - `lg8f328.ts`: Example for LGT8F328 boards
65
+ - `nano.ts`: Example for Arduino Nano
66
+ - `uno.ts`: Example for Arduino Uno
67
+
68
+ These examples show how to set up the board configuration, read hex files, and upload them to the respective Arduino boards.
69
+
70
+ To run an example, use:
71
+
72
+ ```bash
73
+ npx tsx examples/uno.ts /dev/ttyACM0
74
+ ```
75
+
76
+ Replace `uno.ts` with the appropriate example file and `/dev/ttyACM0` with your Arduino's serial port.
77
+
78
+ ## API
79
+
80
+ The main class `STK500` provides the following methods:
81
+
82
+ - `constructor(stream: Duplex, board: Board, opts?: STK500Options)`
83
+ - `bootload(hexData: string | Uint8Array, progressCallback?: BootloadProgressCallback): Promise<void>`
84
+ - `sync(attempts: number): Promise<Uint8Array>`
85
+ - `verifySignature(): Promise<Uint8Array>`
86
+ - `upload(hexData: string | Uint8Array, progressCallback?: (percentage: number) => void): Promise<void>`
87
+ - `verify(hexData: string | Uint8Array, progressCallback?: (percentage: number) => void): Promise<void>`
88
+
89
+ For more detailed API information, please refer to the TypeScript definitions or the source code.
90
+
91
+ ## Contributing
92
+
93
+ Contributions are welcome! Please feel free to submit a Pull Request.
94
+
95
+ ## License
96
+
97
+ This project is licensed under the MIT License. See the [LICENSE](LICENSE) file for details.
@@ -0,0 +1,24 @@
1
+ import type { Board } from './core/types.js';
2
+ import type { ISTKTransport } from './transport/ITransport.js';
3
+ /** Result from a successful auto-detect probe */
4
+ export interface AutoDetectResult {
5
+ /** Detected bootloader protocol */
6
+ protocol: 'stk500v1' | 'stk500v2' | 'avr109';
7
+ /** Raw 3-byte device signature */
8
+ signature: Uint8Array;
9
+ /** Matched board, or undefined if the signature is unknown */
10
+ board: Board | undefined;
11
+ }
12
+ export interface AutoDetectOptions {
13
+ /**
14
+ * Timeout (ms) for each individual protocol probe attempt.
15
+ * Shorter = faster detection but may miss slow bootloaders.
16
+ * Default: 300
17
+ */
18
+ probeTimeoutMs?: number;
19
+ /** Suppress all log output during probing (default: true) */
20
+ quiet?: boolean;
21
+ }
22
+ /** Probe board for a given transport — detect protocol and signature. */
23
+ export declare function autoDetect(transport: ISTKTransport, opts?: AutoDetectOptions): Promise<AutoDetectResult | null>;
24
+ //# sourceMappingURL=autoDetect.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autoDetect.d.ts","sourceRoot":"","sources":["../src/autoDetect.ts"],"names":[],"mappings":"AAuBA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AAC7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,2BAA2B,CAAC;AAE/D,iDAAiD;AACjD,MAAM,WAAW,gBAAgB;IAC/B,mCAAmC;IACnC,QAAQ,EAAE,UAAU,GAAG,UAAU,GAAG,QAAQ,CAAC;IAC7C,kCAAkC;IAClC,SAAS,EAAE,UAAU,CAAC;IACtB,8DAA8D;IAC9D,KAAK,EAAE,KAAK,GAAG,SAAS,CAAC;CAC1B;AAED,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,6DAA6D;IAC7D,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB;AAED,yEAAyE;AACzE,wBAAsB,UAAU,CAC9B,SAAS,EAAE,aAAa,EACxB,IAAI,GAAE,iBAAsB,GAC3B,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CA8ClC"}
@@ -0,0 +1,66 @@
1
+ // Auto-detection: probe an unknown target and determine its protocol + board.
2
+ //
3
+ // Tries each protocol in order with a short timeout:
4
+ // 1. STK500v1 — GET_SYNC (most common: Uno, Nano, Pro Mini)
5
+ // 2. STK500v2 — SIGN_ON (Mega 2560, Mega 1280)
6
+ // 3. AVR109 — get software ID (Leonardo, Micro, Pro Micro)
7
+ //
8
+ // UPDI devices require a BREAK condition first and cannot be auto-detected
9
+ // in this manner — callers must select UPDI explicitly.
10
+ //
11
+ // Usage:
12
+ // const result = await autoDetect(transport, { probeTimeoutMs: 300 });
13
+ // if (result) {
14
+ // console.log(result.protocol, result.board?.name, result.signature);
15
+ // }
16
+ import { STK500 } from './stk500.js';
17
+ import { STK500v2 } from './protocol/stk500v2/programmer.js';
18
+ import { AVR109 } from './protocol/avr109/programmer.js';
19
+ import { BOARDS, detectBoardBySignature, } from './boards/database.js';
20
+ /** Probe board for a given transport — detect protocol and signature. */
21
+ export async function autoDetect(transport, opts = {}) {
22
+ const timeout = opts.probeTimeoutMs ?? 300;
23
+ const quiet = opts.quiet !== false; // default quiet=true
24
+ // Minimal probe board — only timeout matters for probing
25
+ const probeBoard = {
26
+ ...BOARDS['arduino-uno'],
27
+ timeout,
28
+ };
29
+ // ── 1. STK500v1 ────────────────────────────────────────────────────────────
30
+ try {
31
+ const stk = new STK500(transport, probeBoard, {
32
+ quiet,
33
+ retry: { syncAttempts: 1, retryDelayMs: 0 },
34
+ });
35
+ await stk.sync(1);
36
+ const sig = await stk.getSignature();
37
+ const board = detectBoardBySignature(sig) ?? undefined;
38
+ return { protocol: 'stk500v1', signature: sig, board };
39
+ }
40
+ catch { /* not STK500v1 */ }
41
+ // ── 2. STK500v2 ────────────────────────────────────────────────────────────
42
+ try {
43
+ const probeV2Board = { ...BOARDS['arduino-mega2560'], timeout };
44
+ const stk2 = new STK500v2(transport, probeV2Board, {
45
+ quiet,
46
+ retry: { syncAttempts: 1, retryDelayMs: 0 },
47
+ });
48
+ await stk2.sync(1);
49
+ const sig = await stk2.readSignature();
50
+ const board = detectBoardBySignature(sig) ?? undefined;
51
+ return { protocol: 'stk500v2', signature: sig, board };
52
+ }
53
+ catch { /* not STK500v2 */ }
54
+ // ── 3. AVR109 ──────────────────────────────────────────────────────────────
55
+ try {
56
+ const probeAvrBoard = { ...BOARDS['arduino-leonardo'], timeout };
57
+ const avr = new AVR109(transport, probeAvrBoard, { quiet });
58
+ await avr.sync(1);
59
+ const sig = await avr.getSignature();
60
+ const board = detectBoardBySignature(sig) ?? undefined;
61
+ return { protocol: 'avr109', signature: sig, board };
62
+ }
63
+ catch { /* not AVR109 */ }
64
+ return null;
65
+ }
66
+ //# sourceMappingURL=autoDetect.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"autoDetect.js","sourceRoot":"","sources":["../src/autoDetect.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,EAAE;AACF,qDAAqD;AACrD,8DAA8D;AAC9D,kDAAkD;AAClD,+DAA+D;AAC/D,EAAE;AACF,2EAA2E;AAC3E,wDAAwD;AACxD,EAAE;AACF,SAAS;AACT,yEAAyE;AACzE,kBAAkB;AAClB,0EAA0E;AAC1E,MAAM;AAEN,OAAO,EAAE,MAAM,EAAG,MAAS,aAAa,CAAC;AACzC,OAAO,EAAE,QAAQ,EAAE,MAAQ,mCAAmC,CAAC;AAC/D,OAAO,EAAE,MAAM,EAAE,MAAU,iCAAiC,CAAC;AAC7D,OAAO,EACL,MAAM,EACN,sBAAsB,GACvB,MAAM,sBAAsB,CAAC;AAyB9B,yEAAyE;AACzE,MAAM,CAAC,KAAK,UAAU,UAAU,CAC9B,SAAwB,EACxB,OAA0B,EAAE;IAE5B,MAAM,OAAO,GAAG,IAAI,CAAC,cAAc,IAAI,GAAG,CAAC;IAC3C,MAAM,KAAK,GAAK,IAAI,CAAC,KAAK,KAAK,KAAK,CAAC,CAAC,qBAAqB;IAE3D,yDAAyD;IACzD,MAAM,UAAU,GAAU;QACxB,GAAG,MAAM,CAAC,aAAa,CAAE;QACzB,OAAO;KACR,CAAC;IAEF,8EAA8E;IAC9E,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC,SAAS,EAAE,UAAU,EAAE;YAC5C,KAAK;YACL,KAAK,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE;SAC5C,CAAC,CAAC;QACH,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,MAAM,GAAG,GAAK,MAAM,GAAG,CAAC,YAAY,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,sBAAsB,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC;QACvD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;IAE9B,8EAA8E;IAC9E,IAAI,CAAC;QACH,MAAM,YAAY,GAAU,EAAE,GAAG,MAAM,CAAC,kBAAkB,CAAE,EAAE,OAAO,EAAE,CAAC;QACxE,MAAM,IAAI,GAAG,IAAI,QAAQ,CAAC,SAAS,EAAE,YAAY,EAAE;YACjD,KAAK;YACL,KAAK,EAAE,EAAE,YAAY,EAAE,CAAC,EAAE,YAAY,EAAE,CAAC,EAAE;SAC5C,CAAC,CAAC;QACH,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACnB,MAAM,GAAG,GAAK,MAAM,IAAI,CAAC,aAAa,EAAE,CAAC;QACzC,MAAM,KAAK,GAAG,sBAAsB,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC;QACvD,OAAO,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;IACzD,CAAC;IAAC,MAAM,CAAC,CAAC,kBAAkB,CAAC,CAAC;IAE9B,8EAA8E;IAC9E,IAAI,CAAC;QACH,MAAM,aAAa,GAAU,EAAE,GAAG,MAAM,CAAC,kBAAkB,CAAE,EAAE,OAAO,EAAE,CAAC;QACzE,MAAM,GAAG,GAAG,IAAI,MAAM,CAAC,SAAS,EAAE,aAAa,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5D,MAAM,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,MAAM,GAAG,GAAK,MAAM,GAAG,CAAC,YAAY,EAAE,CAAC;QACvC,MAAM,KAAK,GAAG,sBAAsB,CAAC,GAAG,CAAC,IAAI,SAAS,CAAC;QACvD,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,SAAS,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;IACvD,CAAC;IAAC,MAAM,CAAC,CAAC,gBAAgB,CAAC,CAAC;IAE5B,OAAO,IAAI,CAAC;AACd,CAAC"}
@@ -0,0 +1,17 @@
1
+ import type { Board } from '../core/types.js';
2
+ export declare const BOARDS: Readonly<Record<string, Board>>;
3
+ /**
4
+ * Find a board by its 3-byte device signature.
5
+ * Returns the first match, or null if no board matches.
6
+ * Note: multiple boards share the same signature (e.g. all ATmega328P variants).
7
+ */
8
+ export declare function detectBoardBySignature(signature: Uint8Array): Board | null;
9
+ /**
10
+ * Get a board config from an arduino-cli FQBN string.
11
+ * Returns null if the FQBN is not recognised.
12
+ * @example boardFromFqbn('arduino:avr:mega') → BOARDS['arduino-mega2560']
13
+ */
14
+ export declare function boardFromFqbn(fqbn: string): Board | null;
15
+ /** USB Vendor IDs for board auto-detection in WebSerial requestPort() */
16
+ export declare const ARDUINO_USB_VENDOR_IDS: readonly number[];
17
+ //# sourceMappingURL=database.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"database.d.ts","sourceRoot":"","sources":["../../src/boards/database.ts"],"names":[],"mappings":"AAUA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AAE9C,eAAO,MAAM,MAAM,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CA+6BlD,CAAC;AAIF;;;;GAIG;AACH,wBAAgB,sBAAsB,CAAC,SAAS,EAAE,UAAU,GAAG,KAAK,GAAG,IAAI,CAa1E;AA8CD;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,KAAK,GAAG,IAAI,CAGxD;AAED,yEAAyE;AACzE,eAAO,MAAM,sBAAsB,EAAE,SAAS,MAAM,EAQnD,CAAC"}