@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,60 @@
1
+ export declare class PanicError extends Error {
2
+ constructor(message: string, options?: {cause?: unknown})
3
+ }
4
+
5
+ export interface OkResult<T> {
6
+ readonly ok: true
7
+ readonly value: T
8
+ readonly error?: never
9
+ map<U>(fn: (value: T) => U): OkResult<U>
10
+ mapErr<F>(fn: (error: never) => F): OkResult<T>
11
+ andThen<U, F>(fn: (value: T) => Result<U, F>): Result<U, F>
12
+ match<A, B>(handlers: {ok: (value: T) => A; err: (error: never) => B}): A
13
+ /** Get the value, or return the default if this is an Err. */
14
+ orDefault<D>(defaultValue: D): T | D
15
+ /** Get the value, or panic with the given message if this is an Err. */
16
+ orPanic(message: string): T
17
+ }
18
+
19
+ export interface ErrResult<E> {
20
+ readonly ok: false
21
+ readonly value?: never
22
+ readonly error: E
23
+ map<U>(fn: (value: never) => U): ErrResult<E>
24
+ mapErr<F>(fn: (error: E) => F): ErrResult<F>
25
+ andThen<U, F>(fn: (value: never) => Result<U, F>): ErrResult<E>
26
+ match<A, B>(handlers: {ok: (value: never) => A; err: (error: E) => B}): B
27
+ /** Return the default value since this is an Err. */
28
+ orDefault<D>(defaultValue: D): D
29
+ /** Always panics with the given message since this is an Err. The error is included as cause. */
30
+ orPanic(message: string): never
31
+ }
32
+
33
+ export type Result<T, E> = OkResult<T> | ErrResult<E>
34
+
35
+ export declare function ok(): OkResult<void>
36
+ export declare function ok<T>(value: T): OkResult<T>
37
+
38
+ export declare function err<E>(error: E): ErrResult<E>
39
+
40
+ type VariantDef = Record<string, (...args: any[]) => Record<string, unknown>>
41
+
42
+ type ErrorConstructors<D extends VariantDef> = {
43
+ [K in keyof D & string]: (...args: Parameters<D[K]>) => {name: K} & ReturnType<D[K]>
44
+ }
45
+
46
+ export type ErrorOf<T extends Record<string, (...args: any[]) => any>> = {
47
+ [K in keyof T & string]: ReturnType<T[K]>
48
+ }[keyof T & string]
49
+
50
+ export declare function defineError<D extends VariantDef>(
51
+ name: string,
52
+ variants: D,
53
+ ): ErrorConstructors<D>
54
+
55
+ /** Raw error shape returned by native mik__result_err(). */
56
+ export interface NativeError {
57
+ readonly code: number
58
+ readonly message: string
59
+ readonly errno?: number
60
+ }
@@ -0,0 +1,321 @@
1
+ import {defineError, err, ok} from 'mikrojs/result'
2
+
3
+ import type {Result} from '../result/types.js'
4
+
5
+ export const SchemaError = defineError('SchemaError', {
6
+ ValidationFailed: (message: string, path: string) => ({message, path}),
7
+ })
8
+ export type SchemaError = ReturnType<typeof SchemaError.ValidationFailed>
9
+
10
+ // ── Schema types ────────────────────────────────────────────────────
11
+
12
+ type Primitive = string | number | boolean
13
+
14
+ export interface StringSchema {
15
+ readonly kind: 'string'
16
+ }
17
+
18
+ export interface NumberSchema {
19
+ readonly kind: 'number'
20
+ }
21
+
22
+ export interface BooleanSchema {
23
+ readonly kind: 'boolean'
24
+ }
25
+
26
+ export interface UnknownSchema {
27
+ readonly kind: 'unknown'
28
+ }
29
+
30
+ export interface LiteralSchema<T extends Primitive = Primitive> {
31
+ readonly kind: 'literal'
32
+ readonly value: T
33
+ }
34
+
35
+ export interface ArraySchema<S extends Schema = Schema> {
36
+ readonly kind: 'array'
37
+ readonly element: S
38
+ }
39
+
40
+ export interface ObjectSchema<Shape extends Record<string, Schema> = Record<string, Schema>> {
41
+ readonly kind: 'object'
42
+ readonly shape: Shape
43
+ }
44
+
45
+ export interface OptionalSchema<S extends Schema = Schema> {
46
+ readonly kind: 'optional'
47
+ readonly inner: S
48
+ }
49
+
50
+ export interface TupleSchema<Elements extends readonly Schema[] = readonly Schema[]> {
51
+ readonly kind: 'tuple'
52
+ readonly elements: Elements
53
+ }
54
+
55
+ export interface UnionSchema<Members extends readonly Schema[] = readonly Schema[]> {
56
+ readonly kind: 'union'
57
+ readonly members: Members
58
+ }
59
+
60
+ export interface TaggedUnionSchema<
61
+ Key extends string = string,
62
+ Branches extends Record<string, ObjectSchema> = Record<string, ObjectSchema>,
63
+ > {
64
+ readonly kind: 'taggedUnion'
65
+ readonly key: Key
66
+ readonly branches: Branches
67
+ }
68
+
69
+ export type Schema =
70
+ | StringSchema
71
+ | NumberSchema
72
+ | BooleanSchema
73
+ | UnknownSchema
74
+ | LiteralSchema
75
+ | ArraySchema
76
+ | ObjectSchema
77
+ | OptionalSchema
78
+ | TupleSchema
79
+ | UnionSchema
80
+ | TaggedUnionSchema
81
+
82
+ // ── Type inference ──────────────────────────────────────────────────
83
+
84
+ type Simplify<T> = {[K in keyof T]: T[K]} & {}
85
+
86
+ export type Infer<S> = S extends StringSchema
87
+ ? string
88
+ : S extends NumberSchema
89
+ ? number
90
+ : S extends BooleanSchema
91
+ ? boolean
92
+ : S extends UnknownSchema
93
+ ? unknown
94
+ : S extends LiteralSchema<infer T>
95
+ ? T
96
+ : S extends ArraySchema<infer E>
97
+ ? Infer<E>[]
98
+ : S extends ObjectSchema<infer Shape>
99
+ ? Simplify<InferObject<Shape>>
100
+ : S extends TupleSchema<infer Elements>
101
+ ? InferTuple<Elements>
102
+ : S extends OptionalSchema<infer Inner>
103
+ ? Infer<Inner> | undefined
104
+ : S extends UnionSchema<infer Members>
105
+ ? InferUnion<Members>
106
+ : S extends TaggedUnionSchema<infer Key, infer Branches>
107
+ ? InferTaggedUnion<Key, Branches>
108
+ : never
109
+
110
+ type InferObject<Shape> = {
111
+ [K in keyof Shape as Shape[K] extends OptionalSchema ? never : K]: Infer<Shape[K]>
112
+ } & {
113
+ [K in keyof Shape as Shape[K] extends OptionalSchema ? K : never]?: Infer<Shape[K]>
114
+ }
115
+
116
+ type InferTuple<Elements> = Elements extends readonly [infer Head, ...infer Tail]
117
+ ? [Infer<Head>, ...InferTuple<Tail>]
118
+ : []
119
+
120
+ type InferUnion<Members> = Members extends readonly [infer Head, ...infer Tail]
121
+ ? Infer<Head> | InferUnion<Tail>
122
+ : never
123
+
124
+ type InferTaggedUnion<Key extends string, Branches> = {
125
+ [Tag in keyof Branches & string]: {[K in Key]: Tag} & Infer<Branches[Tag]>
126
+ }[keyof Branches & string]
127
+
128
+ // ── Schema constructors ─────────────────────────────────────────────
129
+
130
+ export function string(): StringSchema {
131
+ return {kind: 'string'}
132
+ }
133
+
134
+ export function number(): NumberSchema {
135
+ return {kind: 'number'}
136
+ }
137
+
138
+ export function boolean(): BooleanSchema {
139
+ return {kind: 'boolean'}
140
+ }
141
+
142
+ export function unknown(): UnknownSchema {
143
+ return {kind: 'unknown'}
144
+ }
145
+
146
+ export function literal<T extends Primitive>(value: T): LiteralSchema<T> {
147
+ return {kind: 'literal', value}
148
+ }
149
+
150
+ export function array<S extends Schema>(element: S): ArraySchema<S> {
151
+ return {kind: 'array', element}
152
+ }
153
+
154
+ export function object<Shape extends Record<string, Schema>>(shape: Shape): ObjectSchema<Shape> {
155
+ return {kind: 'object', shape}
156
+ }
157
+
158
+ export function tuple<Elements extends readonly Schema[]>(
159
+ elements: [...Elements],
160
+ ): TupleSchema<Elements> {
161
+ return {kind: 'tuple', elements}
162
+ }
163
+
164
+ export function optional<S extends Schema>(inner: S): OptionalSchema<S> {
165
+ return {kind: 'optional', inner}
166
+ }
167
+
168
+ export function union<Members extends readonly Schema[]>(
169
+ members: [...Members],
170
+ ): UnionSchema<Members> {
171
+ return {kind: 'union', members}
172
+ }
173
+
174
+ export function taggedUnion<Key extends string, Branches extends Record<string, ObjectSchema>>(
175
+ key: Key,
176
+ branches: Branches,
177
+ ): TaggedUnionSchema<Key, Branches> {
178
+ return {kind: 'taggedUnion', key, branches}
179
+ }
180
+
181
+ // ── Parse ───────────────────────────────────────────────────────────
182
+
183
+ export function parse<S extends Schema>(schema: S, value: unknown): Result<Infer<S>, SchemaError> {
184
+ const result = validate(schema, value, '')
185
+ if (result !== null) return result as Result<Infer<S>, SchemaError>
186
+ return ok(value as Infer<S>)
187
+ }
188
+
189
+ function typeOf(value: unknown): string {
190
+ if (value === null) return 'null'
191
+ if (Array.isArray(value)) return 'array'
192
+ return typeof value
193
+ }
194
+
195
+ function validate(
196
+ schema: Schema,
197
+ value: unknown,
198
+ path: string,
199
+ ): ReturnType<typeof err<SchemaError>> | null {
200
+ switch (schema.kind) {
201
+ case 'string':
202
+ if (typeof value !== 'string')
203
+ return err(SchemaError.ValidationFailed(`expected string, got ${typeOf(value)}`, path))
204
+ return null
205
+
206
+ case 'number':
207
+ if (typeof value !== 'number' || Number.isNaN(value))
208
+ return err(SchemaError.ValidationFailed(`expected number, got ${typeOf(value)}`, path))
209
+ return null
210
+
211
+ case 'boolean':
212
+ if (typeof value !== 'boolean')
213
+ return err(SchemaError.ValidationFailed(`expected boolean, got ${typeOf(value)}`, path))
214
+ return null
215
+
216
+ case 'unknown':
217
+ return null
218
+
219
+ case 'literal':
220
+ if (value !== schema.value)
221
+ return err(
222
+ SchemaError.ValidationFailed(
223
+ `expected ${JSON.stringify(schema.value)}, got ${JSON.stringify(value)}`,
224
+ path,
225
+ ),
226
+ )
227
+ return null
228
+
229
+ case 'array': {
230
+ if (!Array.isArray(value))
231
+ return err(SchemaError.ValidationFailed(`expected array, got ${typeOf(value)}`, path))
232
+ for (let i = 0; i < value.length; i++) {
233
+ const result = validate(schema.element, value[i], `${path}[${i}]`)
234
+ if (result !== null) return result
235
+ }
236
+ return null
237
+ }
238
+
239
+ case 'object': {
240
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
241
+ return err(SchemaError.ValidationFailed(`expected object, got ${typeOf(value)}`, path))
242
+ const obj = value as Record<string, unknown>
243
+ const keys = Object.keys(schema.shape)
244
+ for (let i = 0; i < keys.length; i++) {
245
+ const key = keys[i]!
246
+ const fieldSchema = schema.shape[key]!
247
+ const fieldPath = `${path}.${key}`
248
+ if (fieldSchema.kind === 'optional') {
249
+ if (key in obj) {
250
+ const result = validate(fieldSchema, obj[key], fieldPath)
251
+ if (result !== null) return result
252
+ }
253
+ } else {
254
+ if (!(key in obj))
255
+ return err(SchemaError.ValidationFailed(`missing required field`, fieldPath))
256
+ const result = validate(fieldSchema, obj[key], fieldPath)
257
+ if (result !== null) return result
258
+ }
259
+ }
260
+ return null
261
+ }
262
+
263
+ case 'tuple': {
264
+ if (!Array.isArray(value))
265
+ return err(SchemaError.ValidationFailed(`expected array, got ${typeOf(value)}`, path))
266
+ if (value.length !== schema.elements.length)
267
+ return err(
268
+ SchemaError.ValidationFailed(
269
+ `expected ${schema.elements.length} elements, got ${value.length}`,
270
+ path,
271
+ ),
272
+ )
273
+ for (let i = 0; i < schema.elements.length; i++) {
274
+ const result = validate(schema.elements[i]!, value[i], `${path}[${i}]`)
275
+ if (result !== null) return result
276
+ }
277
+ return null
278
+ }
279
+
280
+ case 'optional': {
281
+ if (value === undefined) return null
282
+ return validate(schema.inner, value, path)
283
+ }
284
+
285
+ case 'union': {
286
+ for (let i = 0; i < schema.members.length; i++) {
287
+ const result = validate(schema.members[i]!, value, path)
288
+ if (result === null) return null
289
+ }
290
+ return err(SchemaError.ValidationFailed(`value did not match any union member`, path))
291
+ }
292
+
293
+ case 'taggedUnion': {
294
+ if (typeof value !== 'object' || value === null || Array.isArray(value))
295
+ return err(SchemaError.ValidationFailed(`expected object, got ${typeOf(value)}`, path))
296
+ const obj = value as Record<string, unknown>
297
+ const tag = obj[schema.key]
298
+ if (tag === undefined)
299
+ return err(
300
+ SchemaError.ValidationFailed(`missing discriminator field`, `${path}.${schema.key}`),
301
+ )
302
+ if (typeof tag !== 'string' && typeof tag !== 'number' && typeof tag !== 'boolean')
303
+ return err(
304
+ SchemaError.ValidationFailed(
305
+ `expected primitive discriminator, got ${typeOf(tag)}`,
306
+ `${path}.${schema.key}`,
307
+ ),
308
+ )
309
+ const branch = schema.branches[tag as string]
310
+ if (branch === undefined)
311
+ return err(
312
+ SchemaError.ValidationFailed(
313
+ `unknown tag ${JSON.stringify(tag)}`,
314
+ `${path}.${schema.key}`,
315
+ ),
316
+ )
317
+ return validate(branch, value, path)
318
+ }
319
+ }
320
+ return err(SchemaError.ValidationFailed(`unknown schema kind: ${(schema as any).kind}`, path))
321
+ }
@@ -0,0 +1,152 @@
1
+ import type {Result} from '../result/types.js'
2
+
3
+ type Primitive = string | number | boolean
4
+
5
+ export interface StringSchema {
6
+ readonly kind: 'string'
7
+ }
8
+
9
+ export interface NumberSchema {
10
+ readonly kind: 'number'
11
+ }
12
+
13
+ export interface BooleanSchema {
14
+ readonly kind: 'boolean'
15
+ }
16
+
17
+ export interface UnknownSchema {
18
+ readonly kind: 'unknown'
19
+ }
20
+
21
+ export interface LiteralSchema<T extends Primitive = Primitive> {
22
+ readonly kind: 'literal'
23
+ readonly value: T
24
+ }
25
+
26
+ export interface ArraySchema<S extends Schema = Schema> {
27
+ readonly kind: 'array'
28
+ readonly element: S
29
+ }
30
+
31
+ export interface ObjectSchema<Shape extends Record<string, Schema> = Record<string, Schema>> {
32
+ readonly kind: 'object'
33
+ readonly shape: Shape
34
+ }
35
+
36
+ export interface OptionalSchema<S extends Schema = Schema> {
37
+ readonly kind: 'optional'
38
+ readonly inner: S
39
+ }
40
+
41
+ export interface TupleSchema<Elements extends readonly Schema[] = readonly Schema[]> {
42
+ readonly kind: 'tuple'
43
+ readonly elements: Elements
44
+ }
45
+
46
+ export interface UnionSchema<Members extends readonly Schema[] = readonly Schema[]> {
47
+ readonly kind: 'union'
48
+ readonly members: Members
49
+ }
50
+
51
+ export interface TaggedUnionSchema<
52
+ Key extends string = string,
53
+ Branches extends Record<string, ObjectSchema> = Record<string, ObjectSchema>,
54
+ > {
55
+ readonly kind: 'taggedUnion'
56
+ readonly key: Key
57
+ readonly branches: Branches
58
+ }
59
+
60
+ export type Schema =
61
+ | StringSchema
62
+ | NumberSchema
63
+ | BooleanSchema
64
+ | UnknownSchema
65
+ | LiteralSchema
66
+ | ArraySchema
67
+ | ObjectSchema
68
+ | OptionalSchema
69
+ | TupleSchema
70
+ | UnionSchema
71
+ | TaggedUnionSchema
72
+
73
+ type Simplify<T> = {[K in keyof T]: T[K]} & {}
74
+
75
+ export type Infer<S> = S extends StringSchema
76
+ ? string
77
+ : S extends NumberSchema
78
+ ? number
79
+ : S extends BooleanSchema
80
+ ? boolean
81
+ : S extends UnknownSchema
82
+ ? unknown
83
+ : S extends LiteralSchema<infer T>
84
+ ? T
85
+ : S extends ArraySchema<infer E>
86
+ ? ArraySchema extends S
87
+ ? []
88
+ : Infer<E>[]
89
+ : S extends ObjectSchema<infer Shape>
90
+ ? ObjectSchema extends S
91
+ ? object
92
+ : Simplify<InferObject<Shape>>
93
+ : S extends TupleSchema<infer Elements>
94
+ ? InferTuple<Elements>
95
+ : S extends OptionalSchema<infer Inner>
96
+ ? OptionalSchema extends S
97
+ ? OptionalSchema
98
+ : Infer<Inner> | undefined
99
+ : S extends UnionSchema<infer Members>
100
+ ? InferUnion<Members>
101
+ : S extends TaggedUnionSchema<infer Key, infer Branches>
102
+ ? InferTaggedUnion<Key, Branches>
103
+ : never
104
+
105
+ type InferObject<Shape> = {
106
+ [K in keyof Shape as Shape[K] extends OptionalSchema ? never : K]: Infer<Shape[K]>
107
+ } & {
108
+ [K in keyof Shape as Shape[K] extends OptionalSchema ? K : never]?: Infer<Shape[K]>
109
+ }
110
+
111
+ type InferTuple<Elements> = Elements extends readonly [infer Head, ...infer Tail]
112
+ ? [Infer<Head>, ...InferTuple<Tail>]
113
+ : []
114
+
115
+ type InferUnion<Members> = Members extends readonly [infer Head, ...infer Tail]
116
+ ? Infer<Head> | InferUnion<Tail>
117
+ : never
118
+
119
+ type InferTaggedUnion<Key extends string, Branches> = {
120
+ [Tag in keyof Branches & string]: {[K in Key]: Tag} & Infer<Branches[Tag]>
121
+ }[keyof Branches & string]
122
+
123
+ export type SchemaError = {name: 'ValidationFailed'; message: string; path: string}
124
+
125
+ export declare function string(): StringSchema
126
+ export declare function number(): NumberSchema
127
+ export declare function boolean(): BooleanSchema
128
+ export declare function unknown(): UnknownSchema
129
+ export declare function literal<T extends Primitive>(value: T): LiteralSchema<T>
130
+ export declare function array<S extends Schema>(element: S): ArraySchema<S>
131
+ export declare function object<Shape extends Record<string, Schema>>(
132
+ shape: Shape,
133
+ ): ObjectSchema<Shape>
134
+ export declare function tuple<Elements extends readonly Schema[]>(
135
+ elements: [...Elements],
136
+ ): TupleSchema<Elements>
137
+ export declare function optional<S extends Schema>(inner: S): OptionalSchema<S>
138
+ export declare function union<Members extends readonly Schema[]>(
139
+ members: [...Members],
140
+ ): UnionSchema<Members>
141
+ export declare function taggedUnion<
142
+ Key extends string,
143
+ Branches extends Record<string, ObjectSchema>,
144
+ >(key: Key, branches: Branches): TaggedUnionSchema<Key, Branches>
145
+ export declare function parse<S extends Schema>(
146
+ schema: S,
147
+ value: unknown,
148
+ ): Result<Infer<S>, SchemaError>
149
+
150
+ export declare const SchemaError: {
151
+ ValidationFailed: (message: string, path: string) => SchemaError
152
+ }
@@ -0,0 +1,14 @@
1
+ export {
2
+ deepSleep,
3
+ disableWakeupSource,
4
+ enableExt0Wakeup,
5
+ enableExt1Wakeup,
6
+ enableGpioWakeup,
7
+ enableTimerWakeup,
8
+ getWakeupCause,
9
+ lightSleep,
10
+ } from 'native:sleep'
11
+
12
+ export function sleep(ms: number): Promise<void> {
13
+ return new Promise((resolve) => setTimeout(resolve, ms))
14
+ }
@@ -0,0 +1,44 @@
1
+ import type {Result} from '../result/types.js'
2
+
3
+ export type SleepError =
4
+ | {name: 'WakeupConfigFailed'; message: string}
5
+ | {name: 'LightSleepFailed'; message: string}
6
+ | {name: 'DisableWakeupFailed'; message: string}
7
+
8
+ export declare function deepSleep(time: number): never
9
+
10
+ export declare function lightSleep(time: number): Result<void, SleepError>
11
+
12
+ export declare function getWakeupCause(): string
13
+
14
+ /** Configure timer wakeup source (microseconds). */
15
+ export declare function enableTimerWakeup(us: number): Result<void, SleepError>
16
+
17
+ /**
18
+ * Configure GPIO wakeup for light sleep.
19
+ * @param pin GPIO pin number
20
+ * @param level GPIO interrupt type (e.g. 4 = low, 5 = high)
21
+ */
22
+ export declare function enableGpioWakeup(pin: number, level: number): Result<void, SleepError>
23
+
24
+ /**
25
+ * Configure ext0 wakeup for deep sleep (ESP32, ESP32-S2, ESP32-S3 only).
26
+ * @param pin RTC GPIO pin number
27
+ * @param level 0 = low, 1 = high
28
+ */
29
+ export declare function enableExt0Wakeup(pin: number, level: number): Result<void, SleepError>
30
+
31
+ /**
32
+ * Configure ext1 wakeup for deep sleep.
33
+ * @param pinMask Bitmask of RTC GPIO pins
34
+ * @param mode 0 = ESP_EXT1_WAKEUP_ALL_LOW, 1 = ESP_EXT1_WAKEUP_ANY_HIGH
35
+ */
36
+ export declare function enableExt1Wakeup(pinMask: number, mode: number): Result<void, SleepError>
37
+
38
+ /**
39
+ * Disable a wakeup source. If no source is specified, all sources are disabled.
40
+ * @param source Optional: "timer", "ext0", "ext1", "gpio", "touchpad", "ulp"
41
+ */
42
+ export declare function disableWakeupSource(source?: string): Result<void, SleepError>
43
+
44
+ export declare function sleep(ms: number): Promise<void>
@@ -0,0 +1,54 @@
1
+ import {err, ok} from 'mikrojs/result'
2
+ import {setTimezone, stop as nativeStop, sync as nativeSync} from 'native:sntp'
3
+
4
+ import type {Result} from '../result/types.js'
5
+ import type {Sntp, SntpError, SntpOptions, SntpSyncResult, SntpSyncResultWithStop} from './types.js'
6
+
7
+ // native:sntp emits `InitFailed` / `Cancelled` directly; `Timeout` is a
8
+ // JS-side variant (the Promise racer below owns the clock).
9
+
10
+ const DEFAULT_SERVERS = ['pool.ntp.org']
11
+ const DEFAULT_TIMEZONE = 'UTC0'
12
+ const DEFAULT_TIMEOUT = 60_000
13
+
14
+ function sync(
15
+ options: SntpOptions & {background: true},
16
+ ): Promise<Result<SntpSyncResultWithStop, SntpError>>
17
+ function sync(
18
+ options?: SntpOptions & {background?: false},
19
+ ): Promise<Result<SntpSyncResult, SntpError>>
20
+ function sync(
21
+ options?: SntpOptions & {background?: boolean},
22
+ ): Promise<Result<SntpSyncResult | SntpSyncResultWithStop, SntpError>> {
23
+ const servers = options?.servers ?? DEFAULT_SERVERS
24
+ const timezone = options?.timezone ?? DEFAULT_TIMEZONE
25
+ const background = options?.background ?? false
26
+ const timeout = options?.timeout ?? DEFAULT_TIMEOUT
27
+
28
+ const startResult = nativeSync(servers, timezone, background)
29
+ if (!startResult.ok) return Promise.resolve(startResult)
30
+
31
+ return new Promise((resolve) => {
32
+ const timer = setTimeout(() => {
33
+ nativeStop()
34
+ resolve(err({name: 'Timeout' as const, ms: timeout}))
35
+ }, timeout)
36
+
37
+ void startResult.value.then((asyncResult) => {
38
+ clearTimeout(timer)
39
+ if (!asyncResult.ok) {
40
+ resolve(asyncResult)
41
+ return
42
+ }
43
+ const result: SntpSyncResult = {time: new Date(asyncResult.value.time)}
44
+ if (background) {
45
+ ;(result as SntpSyncResultWithStop).stop = () => nativeStop()
46
+ }
47
+ resolve(ok(result))
48
+ })
49
+ })
50
+ }
51
+
52
+ const sntp: Sntp = {sync, setTimezone}
53
+
54
+ export {sntp}
@@ -0,0 +1,38 @@
1
+ import type {Result} from '../result/types.js'
2
+
3
+ export interface SntpOptions {
4
+ /** NTP server(s). Default: ['pool.ntp.org'] */
5
+ servers?: string[]
6
+ /** POSIX TZ string, e.g. 'CET-1CEST,M3.5.0,M10.5.0/3'. Default: 'UTC0' */
7
+ timezone?: string
8
+ /** Milliseconds before timeout. Default: 60000 */
9
+ timeout?: number
10
+ }
11
+
12
+ export interface SntpSyncResult {
13
+ time: Date
14
+ }
15
+
16
+ export interface SntpSyncResultWithStop extends SntpSyncResult {
17
+ stop: () => void
18
+ }
19
+
20
+ export type SntpError =
21
+ | {name: 'InitFailed'; message: string}
22
+ | {name: 'Timeout'; ms: number}
23
+ | {name: 'Cancelled'}
24
+
25
+ export interface Sntp {
26
+ sync(
27
+ options: SntpOptions & {background: true},
28
+ ): Promise<Result<SntpSyncResultWithStop, SntpError>>
29
+ sync(options?: SntpOptions & {background?: false}): Promise<Result<SntpSyncResult, SntpError>>
30
+ sync(
31
+ options?: SntpOptions & {background?: boolean},
32
+ ): Promise<Result<SntpSyncResult | SntpSyncResultWithStop, SntpError>>
33
+
34
+ /** Set the POSIX timezone string independently of sync. */
35
+ setTimezone(tz: string): void
36
+ }
37
+
38
+ export declare const sntp: Sntp