skir-client 0.0.1

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.
@@ -0,0 +1,697 @@
1
+ /// <reference types="node" resolution-mode="require"/>
2
+ import type { Express as ExpressApp, json as ExpressJson, Request as ExpressRequest, Response as ExpressResponse, text as ExpressText } from "express";
3
+ /**
4
+ * A single moment in time represented in a platform-independent format, with a
5
+ * precision of one millisecond.
6
+ *
7
+ * A `Timestamp` object can represent a maximum of ±8,640,000,000,000,000
8
+ * milliseconds, or ±100,000,000 (one hundred million) days, relative to the
9
+ * Unix epoch. This is the range from April 20, 271821 BC to September 13,
10
+ * 275760 AD.
11
+ *
12
+ * Unlike the Javascript built-in `Date` type, a `Timestamp` is immutable.
13
+ * Like a `Date`, a `Timestamp` object does not contain a timezone.
14
+ */
15
+ export declare class Timestamp {
16
+ /** Number of milliseconds ellapsed since the Unix epoch. */
17
+ readonly unixMillis: number;
18
+ /**
19
+ * Returns a `Timestamp` representing the same moment in time as the given
20
+ * Javascript `Date` object.
21
+ *
22
+ * @throws if the given `Date` object has a timestamp value of NaN
23
+ */
24
+ static from(date: Date): Timestamp;
25
+ /**
26
+ * Creates a `Timestamp` object from a number of milliseconds from the Unix
27
+ * epoch.
28
+ *
29
+ * If the given number if outside the valid range (±8,640,000,000,000,000),
30
+ * this function will return `Timestamp.MAX` or `Timestamp.MIN` depending on
31
+ * the sign of the number.
32
+ *
33
+ * @throws if the given number is NaN
34
+ */
35
+ static fromUnixMillis(unixMillis: number): Timestamp;
36
+ /**
37
+ * Creates a `Timestamp` object from a number of seconds from the Unix epoch.
38
+ *
39
+ * If the given number if outside the valid range (±8,640,000,000,000), this
40
+ * function will return `Timestamp.MAX` or `Timestamp.MIN` depending on the
41
+ * sign of the number.
42
+ *
43
+ * @throws if the given number is NaN
44
+ */
45
+ static fromUnixSeconds(unixSeconds: number): Timestamp;
46
+ /**
47
+ * Parses a date in the date time string format.
48
+ *
49
+ * @throws if the given string is not a date in the date time string format
50
+ * @see https://tc39.es/ecma262/multipage/numbers-and-dates.html#sec-date-time-string-format
51
+ */
52
+ static parse(date: string): Timestamp;
53
+ /** Returns a `Timestamp` representing the current moment in time. */
54
+ static now(): Timestamp;
55
+ /** Thursday, 1 January 1970. */
56
+ static readonly UNIX_EPOCH: Timestamp;
57
+ /**
58
+ * Earliest moment in time representable as a `Timestamp`, namely April 20,
59
+ * 271821 BC.
60
+ *
61
+ * @see https://262.ecma-international.org/5.1/#sec-15.9.1.1
62
+ */
63
+ static readonly MIN: Timestamp;
64
+ /**
65
+ * Latest moment in time representable as a `Timestamp`, namely September 13,
66
+ * 275760 AD.
67
+ *
68
+ * @see https://262.ecma-international.org/5.1/#sec-15.9.1.1
69
+ */
70
+ static readonly MAX: Timestamp;
71
+ private constructor();
72
+ /** Number of seconds ellapsed since the Unix epoch. */
73
+ get unixSeconds(): number;
74
+ /**
75
+ * Returns a `Date` object representing the same moment in time as this
76
+ * `Timestamp`.
77
+ */
78
+ toDate(): Date;
79
+ toString(): string;
80
+ }
81
+ /** An immutable array of bytes. */
82
+ export declare class ByteString {
83
+ private readonly arrayBuffer;
84
+ private readonly byteOffset;
85
+ /** The length of this byte string. */
86
+ readonly byteLength: number;
87
+ /**
88
+ * Returns an immutable byte string containing all the bytes of `input` from
89
+ * `start`, inclusive, up to `end`, exclusive.
90
+ *
91
+ * If `input` is an `ArrayBuffer`, this function copies the bytes. Otherwise
92
+ * this function returns a sliced view of the input `ByteString`.
93
+ *
94
+ * @example <caption>Copy an array buffer into a byte string</caption>
95
+ * const byteString = ByteString.sliceOf(arrayBuffer);
96
+ */
97
+ static sliceOf(input: ArrayBuffer | SharedArrayBuffer | ByteString, start?: number, end?: number): ByteString;
98
+ /**
99
+ * Decodes a Base64 string, which can be obtained by calling `toBase64()`.
100
+ *
101
+ * @throws if the given string is not a valid Base64 string.
102
+ * @see https://en.wikipedia.org/wiki/Base64
103
+ */
104
+ static fromBase64(base64: string): ByteString;
105
+ /**
106
+ * Decodes a hexadecimal string, which can be obtained by calling
107
+ * `toBase16()`.
108
+ *
109
+ * @throws if the given string is not a valid Base64 string.
110
+ */
111
+ static fromBase16(base16: string): ByteString;
112
+ /** An empty byte string. */
113
+ static readonly EMPTY: ByteString;
114
+ /** Copies the contents of this byte string into the given array buffer. */
115
+ copyTo(target: ArrayBuffer, targetOffset?: number): void;
116
+ /** Copies the contents of this byte string into a new array buffer. */
117
+ toBuffer(): ArrayBuffer;
118
+ /**
119
+ * Encodes this byte string into a Base64 string.
120
+ *
121
+ * @see https://en.wikipedia.org/wiki/Base64
122
+ */
123
+ toBase64(): string;
124
+ /** Encodes this byte string into a hexadecimal string. */
125
+ toBase16(): string;
126
+ at(index: number): number | undefined;
127
+ toString(): string;
128
+ private constructor();
129
+ private readonly uint8Array;
130
+ }
131
+ /** A read-only JSON value. */
132
+ export type Json = null | boolean | number | string | readonly Json[] | Readonly<{
133
+ [name: string]: Json;
134
+ }>;
135
+ /**
136
+ * Resolves to the generated mutable class for a struct.
137
+ * The type parameter is the generated frozen class.
138
+ */
139
+ export type MutableForm<Frozen> = Frozen extends _FrozenBase ? ReturnType<Frozen["toMutable"]> & Freezable<Frozen> : Freezable<Frozen>;
140
+ /** Result of encoding a struct using binary encoding format. */
141
+ export interface BinaryForm {
142
+ /** Length (in bytes) of the binary form. */
143
+ readonly byteLength: number;
144
+ /** Copies the contents of the binary form into the given array buffer. */
145
+ copyTo(target: ArrayBuffer, offset?: number): void;
146
+ /** Copies the contents of this byte string into a new array buffer. */
147
+ toBuffer(): ArrayBuffer;
148
+ }
149
+ /**
150
+ * When using the JSON serialization format, you can chose between two flavors.
151
+ *
152
+ * The dense flavor is the default flavor and is preferred in most cases.
153
+ * Structs are converted to JSON arrays, where the number of each field
154
+ * corresponds to the index of the value in the array. This results in a more
155
+ * compact representation than when using JSON objects, and this makes
156
+ * serialization and deserialization a bit faster. Because field names are left
157
+ * out of the JSON, it is a representation which allows persistence: you can
158
+ * safely rename a field in a `.skir` file without breaking backwards
159
+ * compatibility.
160
+ * One con of this representation is that it is harder to tell, just by looking
161
+ * at the JSON, what field of the struct each value in the array corresponds to.
162
+ *
163
+ * When using the readable flavor, structs are converted to JSON objects. The
164
+ * name of each field in the `.skir` file is used as-is in the JSON. This
165
+ * results in a representation which is much more readable by humans, but also
166
+ * not suited for persistence: when you rename a field in a `.skir` file, you
167
+ * will no lonnger be able to deserialize old JSONs.
168
+ *
169
+ * @example
170
+ * const jane = Person.create({firstName: "Jane", lastName: "Doe"});
171
+ *
172
+ * console.log(Person.serializer.toJson(jane, "dense"));
173
+ * // Output: ["Jane","Doe"]
174
+ *
175
+ * console.log(Person.serializer.toJson(jane));
176
+ * // Output: ["Jane","Doe"]
177
+ *
178
+ * console.log(Person.serializer.toJson(jane, "readable"));
179
+ * // Output: {
180
+ * // "firstName": "Jane",
181
+ * // "lastName": "Doe"
182
+ * // }
183
+ */
184
+ export type JsonFlavor = "dense" | "readable";
185
+ /**
186
+ * Serializes and deserializes instances of `T`. Supports two serialization
187
+ * formats: JSON and binary.
188
+ *
189
+ * All deserialization methods return a deeply-immutable `T`. If `T` is the
190
+ * generated frozen class for a struct, all serialization methods accept either
191
+ * a `T` or a `T.Mutable`.
192
+ *
193
+ * Do NOT create your own `Serializer` implementation. Only use implementations
194
+ * provided by Skir.
195
+ *
196
+ * @example
197
+ * let jane = Person.create({firstName: "Jane", lastName: "Doe"});
198
+ * const json = Person.serializer.toJson(jane);
199
+ * jane = Person.serializer.fromJson(json);
200
+ * expect(jane.firstName).toBe("Jane");
201
+ */
202
+ export interface Serializer<T> {
203
+ /**
204
+ * Converts back the given stringified JSON to `T`.
205
+ * Works with both [flavors]{@link JsonFlavor} of JSON.
206
+ *
207
+ * Pass in "keep-unrecognized-values" if and only if the input JSON comes
208
+ * from a trusted program which might have been built from more recent
209
+ * source files.
210
+ */
211
+ fromJsonCode(code: string, keep?: "keep-unrecognized-values"): T;
212
+ /**
213
+ * Converts back the given JSON to `T`.
214
+ * Works with both [flavors]{@link JsonFlavor} of JSON.
215
+ *
216
+ * Pass in "keep-unrecognized-values" if and only if the input JSON comes
217
+ * from a trusted program which might have been built from more recent
218
+ * source files.
219
+ */
220
+ fromJson(json: Json, keep?: "keep-unrecognized-values"): T;
221
+ /**
222
+ * Converts back the given binary form to `T`.
223
+ *
224
+ * Pass in "keep-unrecognized-values" if and only if the input JSON comes
225
+ * from a trusted program which might have been built from more recent
226
+ * source files.
227
+ */
228
+ fromBytes(bytes: ArrayBuffer, keep?: "keep-unrecognized-values"): T;
229
+ /**
230
+ * Converts the given `T` to JSON and returns the stringified JSON. Same as
231
+ * calling `JSON.stringify()` on the result of `toJson()`.
232
+ *
233
+ * @param flavor dense or readable, defaults to dense
234
+ * @see JsonFlavor
235
+ */
236
+ toJsonCode(input: T | MutableForm<T>, flavor?: JsonFlavor): string;
237
+ /**
238
+ * Converts the given `T` to JSON. If you only need the stringified JSON, call
239
+ * `toJsonCode()` instead.
240
+ *
241
+ * @param flavor dense or readable, defaults to dense
242
+ * @see JsonFlavor
243
+ */
244
+ toJson(input: T | MutableForm<T>, flavor?: JsonFlavor): Json;
245
+ /** Converts the given `T` to binary format. */
246
+ toBytes(input: T | MutableForm<T>): BinaryForm;
247
+ /** An object describing the type `T`. Enables reflective programming. */
248
+ typeDescriptor: TypeDescriptorSpecialization<T>;
249
+ }
250
+ /**
251
+ * Returns a serializer of instances of the given Skir primitive type.
252
+ *
253
+ * @example
254
+ * expect(
255
+ * primitiveSerializer("string").toJsonCode("foo")
256
+ * ).toBe(
257
+ * '"foo"'
258
+ * );
259
+ */
260
+ export declare function primitiveSerializer<P extends keyof PrimitiveTypes>(primitiveType: P): Serializer<PrimitiveTypes[P]>;
261
+ /**
262
+ * Returns a serializer of arrays of `Item`s.
263
+ *
264
+ * @example
265
+ * expect(
266
+ * arraySerializer(User.serializer).toJsonCode([JANE, JOE])
267
+ * ).toBe(
268
+ * '[["jane"],["joe"]]'
269
+ * );
270
+ */
271
+ export declare function arraySerializer<Item>(item: Serializer<Item>, keyChain?: string): Serializer<ReadonlyArray<Item>>;
272
+ /** Returns a serializer of nullable `T`s. */
273
+ export declare function optionalSerializer<T>(other: Serializer<T>): Serializer<T | null>;
274
+ /**
275
+ * Describes the type `T`, where `T` is the TypeScript equivalent of a Skir
276
+ * type. Enables reflective programming.
277
+ *
278
+ * Every `TypeDescriptor` instance has a `kind` field which can take one of
279
+ * these 5 values: `"primitive"`, `"optional"`, `"array"`, `"struct"`, `"enum"`.
280
+ */
281
+ export type TypeDescriptor<T = unknown> = OptionalDescriptor<T> | ArrayDescriptor<T> | StructDescriptor<T> | EnumDescriptor<T> | PrimitiveDescriptor;
282
+ /** Specialization of `TypeDescriptor<T>` when `T` is known. */
283
+ export type TypeDescriptorSpecialization<T> = [
284
+ T
285
+ ] extends [_FrozenBase] ? StructDescriptor<T> : [T] extends [_EnumBase] ? EnumDescriptor<T> : TypeDescriptor<T>;
286
+ interface TypeDescriptorBase {
287
+ /** Returns the JSON representation of this `TypeDescriptor`. */
288
+ asJson(): Json;
289
+ /**
290
+ * Returns the JSON code representation of this `TypeDescriptor`.
291
+ * Same as calling `JSON.stringify()` on the result of `asJson()`.
292
+ */
293
+ asJsonCode(): string;
294
+ /**
295
+ * Converts from one serialized form to another.
296
+ *
297
+ * @example
298
+ * const denseJson = User.serializer.toJson(user, "dense");
299
+ * expect(
300
+ * User.serializer.typeDescriptor.transform(denseJson, "readable")
301
+ * ).toMatch(
302
+ * User.serializer.toJson(user, "readable")
303
+ * );
304
+ */
305
+ transform(json_or_bytes: Json | ArrayBuffer, out: JsonFlavor): Json;
306
+ transform(json: Json, out: "bytes"): ArrayBuffer;
307
+ transform(json_or_bytes: Json | ArrayBuffer, out: JsonFlavor | "bytes"): Json | ArrayBuffer;
308
+ }
309
+ /** Describes a primitive Skir type. */
310
+ export interface PrimitiveDescriptor extends TypeDescriptorBase {
311
+ kind: "primitive";
312
+ primitive: keyof PrimitiveTypes;
313
+ }
314
+ /**
315
+ * An interface mapping a primitive Skir type to the corresponding TypeScript
316
+ * type.
317
+ */
318
+ export interface PrimitiveTypes {
319
+ bool: boolean;
320
+ int32: number;
321
+ int64: bigint;
322
+ uint64: bigint;
323
+ float32: number;
324
+ float64: number;
325
+ timestamp: Timestamp;
326
+ string: string;
327
+ bytes: ByteString;
328
+ }
329
+ /**
330
+ * Describes an optional type. In a `.skir` file, an optional type is
331
+ * represented with a question mark at the end of another type.
332
+ */
333
+ export interface OptionalDescriptor<T> extends TypeDescriptorBase {
334
+ readonly kind: "optional";
335
+ /** Describes the other (non-optional) type. */
336
+ readonly otherType: TypeDescriptor<NonNullable<T>>;
337
+ }
338
+ /** Describes an array type. */
339
+ export interface ArrayDescriptor<T> extends TypeDescriptorBase {
340
+ readonly kind: "array";
341
+ /** Describes the type of the array items. */
342
+ readonly itemType: TypeDescriptor<T extends ReadonlyArray<infer Item> ? Item : unknown>;
343
+ readonly keyChain?: string;
344
+ }
345
+ /**
346
+ * Describes a Skir struct.
347
+ * The type parameter `T` refers to the generated frozen class for the struct.
348
+ */
349
+ export interface StructDescriptor<T = unknown> extends TypeDescriptorBase {
350
+ readonly kind: "struct";
351
+ /** Name of the struct as specified in the `.skir` file. */
352
+ readonly name: string;
353
+ /**
354
+ * A string containing all the names in the hierarchic sequence above and
355
+ * including the struct. For example: "Foo.Bar" if "Bar" is nested within a
356
+ * type called "Foo", or simply "Bar" if "Bar" is defined at the top-level of
357
+ * the module.
358
+ */
359
+ readonly qualifiedName: string;
360
+ /**
361
+ * Path to the module where the struct is defined, relative to the root of the
362
+ * project.
363
+ */
364
+ readonly modulePath: string;
365
+ /**
366
+ * If the struct is nested within another type, the descriptor for that type.
367
+ * Undefined if the struct is defined at the top-level of the module.
368
+ */
369
+ readonly parentType: StructDescriptor | EnumDescriptor | undefined;
370
+ /** The fields of the struct in the order they appear in the `.skir` file. */
371
+ readonly fields: ReadonlyArray<StructField<T>>;
372
+ /** The field numbers marked as removed. */
373
+ readonly removedNumbers: ReadonlySet<number>;
374
+ /**
375
+ * Looks up a field. The key can be one of: the field name (e.g. "user_id");
376
+ * the name of the property in the generated class (e.g. "userId"), the field
377
+ * number.
378
+ *
379
+ * The return type is `StructField<T> | undefined` unless the key is known at
380
+ * compile-time to be the name of the property in the generated class, in
381
+ * which case it is `StructField<T>`.
382
+ */
383
+ getField<K extends string | number>(key: K): StructFieldResult<T, K>;
384
+ /**
385
+ * Returns a new instance of the generated mutable class for a struct.
386
+ * Performs a shallow copy of `initializer` if `initializer` is specified.
387
+ */
388
+ newMutable(initializer?: T | MutableForm<T>): MutableForm<T>;
389
+ }
390
+ /** Field of a Skir struct. */
391
+ export interface StructField<Struct = unknown, Value = unknown> {
392
+ /** Field name as specified in the `.skir` file, e.g. "user_id". */
393
+ readonly name: string;
394
+ /** Name of the property in the generated class, e.g. "userId". */
395
+ readonly property: string;
396
+ /** Field number. */
397
+ readonly number: number;
398
+ /** Describes the field type. */
399
+ readonly type: TypeDescriptor<Value>;
400
+ /** Extracts the value of the field from the given struct. */
401
+ get(struct: Struct | MutableForm<Struct>): Value;
402
+ /** Assigns the given value to the field of the given struct. */
403
+ set(struct: MutableForm<Struct>, value: Value): void;
404
+ }
405
+ /**
406
+ * Return type of the `StructDescriptor.getField` method. If the argument is
407
+ * known at compile-time to be the name of a property of the generated class,
408
+ * resolves to `StructField<Struct>`. Otherwise, resolves to
409
+ * `StructField<Struct> | undefined`.
410
+ *
411
+ * @example <caption>The field is kown at compile-time</caption>
412
+ * const fieldNumber: number =
413
+ * User.serializer.typeDescriptor.getField("userId").number;
414
+ *
415
+ * @example <caption>The field is not kown at compile-time</caption>
416
+ * const fieldNumber: number | undefined =
417
+ * User.serializer.typeDescriptor.getField(variable)?.number;
418
+ */
419
+ export type StructFieldResult<Struct, Key extends string | number> = StructField<Struct> | (Struct extends _FrozenBase ? Key extends keyof NonNullable<Struct[typeof _INITIALIZER]> ? never : undefined : undefined);
420
+ /** Describes a Skir enum. */
421
+ export interface EnumDescriptor<T = unknown> extends TypeDescriptorBase {
422
+ readonly kind: "enum";
423
+ /** Name of the enum as specified in the `.skir` file. */
424
+ readonly name: string;
425
+ /**
426
+ * A string containing all the names in the hierarchic sequence above and
427
+ * including the enum. For example: "Foo.Bar" if "Bar" is nested within a type
428
+ * called "Foo", or simply "Bar" if "Bar" is defined at the top-level of the
429
+ * module.
430
+ */
431
+ readonly qualifiedName: string;
432
+ /**
433
+ * Path to the module where the enum is defined, relative to the root of the
434
+ * project.
435
+ */
436
+ readonly modulePath: string;
437
+ /**
438
+ * If the enum is nested within another type, the descriptor for that type.
439
+ * Undefined if the struct is defined at the top-level of the module.
440
+ */
441
+ readonly parentType: StructDescriptor | EnumDescriptor | undefined;
442
+ /**
443
+ * Includes the UNKNOWN variant, followed by the other variants in the order
444
+ * they appear in the `.skir` file.
445
+ */
446
+ readonly variants: ReadonlyArray<EnumVariant<T>>;
447
+ /** The variant numbers marked as removed. */
448
+ readonly removedNumbers: ReadonlySet<number>;
449
+ /**
450
+ * Looks up a variant. The key can be one of the variant name or the variant
451
+ * number.
452
+ *
453
+ * The return type is `EnumVariant<T> | undefined` unless the key is known at
454
+ * compile-time to be a variant name of the enum, in which case it is
455
+ * `EnumVariant<T>`.
456
+ */
457
+ getVariant<K extends string | number>(key: K): EnumVariantResult<T, K>;
458
+ }
459
+ /**
460
+ * Variant of a Skir enum. Variants which don't hold any value are called
461
+ * constant variants. Their name is always in UPPER_CASE. Variants which hold
462
+ * value of a given type are called wrapper variants, and their name is always
463
+ * in lower_case.
464
+ */
465
+ export type EnumVariant<Enum = unknown> = EnumConstantVariant<Enum> | EnumWrapperVariant<Enum, unknown>;
466
+ /** Field of a Skir enum which does not hold any value. */
467
+ export interface EnumConstantVariant<Enum = unknown> {
468
+ /**
469
+ * Variant name as specified in the `.skir` file, e.g. "MONDAY".
470
+ * Always in UPPER_CASE format.
471
+ */
472
+ readonly name: string;
473
+ /** Variant number. */
474
+ readonly number: number;
475
+ /** The instance of the generated class which corresponds to this field. */
476
+ readonly constant: Enum;
477
+ /** Always undefined, unlike the `type` field of `EnumWrapperVariant`. */
478
+ readonly type?: undefined;
479
+ }
480
+ /** Variant of a Skir enum which holds a value of a given type. */
481
+ export interface EnumWrapperVariant<Enum = unknown, Value = unknown> {
482
+ /**
483
+ * Variant name as specified in the `.skir` file, e.g. "v4".
484
+ * Always in lower_case format.
485
+ */
486
+ readonly name: string;
487
+ /** Variant number. */
488
+ readonly number: number;
489
+ /** Describes the type of the value held by the field. */
490
+ readonly type: TypeDescriptor<Value>;
491
+ /** Always undefined, unlike the `type` field of `EnumConstantVariant`. */
492
+ readonly constant?: undefined;
493
+ /**
494
+ * Extracts the value held by the given enum instance if it matches this
495
+ * enum variant. Returns undefined otherwise.
496
+ */
497
+ get(e: Enum): Value | unknown;
498
+ /**
499
+ * Returns a new enum instance matching this enum variant and holding the
500
+ * given value.
501
+ */
502
+ wrap(value: Value): Enum;
503
+ }
504
+ /**
505
+ * Return type of the `EnumDescriptor.getVariant` method. If the argument is
506
+ * known at compile-time to be the name of variant, resolves to
507
+ * `EnumVariant<Enum>`. Otherwise, resolves to
508
+ * `EnumVariant<Struct> | undefined`.
509
+ *
510
+ * @example <caption>The variant is known at compile-time</caption>
511
+ * const variantNumber: number =
512
+ * Weekday.serializer.typeDescriptor.getVariant("MONDAY").number;
513
+ *
514
+ * @example <caption>The variant is not known at compile-time</caption>
515
+ * const variantNumber: number | undefined =
516
+ * Weekday.serializer.typeDescriptor.getVariant(variable)?.number;
517
+ */
518
+ export type EnumVariantResult<Enum, Key extends string | number> = EnumVariant<Enum> | (Enum extends _EnumBase ? Key extends Enum["kind"] ? never : undefined : undefined);
519
+ /**
520
+ * Identifies a procedure (the "P" in "RPC") on both the client side and the
521
+ * server side.
522
+ */
523
+ export interface Method<Request, Response> {
524
+ /** Name of the procedure as specified in the `.skir` file. */
525
+ name: string;
526
+ /**
527
+ * A number which uniquely identifies this procedure.
528
+ * When it is not specified in the `.skir` file, it is obtained by hashing the
529
+ * procedure name.
530
+ */
531
+ number: number;
532
+ /** Serializer of request objects. */
533
+ requestSerializer: Serializer<Request>;
534
+ /** Serializer of response objects. */
535
+ responseSerializer: Serializer<Response>;
536
+ /**
537
+ * Documentation for this procedure specified as doc comments in the `.skir`
538
+ * file.
539
+ */
540
+ doc: string;
541
+ }
542
+ /**
543
+ * Interface implemented by both the frozen and mutable classes generated for a
544
+ * struct. `T` is always the generated frozen class.
545
+ */
546
+ export interface Freezable<T> {
547
+ /**
548
+ * Returns a deeply-immutable object, either by making a copy of `this` if
549
+ * `this` is mutable, or by returning `this` as-is if `this` is already
550
+ * immutable.
551
+ */
552
+ toFrozen(): T;
553
+ }
554
+ /**
555
+ * Returns a `TypeDescriptor` from its JSON representation as returned by
556
+ * `asJson()`.
557
+ */
558
+ export declare function parseTypeDescriptorFromJson(json: Json): TypeDescriptor;
559
+ /**
560
+ * Returns a `TypeDescriptor` from its JSON code representation as returned by
561
+ * `asJsonCode()`.
562
+ */
563
+ export declare function parseTypeDescriptorFromJsonCode(code: string): TypeDescriptor;
564
+ declare class UnrecognizedEnum {
565
+ readonly token: symbol;
566
+ readonly json?: Json | undefined;
567
+ readonly bytes?: ByteString | undefined;
568
+ constructor(token: symbol, json?: Json | undefined, bytes?: ByteString | undefined);
569
+ }
570
+ export declare const _EMPTY_ARRAY: readonly never[];
571
+ export declare function _toFrozenArray<T, Initializer>(initializers: readonly Initializer[], itemToFrozenFn?: (item: Initializer) => T): readonly T[];
572
+ export declare const _INITIALIZER: unique symbol;
573
+ export declare abstract class _FrozenBase {
574
+ protected constructor(privateKey: symbol);
575
+ toMutable(): unknown;
576
+ toFrozen(): this;
577
+ toString(): string;
578
+ [_INITIALIZER]: unknown;
579
+ }
580
+ export declare abstract class _EnumBase {
581
+ readonly kind: string;
582
+ readonly value?: unknown;
583
+ protected constructor(privateKey: symbol, kind: string, value?: unknown, unrecognized?: UnrecognizedEnum);
584
+ toString(): string;
585
+ }
586
+ /** Metadata of an HTTP request sent by a service client. */
587
+ export type RequestMeta = Omit<RequestInit, "body" | "method">;
588
+ /** Sends RPCs to a skir service. */
589
+ export declare class ServiceClient {
590
+ private readonly serviceUrl;
591
+ private readonly getRequestMetadata;
592
+ constructor(serviceUrl: string, getRequestMetadata?: (m: Method<unknown, unknown>) => Promise<RequestMeta> | RequestMeta);
593
+ /** Invokes the given method on the remote server through an RPC. */
594
+ invokeRemote<Request, Response>(method: Method<Request, Response>, request: Request, httpMethod?: "GET" | "POST"): Promise<Response>;
595
+ get lastResponseHeaders(): Headers | undefined;
596
+ private lastRespHeaders;
597
+ }
598
+ /** Raw response returned by the server. */
599
+ export declare class RawResponse {
600
+ readonly data: string;
601
+ readonly type: "ok-json" | "ok-html" | "bad-request" | "server-error";
602
+ constructor(data: string, type: "ok-json" | "ok-html" | "bad-request" | "server-error");
603
+ get statusCode(): number;
604
+ get contentType(): string;
605
+ }
606
+ /**
607
+ * Implementation of a skir service.
608
+ *
609
+ * Usage: call `.addMethod()` to register methods, then install the service on
610
+ * an HTTP server either by:
611
+ * - calling the `installServiceOnExpressApp()` top-level function if you are
612
+ * using ExpressJS
613
+ * - writing your own implementation of `installServiceOn*()` which calls
614
+ * `.handleRequest()` if you are using another web application framework
615
+ */
616
+ export declare class Service<RequestMeta = ExpressRequest, ResponseMeta = ExpressResponse> {
617
+ addMethod<Request, Response>(method: Method<Request, Response>, impl: (req: Request, reqMeta: RequestMeta, resMeta: ResponseMeta) => Promise<Response>): Service<RequestMeta, ResponseMeta>;
618
+ /**
619
+ * Parses the content of a user request and invokes the appropriate method.
620
+ * If you are using ExpressJS as your web application framework, you don't
621
+ * need to call this method, you can simply call the
622
+ * `installServiceOnExpressApp()` top-level function.
623
+ *
624
+ * If the request is a GET request, pass in the decoded query string as the
625
+ * request's body. The query string is the part of the URL after '?', and it
626
+ * can be decoded with DecodeURIComponent.
627
+ *
628
+ * Pass in "keep-unrecognized-values" if the request cannot come from a
629
+ * malicious user.
630
+ */
631
+ handleRequest(reqBody: string, reqMeta: RequestMeta, resMeta: ResponseMeta, keepUnrecognizedValues?: "keep-unrecognized-values"): Promise<RawResponse>;
632
+ private readonly methodImpls;
633
+ }
634
+ export declare function installServiceOnExpressApp(app: ExpressApp, queryPath: string, service: Service<ExpressRequest, ExpressResponse>, text: typeof ExpressText, json: typeof ExpressJson, keepUnrecognizedValues?: "keep-unrecognized-values"): void;
635
+ interface StructSpec {
636
+ kind: "struct";
637
+ ctor: {
638
+ new (privateKey: symbol): unknown;
639
+ };
640
+ initFn: (target: unknown, initializer: unknown) => void;
641
+ name: string;
642
+ parentCtor?: {
643
+ new (): unknown;
644
+ };
645
+ fields: readonly StructFieldSpec[];
646
+ removedNumbers?: readonly number[];
647
+ }
648
+ interface StructFieldSpec {
649
+ name: string;
650
+ property: string;
651
+ number: number;
652
+ type: TypeSpec;
653
+ mutableGetter?: string;
654
+ indexable?: IndexableSpec;
655
+ }
656
+ interface IndexableSpec {
657
+ searchMethod: string;
658
+ keyFn: (v: unknown) => unknown;
659
+ keyToHashable?: (v: unknown) => unknown;
660
+ }
661
+ interface EnumSpec<Enum = unknown> {
662
+ kind: "enum";
663
+ ctor: {
664
+ new (privateKey: symbol, kind: string, value?: unknown, unrecognized?: UnrecognizedEnum): Enum;
665
+ };
666
+ createValueFn?: (initializer: unknown) => unknown;
667
+ name: string;
668
+ parentCtor?: {
669
+ new (): unknown;
670
+ };
671
+ fields: EnumFieldSpec[];
672
+ removedNumbers?: readonly number[];
673
+ }
674
+ interface EnumFieldSpec {
675
+ name: string;
676
+ number: number;
677
+ type?: TypeSpec;
678
+ }
679
+ type TypeSpec = {
680
+ kind: "optional";
681
+ other: TypeSpec;
682
+ } | {
683
+ kind: "array";
684
+ item: TypeSpec;
685
+ keyChain?: string;
686
+ } | {
687
+ kind: "record";
688
+ ctor: {
689
+ new (): unknown;
690
+ };
691
+ } | {
692
+ kind: "primitive";
693
+ primitive: keyof PrimitiveTypes;
694
+ };
695
+ export declare function _initModuleClasses(modulePath: string, records: ReadonlyArray<StructSpec | EnumSpec>): void;
696
+ export {};
697
+ //# sourceMappingURL=skir-client.d.ts.map