@small-web/kitten-types 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.
package/types.d.ts ADDED
@@ -0,0 +1,596 @@
1
+ import EventEmitter from 'node:events'
2
+
3
+ export class Session extends EventEmitter {
4
+ id: string
5
+ authenticated: boolean
6
+ challenge: string
7
+ createdAt: Date
8
+ redirectToAfterSignIn?: string
9
+ hasExpired (): boolean
10
+ }
11
+
12
+ export type { default as WebSocket, BufferLike } from './ws/index.d.ts'
13
+ export type { default as slugify } from './slugify/index.d.ts'
14
+ export type { default as Polka } from './polka/index.d.ts'
15
+ export { default as MarkdownIt } from 'markdown-it'
16
+
17
+ export namespace yaml {
18
+ export function parse(str:string, reviver?:JavaScriptFunction, options?:{}): any
19
+ export function stringify(value:any, replacer?:JavaScriptFunction, options?:{}): string
20
+ }
21
+
22
+ /**
23
+ Upload class.
24
+ */
25
+
26
+ interface UploadConstructorParameters {
27
+ id: string,
28
+ fileName: string,
29
+ filePath: string,
30
+ mimetype: string,
31
+ field: string,
32
+ encoding: string,
33
+ truncated: boolean,
34
+ done: boolean
35
+ }
36
+
37
+ export class Upload {
38
+ constructor(parameters:UploadConstructorParameters)
39
+ resourcePath: string
40
+ downloadPath: string
41
+ delete(): Promise<void>
42
+ }
43
+
44
+ type BoundHandler<T> = (this: T) => void
45
+ type AsyncKittenHandler = (request:KittenRequest, response:KittenResponse, next:AsyncKittenHandler) => Promise<void>
46
+
47
+ /**
48
+ Abstract base class for lazily-loaded routes.
49
+ */
50
+ export class LazilyLoadedRoute {
51
+ filePath:string
52
+ basePath:string
53
+ extension:string
54
+ pattern:string
55
+ method: 'use' | 'get'
56
+
57
+ constructor(filePath:string, basePath:string)
58
+ get handler():BoundHandler<LazilyLoadedRoute>
59
+ lazilyLoadedhandler:AsyncKittenHandler
60
+ }
61
+
62
+ import type {default as WebSocket, BufferLike } from './ws/index.d.ts'
63
+
64
+ type WebSocketWithIsAlive = WebSocket & {isAlive:boolean}
65
+
66
+ /**
67
+ MessageSender class.
68
+
69
+ Provides a namespaced send() method for use in PageSocket.
70
+ */
71
+ export class MessageSender {
72
+ socket:WebSocketWithIsAlive
73
+ sockets: [WebSocketWithIsAlive]
74
+ includeSelf: boolean
75
+
76
+ constructor (parameterObject: {
77
+ socket: WebSocketWithIsAlive,
78
+ connections: [WebSocketWithIsAlive],
79
+ includeSelf: boolean
80
+ })
81
+
82
+ /**
83
+ Sends message either to all connections or to all connections excluding the current one (depending on value of `this.includeSelf`).
84
+
85
+ You can specify an optional swap target that intelligently wraps what you’re sending with the necessary envelope tag. This is normally rather confusing with htmx’s oob swaps, especially when inserting table rows.
86
+
87
+ See: https://htmx.org/attributes/hx-swap-oob/#using-alternate-swap-strategies
88
+ */
89
+ send (message: BufferLike, swapTarget?: {
90
+ before?: string,
91
+ after?: string,
92
+ asFirstChildOf?: string,
93
+ asLastChildOf?: string
94
+ }):void
95
+ }
96
+
97
+ /**
98
+ Kitten component class.
99
+ */
100
+
101
+ /**
102
+ This type definition required due to following shenanigans:
103
+ https://github.com/Microsoft/TypeScript/issues/20007#issuecomment-2255964704
104
+ */
105
+ type JavaScriptFunction = (...args: any[]) => any
106
+
107
+ type Constructor<T> = new (...args: any[]) => T
108
+
109
+ type BoundComponentRenderFunction<T extends KittenComponent> =
110
+ ((...args: Parameters<T['html']>) => Promise<Awaited<ReturnType<T['html']>>>)
111
+ & { boundObject: T }
112
+
113
+ export class Listener {
114
+ /**
115
+ Create EventEmitter listener.
116
+ */
117
+ constructor (target:EventEmitter, eventName:string, eventHandler:JavaScriptFunction)
118
+
119
+ /**
120
+ Remove this listener from its EventEmitter.
121
+ */
122
+ remove ():void
123
+ }
124
+
125
+ export class KittenComponent {
126
+ /**
127
+ Unique ID (crypto.uuid) of this component. You can overwrite it with your own if you like.
128
+ */
129
+ id: string
130
+
131
+ /**
132
+ Array of child components, if any. Instead of manipulating this directly, consider using the childrenOfType() method for operating on collections of components and the childOfType() method – or storing child component references as instance variables – for individual child components.
133
+ */
134
+ _children: Array<KittenComponent>
135
+
136
+ /**
137
+ Listeners this component has set up. There’s no reason to manipulate this directly. When you use the addEventHandler() method, Kitten handles the setup and tear-down of listeners for you automatically to avoid memory leaks.
138
+ */
139
+ _listeners: Array<Listener>
140
+
141
+ /**
142
+ Is this component attached to the live component hiearchy?
143
+ */
144
+ _isAttached: boolean
145
+
146
+ /**
147
+ Is the page this component is on connected to its client via WebSocket?
148
+ */
149
+ _isConnected: boolean
150
+
151
+ /**
152
+ Reference to page this component is attached to. Undefined if the page has not yet connected to the client.
153
+ */
154
+ protected get _page(): KittenPage
155
+
156
+ /**
157
+ This component’s parent. Undefined if component has not been added as a child to another component or a page via the addChild() method.
158
+ */
159
+ protected get _parent(): KittenComponent
160
+
161
+ /**
162
+ This pages socket. Not defined as private although you should only need it for low-level stuff.
163
+ */
164
+ _socket: WebSocketWithIsAlive|undefined
165
+
166
+ /**
167
+ All sockets active on this page. You *really* shouldn’t need to use this for anything. Not marked private as the Kitten web app uses it to introspect the page’s socket status.
168
+ */
169
+ _sockets:Array<WebSocketWithIsAlive>|undefined
170
+
171
+ /**
172
+ Constructor. Good place to set initial state, including instantiating child components.
173
+ */
174
+ constructor ()
175
+
176
+ /**
177
+ Returns a bound version of the render function. Use when adding a child component to your `kitten.html`.
178
+ */
179
+ get component(): BoundComponentRenderFunction<this>
180
+
181
+ /**
182
+ Required hook: override this method with your own render function
183
+ that returns `kitten.html`.
184
+ */
185
+ html(parameterObject?: Record<string, any>):(string|Array<string>|Promise<string|Array<string>>)
186
+
187
+ /**
188
+ Optional hook: override this method to run custom logic when the component has been added to the component hierarchy via addChild() (attached to its parent and, thus, to the component hiearchy).
189
+
190
+ At this point it will have a reference to its parent component, the page it’s on, and to any instance data that it might have, (at `this._parent`, `this._page`, and `this.`, respectively.)
191
+
192
+ However, there is no guarantee that the page this component is attached to has connected to the client via its automatic WebSocket. For that, rely on the
193
+ `onConnect()` handler instead.
194
+ */
195
+ onAddToParent() :void
196
+
197
+ /**
198
+ Optional hook: override this method to provide custom logic for your app
199
+ to be run when the page this component is on connects to the client via its WebSocket.
200
+
201
+ This hook will get called not just for initially-rendered components when the page
202
+ first connects but also for any components dynamically added to an already-connected
203
+ page/component hierarchy after the fact.
204
+
205
+ (So you can be sure that this handler will be called once when a component is fully
206
+ initialised on a connected page. This is a good place to add event handlers or to
207
+ start streaming updates to the client.)
208
+ */
209
+ onConnect(parameterObject: {
210
+ page?: KittenComponent,
211
+ request?: KittenRequest,
212
+ response?: KittenResponse
213
+ }):void
214
+
215
+ /**
216
+ Optional hook: override this method to run custom logic when the page
217
+ this component is on disconnects from the client via its WebSocket.
218
+ (This usually means the page the about to be unloaded, either because the
219
+ person is nagivating away from it or reloading it.)
220
+ */
221
+ onDisconnect(parameterObject: {
222
+ page?: KittenComponent,
223
+ request?: KittenRequest,
224
+ response?: KittenResponse
225
+ }):void
226
+
227
+ /**
228
+ Adds child component to this one.
229
+
230
+ Child components are entered into the event bubbling hierarchy and
231
+ contain a reference to the page that they’re on.
232
+ */
233
+ addChild<T extends KittenComponent> (component: T): T
234
+
235
+ /**
236
+ Removes a child and returns a reference to it.
237
+
238
+ If child cannot be found, returns null.
239
+
240
+ Usually called by the child itself when it is being removed.
241
+ */
242
+ removeChild<T extends KittenComponent>(component: T): T|null
243
+
244
+ /**
245
+ Gets all components of a given type (useful when you have collections of child components that you want to render, say, in a list).
246
+ */
247
+ childrenOfType<T extends KittenComponent>(type: Constructor<T>): T[]
248
+
249
+ /**
250
+ Returns the first child component encountered of type T. Use when you know there is only one child of type T and you don’t want to a reference to it in your KittenComponent subclass.
251
+
252
+ Returns undefined if a child of type T cannot be found.
253
+ */
254
+ childOfType<T extends KittenComponent>(type: Constructor<T>): T|undefined
255
+
256
+ /**
257
+ Add event handler for an EventEmitter.
258
+
259
+ Event listening and listener clean-up are automatically handled so the
260
+ author doesn’t have to worry about implementing this finickety
261
+ aspect manually.
262
+ */
263
+ addEventHandler (target: object, eventName: string, eventHandler: JavaScriptFunction):void
264
+
265
+ /**
266
+ Helper for sending an updated version of this component to the page.
267
+ */
268
+ update ():void
269
+
270
+ /**
271
+ Helper for removing this component from the live component hierachy.
272
+
273
+ Also handles removal of event listeners for itself and all its
274
+ children so we don’t have any leaks.
275
+ */
276
+ remove ():void
277
+
278
+ /**
279
+ Emits an event that is bubbled to all of its children.
280
+
281
+ This is a good way, for example, to set a specific state on a page or component, where each child component knows what it should look like in that state.
282
+
283
+ The event name → event handler naming convention mapping works exactly like it does with events received from the client.
284
+
285
+ @param {string} eventName
286
+ @param {any} data
287
+ @param {any} event
288
+ @param {string} target - if provided, and is prefixed by this component’s Kitten ID, we only bubble to the target and its children.
289
+ @param {any} self - if provided is used to bypass target check for object doing the bubbling.
290
+ */
291
+ emit (eventName:string, data?:any, event?:any, target?:string, self?:any):void
292
+
293
+ /**
294
+ Helper for adding an event handler for a page event and streaming an
295
+ updated version of the component to the client (a common pattern).
296
+
297
+ @param {string} eventName
298
+ */
299
+ updateOnEvent (eventName:string):void
300
+
301
+ /**
302
+ Helper (handler) for sending an updated version of this
303
+ component to the page.
304
+ */
305
+ sendUpdatedComponentToPage ():void
306
+ }
307
+
308
+ /**
309
+ KittenPage class.
310
+
311
+ A KittenPage is a specialised KittenComponent that represents a live
312
+ page in memory (a live page is one that has an automatic WebSocket connection
313
+ to the page rendered by the PageRoute). It constitutes the root of the
314
+ server-side component hierarchy. Its `html()` method is dynamically bound
315
+ by the PageRoute to the authored page route function in function-based authoring
316
+ and it is used directly via its global `kitten.Page` reference when authoring
317
+ class-based page routes.
318
+ */
319
+ export class KittenPage extends KittenComponent {
320
+ request: KittenRequest
321
+ response: KittenResponse
322
+ session: Session
323
+ socket: WebSocketWithIsAlive
324
+ sockets: [WebSocketWithIsAlive]
325
+ data: Record<string, any>
326
+ everyone: MessageSender
327
+ everyoneElse: MessageSender
328
+
329
+ /**
330
+ Construct new KittenPage instance with a reference to the
331
+ request and response objects for the page.
332
+
333
+ Every page has a unique ID (inherited from KittenComponent) and can hold
334
+ ephemeral page-level data. e.g., the states of components when
335
+ using the Streaming HTML workfow. (Page storage is ephemeral is that
336
+ it only lasts for the lifetime of a page in the browser and is destroyed
337
+ when the page is closed or reloaded.)
338
+
339
+ If you need greater persistence, use session storage (request.session) or
340
+ the built-in JSDB database (kitten.db).
341
+
342
+ A page is an authored page if the author of the Kitten app/site wrote
343
+ and exported a KittenPage subclass in the route (as opposed to exporting a
344
+ simple function and function-based event handlers that then resulted
345
+ in a generic page being created by Kitten’s PageRoute class). Keeping
346
+ track of this is an optimisation that enabled the PageSocketRoute to
347
+ not have to import the source file again if the page was authored
348
+ as a page instance and thus already contains its event handlers (as
349
+ opposed to the event handlers being exported as separate functions that
350
+ have be read in and mixed into the generic KittenPage instance by the PageSocketRoute).
351
+ */
352
+ constructor()
353
+
354
+ /**
355
+ The page has connected to its WebSocket. The list of sockets and the
356
+ specific socket for this page are passed for storage on the page and the
357
+ list of event handlers imported from the page (when using function-based
358
+ page routes), if any, to be mixed into this instance as methods.
359
+ */
360
+ connect (socket: WebSocketWithIsAlive, sockets: [WebSocketWithIsAlive], eventHandlers: Record<string, JavaScriptFunction>):void
361
+
362
+ /**
363
+ Dynamically add specified event handler for specified event name.
364
+
365
+ @deprecated Instead of `on(eventName, handler)`, export `onEventName()` from your page (or add `onEventName()` method to your `kitten.Page` subclass if using class-based page routes.)
366
+ */
367
+ on (eventName: string, eventHandler: () => void):void
368
+
369
+ /**
370
+ Send specified message to just this page’s socket.
371
+
372
+ You can specify an optional swap target that intelligently
373
+ wraps what you’re sending with the necessary envelope tag.
374
+ This is normally rather confusing with htmx’s oob swaps,
375
+ especially when inserting table rows. See:
376
+ https://htmx.org/attributes/hx-swap-oob/#using-alternate-swap-strategies
377
+ */
378
+ send (message: BufferLike|Promise<BufferLike>, swapTarget?: {
379
+ before?: string,
380
+ after?: string,
381
+ asFirstChildOf?: string,
382
+ asLastChildOf?: string
383
+ }):void
384
+ }
385
+
386
+ /**
387
+ Request and response types.
388
+
389
+ These vary per route type but are all built on the base of
390
+ Polka’s request and response objects which are, themselves,
391
+ based on the incoming message and server response types of
392
+ Node’s own http module.
393
+ */
394
+
395
+ import type { IncomingMessage, ServerResponse } from 'http'
396
+
397
+ export interface ParsedURL {
398
+ pathname: string
399
+ search: string
400
+ query: Record<string, string | string[]> | void
401
+ raw: string
402
+ }
403
+
404
+ export type PolkaResponse = ServerResponse
405
+
406
+ export interface PolkaRequest extends IncomingMessage {
407
+ url: string
408
+ method: string
409
+ originalUrl: string
410
+ params: Record<string, string>
411
+ path: string
412
+ search: string
413
+ query: Record<string,string>
414
+ body?: any
415
+ _decoded?: true
416
+ _parsedUrl: ParsedURL
417
+ }
418
+
419
+ export interface KittenRequest extends PolkaRequest {
420
+ /**
421
+ The raw body of non-multipart requests. Used, for example, for validation webhook signatures.
422
+ */
423
+ rawBody: Buffer
424
+
425
+ /**
426
+ Check if the incoming request contains the "Content-Type"
427
+ header field, and it contains the given mime `type`.
428
+
429
+ Examples:
430
+
431
+ // With Content-Type: text/html; charset=utf-8
432
+ req.is('html');
433
+ req.is('text/html');
434
+ req.is('text/*');
435
+ // => true
436
+
437
+ // When Content-Type is application/json
438
+ req.is('json');
439
+ req.is('application/json');
440
+ req.is('application/*');
441
+ // => true
442
+ req.is('html');
443
+ // => false
444
+
445
+ @link https://github.com/expressjs/express/blob/master/lib/request.js#L231
446
+ */
447
+ is (types:Array<string>|string):string|false|null
448
+
449
+ session: Session
450
+ }
451
+
452
+ type TypedArray = Int8Array|Uint8Array|Uint8ClampedArray|Int16Array|Uint16Array|Int32Array|Uint32Array|Float32Array|Float64Array|BigInt64Array|BigUint64Array
453
+
454
+ export interface KittenResponse extends PolkaResponse {
455
+ /**
456
+ JSON.stringifies passed data and ends response with
457
+ inline JSON using proper headers.
458
+ */
459
+ json (data:any):void
460
+
461
+ /**
462
+ JSON.stringifies passed data and ends response with JSON attachment
463
+ using proper headers and requested file name (or data.json as fallback
464
+ if no file name is provided).
465
+ */
466
+ jsonFile (data:any, fileName?:string):void
467
+
468
+ /**
469
+ Ends response with a file. Optionally, uses passed file name
470
+ (or 'dowload' as fallback) and passed mime type (or
471
+ 'application/octet-stream' as fallback).
472
+ */
473
+ file (data:string|Buffer|TypedArray|DataView, fileName?:string, mimeType?:string):void
474
+
475
+ /**
476
+ Ends response with 200 OK response code, and the response body,
477
+ if any (and '' if not).
478
+
479
+ @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/200
480
+ */
481
+ ok (body?:string):void
482
+
483
+ /**
484
+ Ends response with 201 Created response code, and the response body,
485
+ if any (and '' if not).
486
+
487
+ @link https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/201
488
+ */
489
+ created (body?:string):void
490
+
491
+ /**
492
+ Ends response with redirect via a GET request (303 See Other) to given location.
493
+
494
+ Alias: seeOther
495
+ */
496
+ get (location:string):void
497
+
498
+ /**
499
+ Redirect (temporary; 307) to requested location without changing the request method.
500
+ */
501
+ redirect (location:string):void
502
+
503
+ /**
504
+ Redirect (permanentl 308) to requested location without changing the request method.
505
+ */
506
+ permanentRedirect (location:string):void
507
+
508
+ /**
509
+ 400 Bad Request
510
+
511
+ Indicates that the server cannot or will not process the request due to something
512
+ that is perceived to be a client error (e.g., malformed request syntax, invalid request
513
+ message framing, or deceptive request routing).
514
+
515
+ @link https://httpwg.org/specs/rfc9110.html#rfc.section.15.5.1
516
+ */
517
+ badRequest (body?:string):void
518
+
519
+ /**
520
+ “401 Unauthorized” (actually, unauthenticated) response.
521
+
522
+ Aliases: unauthorised, unauthorized.
523
+ */
524
+ unauthenticated (body?:string):void
525
+
526
+ /**
527
+ 403 Forbidden response. This should be returned
528
+ if the request is authenticated but lacks the authorisation
529
+ (i.e., sufficient rights) to access the resource.
530
+
531
+ If the request requires authentication but has not been
532
+ authenticated, you should return a “401 Unauthorized”
533
+ (actually: unauthenticated) response.
534
+
535
+ @see unauthenticated
536
+ */
537
+ forbidden (body?:string):void
538
+
539
+ /**
540
+ 404 Not Found response.
541
+ */
542
+ notFound (body?:string):void
543
+
544
+ /**
545
+ 500 Internal Server Error response.
546
+
547
+ Alias: internalServerError.
548
+ */
549
+ error (body?:string):void
550
+
551
+ /**
552
+ General shorthand helper for setting the status code and
553
+ ending the response with an optional body.
554
+ */
555
+ withCode (statusCode:number, body?:string):void
556
+ }
557
+
558
+ export interface KittenPostRequest extends KittenRequest {
559
+ uploads: Upload[]
560
+ }
561
+
562
+ /* Crypto */
563
+
564
+ type Hex = Uint8Array | string;
565
+ type PrivKey = Hex | bigint | number;
566
+
567
+ export class Point {
568
+ readonly x: bigint;
569
+ readonly y: bigint;
570
+ static BASE: Point;
571
+ static ZERO: Point;
572
+ _WINDOW_SIZE?: number;
573
+ constructor(x: bigint, y: bigint);
574
+ _setWindowSize(windowSize: number): void;
575
+ static fromHex(hex: Hex, strict?: boolean): Point;
576
+ static fromPrivateKey(privateKey: PrivKey): Promise<Point>;
577
+ toRawBytes(): Uint8Array;
578
+ toHex(): string;
579
+ toX25519(): Uint8Array;
580
+ isTorsionFree(): boolean;
581
+ equals(other: Point): boolean;
582
+ negate(): Point;
583
+ add(other: Point): Point;
584
+ subtract(other: Point): Point;
585
+ multiply(scalar: number | bigint): Point;
586
+ }
587
+
588
+ export class Signature {
589
+ readonly r: Point;
590
+ readonly s: bigint;
591
+ constructor(r: Point, s: bigint);
592
+ static fromHex(hex: Hex): Signature;
593
+ assertValidity(): this;
594
+ toRawBytes(): Uint8Array;
595
+ toHex(): string;
596
+ }