@bett3r-dev/pv3-types 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (122) hide show
  1. package/build/authentication.d.ts +261 -0
  2. package/build/authentication.d.ts.map +1 -0
  3. package/build/authentication.js +108 -0
  4. package/build/authentication.js.map +1 -0
  5. package/build/cache.d.ts +101 -0
  6. package/build/cache.d.ts.map +1 -0
  7. package/build/cache.js +3 -0
  8. package/build/cache.js.map +1 -0
  9. package/build/clusterAdministration.d.ts +642 -0
  10. package/build/clusterAdministration.d.ts.map +1 -0
  11. package/build/clusterAdministration.js +177 -0
  12. package/build/clusterAdministration.js.map +1 -0
  13. package/build/configuration.d.ts +66 -0
  14. package/build/configuration.d.ts.map +1 -0
  15. package/build/configuration.js +3 -0
  16. package/build/configuration.js.map +1 -0
  17. package/build/database.d.ts +120 -0
  18. package/build/database.d.ts.map +1 -0
  19. package/build/database.js +41 -0
  20. package/build/database.js.map +1 -0
  21. package/build/endpoints.d.ts +183 -0
  22. package/build/endpoints.d.ts.map +1 -0
  23. package/build/endpoints.js +78 -0
  24. package/build/endpoints.js.map +1 -0
  25. package/build/evenstore.d.ts +26 -0
  26. package/build/evenstore.d.ts.map +1 -0
  27. package/build/evenstore.js +12 -0
  28. package/build/evenstore.js.map +1 -0
  29. package/build/eventsourcing/aggregateBuilder.d.ts +10 -0
  30. package/build/eventsourcing/aggregateBuilder.d.ts.map +1 -0
  31. package/build/eventsourcing/aggregateBuilder.js +3 -0
  32. package/build/eventsourcing/aggregateBuilder.js.map +1 -0
  33. package/build/eventsourcing/commandBuilder.d.ts +58 -0
  34. package/build/eventsourcing/commandBuilder.d.ts.map +1 -0
  35. package/build/eventsourcing/commandBuilder.js +6 -0
  36. package/build/eventsourcing/commandBuilder.js.map +1 -0
  37. package/build/eventsourcing/commandHandlers.d.ts +104 -0
  38. package/build/eventsourcing/commandHandlers.d.ts.map +1 -0
  39. package/build/eventsourcing/commandHandlers.js +28 -0
  40. package/build/eventsourcing/commandHandlers.js.map +1 -0
  41. package/build/eventsourcing/eventHandlers.d.ts +102 -0
  42. package/build/eventsourcing/eventHandlers.d.ts.map +1 -0
  43. package/build/eventsourcing/eventHandlers.js +33 -0
  44. package/build/eventsourcing/eventHandlers.js.map +1 -0
  45. package/build/eventsourcing/eventHandlersBuilder.d.ts +36 -0
  46. package/build/eventsourcing/eventHandlersBuilder.d.ts.map +1 -0
  47. package/build/eventsourcing/eventHandlersBuilder.js +13 -0
  48. package/build/eventsourcing/eventHandlersBuilder.js.map +1 -0
  49. package/build/eventsourcing/externalSystemBuilder.d.ts +14 -0
  50. package/build/eventsourcing/externalSystemBuilder.d.ts.map +1 -0
  51. package/build/eventsourcing/externalSystemBuilder.js +3 -0
  52. package/build/eventsourcing/externalSystemBuilder.js.map +1 -0
  53. package/build/eventsourcing/index.d.ts +386 -0
  54. package/build/eventsourcing/index.d.ts.map +1 -0
  55. package/build/eventsourcing/index.js +47 -0
  56. package/build/eventsourcing/index.js.map +1 -0
  57. package/build/eventsourcing/invariants.d.ts +19 -0
  58. package/build/eventsourcing/invariants.d.ts.map +1 -0
  59. package/build/eventsourcing/invariants.js +3 -0
  60. package/build/eventsourcing/invariants.js.map +1 -0
  61. package/build/eventsourcing/utils.d.ts +4 -0
  62. package/build/eventsourcing/utils.d.ts.map +1 -0
  63. package/build/eventsourcing/utils.js +3 -0
  64. package/build/eventsourcing/utils.js.map +1 -0
  65. package/build/index.d.ts +16 -0
  66. package/build/index.d.ts.map +1 -0
  67. package/build/index.js +32 -0
  68. package/build/index.js.map +1 -0
  69. package/build/infrastructure.d.ts +40 -0
  70. package/build/infrastructure.d.ts.map +1 -0
  71. package/build/infrastructure.js +11 -0
  72. package/build/infrastructure.js.map +1 -0
  73. package/build/logger.d.ts +32 -0
  74. package/build/logger.d.ts.map +1 -0
  75. package/build/logger.js +29 -0
  76. package/build/logger.js.map +1 -0
  77. package/build/outboxManager.d.ts +38 -0
  78. package/build/outboxManager.d.ts.map +1 -0
  79. package/build/outboxManager.js +21 -0
  80. package/build/outboxManager.js.map +1 -0
  81. package/build/ports.d.ts +39 -0
  82. package/build/ports.d.ts.map +1 -0
  83. package/build/ports.js +3 -0
  84. package/build/ports.js.map +1 -0
  85. package/build/routesAuth.d.ts +58 -0
  86. package/build/routesAuth.d.ts.map +1 -0
  87. package/build/routesAuth.js +37 -0
  88. package/build/routesAuth.js.map +1 -0
  89. package/build/typedEventEmitter.d.ts +23 -0
  90. package/build/typedEventEmitter.d.ts.map +1 -0
  91. package/build/typedEventEmitter.js +55 -0
  92. package/build/typedEventEmitter.js.map +1 -0
  93. package/build/validation.d.ts +64 -0
  94. package/build/validation.d.ts.map +1 -0
  95. package/build/validation.js +57 -0
  96. package/build/validation.js.map +1 -0
  97. package/package.json +15 -0
  98. package/src/authentication.ts +273 -0
  99. package/src/cache.ts +109 -0
  100. package/src/clusterAdministration.ts +216 -0
  101. package/src/configuration.ts +71 -0
  102. package/src/database.ts +157 -0
  103. package/src/endpoints.ts +198 -0
  104. package/src/evenstore.ts +27 -0
  105. package/src/eventsourcing/aggregateBuilder.ts +11 -0
  106. package/src/eventsourcing/commandBuilder.ts +64 -0
  107. package/src/eventsourcing/commandHandlers.ts +137 -0
  108. package/src/eventsourcing/eventHandlers.ts +118 -0
  109. package/src/eventsourcing/eventHandlersBuilder.ts +42 -0
  110. package/src/eventsourcing/externalSystemBuilder.ts +20 -0
  111. package/src/eventsourcing/index.ts +111 -0
  112. package/src/eventsourcing/invariants.ts +27 -0
  113. package/src/eventsourcing/utils.ts +4 -0
  114. package/src/index.ts +15 -0
  115. package/src/infrastructure.ts +41 -0
  116. package/src/logger.ts +45 -0
  117. package/src/outboxManager.ts +36 -0
  118. package/src/ports.ts +42 -0
  119. package/src/routesAuth.ts +58 -0
  120. package/src/typedEventEmitter.ts +73 -0
  121. package/src/validation.ts +89 -0
  122. package/tsconfig.json +15 -0
@@ -0,0 +1,118 @@
1
+ import S, { ObjectSchema } from '@bett3r-dev/jsonschema-definer';
2
+ import { AppErrorInstance } from '../validation';
3
+ import { Collection, CollectionQueryParams, DatabaseChange, DatabasePort, Document } from '../database';
4
+ import { EndpointActionParams, RequestObject, ResponseObject } from '../endpoints';
5
+ import { CommittedEvent, EventFactory, GetMessageType } from '../eventsourcing';
6
+ import { LoggerType } from '../logger';
7
+ import { System } from './commandHandlers';
8
+ import { TypedEventEmitter } from '../typedEventEmitter';
9
+
10
+ const SortStringSchema = S.string().pattern( /^(\w+),?(asc|desc)?$/ );
11
+ const FilterStringSchema = S
12
+ .string()
13
+ .pattern( /^([\w\d._]+),(eq|neq|lt|gt|lte|gte|in|nin|contains|notContains|some|every|exists|notExists),(.+?)$/ );
14
+
15
+ export const ReadModelDefaultParamsSchema = S.shape({
16
+ id: S.string().optional()
17
+ });
18
+
19
+ export const ReadModelDefaultQuerySchema = S.shape({
20
+ access_token: S.string().optional(),
21
+ apikey: S.string().optional(),
22
+ limit: S.string().optional(),
23
+ after: S.string().optional(),
24
+ sort: S.oneOf( SortStringSchema, S.array().items( SortStringSchema )).optional(),
25
+ select: S.array().items( S.string()).optional(),
26
+ //TODO: scape , for when the value has commas.
27
+ filter: S
28
+ .oneOf( FilterStringSchema, S.array().items( FilterStringSchema ))
29
+ .optional()
30
+ });
31
+
32
+ export type ReadModelDefaultQuery = typeof ReadModelDefaultQuerySchema.type
33
+
34
+ export type ReadModelDefaultParams = typeof ReadModelDefaultParamsSchema.type;
35
+
36
+
37
+ export const defaultParamsSchemas = {
38
+ params: ReadModelDefaultParamsSchema
39
+ };
40
+
41
+ export const defaultQuerySchemas = {
42
+ query: ReadModelDefaultQuerySchema
43
+ };
44
+
45
+ export type EventHandler<EVENTS extends Record<string, EventFactory>=any> = {
46
+ name: string;
47
+ events: EVENTS;
48
+ concurrency?: number;
49
+ errorHandlers?: {
50
+ [Name in keyof EVENTS]?: HandlerExecutionErrorType<CommittedEvent<GetMessageType<EVENTS[Name]>>>
51
+ },
52
+ }
53
+
54
+ export type PolicyResponse = {name: string, id?: string, data?: any};
55
+ export type HandlerExecutionErrorType<EVENT extends CommittedEvent = CommittedEvent> = ( error: AppErrorInstance, event: EVENT ) => Promise<unknown>;
56
+
57
+ //*******************************************
58
+ // Policies
59
+ //*******************************************
60
+
61
+ export type Policy<CommandHandler extends System=any, Events extends Record<string, EventFactory>=any> = EventHandler<Events> & {
62
+ commandHandler?: CommandHandler,
63
+ eventHandlers: {
64
+ [Name in keyof Events]: ( event: CommittedEvent<GetMessageType<Events[Name]>> ) => Promise<PolicyResponse | void>
65
+ }
66
+ }
67
+
68
+ //*******************************************
69
+ // Readmodels
70
+ //*******************************************
71
+
72
+ export type QueryParamsTranslator<Model extends Document, Params, Query> = ( schema: ObjectSchema<Model>, params: Pick<EndpointActionParams<any, Query, Params>, 'params' | 'query'> ) => CollectionQueryParams<Model>;
73
+
74
+ export type QueryHandler<MODEL extends Document=any,PARAMS=any,QUERY=any> = ( repository: Collection<MODEL>, params: CollectionQueryParams<MODEL> & {params: EndpointActionParams<any, QUERY, PARAMS>}) => Promise<MODEL | MODEL[]>;
75
+
76
+ export type QueryTransformer<MODEL extends Document=any,PARAMS=any,QUERY=any> = ( projectionParams: CollectionQueryParams<MODEL>, params: EndpointActionParams<any, QUERY, PARAMS> ) => Promise<CollectionQueryParams<MODEL>> | CollectionQueryParams<MODEL>;
77
+
78
+ export type ReadModelSubscriptionCloseEmitterEvents = {close: string};
79
+
80
+ export type ReadmodelSubscriptionManagerType<Model extends Document = any> = {
81
+ type: string,
82
+ startSubscription: ( projectionParams: CollectionQueryParams<Model>, req: RequestObject, res: ResponseObject ) => string | void;
83
+ notifySubscriptions: ( logger: LoggerType, collection: string ) => <T extends Document>( change: DatabaseChange<T>, subscriptionId?: string ) => void;
84
+ readModelSubscriptionCloseEmitter: TypedEventEmitter<ReadModelSubscriptionCloseEmitterEvents>
85
+ send: ( logger:LoggerType, id: string, change:DatabaseChange,collection: string, res: ResponseObject, data: string ) => void;
86
+ };
87
+
88
+ export type Query<MODEL extends Document=any, PARAMS extends Record<string, any>=any, QUERY extends Record<string, any>=any> = {
89
+ route?: string;
90
+ protocol?: 'http',
91
+ description?: string;
92
+ schemas?: {
93
+ query?: ObjectSchema<QUERY>
94
+ params?: ObjectSchema<PARAMS>
95
+ };
96
+ translator?: QueryParamsTranslator<MODEL, PARAMS, QUERY>;
97
+ subscriptions?: ReadmodelSubscriptionManagerType[];
98
+ transformers?: QueryTransformer<MODEL,PARAMS, QUERY>[],
99
+ queryHandler?: QueryHandler<MODEL, PARAMS, QUERY>;
100
+ };
101
+
102
+ export type EventProjectors<EVENTS extends Record<string, EventFactory>=any> = {
103
+ [Name in keyof EVENTS]: ( event: CommittedEvent<GetMessageType<EVENTS[Name]>> ) => Promise<any>
104
+ };
105
+
106
+ export type ReadModel<Model extends Document =any, EVENTS extends Record<string, EventFactory>=any> = EventHandler<EVENTS> & {
107
+ isReadModel: true;
108
+ schema: ObjectSchema<Model>;
109
+ queries: Query<Model>[];
110
+ eventProjectors?:EventProjectors<EVENTS>;
111
+ database?: DatabasePort;
112
+ collection?:string
113
+ }
114
+
115
+ export type ReadmodelChange<Model extends Document> = {
116
+ type: 'insert' | 'update' | 'delete',
117
+ data: Model
118
+ }
@@ -0,0 +1,42 @@
1
+ import { ObjectSchema } from '@bett3r-dev/jsonschema-definer';
2
+ import { A, O } from 'ts-toolbelt';
3
+ import { Builder, CommittedEvent, EventFactory, EventHandler, EventMetadata, EventProjectors, GetBuilderType, GetMessageType, Message, Policy, PolicyResponse, Query, ReadModel, System } from '.';
4
+ import { AppErrorInstance, DatabasePort, Document } from '..';
5
+
6
+ export type GetCommandType<SYSTEM extends System | EventHandler, Name extends A.Key> = SYSTEM extends System
7
+ ? O.Path<SYSTEM, ['commands', Name]> extends ( Builder<infer T extends Object> ) ? O.Path<T, ['schema', 'type']> : O.Path<SYSTEM, ['commands', Name, 'schema', 'type']>
8
+ : O.Path<SYSTEM, ['commandHandler','commands', Name]> extends ( Builder<infer T extends Object> ) ? O.Path<T, ['schema', 'type']> : O.Path<SYSTEM, ['commandHandler','commands', Name, 'schema', 'type']>
9
+
10
+ export type CommandInstance<Payload=any> = Message<Payload> & {
11
+ name: string;
12
+ id?: string;
13
+ metadata?: EventMetadata
14
+ }
15
+
16
+ export const createCommand = <Handler extends System | EventHandler> ( handler: Handler )=> <COMMAND extends keyof ( Handler extends System ? Handler['commands'] : O.Path<GetBuilderType<Handler>,['commandHandler','commands']> )>( command: COMMAND, id?: string, data?: GetCommandType<Handler, COMMAND>, metadata?: EventMetadata ): CommandInstance => {
17
+ return {
18
+ name: command as string,
19
+ ...( id ? { id } : {}),
20
+ ...( data ? { data } : {}),
21
+ ...( metadata ? { metadata } : {})
22
+ };
23
+ };
24
+
25
+ export type EventHandlerBuilderType<EVENTS extends Record<string, EventFactory>, T extends Policy | ReadModel> = Builder<EventHandler<EVENTS>> & {
26
+ eventHandler: EventHandler<EVENTS>,
27
+ withErrorHandlers: ( errorHandlers: {
28
+ [Name in keyof EVENTS]?: ( error: AppErrorInstance, event: CommittedEvent<GetMessageType<EVENTS[Name]>> ) => Promise<unknown>
29
+ }) => { build: () => T extends Policy ? Policy<T['commandHandler'], EVENTS> : T extends ReadModel ? ReadModel<T['schema'] extends ObjectSchema<infer MODEL extends Document> ? MODEL: Document, EVENTS> : any},
30
+ };
31
+
32
+ export type PolicyBuilderType<CommandHandler extends System, EVENTS extends Record<string, EventFactory>> = Builder<Policy<CommandHandler, EVENTS>> & EventHandlerBuilderType<EVENTS, Policy<CommandHandler, EVENTS>> & {
33
+ withEventHandlers: ( handlers: ( params: {createCommand: ReturnType<typeof createCommand<CommandHandler>>}) => {
34
+ [Name in keyof EVENTS]: ( event: CommittedEvent<GetMessageType<EVENTS[Name]>> ) => Promise<PolicyResponse|void>
35
+ }) => Pick<PolicyBuilderType<CommandHandler, EVENTS>, 'build' | 'withErrorHandlers'>,
36
+ }
37
+
38
+ export type ReadmodelBuilderType<Model extends Document, EVENTS extends Record<string, EventFactory>> = Builder<ReadModel<Model, EVENTS>> & EventHandlerBuilderType<EVENTS, ReadModel<Model, EVENTS>> & {
39
+ withDatabase: ( database: DatabasePort, collection?:string ) => ReadmodelBuilderType<Model, EVENTS>
40
+ withProjector: ( eventProjectors?: ( params: {database: DatabasePort, collection:string}) => EventProjectors<EVENTS> ) => ReadmodelBuilderType<Model, EVENTS>
41
+ withQuery: <PARAMS extends Record<string, any>, QUERY extends Record<string, any>>( query?: Query<Model, PARAMS, QUERY> ) => ReadmodelBuilderType<Model, EVENTS>
42
+ }
@@ -0,0 +1,20 @@
1
+ import { Builder, Command, CommandBuilderType, EventFactory, System } from '.';
2
+ import { CreateEventType } from './utils';
3
+
4
+ export type ExternalSystemBuilderType<Model, EVENTS extends Record<string, EventFactory>> = {
5
+
6
+ withCommandTemplate: ( command: Command ) => ExternalSystemBuilderType<Model, EVENTS>
7
+
8
+
9
+ /**
10
+ * This is the last function that builds the aggregate, the last function you'll call
11
+ */
12
+ withCommands: <
13
+ EVENT extends keyof EVENTS,
14
+ Commands extends Record<string, Command<EVENTS, EVENT, Model> | Builder<Command<EVENTS, EVENT, Model>>>
15
+ > ( commands: ( params: {
16
+ commandBuilder: CommandBuilderType<Model, EVENTS>,
17
+ createEvent: CreateEventType<System< any, EVENTS >>,
18
+ }) => Commands ) => System<Commands, EVENTS>
19
+ system: System<any, EVENTS>
20
+ }
@@ -0,0 +1,111 @@
1
+ import S, { BaseSchema, ObjectSchema } from '@bett3r-dev/jsonschema-definer';
2
+ import { CollectionFilter, Document } from '../database';
3
+ import { ResponseObject } from '../endpoints';
4
+ import { PortEmitter } from '../ports';
5
+ import { EventSourcingCommandHandlers, ExecuteCommandFunction, System } from './commandHandlers';
6
+ import { EventHandler } from './eventHandlers';
7
+
8
+ export * from './commandHandlers';
9
+ export * from './eventHandlers';
10
+ export * from './invariants';
11
+ export * from './aggregateBuilder';
12
+ export * from './commandBuilder';
13
+ export * from './eventHandlersBuilder';
14
+ export * from './externalSystemBuilder';
15
+
16
+ export type Message<Payload, Name = string> = {
17
+ name?: Name,
18
+ data?: Payload,
19
+ description?: string
20
+ }
21
+
22
+ export type MessageSchema<Payload> = {
23
+ schema?: BaseSchema<Payload> | BaseSchema<Payload, false> | ObjectSchema | BaseSchema | null
24
+ }
25
+
26
+ export type EventInstance<Payload=any, Name=any> = Message<Payload, Name> & MessageSchema<Payload>
27
+
28
+ export const Event = <Payload>( eventInstance: EventInstance<Payload> ): EventInstance<Payload> => eventInstance;
29
+
30
+ export type EventFactory<Name=any, EventPayload = any> = () => EventInstance<EventPayload, Name>
31
+
32
+ export const EventMetadataSchema = S.shape({
33
+ causationId: S.string().optional(),
34
+ correlationId: S.string().optional(),
35
+ user: S.any().optional()
36
+ });
37
+
38
+ export type EventMetadata = typeof EventMetadataSchema.type;
39
+
40
+ export type EventToCommit<Payload = any> = {
41
+ name: string,
42
+ data?: Payload,
43
+ stream: string
44
+ metadata: EventMetadata
45
+ };
46
+
47
+ export type CommittedEvent<Payload = any> = EventToCommit<Payload> & {
48
+ id: number
49
+ timestamp: string
50
+ version: number
51
+ }
52
+
53
+ const ensureArray = ( maybeArray: any ) => Array.isArray( maybeArray ) ? maybeArray : [maybeArray];
54
+
55
+ export const CommittedEventSchema = <T>( payloadSchema: BaseSchema<T>, names?: string | string[]) => S.shape({
56
+ id: S.number(),
57
+ name: ( names ? S.string().enum( ...ensureArray( names )) : S.string()),
58
+ timestamp: S.string().format( 'date-time' ),
59
+ data: payloadSchema,
60
+ version: S.number(),
61
+ stream: S.string(),
62
+ metadata: EventMetadataSchema,
63
+ });
64
+
65
+ export type GetMessageType<Payload> = Payload extends (()=> EventInstance<infer T> ) ? T : unknown
66
+
67
+ export type Builder<T = any> = {
68
+ build:() => T
69
+ }
70
+
71
+ export type GetBuilderType<T> = T extends ( Builder<infer InnerT> ) ? InnerT : T
72
+
73
+ //*******************************************
74
+ // Readmodels
75
+ //*******************************************
76
+ // export type GetEventType<SYSTEM extends System, Name extends A.Key> = GetMessageType<O.Path<SYSTEM, ['events', Name]>>
77
+
78
+ // export type GetErrorDataType<Payload> = Payload extends (()=> AppErrorType<infer T>) ? T : unknown
79
+ // export type CreateErrorType<ERRORS extends Record<string, AppErrorFactory>> = (errors: ERRORS)=> <ERROR extends keyof ERRORS>(error: ERROR, params: Pick<AppErrorInstance<GetErrorDataType<ERRORS[ERROR]>>, 'details' | 'description'> ) => AppErrorInstance<GetErrorDataType<ERRORS[ERROR]>>;
80
+
81
+ export type ReadModelSubscription<Model extends Document = any> = {
82
+ id: string;
83
+ res: ResponseObject;
84
+ filter: CollectionFilter<Model>[];
85
+ };
86
+
87
+
88
+ export type ReadStreamOptions = {
89
+ stream?: string,
90
+ direction?: 'forwards' | 'backwards',
91
+ from?: number,
92
+ fromVersion?: number,
93
+ limit?: number,
94
+ events?: string[],
95
+ before?: string,
96
+ after?: string,
97
+ }
98
+
99
+ export type ReadMultipleStreamOptions = Omit<ReadStreamOptions, 'stream'> & {
100
+ streams: string[],
101
+ }
102
+
103
+ export type EventSourcingType = Pick<EventSourcingCommandHandlers, 'executeCommand' | 'loadAggregateState' | 'loadStream'> & {
104
+ routeEventHandler: ( eventHandler: EventHandler | Builder<EventHandler> ) => void,
105
+ routeCommandHandler: ( commandHandler: System ) => void,
106
+
107
+ handleEvent: ( eventHandler: EventHandler, executeCommand: ExecuteCommandFunction ) => ( event: CommittedEvent ) => Promise<any>,
108
+ logEventsourcingRoutes: () => void
109
+ }
110
+
111
+ export type EventSourcingPort = PortEmitter & EventSourcingType;
@@ -0,0 +1,27 @@
1
+ import { DatabaseOps, ErrorTypes, LoggerType } from '..';
2
+
3
+ export type InvariantParams = {
4
+ errorName?: string;
5
+ errorType?: ErrorTypes
6
+ logger?: LoggerType;
7
+ };
8
+
9
+ export type ReadmodelInvariantComparisonOR = {
10
+ OR: ReadmodelInvariantComparison[]
11
+ }
12
+
13
+ export type ReadmodelInvariantComparisonAND = {
14
+ AND: ReadmodelInvariantComparison[]
15
+ }
16
+
17
+ export type ReadmodelInvariantComparisonInstance = {
18
+ path: string;
19
+ readmodelPath: string;
20
+ op: DatabaseOps;
21
+ };
22
+
23
+ export type ReadmodelInvariantComparison = Partial<
24
+ & ReadmodelInvariantComparisonOR
25
+ & ReadmodelInvariantComparisonAND
26
+ & ReadmodelInvariantComparisonInstance
27
+ >
@@ -0,0 +1,4 @@
1
+ import { CommittedEvent, EventFactory, EventHandler, GetMessageType, System } from '.';
2
+ import { O } from 'ts-toolbelt';
3
+
4
+ export type CreateEventType<Handler extends System | EventHandler> = <EVENT extends keyof O.Path<Handler, ['events']>>( event: EVENT, data?: GetMessageType<Handler['events'][EVENT]>, committedEvent?: Partial<Omit<CommittedEvent, 'data' | 'name'>> ) => EventFactory<EVENT, GetMessageType<Handler['events'][EVENT]>>;
package/src/index.ts ADDED
@@ -0,0 +1,15 @@
1
+ export * from './authentication';
2
+ export * from './cache';
3
+ export * from './clusterAdministration';
4
+ export * from './configuration';
5
+ export * from './database';
6
+ export * from './endpoints';
7
+ export * from './evenstore';
8
+ export * from './eventsourcing';
9
+ export * from './infrastructure';
10
+ export * from './logger';
11
+ export * from './outboxManager';
12
+ export * from './ports';
13
+ export * from './routesAuth';
14
+ export * from './typedEventEmitter';
15
+ export * from './validation';
@@ -0,0 +1,41 @@
1
+ import S from '@bett3r-dev/jsonschema-definer';
2
+ import { OpenAPIV3_1 } from 'openapi-types';
3
+ import { StructureServiceType } from './clusterAdministration';
4
+ import { AdapterBase } from './ports';
5
+
6
+ export const InfrastructureConfigSchema = S.shape({
7
+ infrastructureLeaderRandomBackoff: S.number().default( 1000 ).optional()
8
+ });
9
+ export type InfrastructureConfigType = typeof InfrastructureConfigSchema.type;
10
+
11
+ export type EnvironmentServiceType = {
12
+ openApi: OpenAPIV3_1.Document,
13
+ service: string,
14
+ openApiEndpoint?: string,
15
+ instances: {host: string, timeRunning: number}[],
16
+ port: number,
17
+ }
18
+
19
+ export type InfrastructureServiceType = Omit<StructureServiceType, 'hosts'> & {
20
+ instances: {host: string, timeRunning: number}[],
21
+ service: string,
22
+ }
23
+ export type InfrastructureThisServiceType = InfrastructureServiceType & {
24
+ leadershipRank: number;
25
+ host: string;
26
+ }
27
+
28
+ export type InfrastructureAdapterType = AdapterBase & {
29
+ getServices: () => Promise<EnvironmentServiceType[]>;
30
+ // addService: (baseService: string, modules: string[]) => Promise<void>;
31
+ // removeService: (service: string) => Promise<void>;
32
+ scaleService: ( service: string, replicasCount: number ) => Promise<void>;
33
+ listenForInfrastructureChanges: ( callback: ( event: 'destroy' | 'create', service: EnvironmentServiceType ) => void ) => void;
34
+ reloadLoadBalancer: () => Promise<void>;
35
+ };
36
+
37
+ export type InfrastructurePortType = InfrastructureAdapterType & {
38
+ getServicesOpenApiDocumentation: () => Record<string, OpenAPIV3_1.Document>;
39
+ getThisServiceInfo: () => InfrastructureThisServiceType;
40
+ start: InfrastructureAdapterType['start'];
41
+ }
package/src/logger.ts ADDED
@@ -0,0 +1,45 @@
1
+ import S from '@bett3r-dev/jsonschema-definer';
2
+ import { AdapterBase } from './ports';
3
+
4
+ export const LoggerConfigSchema = S.shape({
5
+ logLevel: S.string().enum( 'silly', 'debug', 'log', 'info', 'warn', 'error' ).optional(),
6
+ modulesWhitelist: S.array().items( S.string()).optional(),
7
+ modulesBlacklist: S.array().items( S.string()).optional()
8
+ }).optional();
9
+ export type LoggerConfig = typeof LoggerConfigSchema.type;
10
+
11
+ export type LogLevels = 'silly'| 'debug'| 'log'| 'info'| 'warn'| 'error';
12
+
13
+ export const LogLevelMap = {
14
+ error: 0,
15
+ warn: 1,
16
+ info: 2,
17
+ log: 3,
18
+ debug: 4,
19
+ silly: 5,
20
+ };
21
+ export const LevelLogMap: Record<number, LogLevels> = {
22
+ 0: 'error',
23
+ 1: 'warn',
24
+ 2: 'info',
25
+ 3: 'log',
26
+ 4: 'debug',
27
+ 5: 'silly',
28
+ };
29
+
30
+ export type LoggerAdapter = AdapterBase & {
31
+ log: ( originalArgs: any[], level: LogLevels , module: string ) => void
32
+ }
33
+
34
+ export type LoggerPort = {
35
+ createLoggerInstance: ( module: string ) => LoggerType
36
+ }
37
+
38
+ export type LoggerType = {
39
+ silly: ( ...args: any[])=>void
40
+ debug: ( ...args: any[])=>void
41
+ log: ( ...args: any[])=>void
42
+ info: ( ...args: any[])=>void
43
+ warn: ( ...args: any[])=>void
44
+ error: ( ...args: any[])=>void
45
+ }
@@ -0,0 +1,36 @@
1
+ import S from '@bett3r-dev/jsonschema-definer';
2
+ import { InfrastructureConfigSchema } from '@bett3r-dev/pv3-types';
3
+ import { CommittedEvent } from '@bett3r-dev/pv3-types';
4
+ import { ClusterStructureConfigSchema } from '@bett3r-dev/pv3-types';
5
+
6
+ export const UdpConfigSchema = S.shape({
7
+ port: S.number().default( 16706 ).optional(),
8
+ multicastAddress: S.string().default( '224.0.1.50' ).optional(),
9
+ ttl: S.number().optional()
10
+ });
11
+ export type UdpConfigType = typeof UdpConfigSchema.type;
12
+
13
+
14
+ export const AdminServicesConfigSchema = S.shape({
15
+ udp: UdpConfigSchema.optional().default({}),
16
+ structure: ClusterStructureConfigSchema.optional().default({}),
17
+ infrastructure: InfrastructureConfigSchema.optional().default({}),
18
+ metricsInterval: S.number().optional().default( 1000 )
19
+ });
20
+ export type AdminServicesConfigType = typeof AdminServicesConfigSchema.type;
21
+
22
+ export type OutboxManagerType = {
23
+ start: ( activateDiscoveredSubscriptions?: boolean ) => Promise<void>,
24
+ stop: () => Promise<void>
25
+ }
26
+
27
+ export type TcpEventMessageRequest = {
28
+ endpoint: string,
29
+ event: CommittedEvent
30
+ }
31
+ export type TcpEventMessageResponse = {
32
+ id: number,
33
+ status: number,
34
+ error?: string
35
+ }
36
+
package/src/ports.ts ADDED
@@ -0,0 +1,42 @@
1
+ import { AuthenticationPort } from './authentication';
2
+ import { CachePort } from './cache';
3
+ import { ConfigurationPort } from './configuration';
4
+ import { DatabasePort } from './database';
5
+ import { EndpointsPort } from './endpoints';
6
+ import { EventStorePort } from './evenstore';
7
+ import { EventSourcingPort } from './eventsourcing';
8
+ import { InfrastructurePortType } from './infrastructure';
9
+ import { LoggerPort } from './logger';
10
+ import { TypedEventEmitter } from './typedEventEmitter';
11
+
12
+ export type PortEmitterEvents = {
13
+ started: void,
14
+ }
15
+
16
+ /**
17
+ * Base type for Porst that exposes an EventEmitter interface for handling the 'started' event.
18
+ */
19
+ export type PortEmitter = {
20
+ isStarted: boolean,
21
+ emitter: TypedEventEmitter<PortEmitterEvents>,
22
+ onStarted: ( fn: () => void ) => void
23
+ };
24
+
25
+ export type AdapterBase<T = any> = {
26
+ name: string,
27
+ _adapter: () => T,
28
+ start: () => Promise<void>,
29
+ stop: () => Promise<void>,
30
+ }
31
+
32
+ export type Ports = {
33
+ configuration: ConfigurationPort,
34
+ logger: LoggerPort,
35
+ cache: CachePort,
36
+ endpoints: EndpointsPort,
37
+ database: DatabasePort,
38
+ eventstore: EventStorePort,
39
+ eventsourcing: EventSourcingPort,
40
+ authentication: AuthenticationPort,
41
+ infrastructure: InfrastructurePortType
42
+ }
@@ -0,0 +1,58 @@
1
+ import S from '@bett3r-dev/jsonschema-definer';
2
+ import { METHODS } from 'http';
3
+ import { Event } from './eventsourcing';
4
+ import { Ports } from './ports';
5
+ import { ClusterRoutesConfigType } from './clusterAdministration';
6
+
7
+ export const ClusterRoutesAggregateSchema = S.shape({
8
+ method: S.string().enum( ...METHODS.map( m=>m.toLocaleLowerCase())),
9
+ id: S.string(),
10
+ isPublic: S.boolean().optional(),
11
+ roles: S.array().items( S.string()).optional(),
12
+ });
13
+ export type ClusterRoutesAggregateType = typeof ClusterRoutesAggregateSchema.type;
14
+
15
+ export type RouteManagerEndpointAuth = ClusterRoutesAggregateType;
16
+
17
+ export const UpsertRouteCommandSchema = S.shape({}).additionalProperties( ClusterRoutesAggregateSchema );
18
+ export const DeleteRouteCommandSchema = S.array().items( S.string());
19
+
20
+ export const ClusterManagerEvents = {
21
+ RoutesUpserted: () => Event({
22
+ schema: UpsertRouteCommandSchema
23
+ }),
24
+ RouteDeleted: () => Event({
25
+ schema: DeleteRouteCommandSchema
26
+ })
27
+ };
28
+
29
+
30
+ /**
31
+ * Represents the place where the routes are stored and consumed by an authorization server.
32
+ * Usually this store will live in a Cache and holds all the endpoints of the application
33
+ * and their access requirements. That means if the resource is public, or what roles can have access.
34
+ */
35
+ export type RoutesAuthManagerType = {
36
+ getAllRoutes: () => Promise<RouteManagerEndpointAuth[]>;
37
+ getRoute: ( method:string, route: string ) => Promise<Pick<RouteManagerEndpointAuth, 'isPublic'|'roles'> | false>
38
+ upsertRoute: ( endpoint: RouteManagerEndpointAuth ) => Promise<RouteManagerEndpointAuth>;
39
+ subscribeToRoutesAuthChanges: ( onStructureChanges: ( change: ClusterRoutesAggregateType ) => void ) => Promise<{ unsubscribe: () => void }>;
40
+ stop: () => Promise<void>;
41
+ }
42
+
43
+ export type RouteAuthManagerFactory = ( ports: Pick<Ports, 'database'|'eventstore'>, config: ClusterRoutesConfigType, eventstore?: Ports['eventstore']) => RoutesAuthManagerType
44
+
45
+ // Endpoints Schemas
46
+ export const EndpointMarkedAsPublicSchema = S.shape({
47
+ method: S.string().enum( ...METHODS.map( m=>m.toLocaleLowerCase())),
48
+ id: S.string(),
49
+ isPublic: S.boolean().optional()
50
+ });
51
+ export type EndpointMarkedAsPublic = typeof EndpointMarkedAsPublicSchema.type
52
+
53
+ export const EndpointRolesUpsertedSchema = S.shape({
54
+ method: S.string().enum( ...METHODS.map( m=>m.toLocaleLowerCase())),
55
+ id: S.string(),
56
+ roles: S.array().items( S.string()),
57
+ });
58
+ export type EndpointRolesUpserted = typeof EndpointRolesUpsertedSchema.type
@@ -0,0 +1,73 @@
1
+ import { EventEmitter as NativeEventEmitter } from 'events';
2
+
3
+ declare module 'events' {
4
+ interface EventEmitter {
5
+ on<K extends keyof any>( event: K, listener: ( ...args: any[]) => void ): this;
6
+ emit<K extends keyof any>( event: K, ...args: any[]): boolean;
7
+ }
8
+ }
9
+
10
+ export class TypedEventEmitter<T> {
11
+
12
+ private emitter = new NativeEventEmitter();
13
+
14
+ on<K extends keyof T>( event: K, listener: ( arg: T[K]) => void ): this {
15
+ this.emitter.on( event as string, listener );
16
+ return this;
17
+ }
18
+
19
+ emit<K extends keyof T>( event: K, arg?: T[K]): boolean {
20
+ return this.emitter.emit( event as string, arg );
21
+ }
22
+
23
+ off<K extends keyof T>( event: K, listener: ( arg: T[K]) => void ): this {
24
+ this.emitter.off( event as string, listener );
25
+ return this;
26
+ }
27
+
28
+ once<K extends keyof T>( event: K, listener: ( arg: T[K]) => void ): this {
29
+ this.emitter.once( event as string, listener );
30
+ return this;
31
+ }
32
+
33
+ removeAllListeners<K extends keyof T>( event?: K ): this {
34
+ this.emitter.removeAllListeners( event as string );
35
+ return this;
36
+ }
37
+
38
+ listeners<K extends keyof T>( event: K ): Function[] {
39
+ return this.emitter.listeners( event as string );
40
+ }
41
+
42
+ rawListeners<K extends keyof T>( event: K ): Function[] {
43
+ return this.emitter.rawListeners( event as string );
44
+ }
45
+
46
+ listenerCount<K extends keyof T>( event: K ): number {
47
+ return this.emitter.listenerCount( event as string );
48
+ }
49
+
50
+ prependListener<K extends keyof T>( event: K, listener: ( arg: T[K]) => void ): this {
51
+ this.emitter.prependListener( event as string, listener );
52
+ return this;
53
+ }
54
+
55
+ prependOnceListener<K extends keyof T>( event: K, listener: ( arg: T[K]) => void ): this {
56
+ this.emitter.prependOnceListener( event as string, listener );
57
+ return this;
58
+ }
59
+
60
+ eventNames(): ( keyof T )[] {
61
+ return this.emitter.eventNames() as ( keyof T )[];
62
+ }
63
+
64
+ getMaxListeners(): number {
65
+ return this.emitter.getMaxListeners();
66
+ }
67
+
68
+ setMaxListeners( n: number ): this {
69
+ this.emitter.setMaxListeners( n );
70
+ return this;
71
+ }
72
+
73
+ }