@alepha/protobuf 0.14.3 → 0.15.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/dist/index.d.ts +49 -1116
- package/dist/index.js +4 -1
- package/dist/index.js.map +1 -1
- package/package.json +5 -5
- package/src/index.ts +4 -1
package/dist/index.d.ts
CHANGED
|
@@ -1,1125 +1,58 @@
|
|
|
1
|
+
import * as alepha0 from "alepha";
|
|
2
|
+
import { Alepha, SchemaCodec, Static, TObject, TSchema } from "alepha";
|
|
1
3
|
import protobufjs, { Type } from "protobufjs";
|
|
2
|
-
import
|
|
3
|
-
import { Static, StaticDecode as Static$1, StaticEncode, TArray, TArray as TArray$1, TBoolean, TInteger, TObject, TObject as TObject$1, TOptional, TOptionalAdd, TRecord, TSchema, TSchema as TSchema$1, TString, TUnsafe } from "typebox";
|
|
4
|
-
import { AsyncLocalStorage } from "node:async_hooks";
|
|
5
|
-
import { Validator } from "typebox/compile";
|
|
6
|
-
import "dayjs";
|
|
4
|
+
import "alepha/datetime";
|
|
7
5
|
|
|
8
|
-
//#region ../alepha/src/core/constants/KIND.d.ts
|
|
9
|
-
/**
|
|
10
|
-
* Used for identifying primitives.
|
|
11
|
-
*
|
|
12
|
-
* @internal
|
|
13
|
-
*/
|
|
14
|
-
declare const KIND: unique symbol;
|
|
15
|
-
//#endregion
|
|
16
|
-
//#region ../alepha/src/core/interfaces/Service.d.ts
|
|
17
|
-
/**
|
|
18
|
-
* In Alepha, a service is a class that can be instantiated or an abstract class. Nothing more, nothing less...
|
|
19
|
-
*/
|
|
20
|
-
type Service<T extends object = any> = InstantiableClass<T> | AbstractClass<T> | RunFunction<T>;
|
|
21
|
-
type RunFunction<T extends object = any> = (...args: any[]) => T | void;
|
|
22
|
-
type InstantiableClass<T extends object = any> = new (...args: any[]) => T;
|
|
23
|
-
/**
|
|
24
|
-
* Abstract class is a class that cannot be instantiated directly!
|
|
25
|
-
* It widely used for defining interfaces.
|
|
26
|
-
*/
|
|
27
|
-
type AbstractClass<T extends object = any> = abstract new (...args: any[]) => T;
|
|
28
|
-
/**
|
|
29
|
-
* Service substitution allows you to register a class as a different class.
|
|
30
|
-
* Providing class A, but using class B instead.
|
|
31
|
-
* This is useful for testing, mocking, or providing a different implementation of a service.
|
|
32
|
-
*
|
|
33
|
-
* class A is mostly an AbstractClass, while class B is an InstantiableClass.
|
|
34
|
-
*/
|
|
35
|
-
interface ServiceSubstitution<T extends object = any> {
|
|
36
|
-
/**
|
|
37
|
-
* Every time someone asks for this class, it will be provided with the 'use' class.
|
|
38
|
-
*/
|
|
39
|
-
provide: Service<T>;
|
|
40
|
-
/**
|
|
41
|
-
* Service to use instead of the 'provide' service.
|
|
42
|
-
*
|
|
43
|
-
* Syntax is inspired by Angular's DI system.
|
|
44
|
-
*/
|
|
45
|
-
use: Service<T>;
|
|
46
|
-
/**
|
|
47
|
-
* If true, if the service already exists -> just ignore the substitution and do not throw an error.
|
|
48
|
-
* Mostly used for plugins to enforce a substitution without throwing an error.
|
|
49
|
-
*/
|
|
50
|
-
optional?: boolean;
|
|
51
|
-
}
|
|
52
|
-
/**
|
|
53
|
-
* Every time you register a service, you can use this type to define it.
|
|
54
|
-
*
|
|
55
|
-
* alepha.with( ServiceEntry )
|
|
56
|
-
* or
|
|
57
|
-
* alepha.with( provide: ServiceEntry, use: MyOwnServiceEntry )
|
|
58
|
-
*
|
|
59
|
-
* And yes, you declare the *type* of the service, not the *instance*.
|
|
60
|
-
*/
|
|
61
|
-
type ServiceEntry<T extends object = any> = Service<T> | ServiceSubstitution<T>;
|
|
62
|
-
//#endregion
|
|
63
|
-
//#region ../alepha/src/core/helpers/primitive.d.ts
|
|
64
|
-
interface PrimitiveArgs<T extends object = {}> {
|
|
65
|
-
options: T;
|
|
66
|
-
alepha: Alepha;
|
|
67
|
-
service: InstantiableClass<Service>;
|
|
68
|
-
module?: Service;
|
|
69
|
-
}
|
|
70
|
-
interface PrimitiveConfig {
|
|
71
|
-
propertyKey: string;
|
|
72
|
-
service: InstantiableClass<Service>;
|
|
73
|
-
module?: Service;
|
|
74
|
-
}
|
|
75
|
-
declare abstract class Primitive<T extends object = {}> {
|
|
76
|
-
protected readonly alepha: Alepha;
|
|
77
|
-
readonly options: T;
|
|
78
|
-
readonly config: PrimitiveConfig;
|
|
79
|
-
constructor(args: PrimitiveArgs<T>);
|
|
80
|
-
/**
|
|
81
|
-
* Called automatically by Alepha after the primitive is created.
|
|
82
|
-
*/
|
|
83
|
-
protected onInit(): void;
|
|
84
|
-
}
|
|
85
|
-
type PrimitiveFactoryLike<T extends object = any> = {
|
|
86
|
-
(options: T): any;
|
|
87
|
-
[KIND]: any;
|
|
88
|
-
};
|
|
89
|
-
//#endregion
|
|
90
|
-
//#region ../alepha/src/core/interfaces/Async.d.ts
|
|
91
|
-
/**
|
|
92
|
-
* Represents a value that can be either a value or a promise of value.
|
|
93
|
-
*/
|
|
94
|
-
type Async<T> = T | Promise<T>;
|
|
95
|
-
//#endregion
|
|
96
|
-
//#region ../alepha/src/core/interfaces/LoggerInterface.d.ts
|
|
97
|
-
interface LoggerInterface {
|
|
98
|
-
trace(message: string, data?: unknown): void;
|
|
99
|
-
debug(message: string, data?: unknown): void;
|
|
100
|
-
info(message: string, data?: unknown): void;
|
|
101
|
-
warn(message: string, data?: unknown): void;
|
|
102
|
-
error(message: string, data?: unknown): void;
|
|
103
|
-
}
|
|
104
|
-
//#endregion
|
|
105
|
-
//#region ../alepha/src/core/providers/TypeProvider.d.ts
|
|
106
|
-
declare module "typebox" {
|
|
107
|
-
interface TString {
|
|
108
|
-
format?: string;
|
|
109
|
-
minLength?: number;
|
|
110
|
-
maxLength?: number;
|
|
111
|
-
}
|
|
112
|
-
interface TNumber {
|
|
113
|
-
format?: "int64";
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
//#endregion
|
|
117
|
-
//#region ../alepha/src/core/primitives/$atom.d.ts
|
|
118
|
-
type AtomOptions<T extends TAtomObject, N extends string> = {
|
|
119
|
-
name: N;
|
|
120
|
-
schema: T;
|
|
121
|
-
description?: string;
|
|
122
|
-
} & (T extends TOptionalAdd<T> ? {
|
|
123
|
-
default?: Static$1<T>;
|
|
124
|
-
} : {
|
|
125
|
-
default: Static$1<T>;
|
|
126
|
-
});
|
|
127
|
-
declare class Atom<T extends TAtomObject = TObject$1, N extends string = string> {
|
|
128
|
-
readonly options: AtomOptions<T, N>;
|
|
129
|
-
get schema(): T;
|
|
130
|
-
get key(): N;
|
|
131
|
-
constructor(options: AtomOptions<T, N>);
|
|
132
|
-
}
|
|
133
|
-
type TAtomObject = TObject$1<any> | TArray;
|
|
134
|
-
type AtomStatic<T extends TAtomObject> = T extends TOptionalAdd<T> ? Static$1<T> | undefined : Static$1<T>;
|
|
135
|
-
//#endregion
|
|
136
|
-
//#region ../alepha/src/core/primitives/$inject.d.ts
|
|
137
|
-
interface InjectOptions<T extends object = any> {
|
|
138
|
-
/**
|
|
139
|
-
* - 'transient' → Always a new instance on every inject. Zero caching.
|
|
140
|
-
* - 'singleton' → One instance per Alepha runtime (per-thread). Never disposed until Alepha shuts down. (default)
|
|
141
|
-
* - 'scoped' → One instance per AsyncLocalStorage context.
|
|
142
|
-
* - A new scope is created when Alepha handles a request, a scheduled job, a queue worker task...
|
|
143
|
-
* - You can also start a manual scope via alepha.context.run(() => { ... }).
|
|
144
|
-
* - When the scope ends, the scoped registry is discarded.
|
|
145
|
-
*
|
|
146
|
-
* @default "singleton"
|
|
147
|
-
*/
|
|
148
|
-
lifetime?: "transient" | "singleton" | "scoped";
|
|
149
|
-
/**
|
|
150
|
-
* Constructor arguments to pass when creating a new instance.
|
|
151
|
-
*/
|
|
152
|
-
args?: ConstructorParameters<InstantiableClass<T>>;
|
|
153
|
-
/**
|
|
154
|
-
* Parent that requested the instance.
|
|
155
|
-
*
|
|
156
|
-
* @internal
|
|
157
|
-
*/
|
|
158
|
-
parent?: Service | null;
|
|
159
|
-
}
|
|
160
|
-
//#endregion
|
|
161
|
-
//#region ../alepha/src/core/primitives/$module.d.ts
|
|
162
|
-
interface ModulePrimitiveOptions {
|
|
163
|
-
/**
|
|
164
|
-
* Name of the module.
|
|
165
|
-
*
|
|
166
|
-
* It should be in the format of `project.module.submodule`.
|
|
167
|
-
*/
|
|
168
|
-
name: string;
|
|
169
|
-
/**
|
|
170
|
-
* List all services related to this module.
|
|
171
|
-
*
|
|
172
|
-
* If you don't declare 'register' function, all services will be registered automatically.
|
|
173
|
-
* If you declare 'register' function, you must handle the registration of ALL services manually.
|
|
174
|
-
*/
|
|
175
|
-
services?: Array<Service>;
|
|
176
|
-
/**
|
|
177
|
-
* List of $primitives to register in the module.
|
|
178
|
-
*/
|
|
179
|
-
primitives?: Array<PrimitiveFactoryLike>;
|
|
180
|
-
/**
|
|
181
|
-
* By default, module will register ALL services.
|
|
182
|
-
* You can override this behavior by providing a register function.
|
|
183
|
-
* It's useful when you want to register services conditionally or in a specific order.
|
|
184
|
-
*
|
|
185
|
-
* Again, if you declare 'register', you must handle the registration of ALL services manually.
|
|
186
|
-
*/
|
|
187
|
-
register?: (alepha: Alepha) => void;
|
|
188
|
-
}
|
|
189
|
-
/**
|
|
190
|
-
* Base class for all modules.
|
|
191
|
-
*/
|
|
192
|
-
declare abstract class Module {
|
|
193
|
-
abstract readonly options: ModulePrimitiveOptions;
|
|
194
|
-
abstract register(alepha: Alepha): void;
|
|
195
|
-
static NAME_REGEX: RegExp;
|
|
196
|
-
/**
|
|
197
|
-
* Check if a Service is a Module.
|
|
198
|
-
*/
|
|
199
|
-
static is(ctor: Service): boolean;
|
|
200
|
-
/**
|
|
201
|
-
* Get the Module of a Service.
|
|
202
|
-
*
|
|
203
|
-
* Returns undefined if the Service is not part of a Module.
|
|
204
|
-
*/
|
|
205
|
-
static of(ctor: Service): Service<Module> | undefined;
|
|
206
|
-
}
|
|
207
|
-
//#endregion
|
|
208
|
-
//#region ../alepha/src/core/providers/AlsProvider.d.ts
|
|
209
|
-
type AsyncLocalStorageData = any;
|
|
210
|
-
declare class AlsProvider {
|
|
211
|
-
static create: () => AsyncLocalStorage<AsyncLocalStorageData> | undefined;
|
|
212
|
-
als?: AsyncLocalStorage<AsyncLocalStorageData>;
|
|
213
|
-
constructor();
|
|
214
|
-
createContextId(): string;
|
|
215
|
-
run<R>(callback: () => R, data?: Record<string, any>): R;
|
|
216
|
-
exists(): boolean;
|
|
217
|
-
get<T>(key: string): T | undefined;
|
|
218
|
-
set<T>(key: string, value: T): void;
|
|
219
|
-
}
|
|
220
|
-
//#endregion
|
|
221
|
-
//#region ../alepha/src/core/providers/Json.d.ts
|
|
222
|
-
/**
|
|
223
|
-
* Mimics the JSON global object with stringify and parse methods.
|
|
224
|
-
*
|
|
225
|
-
* Used across the codebase via dependency injection.
|
|
226
|
-
*/
|
|
227
|
-
declare class Json {
|
|
228
|
-
stringify(value: any, replacer?: (this: any, key: string, value: any) => any, space?: string | number): string;
|
|
229
|
-
parse(text: string, reviver?: (this: any, key: string, value: any) => any): any;
|
|
230
|
-
}
|
|
231
|
-
//#endregion
|
|
232
|
-
//#region ../alepha/src/core/providers/SchemaCodec.d.ts
|
|
233
|
-
declare abstract class SchemaCodec {
|
|
234
|
-
/**
|
|
235
|
-
* Encode the value to a string format.
|
|
236
|
-
*/
|
|
237
|
-
abstract encodeToString<T extends TSchema$1>(schema: T, value: Static$1<T>): string;
|
|
238
|
-
/**
|
|
239
|
-
* Encode the value to a binary format.
|
|
240
|
-
*/
|
|
241
|
-
abstract encodeToBinary<T extends TSchema$1>(schema: T, value: Static$1<T>): Uint8Array;
|
|
242
|
-
/**
|
|
243
|
-
* Decode string, binary, or other formats to the schema type.
|
|
244
|
-
*/
|
|
245
|
-
abstract decode<T>(schema: TSchema$1, value: unknown): T;
|
|
246
|
-
}
|
|
247
|
-
//#endregion
|
|
248
|
-
//#region ../alepha/src/core/providers/JsonSchemaCodec.d.ts
|
|
249
|
-
declare class JsonSchemaCodec extends SchemaCodec {
|
|
250
|
-
protected readonly json: Json;
|
|
251
|
-
protected readonly encoder: TextEncoder;
|
|
252
|
-
protected readonly decoder: TextDecoder;
|
|
253
|
-
encodeToString<T extends TSchema>(schema: T, value: Static$1<T>): string;
|
|
254
|
-
encodeToBinary<T extends TSchema>(schema: T, value: Static$1<T>): Uint8Array;
|
|
255
|
-
decode<T>(schema: TSchema, value: unknown): T;
|
|
256
|
-
}
|
|
257
|
-
//#endregion
|
|
258
|
-
//#region ../alepha/src/core/primitives/$hook.d.ts
|
|
259
|
-
interface HookOptions<T extends keyof Hooks> {
|
|
260
|
-
/**
|
|
261
|
-
* The name of the hook. "configure", "start", "ready", "stop", ...
|
|
262
|
-
*/
|
|
263
|
-
on: T;
|
|
264
|
-
/**
|
|
265
|
-
* The handler to run when the hook is triggered.
|
|
266
|
-
*/
|
|
267
|
-
handler: (args: Hooks[T]) => Async<any>;
|
|
268
|
-
/**
|
|
269
|
-
* Force the hook to run first or last on the list of hooks.
|
|
270
|
-
*/
|
|
271
|
-
priority?: "first" | "last";
|
|
272
|
-
/**
|
|
273
|
-
* Empty placeholder, not implemented yet. :-)
|
|
274
|
-
*/
|
|
275
|
-
before?: object | Array<object>;
|
|
276
|
-
/**
|
|
277
|
-
* Empty placeholder, not implemented yet. :-)
|
|
278
|
-
*/
|
|
279
|
-
after?: object | Array<object>;
|
|
280
|
-
}
|
|
281
|
-
declare class HookPrimitive<T extends keyof Hooks> extends Primitive<HookOptions<T>> {
|
|
282
|
-
called: number;
|
|
283
|
-
protected onInit(): void;
|
|
284
|
-
}
|
|
285
|
-
//#endregion
|
|
286
|
-
//#region ../alepha/src/core/providers/SchemaValidator.d.ts
|
|
287
|
-
declare class SchemaValidator {
|
|
288
|
-
protected cache: Map<TSchema, Validator<typebox3.TProperties, TSchema, unknown, unknown>>;
|
|
289
|
-
protected useEval: boolean;
|
|
290
|
-
/**
|
|
291
|
-
* Validate the value against the provided schema.
|
|
292
|
-
*
|
|
293
|
-
* Validation create a new value by applying some preprocessing. (e.g., trimming text)
|
|
294
|
-
*/
|
|
295
|
-
validate<T extends TSchema>(schema: T, value: unknown, options?: ValidateOptions): Static$1<T>;
|
|
296
|
-
protected getValidator<T extends TSchema>(schema: T): Validator<{}, T>;
|
|
297
|
-
/**
|
|
298
|
-
* Preprocess the value based on the schema before validation.
|
|
299
|
-
*
|
|
300
|
-
* - If the value is `null` and the schema does not allow `null`, it converts it to `undefined`.
|
|
301
|
-
* - If the value is a string and the schema has a `~options.trim` flag, it trims whitespace from the string.
|
|
302
|
-
*/
|
|
303
|
-
beforeParse(schema: any, value: any, options: ValidateOptions): any;
|
|
304
|
-
/**
|
|
305
|
-
* Used by `beforeParse` to determine if a schema allows null values.
|
|
306
|
-
*/
|
|
307
|
-
protected isSchemaNullable: (schema: any) => boolean;
|
|
308
|
-
protected onConfigure: HookPrimitive<"configure">;
|
|
309
|
-
protected canEval(): boolean;
|
|
310
|
-
}
|
|
311
|
-
interface ValidateOptions {
|
|
312
|
-
trim?: boolean;
|
|
313
|
-
nullToUndefined?: boolean;
|
|
314
|
-
deleteUndefined?: boolean;
|
|
315
|
-
}
|
|
316
|
-
//#endregion
|
|
317
|
-
//#region ../alepha/src/core/providers/CodecManager.d.ts
|
|
318
|
-
type Encoding = "object" | "string" | "binary";
|
|
319
|
-
interface EncodeOptions<T extends Encoding = Encoding> {
|
|
320
|
-
/**
|
|
321
|
-
* The output encoding format:
|
|
322
|
-
* - 'string': Returns JSON string
|
|
323
|
-
* - 'binary': Returns Uint8Array (for protobuf, msgpack, etc.)
|
|
324
|
-
*
|
|
325
|
-
* @default "string"
|
|
326
|
-
*/
|
|
327
|
-
as?: T;
|
|
328
|
-
/**
|
|
329
|
-
* The encoder to use (e.g., 'json', 'protobuf', 'msgpack')
|
|
330
|
-
*
|
|
331
|
-
* @default "json"
|
|
332
|
-
*/
|
|
333
|
-
encoder?: string;
|
|
334
|
-
/**
|
|
335
|
-
* Validation options to apply before encoding.
|
|
336
|
-
*/
|
|
337
|
-
validation?: ValidateOptions | false;
|
|
338
|
-
}
|
|
339
|
-
type EncodeResult<T extends TSchema, E extends Encoding> = E extends "string" ? string : E extends "binary" ? Uint8Array : StaticEncode<T>;
|
|
340
|
-
interface DecodeOptions {
|
|
341
|
-
/**
|
|
342
|
-
* The encoder to use (e.g., 'json', 'protobuf', 'msgpack')
|
|
343
|
-
*
|
|
344
|
-
* @default "json"
|
|
345
|
-
*/
|
|
346
|
-
encoder?: string;
|
|
347
|
-
/**
|
|
348
|
-
* Validation options to apply before encoding.
|
|
349
|
-
*/
|
|
350
|
-
validation?: ValidateOptions | false;
|
|
351
|
-
}
|
|
352
|
-
/**
|
|
353
|
-
* CodecManager manages multiple codec formats and provides a unified interface
|
|
354
|
-
* for encoding and decoding data with different formats.
|
|
355
|
-
*/
|
|
356
|
-
declare class CodecManager {
|
|
357
|
-
protected readonly codecs: Map<string, SchemaCodec>;
|
|
358
|
-
protected readonly jsonCodec: JsonSchemaCodec;
|
|
359
|
-
protected readonly schemaValidator: SchemaValidator;
|
|
360
|
-
default: string;
|
|
361
|
-
constructor();
|
|
362
|
-
/**
|
|
363
|
-
* Register a new codec format.
|
|
364
|
-
*
|
|
365
|
-
* @param name - The name of the codec (e.g., 'json', 'protobuf')
|
|
366
|
-
* @param codec - The codec implementation
|
|
367
|
-
*/
|
|
368
|
-
register(name: string, codec: SchemaCodec): void;
|
|
369
|
-
/**
|
|
370
|
-
* Get a specific codec by name.
|
|
371
|
-
*
|
|
372
|
-
* @param name - The name of the codec
|
|
373
|
-
* @returns The codec instance
|
|
374
|
-
* @throws {AlephaError} If the codec is not found
|
|
375
|
-
*/
|
|
376
|
-
getCodec(name: string): SchemaCodec;
|
|
377
|
-
/**
|
|
378
|
-
* Encode data using the specified codec and output format.
|
|
379
|
-
*/
|
|
380
|
-
encode<T extends TSchema, E extends Encoding = "object">(schema: T, value: unknown, options?: EncodeOptions<E>): EncodeResult<T, E>;
|
|
381
|
-
/**
|
|
382
|
-
* Decode data using the specified codec.
|
|
383
|
-
*/
|
|
384
|
-
decode<T extends TSchema>(schema: T, data: any, options?: DecodeOptions): Static$1<T>;
|
|
385
|
-
/**
|
|
386
|
-
* Validate decoded data against the schema.
|
|
387
|
-
*
|
|
388
|
-
* This is automatically called before encoding or after decoding.
|
|
389
|
-
*/
|
|
390
|
-
validate<T extends TSchema>(schema: T, value: unknown, options?: ValidateOptions): Static$1<T>;
|
|
391
|
-
}
|
|
392
|
-
//#endregion
|
|
393
|
-
//#region ../alepha/src/core/providers/EventManager.d.ts
|
|
394
|
-
declare class EventManager {
|
|
395
|
-
logFn?: () => LoggerInterface | undefined;
|
|
396
|
-
/**
|
|
397
|
-
* List of events that can be triggered. Powered by $hook().
|
|
398
|
-
*/
|
|
399
|
-
protected events: Record<string, Array<Hook>>;
|
|
400
|
-
constructor(logFn?: () => LoggerInterface | undefined);
|
|
401
|
-
protected get log(): LoggerInterface | undefined;
|
|
402
|
-
clear(): void;
|
|
403
|
-
/**
|
|
404
|
-
* Registers a hook for the specified event.
|
|
405
|
-
*/
|
|
406
|
-
on<T extends keyof Hooks>(event: T, hookOrFunc: Hook<T> | ((payload: Hooks[T]) => Async<void>)): () => void;
|
|
407
|
-
/**
|
|
408
|
-
* Emits the specified event with the given payload.
|
|
409
|
-
*/
|
|
410
|
-
emit<T extends keyof Hooks>(func: T, payload: Hooks[T], options?: {
|
|
411
|
-
/**
|
|
412
|
-
* If true, the hooks will be executed in reverse order.
|
|
413
|
-
* This is useful for "stop" hooks that should be executed in reverse order.
|
|
414
|
-
*
|
|
415
|
-
* @default false
|
|
416
|
-
*/
|
|
417
|
-
reverse?: boolean;
|
|
418
|
-
/**
|
|
419
|
-
* If true, the hooks will be logged with their execution time.
|
|
420
|
-
*
|
|
421
|
-
* @default false
|
|
422
|
-
*/
|
|
423
|
-
log?: boolean;
|
|
424
|
-
/**
|
|
425
|
-
* If true, errors will be caught and logged instead of throwing.
|
|
426
|
-
*
|
|
427
|
-
* @default false
|
|
428
|
-
*/
|
|
429
|
-
catch?: boolean;
|
|
430
|
-
}): Promise<void>;
|
|
431
|
-
}
|
|
432
|
-
//#endregion
|
|
433
|
-
//#region ../alepha/src/core/providers/StateManager.d.ts
|
|
434
|
-
interface AtomWithValue {
|
|
435
|
-
atom: Atom;
|
|
436
|
-
value: unknown;
|
|
437
|
-
}
|
|
438
|
-
declare class StateManager<State$1 extends object = State> {
|
|
439
|
-
protected readonly als: AlsProvider;
|
|
440
|
-
protected readonly events: EventManager;
|
|
441
|
-
protected readonly codec: JsonSchemaCodec;
|
|
442
|
-
protected readonly atoms: Map<keyof State$1, Atom<TObject<typebox3.TProperties>, string>>;
|
|
443
|
-
protected store: Partial<State$1>;
|
|
444
|
-
constructor(store?: Partial<State$1>);
|
|
445
|
-
getAtoms(context?: boolean): Array<AtomWithValue>;
|
|
446
|
-
register(atom: Atom<any>): this;
|
|
447
|
-
/**
|
|
448
|
-
* Get a value from the state with proper typing
|
|
449
|
-
*/
|
|
450
|
-
get<T extends TAtomObject>(target: Atom<T>): Static$1<T>;
|
|
451
|
-
get<Key extends keyof State$1>(target: Key): State$1[Key] | undefined;
|
|
452
|
-
/**
|
|
453
|
-
* Set a value in the state
|
|
454
|
-
*/
|
|
455
|
-
set<T extends TAtomObject>(target: Atom<T>, value: AtomStatic<T>, options?: SetStateOptions): this;
|
|
456
|
-
set<Key extends keyof State$1>(target: Key, value: State$1[Key] | undefined, options?: SetStateOptions): this;
|
|
457
|
-
/**
|
|
458
|
-
* Mutate a value in the state.
|
|
459
|
-
*/
|
|
460
|
-
mut<T extends TObject>(target: Atom<T>, mutator: (current: Static$1<T>) => Static$1<T>): this;
|
|
461
|
-
mut<Key extends keyof State$1>(target: Key, mutator: (current: State$1[Key] | undefined) => State$1[Key] | undefined): this;
|
|
462
|
-
/**
|
|
463
|
-
* Check if a key exists in the state
|
|
464
|
-
*/
|
|
465
|
-
has<Key extends keyof State$1>(key: Key): boolean;
|
|
466
|
-
/**
|
|
467
|
-
* Delete a key from the state (set to undefined)
|
|
468
|
-
*/
|
|
469
|
-
del<Key extends keyof State$1>(key: Key): this;
|
|
470
|
-
/**
|
|
471
|
-
* Push a value to an array in the state
|
|
472
|
-
*/
|
|
473
|
-
push<Key extends keyof OnlyArray<State$1>>(key: Key, ...value: Array<NonNullable<State$1[Key]> extends Array<infer U> ? U : never>): this;
|
|
474
|
-
/**
|
|
475
|
-
* Clear all state
|
|
476
|
-
*/
|
|
477
|
-
clear(): this;
|
|
478
|
-
/**
|
|
479
|
-
* Get all keys that exist in the state
|
|
480
|
-
*/
|
|
481
|
-
keys(): (keyof State$1)[];
|
|
482
|
-
}
|
|
483
|
-
type OnlyArray<T extends object> = { [K in keyof T]: NonNullable<T[K]> extends Array<any> ? K : never };
|
|
484
|
-
interface SetStateOptions {
|
|
485
|
-
skipContext?: boolean;
|
|
486
|
-
skipEvents?: boolean;
|
|
487
|
-
}
|
|
488
|
-
//#endregion
|
|
489
|
-
//#region ../alepha/src/core/Alepha.d.ts
|
|
490
|
-
/**
|
|
491
|
-
* Core container of the Alepha framework.
|
|
492
|
-
*
|
|
493
|
-
* It is responsible for managing the lifecycle of services,
|
|
494
|
-
* handling dependency injection,
|
|
495
|
-
* and providing a unified interface for the application.
|
|
496
|
-
*
|
|
497
|
-
* @example
|
|
498
|
-
* ```ts
|
|
499
|
-
* import { Alepha, run } from "alepha";
|
|
500
|
-
*
|
|
501
|
-
* class MyService {
|
|
502
|
-
* // business logic here
|
|
503
|
-
* }
|
|
504
|
-
*
|
|
505
|
-
* const alepha = Alepha.create({
|
|
506
|
-
* // state, env, and other properties
|
|
507
|
-
* })
|
|
508
|
-
*
|
|
509
|
-
* alepha.with(MyService);
|
|
510
|
-
*
|
|
511
|
-
* run(alepha); // trigger .start (and .stop) automatically
|
|
512
|
-
* ```
|
|
513
|
-
*
|
|
514
|
-
* ### Alepha Factory
|
|
515
|
-
*
|
|
516
|
-
* Alepha.create() is an enhanced version of new Alepha().
|
|
517
|
-
* - It merges `process.env` with the provided state.env when available.
|
|
518
|
-
* - It populates the test hooks for Vitest or Jest environments when available.
|
|
519
|
-
*
|
|
520
|
-
* new Alepha() is fine if you don't need these helpers.
|
|
521
|
-
*
|
|
522
|
-
* ### Platforms & Environments
|
|
523
|
-
*
|
|
524
|
-
* Alepha is designed to work in various environments:
|
|
525
|
-
* - **Browser**: Runs in the browser, using the global `window` object.
|
|
526
|
-
* - **Serverless**: Runs in serverless environments like Vercel or Vite.
|
|
527
|
-
* - **Test**: Runs in test environments like Jest or Vitest.
|
|
528
|
-
* - **Production**: Runs in production environments, typically with NODE_ENV set to "production".
|
|
529
|
-
* * You can check the current environment using the following methods:
|
|
530
|
-
*
|
|
531
|
-
* - `isBrowser()`: Returns true if the App is running in a browser environment.
|
|
532
|
-
* - `isServerless()`: Returns true if the App is running in a serverless environment.
|
|
533
|
-
* - `isTest()`: Returns true if the App is running in a test environment.
|
|
534
|
-
* - `isProduction()`: Returns true if the App is running in a production environment.
|
|
535
|
-
*
|
|
536
|
-
* ### State & Environment
|
|
537
|
-
*
|
|
538
|
-
* The state of the Alepha container is stored in the `store` property.
|
|
539
|
-
* Most important property is `store.env`, which contains the environment variables.
|
|
540
|
-
*
|
|
541
|
-
* ```ts
|
|
542
|
-
* const alepha = Alepha.create({ env: { MY_VAR: "value" } });
|
|
543
|
-
*
|
|
544
|
-
* // You can access the environment variables using alepha.env
|
|
545
|
-
* console.log(alepha.env.MY_VAR); // "value"
|
|
546
|
-
*
|
|
547
|
-
* // But you should use $env() primitive to get typed values from the environment.
|
|
548
|
-
* class App {
|
|
549
|
-
* env = $env(
|
|
550
|
-
* t.object({
|
|
551
|
-
* MY_VAR: t.text(),
|
|
552
|
-
* })
|
|
553
|
-
* );
|
|
554
|
-
* }
|
|
555
|
-
* ```
|
|
556
|
-
*
|
|
557
|
-
* ### Modules
|
|
558
|
-
*
|
|
559
|
-
* Modules are a way to group services together.
|
|
560
|
-
* You can register a module using the `$module` primitive.
|
|
561
|
-
*
|
|
562
|
-
* ```ts
|
|
563
|
-
* import { $module } from "alepha";
|
|
564
|
-
*
|
|
565
|
-
* class MyLib {}
|
|
566
|
-
*
|
|
567
|
-
* const myModule = $module({
|
|
568
|
-
* name: "my.project.module",
|
|
569
|
-
* services: [MyLib],
|
|
570
|
-
* });
|
|
571
|
-
* ```
|
|
572
|
-
*
|
|
573
|
-
* Do not use modules for small applications.
|
|
574
|
-
*
|
|
575
|
-
* ### Hooks
|
|
576
|
-
*
|
|
577
|
-
* Hooks are a way to run async functions from all registered providers/services.
|
|
578
|
-
* You can register a hook using the `$hook` primitive.
|
|
579
|
-
*
|
|
580
|
-
* ```ts
|
|
581
|
-
* import { $hook } from "alepha";
|
|
582
|
-
*
|
|
583
|
-
* class App {
|
|
584
|
-
* log = $logger();
|
|
585
|
-
* onCustomerHook = $hook({
|
|
586
|
-
* on: "my:custom:hook",
|
|
587
|
-
* handler: () => {
|
|
588
|
-
* this.log?.info("App is being configured");
|
|
589
|
-
* },
|
|
590
|
-
* });
|
|
591
|
-
* }
|
|
592
|
-
*
|
|
593
|
-
* Alepha.create()
|
|
594
|
-
* .with(App)
|
|
595
|
-
* .start()
|
|
596
|
-
* .then(alepha => alepha.events.emit("my:custom:hook"));
|
|
597
|
-
* ```
|
|
598
|
-
*
|
|
599
|
-
* Hooks are fully typed. You can create your own hooks by using module augmentation:
|
|
600
|
-
*
|
|
601
|
-
* ```ts
|
|
602
|
-
* declare module "alepha" {
|
|
603
|
-
* interface Hooks {
|
|
604
|
-
* "my:custom:hook": {
|
|
605
|
-
* arg1: string;
|
|
606
|
-
* }
|
|
607
|
-
* }
|
|
608
|
-
* }
|
|
609
|
-
* ```
|
|
610
|
-
*
|
|
611
|
-
* @module alepha
|
|
612
|
-
*/
|
|
613
|
-
declare class Alepha {
|
|
614
|
-
/**
|
|
615
|
-
* Creates a new instance of the Alepha container with some helpers:
|
|
616
|
-
*
|
|
617
|
-
* - merges `process.env` with the provided state.env when available.
|
|
618
|
-
* - populates the test hooks for Vitest or Jest environments when available.
|
|
619
|
-
*
|
|
620
|
-
* If you are not interested about these helpers, you can use the constructor directly.
|
|
621
|
-
*/
|
|
622
|
-
static create(state?: Partial<State>): Alepha;
|
|
623
|
-
/**
|
|
624
|
-
* Flag indicating whether the App won't accept any further changes.
|
|
625
|
-
* Pass to true when #start() is called.
|
|
626
|
-
*/
|
|
627
|
-
protected locked: boolean;
|
|
628
|
-
/**
|
|
629
|
-
* True if the App has been configured.
|
|
630
|
-
*/
|
|
631
|
-
protected configured: boolean;
|
|
632
|
-
/**
|
|
633
|
-
* True if the App has started.
|
|
634
|
-
*/
|
|
635
|
-
protected started: boolean;
|
|
636
|
-
/**
|
|
637
|
-
* True if the App is ready.
|
|
638
|
-
*/
|
|
639
|
-
protected ready: boolean;
|
|
640
|
-
/**
|
|
641
|
-
* A promise that resolves when the App has started.
|
|
642
|
-
*/
|
|
643
|
-
protected starting?: PromiseWithResolvers<this>;
|
|
644
|
-
/**
|
|
645
|
-
* During the instantiation process, we keep a list of pending instantiations.
|
|
646
|
-
* > It allows us to detect circular dependencies.
|
|
647
|
-
*/
|
|
648
|
-
protected pendingInstantiations: Service[];
|
|
649
|
-
/**
|
|
650
|
-
* Cache for environment variables.
|
|
651
|
-
* > It allows us to avoid parsing the same schema multiple times.
|
|
652
|
-
*/
|
|
653
|
-
protected cacheEnv: Map<TSchema$1, any>;
|
|
654
|
-
/**
|
|
655
|
-
* List of modules that are registered in the container.
|
|
656
|
-
*
|
|
657
|
-
* Modules are used to group services and provide a way to register them in the container.
|
|
658
|
-
*/
|
|
659
|
-
protected modules: Array<Module>;
|
|
660
|
-
/**
|
|
661
|
-
* List of service substitutions.
|
|
662
|
-
*
|
|
663
|
-
* Services registered here will be replaced by the specified service when injected.
|
|
664
|
-
*/
|
|
665
|
-
protected substitutions: Map<Service, {
|
|
666
|
-
use: Service;
|
|
667
|
-
}>;
|
|
668
|
-
/**
|
|
669
|
-
* Registry of primitives.
|
|
670
|
-
*/
|
|
671
|
-
protected primitiveRegistry: Map<Service<Primitive<{}>>, Primitive<{}>[]>;
|
|
672
|
-
/**
|
|
673
|
-
* List of all services + how they are provided.
|
|
674
|
-
*/
|
|
675
|
-
protected registry: Map<Service, ServiceDefinition>;
|
|
676
|
-
/**
|
|
677
|
-
* Node.js feature that allows to store context across asynchronous calls.
|
|
678
|
-
*
|
|
679
|
-
* This is used for logging, tracing, and other context-related features.
|
|
680
|
-
*
|
|
681
|
-
* Mocked for browser environments.
|
|
682
|
-
*/
|
|
683
|
-
context: AlsProvider;
|
|
684
|
-
/**
|
|
685
|
-
* Event manager to handle lifecycle events and custom events.
|
|
686
|
-
*/
|
|
687
|
-
events: EventManager;
|
|
688
|
-
/**
|
|
689
|
-
* State manager to store arbitrary values.
|
|
690
|
-
*/
|
|
691
|
-
store: StateManager<State>;
|
|
692
|
-
/**
|
|
693
|
-
* Codec manager for encoding and decoding data with different formats.
|
|
694
|
-
*
|
|
695
|
-
* Supports multiple codec formats (JSON, Protobuf, etc.) with a unified interface.
|
|
696
|
-
*/
|
|
697
|
-
codec: CodecManager;
|
|
698
|
-
/**
|
|
699
|
-
* Get logger instance.
|
|
700
|
-
*/
|
|
701
|
-
get log(): LoggerInterface | undefined;
|
|
702
|
-
/**
|
|
703
|
-
* The environment variables for the App.
|
|
704
|
-
*/
|
|
705
|
-
get env(): Readonly<Env>;
|
|
706
|
-
constructor(state?: Partial<State>);
|
|
707
|
-
set<T extends TAtomObject>(target: Atom<T>, value: AtomStatic<T>): this;
|
|
708
|
-
set<Key extends keyof State>(target: Key, value: State[Key] | undefined): this;
|
|
709
|
-
/**
|
|
710
|
-
* True when start() is called.
|
|
711
|
-
*
|
|
712
|
-
* -> No more services can be added, it's over, bye!
|
|
713
|
-
*/
|
|
714
|
-
isLocked(): boolean;
|
|
715
|
-
/**
|
|
716
|
-
* Returns whether the App is configured.
|
|
717
|
-
*
|
|
718
|
-
* It means that Alepha#configure() has been called.
|
|
719
|
-
*
|
|
720
|
-
* > By default, configure() is called automatically when start() is called, but you can also call it manually.
|
|
721
|
-
*/
|
|
722
|
-
isConfigured(): boolean;
|
|
723
|
-
/**
|
|
724
|
-
* Returns whether the App has started.
|
|
725
|
-
*
|
|
726
|
-
* It means that #start() has been called but maybe not all services are ready.
|
|
727
|
-
*/
|
|
728
|
-
isStarted(): boolean;
|
|
729
|
-
/**
|
|
730
|
-
* True if the App is ready. It means that Alepha is started AND ready() hook has beed called.
|
|
731
|
-
*/
|
|
732
|
-
isReady(): boolean;
|
|
733
|
-
/**
|
|
734
|
-
* True if the App is running in a Continuous Integration environment.
|
|
735
|
-
*/
|
|
736
|
-
isCI(): boolean;
|
|
737
|
-
/**
|
|
738
|
-
* True if the App is running in a browser environment.
|
|
739
|
-
*/
|
|
740
|
-
isBrowser(): boolean;
|
|
741
|
-
/**
|
|
742
|
-
* Returns whether the App is running in Vite dev mode.
|
|
743
|
-
*/
|
|
744
|
-
isViteDev(): boolean;
|
|
745
|
-
isBun(): boolean;
|
|
746
|
-
/**
|
|
747
|
-
* Returns whether the App is running in a serverless environment.
|
|
748
|
-
*/
|
|
749
|
-
isServerless(): boolean;
|
|
750
|
-
/**
|
|
751
|
-
* Returns whether the App is in test mode. (Running in a test environment)
|
|
752
|
-
*
|
|
753
|
-
* > This is automatically set when running tests with Jest or Vitest.
|
|
754
|
-
*/
|
|
755
|
-
isTest(): boolean;
|
|
756
|
-
/**
|
|
757
|
-
* Returns whether the App is in production mode. (Running in a production environment)
|
|
758
|
-
*
|
|
759
|
-
* > This is automatically set by Vite or Vercel. However, you have to set it manually when running Docker apps.
|
|
760
|
-
*/
|
|
761
|
-
isProduction(): boolean;
|
|
762
|
-
/**
|
|
763
|
-
* Starts the App.
|
|
764
|
-
*
|
|
765
|
-
* - Lock any further changes to the container.
|
|
766
|
-
* - Run "configure" hook for all services. Primitives will be processed.
|
|
767
|
-
* - Run "start" hook for all services. Providers will connect/listen/...
|
|
768
|
-
* - Run "ready" hook for all services. This is the point where the App is ready to serve requests.
|
|
769
|
-
*
|
|
770
|
-
* @return A promise that resolves when the App has started.
|
|
771
|
-
*/
|
|
772
|
-
start(): Promise<this>;
|
|
773
|
-
/**
|
|
774
|
-
* Stops the App.
|
|
775
|
-
*
|
|
776
|
-
* - Run "stop" hook for all services.
|
|
777
|
-
*
|
|
778
|
-
* Stop will NOT reset the container.
|
|
779
|
-
* Stop will NOT unlock the container.
|
|
780
|
-
*
|
|
781
|
-
* > Stop is used to gracefully shut down the application, nothing more. There is no "restart".
|
|
782
|
-
*
|
|
783
|
-
* @return A promise that resolves when the App has stopped.
|
|
784
|
-
*/
|
|
785
|
-
stop(): Promise<void>;
|
|
786
|
-
/**
|
|
787
|
-
* Check if entry is registered in the container.
|
|
788
|
-
*/
|
|
789
|
-
has(entry: ServiceEntry, opts?: {
|
|
790
|
-
/**
|
|
791
|
-
* Check if the entry is registered in the pending instantiation stack.
|
|
792
|
-
*
|
|
793
|
-
* @default true
|
|
794
|
-
*/
|
|
795
|
-
inStack?: boolean;
|
|
796
|
-
/**
|
|
797
|
-
* Check if the entry is registered in the container registry.
|
|
798
|
-
*
|
|
799
|
-
* @default true
|
|
800
|
-
*/
|
|
801
|
-
inRegistry?: boolean;
|
|
802
|
-
/**
|
|
803
|
-
* Check if the entry is registered in the substitutions.
|
|
804
|
-
*
|
|
805
|
-
* @default true
|
|
806
|
-
*/
|
|
807
|
-
inSubstitutions?: boolean;
|
|
808
|
-
/**
|
|
809
|
-
* Where to look for registered services.
|
|
810
|
-
*
|
|
811
|
-
* @default this.registry
|
|
812
|
-
*/
|
|
813
|
-
registry?: Map<Service, ServiceDefinition>;
|
|
814
|
-
}): boolean;
|
|
815
|
-
/**
|
|
816
|
-
* Registers the specified service in the container.
|
|
817
|
-
*
|
|
818
|
-
* - If the service is ALREADY registered, the method does nothing.
|
|
819
|
-
* - If the service is NOT registered, a new instance is created and registered.
|
|
820
|
-
*
|
|
821
|
-
* Method is chainable, so you can register multiple services in a single call.
|
|
822
|
-
*
|
|
823
|
-
* > ServiceEntry allows to provide a service **substitution** feature.
|
|
824
|
-
*
|
|
825
|
-
* @example
|
|
826
|
-
* ```ts
|
|
827
|
-
* class A { value = "a"; }
|
|
828
|
-
* class B { value = "b"; }
|
|
829
|
-
* class M { a = $inject(A); }
|
|
830
|
-
*
|
|
831
|
-
* Alepha.create().with({ provide: A, use: B }).get(M).a.value; // "b"
|
|
832
|
-
* ```
|
|
833
|
-
*
|
|
834
|
-
* > **Substitution** is an advanced feature that allows you to replace a service with another service.
|
|
835
|
-
* > It's useful for testing or for providing different implementations of a service.
|
|
836
|
-
* > If you are interested in configuring a service, use Alepha#configure() instead.
|
|
837
|
-
*
|
|
838
|
-
* @param serviceEntry - The service to register in the container.
|
|
839
|
-
* @return Current instance of Alepha.
|
|
840
|
-
*/
|
|
841
|
-
with<T extends object>(serviceEntry: ServiceEntry<T> | {
|
|
842
|
-
default: ServiceEntry<T>;
|
|
843
|
-
}): this;
|
|
844
|
-
/**
|
|
845
|
-
* Get an instance of the specified service from the container.
|
|
846
|
-
*
|
|
847
|
-
* @see {@link InjectOptions} for the available options.
|
|
848
|
-
*/
|
|
849
|
-
inject<T extends object>(service: Service<T> | string, opts?: InjectOptions<T>): T;
|
|
850
|
-
/**
|
|
851
|
-
* Applies environment variables to the provided schema and state object.
|
|
852
|
-
*
|
|
853
|
-
* It replaces also all templated $ENV inside string values.
|
|
854
|
-
*
|
|
855
|
-
* @param schema - The schema object to apply environment variables to.
|
|
856
|
-
* @return The schema object with environment variables applied.
|
|
857
|
-
*/
|
|
858
|
-
parseEnv<T extends TObject>(schema: T): Static<T>;
|
|
859
|
-
/**
|
|
860
|
-
* Get all environment variable schemas and their parsed values.
|
|
861
|
-
*
|
|
862
|
-
* This is useful for DevTools to display all expected environment variables.
|
|
863
|
-
*/
|
|
864
|
-
getEnvSchemas(): Array<{
|
|
865
|
-
schema: TSchema$1;
|
|
866
|
-
values: Record<string, any>;
|
|
867
|
-
}>;
|
|
868
|
-
/**
|
|
869
|
-
* Dump the current dependency graph of the App.
|
|
870
|
-
*
|
|
871
|
-
* This method returns a record where the keys are the names of the services.
|
|
872
|
-
*/
|
|
873
|
-
graph(): Record<string, {
|
|
874
|
-
from: string[];
|
|
875
|
-
as?: string[];
|
|
876
|
-
module?: string;
|
|
877
|
-
}>;
|
|
878
|
-
services<T extends object>(base: Service<T>): Array<T>;
|
|
879
|
-
/**
|
|
880
|
-
* Get all primitives of the specified type.
|
|
881
|
-
*/
|
|
882
|
-
primitives<TPrimitive extends Primitive>(factory: {
|
|
883
|
-
[KIND]: InstantiableClass<TPrimitive>;
|
|
884
|
-
} | string): Array<TPrimitive>;
|
|
885
|
-
protected new<T extends object>(service: Service<T>, args?: any[]): T;
|
|
886
|
-
protected processPrimitive(value: Primitive, propertyKey?: string): void;
|
|
887
|
-
}
|
|
888
|
-
interface Hook<T extends keyof Hooks = any> {
|
|
889
|
-
caller?: Service;
|
|
890
|
-
priority?: "first" | "last";
|
|
891
|
-
callback: (payload: Hooks[T]) => Async<void>;
|
|
892
|
-
}
|
|
893
|
-
/**
|
|
894
|
-
* This is how we store services in the Alepha container.
|
|
895
|
-
*/
|
|
896
|
-
interface ServiceDefinition<T extends object = any> {
|
|
897
|
-
/**
|
|
898
|
-
* The instance of the class or type definition.
|
|
899
|
-
* Mostly used for caching / singleton but can be used for other purposes like forcing the instance.
|
|
900
|
-
*/
|
|
901
|
-
instance: T;
|
|
902
|
-
/**
|
|
903
|
-
* List of classes which use this class.
|
|
904
|
-
*/
|
|
905
|
-
parents: Array<Service | null>;
|
|
906
|
-
}
|
|
907
|
-
interface Env {
|
|
908
|
-
[key: string]: string | boolean | number | undefined;
|
|
909
|
-
/**
|
|
910
|
-
* Optional environment variable that indicates the current environment.
|
|
911
|
-
*/
|
|
912
|
-
NODE_ENV?: string;
|
|
913
|
-
/**
|
|
914
|
-
* Optional name of the application.
|
|
915
|
-
*/
|
|
916
|
-
APP_NAME?: string;
|
|
917
|
-
/**
|
|
918
|
-
* Optional root module name.
|
|
919
|
-
*/
|
|
920
|
-
MODULE_NAME?: string;
|
|
921
|
-
}
|
|
922
|
-
interface State {
|
|
923
|
-
/**
|
|
924
|
-
* Environment variables for the application.
|
|
925
|
-
*/
|
|
926
|
-
env?: Readonly<Env>;
|
|
927
|
-
/**
|
|
928
|
-
* Logger instance to be used by the Alepha container.
|
|
929
|
-
*
|
|
930
|
-
* @internal
|
|
931
|
-
*/
|
|
932
|
-
"alepha.logger"?: LoggerInterface;
|
|
933
|
-
/**
|
|
934
|
-
* If defined, the Alepha container will only register this service and its dependencies.
|
|
935
|
-
*
|
|
936
|
-
* @example
|
|
937
|
-
* ```ts
|
|
938
|
-
* class MigrateCmd {
|
|
939
|
-
* db = $inject(DatabaseProvider);
|
|
940
|
-
* alepha = $inject(Alepha);
|
|
941
|
-
* env = $env(
|
|
942
|
-
* t.object({
|
|
943
|
-
* MIGRATE: t.optional(t.boolean()),
|
|
944
|
-
* }),
|
|
945
|
-
* );
|
|
946
|
-
*
|
|
947
|
-
* constructor() {
|
|
948
|
-
* if (this.env.MIGRATE) {
|
|
949
|
-
* this.alepha.set("alepha.target", MigrateCmd);
|
|
950
|
-
* }
|
|
951
|
-
* }
|
|
952
|
-
*
|
|
953
|
-
* ready = $hook({
|
|
954
|
-
* on: "ready",
|
|
955
|
-
* handler: async () => {
|
|
956
|
-
* if (this.env.MIGRATE) {
|
|
957
|
-
* await this.db.migrate();
|
|
958
|
-
* }
|
|
959
|
-
* },
|
|
960
|
-
* });
|
|
961
|
-
* }
|
|
962
|
-
* ```
|
|
963
|
-
*/
|
|
964
|
-
"alepha.target"?: Service;
|
|
965
|
-
/**
|
|
966
|
-
* Bind to Vitest 'beforeAll' hook.
|
|
967
|
-
* Used for testing purposes.
|
|
968
|
-
* This is automatically attached if Alepha#create() detects a test environment and global 'beforeAll' is available.
|
|
969
|
-
*/
|
|
970
|
-
"alepha.test.beforeAll"?: (run: any) => any;
|
|
971
|
-
/**
|
|
972
|
-
* Bind to Vitest 'afterAll' hook.
|
|
973
|
-
* Used for testing purposes.
|
|
974
|
-
* This is automatically attached if Alepha#create() detects a test environment and global 'afterAll' is available.
|
|
975
|
-
*/
|
|
976
|
-
"alepha.test.afterAll"?: (run: any) => any;
|
|
977
|
-
/**
|
|
978
|
-
* Bind to Vitest 'afterEach' hook.
|
|
979
|
-
* Used for testing purposes.
|
|
980
|
-
* This is automatically attached if Alepha#create() detects a test environment and global 'afterEach' is available.
|
|
981
|
-
*/
|
|
982
|
-
"alepha.test.afterEach"?: (run: any) => any;
|
|
983
|
-
/**
|
|
984
|
-
* Bind to Vitest 'onTestFinished' hook.
|
|
985
|
-
* Used for testing purposes.
|
|
986
|
-
* This is automatically attached if Alepha#create() detects a test environment and global 'onTestFinished' is available.
|
|
987
|
-
*/
|
|
988
|
-
"alepha.test.onTestFinished"?: (run: any) => any;
|
|
989
|
-
/**
|
|
990
|
-
* List of static assets to be copied to the output directory during the build process.
|
|
991
|
-
*
|
|
992
|
-
* Used for Alepha-based applications that require static assets.
|
|
993
|
-
*
|
|
994
|
-
* See alepha/vite for more details.
|
|
995
|
-
*/
|
|
996
|
-
"alepha.build.assets"?: Array<string>;
|
|
997
|
-
}
|
|
998
|
-
interface Hooks {
|
|
999
|
-
/**
|
|
1000
|
-
* Used for testing purposes.
|
|
1001
|
-
*/
|
|
1002
|
-
echo: unknown;
|
|
1003
|
-
/**
|
|
1004
|
-
* Triggered during the configuration phase. Before the start phase.
|
|
1005
|
-
*/
|
|
1006
|
-
configure: Alepha;
|
|
1007
|
-
/**
|
|
1008
|
-
* Triggered during the start phase. When `Alepha#start()` is called.
|
|
1009
|
-
*/
|
|
1010
|
-
start: Alepha;
|
|
1011
|
-
/**
|
|
1012
|
-
* Triggered during the ready phase. After the start phase.
|
|
1013
|
-
*/
|
|
1014
|
-
ready: Alepha;
|
|
1015
|
-
/**
|
|
1016
|
-
* Triggered during the stop phase.
|
|
1017
|
-
*
|
|
1018
|
-
* - Stop should be called after a SIGINT or SIGTERM signal in order to gracefully shutdown the application. (@see `run()` method)
|
|
1019
|
-
*
|
|
1020
|
-
*/
|
|
1021
|
-
stop: Alepha;
|
|
1022
|
-
/**
|
|
1023
|
-
* Triggered when a state value is mutated.
|
|
1024
|
-
*/
|
|
1025
|
-
"state:mutate": {
|
|
1026
|
-
/**
|
|
1027
|
-
* The key of the state that was mutated.
|
|
1028
|
-
*/
|
|
1029
|
-
key: keyof State;
|
|
1030
|
-
/**
|
|
1031
|
-
* The new value of the state.
|
|
1032
|
-
*/
|
|
1033
|
-
value: any;
|
|
1034
|
-
/**
|
|
1035
|
-
* The previous value of the state.
|
|
1036
|
-
*/
|
|
1037
|
-
prevValue: any;
|
|
1038
|
-
};
|
|
1039
|
-
}
|
|
1040
|
-
//#endregion
|
|
1041
|
-
//#region ../alepha/src/core/schemas/pageSchema.d.ts
|
|
1042
|
-
declare const pageMetadataSchema: TObject$1<{
|
|
1043
|
-
number: TInteger;
|
|
1044
|
-
size: TInteger;
|
|
1045
|
-
offset: TInteger;
|
|
1046
|
-
numberOfElements: TInteger;
|
|
1047
|
-
totalElements: TOptional<TInteger>;
|
|
1048
|
-
totalPages: TOptional<TInteger>;
|
|
1049
|
-
isEmpty: TBoolean;
|
|
1050
|
-
isFirst: TBoolean;
|
|
1051
|
-
isLast: TBoolean;
|
|
1052
|
-
sort: TOptional<TObject$1<{
|
|
1053
|
-
sorted: TBoolean;
|
|
1054
|
-
fields: TArray$1<TObject$1<{
|
|
1055
|
-
field: TString;
|
|
1056
|
-
direction: TUnsafe<"asc" | "desc">;
|
|
1057
|
-
}>>;
|
|
1058
|
-
}>>;
|
|
1059
|
-
}>;
|
|
1060
|
-
type TPage<T extends TObject$1 | TRecord> = TObject$1<{
|
|
1061
|
-
content: TArray$1<T>;
|
|
1062
|
-
page: typeof pageMetadataSchema;
|
|
1063
|
-
}>;
|
|
1064
|
-
declare module "alepha" {
|
|
1065
|
-
interface TypeProvider {
|
|
1066
|
-
/**
|
|
1067
|
-
* Create a schema for a paginated response.
|
|
1068
|
-
*/
|
|
1069
|
-
page<T extends TObject$1 | TRecord>(itemSchema: T): TPage<T>;
|
|
1070
|
-
}
|
|
1071
|
-
}
|
|
1072
|
-
//#endregion
|
|
1073
6
|
//#region src/providers/ProtobufProvider.d.ts
|
|
1074
7
|
declare class ProtobufProvider {
|
|
1075
8
|
protected readonly alepha: Alepha;
|
|
1076
|
-
protected readonly schemas: Map<string | TObject
|
|
9
|
+
protected readonly schemas: Map<string | TObject, Type>;
|
|
1077
10
|
protected readonly protobuf: typeof protobufjs;
|
|
1078
11
|
protected readonly enumDefinitions: Map<string, string[]>;
|
|
1079
12
|
/**
|
|
1080
|
-
|
|
1081
|
-
|
|
13
|
+
* Encode an object to a Uint8Array.
|
|
14
|
+
*/
|
|
1082
15
|
encode(schema: ProtobufSchema, message: any): Uint8Array;
|
|
1083
16
|
/**
|
|
1084
|
-
|
|
1085
|
-
|
|
17
|
+
* Decode a Uint8Array to an object.
|
|
18
|
+
*/
|
|
1086
19
|
decode<T = any>(schema: ProtobufSchema, data: Uint8Array): T;
|
|
1087
20
|
/**
|
|
1088
|
-
|
|
1089
|
-
|
|
21
|
+
* Parse a TypeBox schema to a Protobuf Type schema ready for encoding/decoding.
|
|
22
|
+
*/
|
|
1090
23
|
parse(schema: ProtobufSchema, typeName?: string): Type;
|
|
1091
24
|
/**
|
|
1092
|
-
|
|
1093
|
-
|
|
1094
|
-
createProtobufSchema(schema: TSchema
|
|
25
|
+
* Convert a TypeBox schema to a Protobuf schema as a string.
|
|
26
|
+
*/
|
|
27
|
+
createProtobufSchema(schema: TSchema, options?: CreateProtobufSchemaOptions): string;
|
|
1095
28
|
/**
|
|
1096
|
-
|
|
1097
|
-
|
|
1098
|
-
protected parseObjectWithDependencies(obj: TSchema
|
|
29
|
+
* Parse an object schema with dependencies (sub-messages).
|
|
30
|
+
*/
|
|
31
|
+
protected parseObjectWithDependencies(obj: TSchema, parentName: string): {
|
|
1099
32
|
message: string;
|
|
1100
33
|
subMessages: string[];
|
|
1101
34
|
};
|
|
1102
35
|
/**
|
|
1103
|
-
|
|
1104
|
-
|
|
1105
|
-
protected convertType(schema: TSchema
|
|
36
|
+
* Convert a primitive TypeBox schema type to a Protobuf spec type.
|
|
37
|
+
*/
|
|
38
|
+
protected convertType(schema: TSchema): string;
|
|
1106
39
|
/**
|
|
1107
|
-
|
|
1108
|
-
|
|
1109
|
-
|
|
1110
|
-
protected isEnum(schema: TSchema
|
|
40
|
+
* Check if a schema is an enum type.
|
|
41
|
+
* TypeBox enums have an "enum" property with an array of values.
|
|
42
|
+
*/
|
|
43
|
+
protected isEnum(schema: TSchema): boolean;
|
|
1111
44
|
/**
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
protected getEnumValues(schema: TSchema
|
|
45
|
+
* Extract enum values from a TypeBox enum schema.
|
|
46
|
+
*/
|
|
47
|
+
protected getEnumValues(schema: TSchema): string[];
|
|
1115
48
|
/**
|
|
1116
|
-
|
|
1117
|
-
|
|
1118
|
-
|
|
49
|
+
* Register an enum and return its type name.
|
|
50
|
+
* Generates a PascalCase name from the field name.
|
|
51
|
+
*/
|
|
1119
52
|
protected registerEnum(fieldName: string, values: string[]): string;
|
|
1120
53
|
/**
|
|
1121
|
-
|
|
1122
|
-
|
|
54
|
+
* Generate a protobuf enum definition.
|
|
55
|
+
*/
|
|
1123
56
|
protected generateEnumDefinition(enumName: string, values: string[]): string;
|
|
1124
57
|
}
|
|
1125
58
|
type ProtobufSchema = string;
|
|
@@ -1141,31 +74,31 @@ interface CreateProtobufSchemaOptions {
|
|
|
1141
74
|
declare class ProtobufSchemaCodec extends SchemaCodec {
|
|
1142
75
|
protected protobufProvider: ProtobufProvider;
|
|
1143
76
|
protected decoder: TextDecoder;
|
|
1144
|
-
encodeToString<T extends TSchema
|
|
1145
|
-
encodeToBinary<T extends TSchema
|
|
1146
|
-
decode<T>(schema: TSchema
|
|
77
|
+
encodeToString<T extends TSchema>(schema: T, value: Static<T>): string;
|
|
78
|
+
encodeToBinary<T extends TSchema>(schema: T, value: Static<T>): Uint8Array;
|
|
79
|
+
decode<T>(schema: TSchema, value: unknown): T;
|
|
1147
80
|
/**
|
|
1148
|
-
|
|
1149
|
-
|
|
1150
|
-
|
|
1151
|
-
|
|
1152
|
-
protected applyProto3Defaults(schema: TSchema
|
|
81
|
+
* Apply proto3 default values for fields that were omitted during encoding.
|
|
82
|
+
* Proto3 omits fields with default values, so we need to restore them.
|
|
83
|
+
* Also converts enum integers back to their string values.
|
|
84
|
+
*/
|
|
85
|
+
protected applyProto3Defaults(schema: TSchema, value: any): any;
|
|
1153
86
|
/**
|
|
1154
|
-
|
|
1155
|
-
|
|
1156
|
-
protected isEnum(schema: TSchema
|
|
87
|
+
* Check if a schema is an enum type.
|
|
88
|
+
*/
|
|
89
|
+
protected isEnum(schema: TSchema): boolean;
|
|
1157
90
|
/**
|
|
1158
|
-
|
|
1159
|
-
|
|
1160
|
-
protected convertEnumValue(schema: TSchema
|
|
91
|
+
* Convert an enum value from protobuf integer to TypeBox string.
|
|
92
|
+
*/
|
|
93
|
+
protected convertEnumValue(schema: TSchema, value: any): any;
|
|
1161
94
|
/**
|
|
1162
|
-
|
|
1163
|
-
|
|
1164
|
-
protected getProto3Default(schema: TSchema
|
|
95
|
+
* Get the proto3 default value for a schema type.
|
|
96
|
+
*/
|
|
97
|
+
protected getProto3Default(schema: TSchema): any;
|
|
1165
98
|
}
|
|
1166
99
|
//#endregion
|
|
1167
100
|
//#region src/index.d.ts
|
|
1168
|
-
declare const AlephaProtobuf: Service<Module>;
|
|
101
|
+
declare const AlephaProtobuf: alepha0.Service<alepha0.Module>;
|
|
1169
102
|
//#endregion
|
|
1170
103
|
export { AlephaProtobuf, CreateProtobufSchemaOptions, ProtobufProvider, ProtobufSchema, ProtobufSchemaCodec };
|
|
1171
104
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -270,7 +270,10 @@ const AlephaProtobuf = $module({
|
|
|
270
270
|
services: [ProtobufProvider, ProtobufSchemaCodec],
|
|
271
271
|
register: (alepha) => {
|
|
272
272
|
alepha.with(ProtobufProvider);
|
|
273
|
-
alepha.codec.register(
|
|
273
|
+
alepha.codec.register({
|
|
274
|
+
name: "protobuf",
|
|
275
|
+
codec: alepha.inject(ProtobufSchemaCodec)
|
|
276
|
+
});
|
|
274
277
|
}
|
|
275
278
|
});
|
|
276
279
|
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["fieldType"],"sources":["../src/providers/ProtobufProvider.ts","../src/providers/ProtobufSchemaCodec.ts","../src/index.ts"],"sourcesContent":["import { $inject, Alepha, type TObject, type TSchema, t } from \"alepha\";\nimport type { Type } from \"protobufjs\";\nimport protobufjs from \"protobufjs\";\n\nexport class ProtobufProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly schemas: Map<string | TObject, Type> = new Map();\n protected readonly protobuf: typeof protobufjs = protobufjs;\n protected readonly enumDefinitions: Map<string, string[]> = new Map();\n\n /**\n * Encode an object to a Uint8Array.\n */\n public encode(schema: ProtobufSchema, message: any): Uint8Array {\n return this.parse(schema).encode(message).finish();\n }\n\n /**\n * Decode a Uint8Array to an object.\n */\n public decode<T = any>(schema: ProtobufSchema, data: Uint8Array): T {\n return this.parse(schema).decode(data) as T;\n }\n\n /**\n * Parse a TypeBox schema to a Protobuf Type schema ready for encoding/decoding.\n */\n public parse(schema: ProtobufSchema, typeName = \"root.Target\"): Type {\n const exists = this.schemas.get(schema);\n if (exists) {\n return exists;\n }\n\n const result = this.protobuf.parse(schema);\n const type = result.root.lookupType(typeName);\n this.schemas.set(schema, type);\n return type;\n }\n\n /**\n * Convert a TypeBox schema to a Protobuf schema as a string.\n */\n public createProtobufSchema(\n schema: TSchema,\n options: CreateProtobufSchemaOptions = {},\n ): string {\n const { rootName = \"root\", mainMessageName = \"Target\" } = options;\n // Clear enum definitions for this schema generation\n this.enumDefinitions.clear();\n\n const context = {\n proto: `package ${rootName};\\nsyntax = \"proto3\";\\n\\n`,\n fieldIndex: 1,\n };\n\n if (t.schema.isObject(schema)) {\n const { message, subMessages } = this.parseObjectWithDependencies(\n schema,\n mainMessageName,\n );\n\n // Add all enum definitions first\n for (const [enumName, values] of this.enumDefinitions) {\n context.proto += this.generateEnumDefinition(enumName, values);\n }\n\n // Add all sub-messages\n context.proto += subMessages.join(\"\");\n // Then add the main message\n context.proto += message;\n }\n\n return context.proto;\n }\n\n /**\n * Parse an object schema with dependencies (sub-messages).\n */\n protected parseObjectWithDependencies(\n obj: TSchema,\n parentName: string,\n ): { message: string; subMessages: string[] } {\n if (!t.schema.isObject(obj)) {\n return { message: \"\", subMessages: [] };\n }\n\n const fields: string[] = [];\n const subMessages: string[] = [];\n let fieldIndex = 1;\n\n for (const [key, value] of Object.entries(obj.properties)) {\n // Handle arrays\n if (t.schema.isArray(value)) {\n // Check if array items are enums\n if (this.isEnum(value.items)) {\n const enumValues = this.getEnumValues(value.items);\n const enumName = this.registerEnum(key, enumValues);\n fields.push(` repeated ${enumName} ${key} = ${fieldIndex++};`);\n continue;\n }\n\n if (t.schema.isObject(value.items)) {\n const subMessageName =\n \"title\" in value.items && typeof value.items.title === \"string\"\n ? value.items.title\n : `${parentName}_${key}`;\n const { message: subMessage, subMessages: nestedSubMessages } =\n this.parseObjectWithDependencies(value.items, subMessageName);\n subMessages.push(...nestedSubMessages);\n subMessages.push(subMessage);\n fields.push(` repeated ${subMessageName} ${key} = ${fieldIndex++};`);\n continue;\n }\n\n const itemType = this.convertType(value.items);\n fields.push(` repeated ${itemType} ${key} = ${fieldIndex++};`);\n continue;\n }\n\n // Handle nested objects\n if (t.schema.isObject(value)) {\n const subMessageName =\n \"title\" in value && typeof value.title === \"string\"\n ? value.title\n : `${parentName}_${key}`;\n const { message: subMessage, subMessages: nestedSubMessages } =\n this.parseObjectWithDependencies(value, subMessageName);\n subMessages.push(...nestedSubMessages);\n subMessages.push(subMessage);\n fields.push(` ${subMessageName} ${key} = ${fieldIndex++};`);\n continue;\n }\n\n // Handle union types (nullable fields)\n if (t.schema.isUnion(value)) {\n const nonNullType = value.anyOf.find(\n (type: TSchema) => !t.schema.isNull(type),\n );\n if (nonNullType) {\n // Check if it's an enum\n if (this.isEnum(nonNullType)) {\n const enumValues = this.getEnumValues(nonNullType);\n const enumName = this.registerEnum(key, enumValues);\n fields.push(` ${enumName} ${key} = ${fieldIndex++};`);\n continue;\n }\n\n if (t.schema.isObject(nonNullType)) {\n const subMessageName =\n \"title\" in nonNullType && typeof nonNullType.title === \"string\"\n ? nonNullType.title\n : `${parentName}_${key}`;\n const { message: subMessage, subMessages: nestedSubMessages } =\n this.parseObjectWithDependencies(nonNullType, subMessageName);\n subMessages.push(...nestedSubMessages);\n subMessages.push(subMessage);\n fields.push(` ${subMessageName} ${key} = ${fieldIndex++};`);\n continue;\n }\n const fieldType = this.convertType(nonNullType);\n fields.push(` ${fieldType} ${key} = ${fieldIndex++};`);\n continue;\n }\n }\n\n // Handle records (maps)\n if (t.schema.isRecord(value)) {\n // TypeBox records use additionalProperties or patternProperties for the value type\n let valueSchema: TSchema | undefined;\n if (\n \"additionalProperties\" in value &&\n value.additionalProperties &&\n typeof value.additionalProperties === \"object\"\n ) {\n valueSchema = value.additionalProperties;\n } else if (\n value.patternProperties &&\n typeof value.patternProperties === \"object\"\n ) {\n // Get the first pattern property (usually \"^(.*)$\" or similar)\n const patterns = Object.values(value.patternProperties);\n if (patterns.length > 0 && typeof patterns[0] === \"object\") {\n valueSchema = patterns[0] as TSchema;\n }\n }\n\n if (valueSchema) {\n const valueType = this.convertType(valueSchema);\n fields.push(` map<string, ${valueType}> ${key} = ${fieldIndex++};`);\n continue;\n }\n }\n\n // Handle enum fields\n if (this.isEnum(value)) {\n const enumValues = this.getEnumValues(value);\n const enumName = this.registerEnum(key, enumValues);\n fields.push(` ${enumName} ${key} = ${fieldIndex++};`);\n continue;\n }\n\n // Handle regular fields\n const fieldType = this.convertType(value);\n fields.push(` ${fieldType} ${key} = ${fieldIndex++};`);\n }\n\n const message = `message ${parentName} {\\n${fields.join(\"\\n\")}\\n}\\n`;\n return { message, subMessages };\n }\n\n /**\n * Convert a primitive TypeBox schema type to a Protobuf spec type.\n */\n protected convertType(schema: TSchema): string {\n if (t.schema.isBoolean(schema)) return \"bool\";\n if (t.schema.isNumber(schema) && schema.format === \"int64\") return \"int64\";\n if (t.schema.isNumber(schema)) return \"double\";\n if (t.schema.isInteger(schema)) return \"int32\";\n if (t.schema.isBigInt(schema)) return \"int64\";\n if (t.schema.isString(schema)) return \"string\";\n\n // Handle union types (nullable)\n if (t.schema.isUnion(schema)) {\n // Find the non-null type in the union\n const nonNullType = schema.anyOf.find(\n (type: TSchema) => !t.schema.isNull(type),\n );\n if (nonNullType) {\n return this.convertType(nonNullType);\n }\n }\n\n // Handle optional types\n if (t.schema.isOptional(schema)) {\n return this.convertType(schema);\n }\n\n // Handle unsafe types (like enums)\n if (t.schema.isUnsafe(schema)) {\n // if it's an enum or other unsafe types, default to string\n return \"string\";\n }\n\n throw new Error(`Unsupported type: ${JSON.stringify(schema)}`);\n }\n\n /**\n * Check if a schema is an enum type.\n * TypeBox enums have an \"enum\" property with an array of values.\n */\n protected isEnum(schema: TSchema): boolean {\n return \"enum\" in schema && Array.isArray(schema.enum);\n }\n\n /**\n * Extract enum values from a TypeBox enum schema.\n */\n protected getEnumValues(schema: TSchema): string[] {\n if (\"enum\" in schema && Array.isArray(schema.enum)) {\n return schema.enum.map(String);\n }\n return [];\n }\n\n /**\n * Register an enum and return its type name.\n * Generates a PascalCase name from the field name.\n */\n protected registerEnum(fieldName: string, values: string[]): string {\n // Capitalize first letter of field name for enum type name\n const enumName = fieldName.charAt(0).toUpperCase() + fieldName.slice(1);\n\n // Check if we already have this exact enum registered\n const valueKey = values.join(\",\");\n const existingEnum = Array.from(this.enumDefinitions.entries()).find(\n ([_, enumValues]) => enumValues.join(\",\") === valueKey,\n );\n\n if (existingEnum) {\n // Reuse existing enum with same values\n return existingEnum[0];\n }\n\n // Register new enum\n this.enumDefinitions.set(enumName, values);\n return enumName;\n }\n\n /**\n * Generate a protobuf enum definition.\n */\n protected generateEnumDefinition(enumName: string, values: string[]): string {\n const enumValues = values\n .map((value, index) => ` ${value} = ${index};`)\n .join(\"\\n\");\n return `enum ${enumName} {\\n${enumValues}\\n}\\n`;\n }\n}\n\nexport type ProtobufSchema = string;\n\nexport interface CreateProtobufSchemaOptions {\n rootName?: string;\n mainMessageName?: string;\n}\n","import {\n $inject,\n AlephaError,\n SchemaCodec,\n type Static,\n type TSchema,\n t,\n} from \"alepha\";\nimport \"alepha/datetime\";\nimport { ProtobufProvider } from \"./ProtobufProvider.ts\";\n\n/**\n * ProtobufSchemaCodec handles encoding/decoding for Protobuf format.\n *\n * Key differences from JSON codec:\n * - BigInt values are kept as BigInt (not converted to string)\n * - Date values are converted to ISO strings for protobuf compatibility\n * - Binary data (Uint8Array) is kept as-is\n * - Proto3 default values are applied when decoding (to handle omitted fields)\n */\nexport class ProtobufSchemaCodec extends SchemaCodec {\n protected protobufProvider = $inject(ProtobufProvider);\n protected decoder = new TextDecoder();\n\n public encodeToString<T extends TSchema>(\n schema: T,\n value: Static<T>,\n ): string {\n const binary = this.encodeToBinary(schema, value);\n // convert binary to base64 string for text representation\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(binary).toString(\"base64\");\n } else {\n return btoa(String.fromCharCode(...binary));\n }\n }\n\n public encodeToBinary<T extends TSchema>(\n schema: T,\n value: Static<T>,\n ): Uint8Array {\n const proto = this.protobufProvider.createProtobufSchema(schema);\n return this.protobufProvider.encode(proto, value);\n }\n\n public decode<T>(schema: TSchema, value: unknown): T {\n // First decode from protobuf binary to object\n const proto = this.protobufProvider.createProtobufSchema(schema);\n\n if (value instanceof Uint8Array) {\n return this.applyProto3Defaults(\n schema,\n this.protobufProvider.decode(proto, value),\n );\n }\n\n if (typeof value === \"string\") {\n return this.applyProto3Defaults(\n schema,\n this.protobufProvider.decode(\n proto,\n typeof Buffer !== \"undefined\"\n ? Uint8Array.from(Buffer.from(value, \"base64\"))\n : Uint8Array.from(\n atob(value)\n .split(\"\")\n .map((c) => c.charCodeAt(0)),\n ),\n ),\n );\n }\n\n throw new AlephaError(\n `Unsupported value type for Protobuf decoding: ${typeof value}`,\n );\n }\n\n /**\n * Apply proto3 default values for fields that were omitted during encoding.\n * Proto3 omits fields with default values, so we need to restore them.\n * Also converts enum integers back to their string values.\n */\n protected applyProto3Defaults(schema: TSchema, value: any): any {\n if (!value || typeof value !== \"object\") {\n return value;\n }\n\n if (t.schema.isObject(schema)) {\n const result: any = { ...value };\n\n for (const [key, propSchema] of Object.entries(schema.properties)) {\n if (!(key in result) || result[key] === undefined) {\n // Apply proto3 default values based on type\n result[key] = this.getProto3Default(propSchema);\n } else {\n // Convert enum integers to strings\n if (this.isEnum(propSchema)) {\n result[key] = this.convertEnumValue(propSchema, result[key]);\n } else if (typeof result[key] === \"object\" && result[key] !== null) {\n // Recursively apply defaults to nested objects\n result[key] = this.applyProto3Defaults(propSchema, result[key]);\n }\n }\n }\n\n return result;\n }\n\n if (t.schema.isArray(schema) && Array.isArray(value)) {\n return value.map((item) => this.applyProto3Defaults(schema.items, item));\n }\n\n return value;\n }\n\n /**\n * Check if a schema is an enum type.\n */\n protected isEnum(schema: TSchema): boolean {\n return \"enum\" in schema && Array.isArray(schema.enum);\n }\n\n /**\n * Convert an enum value from protobuf integer to TypeBox string.\n */\n protected convertEnumValue(schema: TSchema, value: any): any {\n if (\n typeof value === \"number\" &&\n \"enum\" in schema &&\n Array.isArray(schema.enum)\n ) {\n // Protobuf encodes enums as integers, convert back to string\n return schema.enum[value];\n }\n return value;\n }\n\n /**\n * Get the proto3 default value for a schema type.\n */\n protected getProto3Default(schema: TSchema): any {\n // Handle nullable/optional types - they can be undefined\n if (t.schema.isOptional(schema) || t.schema.isUnion(schema)) {\n return undefined;\n }\n\n // Handle arrays - default is empty array\n if (t.schema.isArray(schema)) {\n return [];\n }\n\n // Handle records (maps) - default is empty object\n if (t.schema.isRecord(schema)) {\n return {};\n }\n\n // Handle primitive types\n if (t.schema.isString(schema)) return \"\";\n if (t.schema.isNumber(schema)) return 0;\n if (t.schema.isInteger(schema)) return 0;\n if (t.schema.isBigInt(schema)) return BigInt(0);\n if (t.schema.isBoolean(schema)) return false;\n\n // For objects, return empty object (will be filled in recursively)\n if (t.schema.isObject(schema)) {\n return {};\n }\n\n return undefined;\n }\n}\n","import { $module } from \"alepha\";\nimport { ProtobufProvider } from \"./providers/ProtobufProvider.ts\";\nimport { ProtobufSchemaCodec } from \"./providers/ProtobufSchemaCodec.ts\";\n\nexport * from \"./providers/ProtobufProvider.ts\";\nexport * from \"./providers/ProtobufSchemaCodec.ts\";\n\nexport const AlephaProtobuf = $module({\n name: \"alepha.protobuf\",\n services: [ProtobufProvider, ProtobufSchemaCodec],\n register: (alepha) => {\n alepha.with(ProtobufProvider);\n alepha.codec.register(\"protobuf\", alepha.inject(ProtobufSchemaCodec));\n },\n});\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["fieldType"],"sources":["../src/providers/ProtobufProvider.ts","../src/providers/ProtobufSchemaCodec.ts","../src/index.ts"],"sourcesContent":["import { $inject, Alepha, type TObject, type TSchema, t } from \"alepha\";\nimport type { Type } from \"protobufjs\";\nimport protobufjs from \"protobufjs\";\n\nexport class ProtobufProvider {\n protected readonly alepha = $inject(Alepha);\n protected readonly schemas: Map<string | TObject, Type> = new Map();\n protected readonly protobuf: typeof protobufjs = protobufjs;\n protected readonly enumDefinitions: Map<string, string[]> = new Map();\n\n /**\n * Encode an object to a Uint8Array.\n */\n public encode(schema: ProtobufSchema, message: any): Uint8Array {\n return this.parse(schema).encode(message).finish();\n }\n\n /**\n * Decode a Uint8Array to an object.\n */\n public decode<T = any>(schema: ProtobufSchema, data: Uint8Array): T {\n return this.parse(schema).decode(data) as T;\n }\n\n /**\n * Parse a TypeBox schema to a Protobuf Type schema ready for encoding/decoding.\n */\n public parse(schema: ProtobufSchema, typeName = \"root.Target\"): Type {\n const exists = this.schemas.get(schema);\n if (exists) {\n return exists;\n }\n\n const result = this.protobuf.parse(schema);\n const type = result.root.lookupType(typeName);\n this.schemas.set(schema, type);\n return type;\n }\n\n /**\n * Convert a TypeBox schema to a Protobuf schema as a string.\n */\n public createProtobufSchema(\n schema: TSchema,\n options: CreateProtobufSchemaOptions = {},\n ): string {\n const { rootName = \"root\", mainMessageName = \"Target\" } = options;\n // Clear enum definitions for this schema generation\n this.enumDefinitions.clear();\n\n const context = {\n proto: `package ${rootName};\\nsyntax = \"proto3\";\\n\\n`,\n fieldIndex: 1,\n };\n\n if (t.schema.isObject(schema)) {\n const { message, subMessages } = this.parseObjectWithDependencies(\n schema,\n mainMessageName,\n );\n\n // Add all enum definitions first\n for (const [enumName, values] of this.enumDefinitions) {\n context.proto += this.generateEnumDefinition(enumName, values);\n }\n\n // Add all sub-messages\n context.proto += subMessages.join(\"\");\n // Then add the main message\n context.proto += message;\n }\n\n return context.proto;\n }\n\n /**\n * Parse an object schema with dependencies (sub-messages).\n */\n protected parseObjectWithDependencies(\n obj: TSchema,\n parentName: string,\n ): { message: string; subMessages: string[] } {\n if (!t.schema.isObject(obj)) {\n return { message: \"\", subMessages: [] };\n }\n\n const fields: string[] = [];\n const subMessages: string[] = [];\n let fieldIndex = 1;\n\n for (const [key, value] of Object.entries(obj.properties)) {\n // Handle arrays\n if (t.schema.isArray(value)) {\n // Check if array items are enums\n if (this.isEnum(value.items)) {\n const enumValues = this.getEnumValues(value.items);\n const enumName = this.registerEnum(key, enumValues);\n fields.push(` repeated ${enumName} ${key} = ${fieldIndex++};`);\n continue;\n }\n\n if (t.schema.isObject(value.items)) {\n const subMessageName =\n \"title\" in value.items && typeof value.items.title === \"string\"\n ? value.items.title\n : `${parentName}_${key}`;\n const { message: subMessage, subMessages: nestedSubMessages } =\n this.parseObjectWithDependencies(value.items, subMessageName);\n subMessages.push(...nestedSubMessages);\n subMessages.push(subMessage);\n fields.push(` repeated ${subMessageName} ${key} = ${fieldIndex++};`);\n continue;\n }\n\n const itemType = this.convertType(value.items);\n fields.push(` repeated ${itemType} ${key} = ${fieldIndex++};`);\n continue;\n }\n\n // Handle nested objects\n if (t.schema.isObject(value)) {\n const subMessageName =\n \"title\" in value && typeof value.title === \"string\"\n ? value.title\n : `${parentName}_${key}`;\n const { message: subMessage, subMessages: nestedSubMessages } =\n this.parseObjectWithDependencies(value, subMessageName);\n subMessages.push(...nestedSubMessages);\n subMessages.push(subMessage);\n fields.push(` ${subMessageName} ${key} = ${fieldIndex++};`);\n continue;\n }\n\n // Handle union types (nullable fields)\n if (t.schema.isUnion(value)) {\n const nonNullType = value.anyOf.find(\n (type: TSchema) => !t.schema.isNull(type),\n );\n if (nonNullType) {\n // Check if it's an enum\n if (this.isEnum(nonNullType)) {\n const enumValues = this.getEnumValues(nonNullType);\n const enumName = this.registerEnum(key, enumValues);\n fields.push(` ${enumName} ${key} = ${fieldIndex++};`);\n continue;\n }\n\n if (t.schema.isObject(nonNullType)) {\n const subMessageName =\n \"title\" in nonNullType && typeof nonNullType.title === \"string\"\n ? nonNullType.title\n : `${parentName}_${key}`;\n const { message: subMessage, subMessages: nestedSubMessages } =\n this.parseObjectWithDependencies(nonNullType, subMessageName);\n subMessages.push(...nestedSubMessages);\n subMessages.push(subMessage);\n fields.push(` ${subMessageName} ${key} = ${fieldIndex++};`);\n continue;\n }\n const fieldType = this.convertType(nonNullType);\n fields.push(` ${fieldType} ${key} = ${fieldIndex++};`);\n continue;\n }\n }\n\n // Handle records (maps)\n if (t.schema.isRecord(value)) {\n // TypeBox records use additionalProperties or patternProperties for the value type\n let valueSchema: TSchema | undefined;\n if (\n \"additionalProperties\" in value &&\n value.additionalProperties &&\n typeof value.additionalProperties === \"object\"\n ) {\n valueSchema = value.additionalProperties;\n } else if (\n value.patternProperties &&\n typeof value.patternProperties === \"object\"\n ) {\n // Get the first pattern property (usually \"^(.*)$\" or similar)\n const patterns = Object.values(value.patternProperties);\n if (patterns.length > 0 && typeof patterns[0] === \"object\") {\n valueSchema = patterns[0] as TSchema;\n }\n }\n\n if (valueSchema) {\n const valueType = this.convertType(valueSchema);\n fields.push(` map<string, ${valueType}> ${key} = ${fieldIndex++};`);\n continue;\n }\n }\n\n // Handle enum fields\n if (this.isEnum(value)) {\n const enumValues = this.getEnumValues(value);\n const enumName = this.registerEnum(key, enumValues);\n fields.push(` ${enumName} ${key} = ${fieldIndex++};`);\n continue;\n }\n\n // Handle regular fields\n const fieldType = this.convertType(value);\n fields.push(` ${fieldType} ${key} = ${fieldIndex++};`);\n }\n\n const message = `message ${parentName} {\\n${fields.join(\"\\n\")}\\n}\\n`;\n return { message, subMessages };\n }\n\n /**\n * Convert a primitive TypeBox schema type to a Protobuf spec type.\n */\n protected convertType(schema: TSchema): string {\n if (t.schema.isBoolean(schema)) return \"bool\";\n if (t.schema.isNumber(schema) && schema.format === \"int64\") return \"int64\";\n if (t.schema.isNumber(schema)) return \"double\";\n if (t.schema.isInteger(schema)) return \"int32\";\n if (t.schema.isBigInt(schema)) return \"int64\";\n if (t.schema.isString(schema)) return \"string\";\n\n // Handle union types (nullable)\n if (t.schema.isUnion(schema)) {\n // Find the non-null type in the union\n const nonNullType = schema.anyOf.find(\n (type: TSchema) => !t.schema.isNull(type),\n );\n if (nonNullType) {\n return this.convertType(nonNullType);\n }\n }\n\n // Handle optional types\n if (t.schema.isOptional(schema)) {\n return this.convertType(schema);\n }\n\n // Handle unsafe types (like enums)\n if (t.schema.isUnsafe(schema)) {\n // if it's an enum or other unsafe types, default to string\n return \"string\";\n }\n\n throw new Error(`Unsupported type: ${JSON.stringify(schema)}`);\n }\n\n /**\n * Check if a schema is an enum type.\n * TypeBox enums have an \"enum\" property with an array of values.\n */\n protected isEnum(schema: TSchema): boolean {\n return \"enum\" in schema && Array.isArray(schema.enum);\n }\n\n /**\n * Extract enum values from a TypeBox enum schema.\n */\n protected getEnumValues(schema: TSchema): string[] {\n if (\"enum\" in schema && Array.isArray(schema.enum)) {\n return schema.enum.map(String);\n }\n return [];\n }\n\n /**\n * Register an enum and return its type name.\n * Generates a PascalCase name from the field name.\n */\n protected registerEnum(fieldName: string, values: string[]): string {\n // Capitalize first letter of field name for enum type name\n const enumName = fieldName.charAt(0).toUpperCase() + fieldName.slice(1);\n\n // Check if we already have this exact enum registered\n const valueKey = values.join(\",\");\n const existingEnum = Array.from(this.enumDefinitions.entries()).find(\n ([_, enumValues]) => enumValues.join(\",\") === valueKey,\n );\n\n if (existingEnum) {\n // Reuse existing enum with same values\n return existingEnum[0];\n }\n\n // Register new enum\n this.enumDefinitions.set(enumName, values);\n return enumName;\n }\n\n /**\n * Generate a protobuf enum definition.\n */\n protected generateEnumDefinition(enumName: string, values: string[]): string {\n const enumValues = values\n .map((value, index) => ` ${value} = ${index};`)\n .join(\"\\n\");\n return `enum ${enumName} {\\n${enumValues}\\n}\\n`;\n }\n}\n\nexport type ProtobufSchema = string;\n\nexport interface CreateProtobufSchemaOptions {\n rootName?: string;\n mainMessageName?: string;\n}\n","import {\n $inject,\n AlephaError,\n SchemaCodec,\n type Static,\n type TSchema,\n t,\n} from \"alepha\";\nimport \"alepha/datetime\";\nimport { ProtobufProvider } from \"./ProtobufProvider.ts\";\n\n/**\n * ProtobufSchemaCodec handles encoding/decoding for Protobuf format.\n *\n * Key differences from JSON codec:\n * - BigInt values are kept as BigInt (not converted to string)\n * - Date values are converted to ISO strings for protobuf compatibility\n * - Binary data (Uint8Array) is kept as-is\n * - Proto3 default values are applied when decoding (to handle omitted fields)\n */\nexport class ProtobufSchemaCodec extends SchemaCodec {\n protected protobufProvider = $inject(ProtobufProvider);\n protected decoder = new TextDecoder();\n\n public encodeToString<T extends TSchema>(\n schema: T,\n value: Static<T>,\n ): string {\n const binary = this.encodeToBinary(schema, value);\n // convert binary to base64 string for text representation\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(binary).toString(\"base64\");\n } else {\n return btoa(String.fromCharCode(...binary));\n }\n }\n\n public encodeToBinary<T extends TSchema>(\n schema: T,\n value: Static<T>,\n ): Uint8Array {\n const proto = this.protobufProvider.createProtobufSchema(schema);\n return this.protobufProvider.encode(proto, value);\n }\n\n public decode<T>(schema: TSchema, value: unknown): T {\n // First decode from protobuf binary to object\n const proto = this.protobufProvider.createProtobufSchema(schema);\n\n if (value instanceof Uint8Array) {\n return this.applyProto3Defaults(\n schema,\n this.protobufProvider.decode(proto, value),\n );\n }\n\n if (typeof value === \"string\") {\n return this.applyProto3Defaults(\n schema,\n this.protobufProvider.decode(\n proto,\n typeof Buffer !== \"undefined\"\n ? Uint8Array.from(Buffer.from(value, \"base64\"))\n : Uint8Array.from(\n atob(value)\n .split(\"\")\n .map((c) => c.charCodeAt(0)),\n ),\n ),\n );\n }\n\n throw new AlephaError(\n `Unsupported value type for Protobuf decoding: ${typeof value}`,\n );\n }\n\n /**\n * Apply proto3 default values for fields that were omitted during encoding.\n * Proto3 omits fields with default values, so we need to restore them.\n * Also converts enum integers back to their string values.\n */\n protected applyProto3Defaults(schema: TSchema, value: any): any {\n if (!value || typeof value !== \"object\") {\n return value;\n }\n\n if (t.schema.isObject(schema)) {\n const result: any = { ...value };\n\n for (const [key, propSchema] of Object.entries(schema.properties)) {\n if (!(key in result) || result[key] === undefined) {\n // Apply proto3 default values based on type\n result[key] = this.getProto3Default(propSchema);\n } else {\n // Convert enum integers to strings\n if (this.isEnum(propSchema)) {\n result[key] = this.convertEnumValue(propSchema, result[key]);\n } else if (typeof result[key] === \"object\" && result[key] !== null) {\n // Recursively apply defaults to nested objects\n result[key] = this.applyProto3Defaults(propSchema, result[key]);\n }\n }\n }\n\n return result;\n }\n\n if (t.schema.isArray(schema) && Array.isArray(value)) {\n return value.map((item) => this.applyProto3Defaults(schema.items, item));\n }\n\n return value;\n }\n\n /**\n * Check if a schema is an enum type.\n */\n protected isEnum(schema: TSchema): boolean {\n return \"enum\" in schema && Array.isArray(schema.enum);\n }\n\n /**\n * Convert an enum value from protobuf integer to TypeBox string.\n */\n protected convertEnumValue(schema: TSchema, value: any): any {\n if (\n typeof value === \"number\" &&\n \"enum\" in schema &&\n Array.isArray(schema.enum)\n ) {\n // Protobuf encodes enums as integers, convert back to string\n return schema.enum[value];\n }\n return value;\n }\n\n /**\n * Get the proto3 default value for a schema type.\n */\n protected getProto3Default(schema: TSchema): any {\n // Handle nullable/optional types - they can be undefined\n if (t.schema.isOptional(schema) || t.schema.isUnion(schema)) {\n return undefined;\n }\n\n // Handle arrays - default is empty array\n if (t.schema.isArray(schema)) {\n return [];\n }\n\n // Handle records (maps) - default is empty object\n if (t.schema.isRecord(schema)) {\n return {};\n }\n\n // Handle primitive types\n if (t.schema.isString(schema)) return \"\";\n if (t.schema.isNumber(schema)) return 0;\n if (t.schema.isInteger(schema)) return 0;\n if (t.schema.isBigInt(schema)) return BigInt(0);\n if (t.schema.isBoolean(schema)) return false;\n\n // For objects, return empty object (will be filled in recursively)\n if (t.schema.isObject(schema)) {\n return {};\n }\n\n return undefined;\n }\n}\n","import { $module } from \"alepha\";\nimport { ProtobufProvider } from \"./providers/ProtobufProvider.ts\";\nimport { ProtobufSchemaCodec } from \"./providers/ProtobufSchemaCodec.ts\";\n\nexport * from \"./providers/ProtobufProvider.ts\";\nexport * from \"./providers/ProtobufSchemaCodec.ts\";\n\nexport const AlephaProtobuf = $module({\n name: \"alepha.protobuf\",\n services: [ProtobufProvider, ProtobufSchemaCodec],\n register: (alepha) => {\n alepha.with(ProtobufProvider);\n alepha.codec.register({\n name: \"protobuf\",\n codec: alepha.inject(ProtobufSchemaCodec),\n });\n },\n});\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
"name": "@alepha/protobuf",
|
|
3
3
|
"description": "Protocol Buffers (Protobuf) codec support for Alepha framework.",
|
|
4
4
|
"author": "Nicolas Foures",
|
|
5
|
-
"version": "0.
|
|
5
|
+
"version": "0.15.0",
|
|
6
6
|
"type": "module",
|
|
7
7
|
"engines": {
|
|
8
8
|
"node": ">=22.0.0"
|
|
@@ -18,13 +18,13 @@
|
|
|
18
18
|
"protobufjs": "^8.0.0"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"alepha": "0.
|
|
22
|
-
"tsdown": "^0.
|
|
21
|
+
"alepha": "0.15.0",
|
|
22
|
+
"tsdown": "^0.20.0-beta.3",
|
|
23
23
|
"typescript": "^5.9.3",
|
|
24
|
-
"vitest": "^4.0.
|
|
24
|
+
"vitest": "^4.0.17"
|
|
25
25
|
},
|
|
26
26
|
"peerDependencies": {
|
|
27
|
-
"alepha": "0.
|
|
27
|
+
"alepha": "0.15.0"
|
|
28
28
|
},
|
|
29
29
|
"scripts": {
|
|
30
30
|
"lint": "alepha lint",
|
package/src/index.ts
CHANGED
|
@@ -10,6 +10,9 @@ export const AlephaProtobuf = $module({
|
|
|
10
10
|
services: [ProtobufProvider, ProtobufSchemaCodec],
|
|
11
11
|
register: (alepha) => {
|
|
12
12
|
alepha.with(ProtobufProvider);
|
|
13
|
-
alepha.codec.register(
|
|
13
|
+
alepha.codec.register({
|
|
14
|
+
name: "protobuf",
|
|
15
|
+
codec: alepha.inject(ProtobufSchemaCodec),
|
|
16
|
+
});
|
|
14
17
|
},
|
|
15
18
|
});
|