@mikrojs/native 0.0.7

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 (109) hide show
  1. package/CMakeLists.txt +198 -0
  2. package/LICENSE +21 -0
  3. package/README.md +49 -0
  4. package/cmake/mikrojs_bytecode.cmake +146 -0
  5. package/cmake.js +22 -0
  6. package/dist/index.d.ts +52 -0
  7. package/dist/index.d.ts.map +1 -0
  8. package/dist/index.js +132 -0
  9. package/dist/index.js.map +1 -0
  10. package/dist/types.d.ts +43 -0
  11. package/dist/types.d.ts.map +1 -0
  12. package/dist/types.js +2 -0
  13. package/dist/types.js.map +1 -0
  14. package/include/byteorder_apple.h +11 -0
  15. package/include/byteorder_windows.h +12 -0
  16. package/include/mikrojs/cbor_helpers.h +24 -0
  17. package/include/mikrojs/cutils_wrap.h +59 -0
  18. package/include/mikrojs/errors.h +144 -0
  19. package/include/mikrojs/mem.h +11 -0
  20. package/include/mikrojs/mik_color.h +32 -0
  21. package/include/mikrojs/mikrojs.h +331 -0
  22. package/include/mikrojs/platform.h +82 -0
  23. package/include/mikrojs/private.h +281 -0
  24. package/include/mikrojs/utils.h +125 -0
  25. package/package.json +100 -0
  26. package/prebuilds/darwin-arm64/mikrojs.napi.node +0 -0
  27. package/prebuilds/linux-arm64/mikrojs.napi.node +0 -0
  28. package/prebuilds/linux-x64/mikrojs.napi.node +0 -0
  29. package/runtime/ble/ble.ts +231 -0
  30. package/runtime/ble/types.ts +194 -0
  31. package/runtime/ble/uuid.ts +89 -0
  32. package/runtime/ble/validators.ts +61 -0
  33. package/runtime/cbor/cbor.ts +1 -0
  34. package/runtime/cbor/types.ts +8 -0
  35. package/runtime/console/types.ts +50 -0
  36. package/runtime/env/env.ts +17 -0
  37. package/runtime/env/types.ts +12 -0
  38. package/runtime/format/types.ts +4 -0
  39. package/runtime/fs/fs.ts +93 -0
  40. package/runtime/fs/types.ts +92 -0
  41. package/runtime/globals.d.ts +87 -0
  42. package/runtime/http/helpers.ts +222 -0
  43. package/runtime/http/native.ts +151 -0
  44. package/runtime/http/request.ts +25 -0
  45. package/runtime/i2c/i2c.ts +35 -0
  46. package/runtime/i2c/types.ts +55 -0
  47. package/runtime/inspect/types.ts +10 -0
  48. package/runtime/internal.d.ts +456 -0
  49. package/runtime/kv/nvs.ts +17 -0
  50. package/runtime/kv/rtc.ts +17 -0
  51. package/runtime/kv/shared.ts +107 -0
  52. package/runtime/kv/types.ts +150 -0
  53. package/runtime/neopixel/neopixel.ts +38 -0
  54. package/runtime/neopixel/types.ts +27 -0
  55. package/runtime/pin/pin.ts +51 -0
  56. package/runtime/pin/types.ts +49 -0
  57. package/runtime/pwm/pwm.ts +32 -0
  58. package/runtime/pwm/types.ts +29 -0
  59. package/runtime/reader/reader.ts +167 -0
  60. package/runtime/reader/types.ts +34 -0
  61. package/runtime/result/native-result.node-shim.ts +44 -0
  62. package/runtime/result/result.ts +26 -0
  63. package/runtime/result/types.ts +60 -0
  64. package/runtime/schema/schema.ts +321 -0
  65. package/runtime/schema/types.ts +152 -0
  66. package/runtime/sleep/sleep.ts +14 -0
  67. package/runtime/sleep/types.ts +44 -0
  68. package/runtime/sntp/sntp.ts +54 -0
  69. package/runtime/sntp/types.ts +38 -0
  70. package/runtime/spi/spi.ts +31 -0
  71. package/runtime/spi/types.ts +42 -0
  72. package/runtime/stdio/stdio.ts +44 -0
  73. package/runtime/stdio/types.ts +22 -0
  74. package/runtime/stream/stream.ts +150 -0
  75. package/runtime/stream/types.ts +47 -0
  76. package/runtime/sys/sys.ts +90 -0
  77. package/runtime/sys/types.ts +131 -0
  78. package/runtime/test/test.ts +595 -0
  79. package/runtime/test/types.ts +97 -0
  80. package/runtime/uart/types.ts +75 -0
  81. package/runtime/uart/uart.ts +51 -0
  82. package/runtime/wifi/types.ts +156 -0
  83. package/runtime/wifi/wifi.ts +208 -0
  84. package/scripts/bundle-runtime.js +149 -0
  85. package/scripts/compare-minifiers.js +189 -0
  86. package/scripts/compile-bytecode.sh +38 -0
  87. package/scripts/copy-prebuild.js +20 -0
  88. package/scripts/generate-symbol-map.js +146 -0
  89. package/src/builtins.cpp +82 -0
  90. package/src/cutils_compat.c +38 -0
  91. package/src/eval_bytecode.cpp +42 -0
  92. package/src/fs.cpp +878 -0
  93. package/src/mem.cpp +63 -0
  94. package/src/mik_abort.cpp +160 -0
  95. package/src/mik_app_config.cpp +358 -0
  96. package/src/mik_cbor.cpp +334 -0
  97. package/src/mik_color.cpp +46 -0
  98. package/src/mik_console.cpp +422 -0
  99. package/src/mik_inspect.cpp +850 -0
  100. package/src/mik_repl.cpp +1122 -0
  101. package/src/mik_result.cpp +344 -0
  102. package/src/mik_stdio.cpp +147 -0
  103. package/src/mik_sys.cpp +239 -0
  104. package/src/mik_text_encoding.cpp +443 -0
  105. package/src/mikrojs.cpp +942 -0
  106. package/src/modules.cpp +944 -0
  107. package/src/platform_posix.cpp +134 -0
  108. package/src/timers.cpp +208 -0
  109. package/src/utils.cpp +173 -0
@@ -0,0 +1,35 @@
1
+ import * as native from 'native:i2c'
2
+
3
+ import type {Result} from '../result/types.js'
4
+ import type {I2c as PlatformI2c, I2cError, I2cOptions} from './types.js'
5
+
6
+ /**
7
+ * @public
8
+ */
9
+ export class I2c implements PlatformI2c {
10
+ #native: native.I2c
11
+
12
+ constructor(busNo: 0 | 1, options?: I2cOptions) {
13
+ this.#native = new native.I2c(busNo, options)
14
+ }
15
+
16
+ begin(): Result<void, I2cError> {
17
+ return this.#native.begin()
18
+ }
19
+
20
+ end(): Result<void, I2cError> {
21
+ return this.#native.end()
22
+ }
23
+
24
+ scan(): Result<Uint8Array, I2cError> {
25
+ return this.#native.scan()
26
+ }
27
+
28
+ write(address: number, data: Uint8Array, stop?: boolean): Result<void, I2cError> {
29
+ return this.#native.write(address, data, stop)
30
+ }
31
+
32
+ read(address: number, bytes: number): Result<Uint8Array, I2cError> {
33
+ return this.#native.read(address, bytes)
34
+ }
35
+ }
@@ -0,0 +1,55 @@
1
+ import type {Result} from '../result/types.js'
2
+
3
+ /**
4
+ * @public
5
+ */
6
+ export interface I2cBaseOptions {
7
+ freq?: number
8
+ timeout?: number
9
+ }
10
+
11
+ /**
12
+ * @public
13
+ */
14
+ export interface I2cOptionsWithPins extends I2cBaseOptions {
15
+ sda: number
16
+ scl: number
17
+ }
18
+
19
+ /**
20
+ * @public
21
+ */
22
+ export type I2cOptions = I2cBaseOptions | I2cOptionsWithPins
23
+
24
+ export type I2cError =
25
+ | {name: 'BusInitFailed'; message: string}
26
+ | {name: 'BusDeinitFailed'; message: string}
27
+ | {name: 'NotStarted'}
28
+ | {name: 'MissingPins'}
29
+ | {name: 'AddDeviceFailed'; message: string}
30
+ | {name: 'WriteFailed'; message: string}
31
+ | {name: 'WriteTooLarge'}
32
+ | {name: 'ReadFailed'; message: string}
33
+
34
+ /**
35
+ * @public
36
+ */
37
+ export declare const I2c: {
38
+ prototype: I2c
39
+ new (busNo: 0 | 1, options?: I2cOptions): I2c
40
+ }
41
+
42
+ /**
43
+ * @public
44
+ */
45
+ export interface I2c {
46
+ begin(): Result<void, I2cError>
47
+
48
+ end(): Result<void, I2cError>
49
+
50
+ read(address: number, bytes: number): Result<Uint8Array, I2cError>
51
+
52
+ write(address: number, data: Uint8Array, stop?: boolean): Result<void, I2cError>
53
+
54
+ scan(): Result<Uint8Array, I2cError>
55
+ }
@@ -0,0 +1,10 @@
1
+ export interface InspectOptions {
2
+ showHidden?: boolean
3
+ depth?: number
4
+ truncate?: number
5
+ colors?: boolean
6
+ }
7
+
8
+ export type InspectFn = (value: unknown, options?: InspectOptions) => string
9
+
10
+ export declare const inspect: InspectFn
@@ -0,0 +1,456 @@
1
+ // Native C modules provided by the firmware, not importable by user scripts
2
+
3
+ type NR<T> = {ok: true; value: T} | {ok: false; error: {code: number; message: string}}
4
+
5
+ // Internal shared runtime modules. Registered as builtins so sibling bundles
6
+ // can reference them at runtime to dedupe shared code, but not exposed via
7
+ // the public `mikrojs/*` subpath exports so user apps can't accidentally
8
+ // import them. Keep these in sync with the MODULES list in the firmware +
9
+ // @mikrojs/native CMakeLists.
10
+ declare module 'mikrojs/kv/shared' {
11
+ export {KVError, makeCreateValue, type NativeKvFns} from './kv/shared.js'
12
+ }
13
+
14
+ declare module 'native:cbor' {
15
+ import type {CborError} from '@mikrojs/native/runtime/cbor/types'
16
+ import type {Result} from 'mikrojs/result'
17
+ export function encode(value: unknown): Result<Uint8Array, CborError>
18
+ export function decode(data: Uint8Array): Result<unknown, CborError>
19
+ }
20
+
21
+ declare module 'native:result' {
22
+ import type {ErrResult, OkResult} from './result/types.js'
23
+ export function ok(): OkResult<void>
24
+ export function ok<T>(value: T): OkResult<T>
25
+ export function err<E>(error: E): ErrResult<E>
26
+ }
27
+
28
+ declare module 'native:sys' {
29
+ import type {JsMemoryUsage} from './sys/types.js'
30
+ export function evalScript(code: string): Promise<{value: unknown}>
31
+ export function memoryUsage(): {
32
+ heapUsed: number
33
+ heapTotal: number
34
+ systemFree: number
35
+ systemMinFree: number
36
+ systemTotal: number
37
+ systemLargestFree: number
38
+ }
39
+ export function jsMemoryUsage(): JsMemoryUsage
40
+ export function gc(): void
41
+ export function activeTimers(): number
42
+ export function setTime(millisSinceEpoch: number): void
43
+ export function uptime(): {boot: number; rtc: number}
44
+ export function restart(): never
45
+ export const version: string
46
+ export const board: {
47
+ name: string
48
+ chip: string
49
+ cores: number
50
+ revision: number
51
+ features: string[]
52
+ flash: number
53
+ psram: number
54
+ }
55
+ export const firmware: {hash: string; date: string; idfVersion: string | undefined}
56
+ export const deviceId: string
57
+ }
58
+
59
+ declare module 'native:fs' {
60
+ import type {DirEntry, FSError, MkdirOptions, StatResult, WriteFileOptions} from './fs/types.js'
61
+ import type {Result} from './result/types.js'
62
+
63
+ export interface FileHandle {
64
+ /** Reads up to `size` bytes. Value is `undefined` at EOF. */
65
+ read(size: number): Result<Uint8Array | undefined, FSError>
66
+ write(data: Uint8Array | string): Result<number, FSError>
67
+ seek(offset: number, whence?: 'start' | 'current' | 'end'): Result<number, FSError>
68
+ close(): Result<void, FSError>
69
+ stat(): Result<StatResult, FSError>
70
+ readonly path: string
71
+ }
72
+
73
+ export type OpenMode = 'r' | 'w' | 'a' | 'r+' | 'w+' | 'a+'
74
+
75
+ export function open(path: string, mode?: OpenMode): Result<FileHandle, FSError>
76
+ export function readFile(path: string): Result<Uint8Array, FSError>
77
+ export function readFile(path: string, encoding: 'utf-8'): Result<string, FSError>
78
+ export function writeFile(
79
+ path: string,
80
+ contents: string,
81
+ options?: WriteFileOptions,
82
+ ): Result<void, FSError>
83
+ export function writeFile(
84
+ path: string,
85
+ contents: Uint8Array,
86
+ options?: WriteFileOptions,
87
+ ): Result<void, FSError>
88
+ export function stat(path: string): Result<StatResult, FSError>
89
+ export function readDir(path: string): Result<DirEntry[], FSError>
90
+ export function unlink(path: string): Result<void, FSError>
91
+ export function rename(from: string, to: string): Result<void, FSError>
92
+ export function mkdir(path: string, options?: MkdirOptions): Result<void, FSError>
93
+ export function rmdir(path: string): Result<void, FSError>
94
+ export function exists(path: string): boolean
95
+ }
96
+
97
+ declare module 'native:stdio' {
98
+ export const stdout: {
99
+ write(output: Uint8Array | string): boolean
100
+ flush(): void
101
+ }
102
+
103
+ export const stdin: {
104
+ read(): undefined | Uint8Array
105
+ setHandler(handler: (data: Uint8Array) => void): void
106
+ clearHandler(): void
107
+ }
108
+ }
109
+
110
+ declare module 'native:pin' {
111
+ import type {PinError} from '@mikrojs/native/runtime/pin/types'
112
+ import type {Result} from 'mikrojs/result'
113
+ export type PinMode = 0x01 | 0x03 | 0x05
114
+ export function pinMode(pin: number, value: PinMode): Result<void, PinError>
115
+ export function digitalWrite(pin: number, value: 0 | 1): Result<void, PinError>
116
+ export function digitalRead(pin: number): number
117
+ // attenuation: 0=0dB, 1=2.5dB, 2=6dB, 3=11dB
118
+ export function analogRead(pin: number, attenuation: number): Result<number, PinError>
119
+ export function analogReadMillivolts(pin: number, attenuation: number): Result<number, PinError>
120
+ }
121
+
122
+ declare module 'native:sleep' {
123
+ import type {SleepError} from '@mikrojs/native/runtime/sleep/types'
124
+ import type {Result} from 'mikrojs/result'
125
+
126
+ export function deepSleep(ms: number): never
127
+ export function lightSleep(ms: number): Result<void, SleepError>
128
+ export function getWakeupCause(): string
129
+ export function enableTimerWakeup(us: number): Result<void, SleepError>
130
+ export function enableGpioWakeup(pin: number, level: number): Result<void, SleepError>
131
+ export function enableExt0Wakeup(pin: number, level: number): Result<void, SleepError>
132
+ export function enableExt1Wakeup(pinMask: number, mode: number): Result<void, SleepError>
133
+ export function disableWakeupSource(source?: string): Result<void, SleepError>
134
+ }
135
+
136
+ declare module 'native:http' {
137
+ import type {RequestError} from 'mikrojs/http/helpers'
138
+ import type {Result} from 'mikrojs/result'
139
+
140
+ import type {ErrResult} from './result/types.js'
141
+ type HeadersMsg = {status: number; headers: [string, string][]}
142
+ export type HttpMessage =
143
+ | {kind: 'chunk'; data: Uint8Array}
144
+ | {kind: 'end'}
145
+ | {kind: 'error'; cancelled: boolean; message: string}
146
+ export type HttpRequestStart =
147
+ | {ok: true; id: number; headers: Promise<Result<HeadersMsg, RequestError>>}
148
+ | ErrResult<RequestError>
149
+ export function request(
150
+ url: string,
151
+ options?: {method?: string; body?: Uint8Array; headers?: [string, string][]},
152
+ ): HttpRequestStart
153
+ export function nextMessage(id: number): Promise<HttpMessage>
154
+ export function cancel(id: number): void
155
+ export function pendingCount(): number
156
+ }
157
+ declare module 'native:i2c' {
158
+ import type {I2cError} from '@mikrojs/native/runtime/i2c/types'
159
+ import type {Result} from 'mikrojs/result'
160
+
161
+ export interface I2cBaseOptions {
162
+ freq?: number
163
+ timeout?: number
164
+ }
165
+
166
+ export interface I2cOptionsWithPins extends I2cBaseOptions {
167
+ sda: number
168
+ scl: number
169
+ }
170
+
171
+ export type I2cOptions = I2cBaseOptions | I2cOptionsWithPins
172
+ export declare const I2c: {
173
+ prototype: I2c
174
+ new (busNo: 0 | 1, options?: I2cOptions): I2c
175
+ }
176
+
177
+ export interface I2c {
178
+ begin(): Result<void, I2cError>
179
+
180
+ end(): Result<void, I2cError>
181
+
182
+ read(address: number, bytes: number): Result<Uint8Array, I2cError>
183
+
184
+ write(address: number, data: Uint8Array, stop?: boolean): Result<void, I2cError>
185
+
186
+ scan(): Result<Uint8Array, I2cError>
187
+ }
188
+ }
189
+ declare module 'native:spi' {
190
+ import type {SpiError} from '@mikrojs/native/runtime/spi/types'
191
+ import type {Result} from 'mikrojs/result'
192
+
193
+ export interface SpiOptions {
194
+ clk: number
195
+ mosi: number
196
+ miso?: number
197
+ cs?: number
198
+ freq?: number
199
+ mode?: 0 | 1 | 2 | 3
200
+ }
201
+
202
+ export declare const Spi: {
203
+ prototype: Spi
204
+ new (hostNo: 1 | 2, options: SpiOptions): Spi
205
+ }
206
+
207
+ export interface Spi {
208
+ begin(): Result<void, SpiError>
209
+
210
+ end(): Result<void, SpiError>
211
+
212
+ transfer(data: Uint8Array): Result<Uint8Array, SpiError>
213
+
214
+ write(data: Uint8Array): Result<void, SpiError>
215
+ }
216
+ }
217
+
218
+ declare module 'native:sntp' {
219
+ import type {SntpError} from '@mikrojs/native/runtime/sntp/types'
220
+ import type {Result} from 'mikrojs/result'
221
+ /**
222
+ * Native errors: the outer Result covers init/config failures (InitFailed);
223
+ * the inner Result on resolve covers post-start errors (Cancelled).
224
+ * `Timeout` is owned by the JS-side Promise racer in mikrojs/sntp, not
225
+ * emitted by native.
226
+ */
227
+ export function sync(
228
+ servers: string[],
229
+ timezone: string,
230
+ background: boolean,
231
+ ): Result<Promise<Result<{time: number}, SntpError>>, SntpError>
232
+ export function stop(): void
233
+ export function setTimezone(tz: string): void
234
+ }
235
+
236
+ declare module 'native:rtc' {
237
+ type NRV = {ok: true} | {ok: false; error: {code: number; message: string}}
238
+ export function set(key: string, value: unknown): NRV
239
+ export function get(key: string): unknown
240
+ export function remove(key: string): boolean
241
+ export function clear(): void
242
+ export function info(): {used: number; total: number; entries: number}
243
+ }
244
+
245
+ declare module 'native:nvs_kv' {
246
+ type NRV = {ok: true} | {ok: false; error: {code: number; message: string}}
247
+ export function set(key: string, value: unknown): NRV
248
+ export function get(key: string): unknown
249
+ export function remove(key: string): boolean
250
+ export function clear(): void
251
+ export function info(): {entries: number; used: number; total: number; free: number}
252
+ }
253
+
254
+ declare module 'native:pwm' {
255
+ import type {PwmError} from '@mikrojs/native/runtime/pwm/types'
256
+ import type {Result} from 'mikrojs/result'
257
+
258
+ export declare const Pwm: {
259
+ prototype: Pwm
260
+ new (pin: number, freq: number, duty: number): Pwm
261
+ }
262
+
263
+ export interface Pwm {
264
+ duty(value?: number): Result<number, PwmError>
265
+ freq(value?: number): Result<number, PwmError>
266
+ fade(target: number, durationMs: number): Result<Promise<void>, PwmError>
267
+ end(): Result<void, PwmError>
268
+ }
269
+ }
270
+
271
+ declare module 'native:neopixel' {
272
+ import type {NeoPixelError} from '@mikrojs/native/runtime/neopixel/types'
273
+ import type {Result} from 'mikrojs/result'
274
+
275
+ export declare const NeoPixel: {
276
+ prototype: NeoPixel
277
+ new (pin: number, numLeds: number, bytesPerLed: number): NeoPixel
278
+ }
279
+
280
+ export interface NeoPixel {
281
+ setPixel(index: number, r: number, g: number, b: number, w: number): Result<void, NeoPixelError>
282
+ fill(r: number, g: number, b: number, w: number): Result<void, NeoPixelError>
283
+ show(): Result<void, NeoPixelError>
284
+ clear(): Result<void, NeoPixelError>
285
+ end(): Result<void, NeoPixelError>
286
+ }
287
+ }
288
+
289
+ declare module 'native:uart' {
290
+ import type {UartError} from '@mikrojs/native/runtime/uart/types'
291
+ import type {Result} from 'mikrojs/result'
292
+
293
+ export interface UartOptions {
294
+ tx?: number
295
+ rx?: number
296
+ baudRate: number
297
+ }
298
+
299
+ export declare const Uart: {
300
+ prototype: Uart
301
+ new (port: number, options: UartOptions): Uart
302
+ }
303
+
304
+ export interface Uart {
305
+ begin(): Result<void, UartError>
306
+
307
+ end(): Result<void, UartError>
308
+
309
+ write(data: Uint8Array): Result<void, UartError>
310
+
311
+ read(): Result<
312
+ {
313
+ next(): Promise<IteratorResult<Uint8Array>>
314
+ return(): Promise<IteratorResult<Uint8Array>>
315
+ },
316
+ UartError
317
+ >
318
+ }
319
+ }
320
+
321
+ declare module 'native:ble' {
322
+ import type {BleError} from '@mikrojs/native/runtime/ble/types'
323
+ import type {Result} from 'mikrojs/result'
324
+
325
+ type R<T> = Result<T, BleError>
326
+
327
+ export interface CharacteristicNative {
328
+ uuid: string
329
+ properties: number // bitmask
330
+ value?: Uint8Array
331
+ onWrite?: (value: Uint8Array) => void
332
+ writeMode?: string
333
+ security?: string
334
+ }
335
+
336
+ export interface ServiceNative {
337
+ uuid: string
338
+ characteristics: CharacteristicNative[]
339
+ }
340
+
341
+ export interface AdvertiseOptionsNative {
342
+ name?: string
343
+ connectable?: boolean
344
+ services?: ServiceNative[]
345
+ interval?: {min: number; max: number}
346
+ includeTxPower?: boolean
347
+ manufacturerData?: Uint8Array
348
+ }
349
+
350
+ export interface Ble {
351
+ getName(): string
352
+ setName(name: string): R<void>
353
+ getAddress(): R<string>
354
+
355
+ getTxPower(): R<number>
356
+ setTxPower(dbm: number): R<void>
357
+
358
+ advertise(options: AdvertiseOptionsNative): R<void>
359
+ stopAdvertising(): R<void>
360
+ stop(): R<void>
361
+
362
+ setValue(serviceUuid: string, characteristicUuid: string, value: Uint8Array): R<void>
363
+ notify(serviceUuid: string, characteristicUuid: string, value: Uint8Array): R<void>
364
+
365
+ on(event: string, listener: (...args: unknown[]) => void): void
366
+ off(event: string, listener: (...args: unknown[]) => void): void
367
+ }
368
+
369
+ export declare const Ble: {
370
+ prototype: Ble
371
+ new (): Ble
372
+ }
373
+ }
374
+
375
+ declare module 'native:wifi' {
376
+ import type {WifiError} from '@mikrojs/native/runtime/wifi/types'
377
+ import type {Result} from 'mikrojs/result'
378
+
379
+ type R<T> = Result<T, WifiError>
380
+
381
+ export interface Wifi {
382
+ connect(
383
+ ssid: string,
384
+ passphrase: string,
385
+ ): R<Promise<R<{ip: string; netmask: string; gateway: string}>>>
386
+ disconnect(): R<void>
387
+ rssi(): R<number>
388
+ ip(): string
389
+ status(): number
390
+ scan(opts?: {ssid?: string; channel?: number; passive?: boolean}): R<
391
+ Promise<
392
+ R<
393
+ {
394
+ ssid: string
395
+ bssid: string
396
+ channel: number
397
+ rssi: number
398
+ authMode: string
399
+ hidden: boolean
400
+ }[]
401
+ >
402
+ >
403
+ >
404
+ on(event: string, listener: (...args: unknown[]) => void): void
405
+ off(event: string, listener: (...args: unknown[]) => void): void
406
+
407
+ // Network config
408
+ mac(): R<string>
409
+ getHostname(): string | undefined
410
+ setHostname(hostname: string): R<void>
411
+ getIpConfig(): R<{ip: string; netmask: string; gateway: string; dns: string} | undefined>
412
+ setIpConfig(opts: {
413
+ ip?: string
414
+ netmask?: string
415
+ gateway?: string
416
+ dns?: string
417
+ dhcp?: boolean
418
+ }): R<void>
419
+
420
+ // AP mode
421
+ apStart(opts: {
422
+ ssid: string
423
+ passphrase?: string
424
+ authMode?: string
425
+ channel?: number
426
+ hidden?: boolean
427
+ maxConnections?: number
428
+ }): R<void>
429
+ apStop(): R<void>
430
+ apIsActive(): boolean
431
+ apIp(): string | undefined
432
+ apStations(): {mac: string; rssi: number}[]
433
+
434
+ // TX power & RSSI threshold
435
+ getTxPower(): R<number>
436
+ setTxPower(dbm: number): R<void>
437
+ getRssiThreshold(): number
438
+ setRssiThreshold(threshold: number): R<void>
439
+
440
+ // AP extras
441
+ apDeauthStation(mac: string): R<void>
442
+ apGetInactiveTimeout(): R<number>
443
+ apSetInactiveTimeout(seconds: number): R<void>
444
+
445
+ // Power management & misc
446
+ getPowerSave(): string
447
+ setPowerSave(mode: string): R<void>
448
+ getCountry(): string | undefined
449
+ setCountry(cc: string): R<void>
450
+ }
451
+
452
+ export declare const Wifi: {
453
+ prototype: Wifi
454
+ new (): Wifi
455
+ }
456
+ }
@@ -0,0 +1,17 @@
1
+ import {KVError, makeCreateValue} from 'mikrojs/kv/shared'
2
+ import {clear, get, info, remove, set} from 'native:nvs_kv'
3
+
4
+ import type {NvsStorage} from './types.js'
5
+
6
+ // Loaded in isolation: this file avoids `native:rtc`, so apps importing
7
+ // `mikrojs/kv/nvs` directly don't pay for the RTC backend. `KVError` and
8
+ // `makeCreateValue` come from the shared bytecode module at runtime so
9
+ // they aren't duplicated across nvs.js and rtc.js.
10
+
11
+ export {KVError}
12
+
13
+ export const nvsStorage = {
14
+ createValue: makeCreateValue({get, set, remove, clear, info}),
15
+ clear,
16
+ info,
17
+ } as NvsStorage
@@ -0,0 +1,17 @@
1
+ import {KVError, makeCreateValue} from 'mikrojs/kv/shared'
2
+ import {clear, get, info, remove, set} from 'native:rtc'
3
+
4
+ import type {RtcStorage} from './types.js'
5
+
6
+ // Loaded in isolation: this file avoids `native:nvs_kv`, so apps importing
7
+ // `mikrojs/kv/rtc` directly don't pay for the NVS backend. `KVError` and
8
+ // `makeCreateValue` come from the shared bytecode module at runtime so
9
+ // they aren't duplicated across nvs.js and rtc.js.
10
+
11
+ export {KVError}
12
+
13
+ export const rtcStorage = {
14
+ createValue: makeCreateValue({get, set, remove, clear, info}),
15
+ clear,
16
+ info,
17
+ } as RtcStorage
@@ -0,0 +1,107 @@
1
+ import {defineError, err, ok} from 'mikrojs/result'
2
+ // Typed loosely to avoid deep type instantiation from Infer<S> in parse's generics.
3
+ // Type safety is provided by the storage interface overloads in types.ts.
4
+ import {parse as _parse} from 'mikrojs/schema'
5
+
6
+ import type {NativeError} from '../result/types.js'
7
+
8
+ type ParseResult = {ok: true; value: unknown} | {ok: false; error: {message: string; path: string}}
9
+ const parse = _parse as unknown as (schema: unknown, value: unknown) => ParseResult
10
+
11
+ export const KVError = defineError('KVError', {
12
+ StorageFull: (message: string) => ({message}),
13
+ EncodeFailed: (message: string) => ({message}),
14
+ WriteFailed: (message: string) => ({message}),
15
+ ValidationFailed: (message: string, path: string) => ({message, path}),
16
+ })
17
+
18
+ /* Error codes from errors.h (MIK_ERR_BASE + 0xD0..0xD4) */
19
+ const KV_INVALID_KEY = 0x80d0
20
+ const KV_ENCODE = 0x80d1
21
+ const KV_TOO_LARGE = 0x80d2
22
+ const KV_STORAGE_FULL = 0x80d3
23
+ const KV_WRITE = 0x80d4
24
+
25
+ type NativeResult = {ok: true} | {ok: false; error: NativeError}
26
+
27
+ export type NativeKvFns = {
28
+ get: (key: string) => unknown
29
+ set: (key: string, value: unknown) => NativeResult
30
+ remove: (key: string) => boolean
31
+ clear: () => void
32
+ info: () => unknown
33
+ }
34
+
35
+ function mapKvError(e: NativeError) {
36
+ switch (e.code) {
37
+ case KV_STORAGE_FULL:
38
+ case KV_TOO_LARGE:
39
+ return KVError.StorageFull(e.message)
40
+ case KV_ENCODE:
41
+ case KV_INVALID_KEY:
42
+ return KVError.EncodeFailed(e.message)
43
+ case KV_WRITE:
44
+ return KVError.WriteFailed(e.message)
45
+ default:
46
+ throw new Error(`unexpected native kv error: code=0x${e.code.toString(16)}`)
47
+ }
48
+ }
49
+
50
+ export function makeCreateValue(native: NativeKvFns) {
51
+ return function createValue(key: string, options?: any): any {
52
+ const schema = options?.schema
53
+ const initialValue = options?.initialValue
54
+ const hasInitialValue = options !== undefined && 'initialValue' in options
55
+ const onReadError = options?.onReadError ?? (() => undefined)
56
+
57
+ function doGet(): unknown {
58
+ try {
59
+ const v = native.get(key)
60
+ if (v === undefined) return hasInitialValue ? initialValue : undefined
61
+ if (schema) {
62
+ const result = parse(schema, v)
63
+ if (!result.ok) {
64
+ // Schema mismatch: data decoded fine, don't delete it
65
+ return onReadError(result.error)
66
+ }
67
+ return result.value
68
+ }
69
+ return v
70
+ } catch (e) {
71
+ // Decode failure: corrupt data, delete it
72
+ native.remove(key)
73
+ const fallback = onReadError(e)
74
+ if (fallback !== undefined) native.set(key, fallback)
75
+ return fallback
76
+ }
77
+ }
78
+
79
+ function doSet(value: unknown) {
80
+ if (value === undefined) {
81
+ native.remove(key)
82
+ return ok(undefined)
83
+ }
84
+ if (schema) {
85
+ const result = parse(schema, value)
86
+ if (!result.ok) {
87
+ return err(KVError.ValidationFailed(result.error.message, result.error.path))
88
+ }
89
+ }
90
+ const result = native.set(key, value)
91
+ if (!result.ok) return err(mapKvError(result.error))
92
+ return ok(value)
93
+ }
94
+
95
+ return {
96
+ get: doGet,
97
+ set: doSet,
98
+ update(updater: (value: any) => any) {
99
+ return doSet(updater(doGet()))
100
+ },
101
+ delete() {
102
+ const removed = native.remove(key)
103
+ return removed ? ok() : err(KVError.WriteFailed(`failed to delete key "${key}"`))
104
+ },
105
+ }
106
+ }
107
+ }