@cratis/chronicle.contracts 15.25.2 → 15.25.4

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 (76) hide show
  1. package/dist/cjs/index.d.ts +0 -5
  2. package/dist/cjs/index.d.ts.map +1 -1
  3. package/dist/cjs/index.js +0 -15
  4. package/dist/cjs/index.js.map +1 -1
  5. package/dist/esm/index.d.ts +0 -5
  6. package/dist/esm/index.d.ts.map +1 -1
  7. package/dist/esm/index.js +0 -4
  8. package/dist/esm/index.js.map +1 -1
  9. package/dist/index.d.ts +0 -5
  10. package/dist/index.d.ts.map +1 -1
  11. package/dist/index.js +0 -5
  12. package/dist/index.js.map +1 -1
  13. package/dist/tsconfig.tsbuildinfo +1 -1
  14. package/index.ts +0 -7
  15. package/package.json +1 -1
  16. package/ChronicleConnection.ts +0 -530
  17. package/ChronicleConnectionString.ts +0 -462
  18. package/ChronicleServices.ts +0 -104
  19. package/DateTimeOffset.ts +0 -27
  20. package/TokenProvider.ts +0 -167
  21. package/dist/ChronicleConnection.d.ts +0 -51
  22. package/dist/ChronicleConnection.d.ts.map +0 -1
  23. package/dist/ChronicleConnection.js +0 -278
  24. package/dist/ChronicleConnection.js.map +0 -1
  25. package/dist/ChronicleConnectionString.d.ts +0 -67
  26. package/dist/ChronicleConnectionString.d.ts.map +0 -1
  27. package/dist/ChronicleConnectionString.js +0 -255
  28. package/dist/ChronicleConnectionString.js.map +0 -1
  29. package/dist/ChronicleServices.d.ts +0 -35
  30. package/dist/ChronicleServices.d.ts.map +0 -1
  31. package/dist/ChronicleServices.js +0 -2
  32. package/dist/ChronicleServices.js.map +0 -1
  33. package/dist/DateTimeOffset.d.ts +0 -4
  34. package/dist/DateTimeOffset.d.ts.map +0 -1
  35. package/dist/DateTimeOffset.js +0 -11
  36. package/dist/DateTimeOffset.js.map +0 -1
  37. package/dist/TokenProvider.d.ts +0 -21
  38. package/dist/TokenProvider.d.ts.map +0 -1
  39. package/dist/TokenProvider.js +0 -92
  40. package/dist/TokenProvider.js.map +0 -1
  41. package/dist/cjs/ChronicleConnection.d.ts +0 -51
  42. package/dist/cjs/ChronicleConnection.d.ts.map +0 -1
  43. package/dist/cjs/ChronicleConnection.js +0 -302
  44. package/dist/cjs/ChronicleConnection.js.map +0 -1
  45. package/dist/cjs/ChronicleConnectionString.d.ts +0 -67
  46. package/dist/cjs/ChronicleConnectionString.d.ts.map +0 -1
  47. package/dist/cjs/ChronicleConnectionString.js +0 -280
  48. package/dist/cjs/ChronicleConnectionString.js.map +0 -1
  49. package/dist/cjs/ChronicleServices.d.ts +0 -35
  50. package/dist/cjs/ChronicleServices.d.ts.map +0 -1
  51. package/dist/cjs/DateTimeOffset.d.ts +0 -4
  52. package/dist/cjs/DateTimeOffset.d.ts.map +0 -1
  53. package/dist/cjs/DateTimeOffset.js +0 -16
  54. package/dist/cjs/DateTimeOffset.js.map +0 -1
  55. package/dist/cjs/TokenProvider.d.ts +0 -21
  56. package/dist/cjs/TokenProvider.d.ts.map +0 -1
  57. package/dist/cjs/TokenProvider.js +0 -118
  58. package/dist/cjs/TokenProvider.js.map +0 -1
  59. package/dist/esm/ChronicleConnection.d.ts +0 -51
  60. package/dist/esm/ChronicleConnection.d.ts.map +0 -1
  61. package/dist/esm/ChronicleConnection.js +0 -281
  62. package/dist/esm/ChronicleConnection.js.map +0 -1
  63. package/dist/esm/ChronicleConnectionString.d.ts +0 -67
  64. package/dist/esm/ChronicleConnectionString.d.ts.map +0 -1
  65. package/dist/esm/ChronicleConnectionString.js +0 -258
  66. package/dist/esm/ChronicleConnectionString.js.map +0 -1
  67. package/dist/esm/ChronicleServices.d.ts +0 -35
  68. package/dist/esm/ChronicleServices.d.ts.map +0 -1
  69. package/dist/esm/DateTimeOffset.d.ts +0 -4
  70. package/dist/esm/DateTimeOffset.d.ts.map +0 -1
  71. package/dist/esm/DateTimeOffset.js +0 -13
  72. package/dist/esm/DateTimeOffset.js.map +0 -1
  73. package/dist/esm/TokenProvider.d.ts +0 -21
  74. package/dist/esm/TokenProvider.d.ts.map +0 -1
  75. package/dist/esm/TokenProvider.js +0 -95
  76. package/dist/esm/TokenProvider.js.map +0 -1
@@ -1,530 +0,0 @@
1
- // Copyright (c) Cratis. All rights reserved.
2
- // Licensed under the MIT license. See LICENSE file in the project root for full license information.
3
-
4
- import * as grpc from '@grpc/grpc-js';
5
- import { createClient, createClientFactory } from 'nice-grpc';
6
- import type { ClientMiddleware } from 'nice-grpc-common';
7
- import { Metadata } from 'nice-grpc-common';
8
-
9
- // Import service definitions from generated files
10
- import { EventStoresDefinition, NamespacesDefinition } from './generated/cratis_chronicle_contracts';
11
- import { RecommendationsDefinition } from './generated/recommendations';
12
- import { IdentitiesDefinition } from './generated/identities';
13
- import { EventSequencesDefinition } from './generated/eventsequences';
14
- import { EventTypesDefinition } from './generated/events';
15
- import { ConstraintsDefinition } from './generated/events_constraints';
16
- import { ObserversDefinition, FailedPartitionsDefinition } from './generated/observation';
17
- import { ReactorsDefinition } from './generated/observation_reactors';
18
- import { ReducersDefinition } from './generated/observation_reducers';
19
- import { ProjectionsDefinition } from './generated/projections';
20
- import { ReadModelsDefinition } from './generated/readmodels';
21
- import { JobsDefinition } from './generated/jobs';
22
- import { EventSeedingDefinition } from './generated/seeding';
23
- import { ServerDefinition } from './generated/host';
24
- import { ConnectionServiceDefinition } from './generated/clients';
25
-
26
- // Import client types
27
- import type {
28
- EventStoresClient,
29
- NamespacesClient,
30
- RecommendationsClient,
31
- IdentitiesClient,
32
- EventSequencesClient,
33
- EventTypesClient,
34
- ConstraintsClient,
35
- ObserversClient,
36
- FailedPartitionsClient,
37
- ReactorsClient,
38
- ReducersClient,
39
- ProjectionsClient,
40
- ReadModelsClient,
41
- JobsClient,
42
- EventSeedingClient,
43
- ServerClient,
44
- ConnectionServiceClient,
45
- } from './generated/index';
46
-
47
- import type { ChronicleServices } from './ChronicleServices';
48
- import { ChronicleConnectionString, AuthenticationMode } from './ChronicleConnectionString';
49
- import { ITokenProvider, OAuthTokenProvider, NoOpTokenProvider } from './TokenProvider';
50
-
51
- /**
52
- * Configuration options for Chronicle connection
53
- */
54
- export interface ChronicleConnectionOptions {
55
- /**
56
- * The connection string (e.g., 'chronicle://localhost:35000' or 'chronicle://user:pass@localhost:35000')
57
- * Can also be a ChronicleConnectionString instance
58
- */
59
- connectionString?: string | ChronicleConnectionString;
60
-
61
- /**
62
- * The host and port of the Chronicle server (e.g., 'localhost:35000')
63
- * This is used if connectionString is not provided
64
- */
65
- serverAddress?: string;
66
-
67
- /**
68
- * Optional gRPC credentials (defaults to credentials based on connection string)
69
- */
70
- credentials?: grpc.ChannelCredentials;
71
-
72
- /**
73
- * Optional connection timeout in milliseconds (defaults to 10000)
74
- */
75
- connectTimeout?: number;
76
-
77
- /**
78
- * Optional maximum receive message size in bytes
79
- */
80
- maxReceiveMessageSize?: number;
81
-
82
- /**
83
- * Optional maximum send message size in bytes
84
- */
85
- maxSendMessageSize?: number;
86
-
87
- /**
88
- * Optional correlation ID for tracking requests
89
- */
90
- correlationId?: string;
91
-
92
- /**
93
- * Optional authentication authority URL. If not set, uses the Chronicle server itself as the authority
94
- */
95
- authority?: string;
96
-
97
- /**
98
- * Optional management port for authentication endpoint (defaults to 8080)
99
- */
100
- managementPort?: number;
101
- }
102
-
103
- /**
104
- * Manages the connection to Chronicle Kernel and provides access to all gRPC services
105
- */
106
- export class ChronicleConnection implements ChronicleServices {
107
- private readonly channel: grpc.Channel;
108
- private readonly services: ChronicleServices;
109
- private readonly _connectionString: ChronicleConnectionString;
110
- private readonly tokenProvider: ITokenProvider;
111
- private _isConnected = false;
112
-
113
- /**
114
- * Event stores service
115
- */
116
- get eventStores(): EventStoresClient {
117
- return this.services.eventStores;
118
- }
119
-
120
- /**
121
- * Namespaces service
122
- */
123
- get namespaces(): NamespacesClient {
124
- return this.services.namespaces;
125
- }
126
-
127
- /**
128
- * Recommendations service
129
- */
130
- get recommendations(): RecommendationsClient {
131
- return this.services.recommendations;
132
- }
133
-
134
- /**
135
- * Identities service
136
- */
137
- get identities(): IdentitiesClient {
138
- return this.services.identities;
139
- }
140
-
141
- /**
142
- * Event sequences service
143
- */
144
- get eventSequences(): EventSequencesClient {
145
- return this.services.eventSequences;
146
- }
147
-
148
- /**
149
- * Event types service
150
- */
151
- get eventTypes(): EventTypesClient {
152
- return this.services.eventTypes;
153
- }
154
-
155
- /**
156
- * Constraints service
157
- */
158
- get constraints(): ConstraintsClient {
159
- return this.services.constraints;
160
- }
161
-
162
- /**
163
- * Observers service
164
- */
165
- get observers(): ObserversClient {
166
- return this.services.observers;
167
- }
168
-
169
- /**
170
- * Failed partitions service
171
- */
172
- get failedPartitions(): FailedPartitionsClient {
173
- return this.services.failedPartitions;
174
- }
175
-
176
- /**
177
- * Reactors service
178
- */
179
- get reactors(): ReactorsClient {
180
- return this.services.reactors;
181
- }
182
-
183
- /**
184
- * Reducers service
185
- */
186
- get reducers(): ReducersClient {
187
- return this.services.reducers;
188
- }
189
-
190
- /**
191
- * Projections service
192
- */
193
- get projections(): ProjectionsClient {
194
- return this.services.projections;
195
- }
196
-
197
- /**
198
- * Read models service
199
- */
200
- get readModels(): ReadModelsClient {
201
- return this.services.readModels;
202
- }
203
-
204
- /**
205
- * Jobs service
206
- */
207
- get jobs(): JobsClient {
208
- return this.services.jobs;
209
- }
210
-
211
- /**
212
- * Event seeding service
213
- */
214
- get eventSeeding(): EventSeedingClient {
215
- return this.services.eventSeeding;
216
- }
217
-
218
- /**
219
- * Server service
220
- */
221
- get server(): ServerClient {
222
- return this.services.server;
223
- }
224
-
225
- /**
226
- * Connection service for managing the connection
227
- */
228
- private connectionService: ConnectionServiceClient;
229
-
230
- /**
231
- * Gets the connection string used for this connection
232
- */
233
- get connectionString(): ChronicleConnectionString {
234
- return this._connectionString;
235
- }
236
-
237
- /**
238
- * Creates a new Chronicle connection
239
- * @param options Connection configuration options
240
- */
241
- constructor(options: ChronicleConnectionOptions) {
242
- // Parse connection string or create from serverAddress
243
- if (options.connectionString) {
244
- this._connectionString =
245
- typeof options.connectionString === 'string'
246
- ? new ChronicleConnectionString(options.connectionString)
247
- : options.connectionString;
248
- } else if (options.serverAddress) {
249
- this._connectionString = new ChronicleConnectionString(
250
- `chronicle://${options.serverAddress}`
251
- );
252
- } else {
253
- this._connectionString = ChronicleConnectionString.Default;
254
- }
255
-
256
- // Create server address string
257
- const serverAddress = `${this._connectionString.serverAddress.host}:${this._connectionString.serverAddress.port}`;
258
-
259
- // Create token provider for authentication
260
- this.tokenProvider = this.createTokenProvider(options);
261
-
262
- // Create channel options
263
- const channelOptions: grpc.ChannelOptions = {};
264
-
265
- if (options.maxReceiveMessageSize) {
266
- channelOptions['grpc.max_receive_message_length'] = options.maxReceiveMessageSize;
267
- }
268
-
269
- if (options.maxSendMessageSize) {
270
- channelOptions['grpc.max_send_message_length'] = options.maxSendMessageSize;
271
- }
272
-
273
- // Create gRPC channel credentials
274
- let channelCredentials = options.credentials;
275
- if (!channelCredentials) {
276
- channelCredentials = this._connectionString.createCredentials();
277
-
278
- if (!this._connectionString.disableTls) {
279
- const callCredentials = this.createAuthCallCredentials();
280
- if (callCredentials) {
281
- channelCredentials = grpc.credentials.combineChannelCredentials(
282
- channelCredentials,
283
- callCredentials
284
- );
285
- }
286
- }
287
- }
288
-
289
- // Create the gRPC channel
290
- this.channel = new grpc.Channel(serverAddress, channelCredentials, channelOptions);
291
-
292
- // Create services using nice-grpc's createClient
293
- this.connectionService = createClient(ConnectionServiceDefinition, this.channel);
294
- this.services = this.createServices();
295
- }
296
-
297
- private createServices(): ChronicleServices {
298
- console.log('[Chronicle] Creating services with middleware');
299
- // Create a client factory and attach auth middleware for all calls
300
- let factory = createClientFactory();
301
-
302
- console.log('[Chronicle] Attaching auth middleware');
303
- // Attach authentication middleware that works for both TLS and insecure channels
304
- factory = factory.use(this.createAuthMiddleware());
305
- console.log('[Chronicle] Middleware attached, creating service clients');
306
-
307
- return {
308
- eventStores: factory.create(EventStoresDefinition, this.channel),
309
- namespaces: factory.create(NamespacesDefinition, this.channel),
310
- recommendations: factory.create(RecommendationsDefinition, this.channel),
311
- identities: factory.create(IdentitiesDefinition, this.channel),
312
- eventSequences: factory.create(EventSequencesDefinition, this.channel),
313
- eventTypes: factory.create(EventTypesDefinition, this.channel),
314
- constraints: factory.create(ConstraintsDefinition, this.channel),
315
- observers: factory.create(ObserversDefinition, this.channel),
316
- failedPartitions: factory.create(FailedPartitionsDefinition, this.channel),
317
- reactors: factory.create(ReactorsDefinition, this.channel),
318
- reducers: factory.create(ReducersDefinition, this.channel),
319
- projections: factory.create(ProjectionsDefinition, this.channel),
320
- readModels: factory.create(ReadModelsDefinition, this.channel),
321
- jobs: factory.create(JobsDefinition, this.channel),
322
- eventSeeding: factory.create(EventSeedingDefinition, this.channel),
323
- server: factory.create(ServerDefinition, this.channel),
324
- };
325
- }
326
-
327
- /**
328
- * Creates a token provider based on connection configuration
329
- */
330
- private createTokenProvider(options: ChronicleConnectionOptions): ITokenProvider {
331
- const hasUsername = !!this._connectionString.username;
332
- const hasPassword = !!this._connectionString.password;
333
- const hasApiKey = !!this._connectionString.apiKey;
334
-
335
- if (hasApiKey) {
336
- // API key authentication is handled directly through call metadata.
337
- return new NoOpTokenProvider();
338
- }
339
-
340
- if (hasUsername !== hasPassword) {
341
- // Incomplete client credentials cannot produce a valid OAuth token.
342
- return new NoOpTokenProvider();
343
- }
344
-
345
- if (hasUsername && hasPassword) {
346
- return this.createOAuthTokenProvider(
347
- options,
348
- this._connectionString.username!,
349
- this._connectionString.password!
350
- );
351
- }
352
-
353
- // Development support: no app credentials provided, so use default dev credentials.
354
- return this.createOAuthTokenProvider(
355
- options,
356
- ChronicleConnectionString.DEVELOPMENT_CLIENT,
357
- ChronicleConnectionString.DEVELOPMENT_CLIENT_SECRET
358
- );
359
- }
360
-
361
- private createOAuthTokenProvider(
362
- options: ChronicleConnectionOptions,
363
- username: string,
364
- password: string
365
- ): ITokenProvider {
366
- const managementPort = options.managementPort || 8080;
367
- let authorityHost: string;
368
- let authorityPort: number;
369
-
370
- if (options.authority) {
371
- const authorityUrl = new URL(options.authority);
372
- authorityHost = authorityUrl.hostname;
373
- authorityPort = authorityUrl.port ? parseInt(authorityUrl.port, 10) : managementPort;
374
- } else {
375
- authorityHost = this._connectionString.serverAddress.host;
376
- authorityPort = managementPort;
377
- }
378
-
379
- const scheme = this._connectionString.disableTls ? 'http' : 'https';
380
- const tokenEndpoint = `${scheme}://${authorityHost}:${authorityPort}/connect/token`;
381
-
382
- return new OAuthTokenProvider(tokenEndpoint, username, password);
383
- }
384
-
385
- /**
386
- * Creates call credentials with bearer token from token provider
387
- */
388
- private createAuthCallCredentials(): grpc.CallCredentials | undefined {
389
- // Insecure channels cannot compose with call credentials — skip when TLS is disabled.
390
- if (this._connectionString.disableTls) {
391
- return undefined;
392
- }
393
- return grpc.credentials.createFromMetadataGenerator(async (params, callback) => {
394
- try {
395
- const token = await this.tokenProvider.getAccessToken();
396
- const metadata = new grpc.Metadata();
397
-
398
- if (token) {
399
- metadata.add('authorization', `Bearer ${token}`);
400
- } else {
401
- // Check for API key authentication
402
- try {
403
- const authMode = this._connectionString.authenticationMode;
404
- if (authMode === AuthenticationMode.ApiKey && this._connectionString.apiKey) {
405
- metadata.add('api-key', this._connectionString.apiKey);
406
- }
407
- } catch {
408
- // No API key configured
409
- }
410
- }
411
-
412
- callback(null, metadata);
413
- } catch (error) {
414
- callback(error as Error, new grpc.Metadata());
415
- }
416
- });
417
- }
418
-
419
- /**
420
- * Gets whether the connection is established
421
- */
422
- get isConnected(): boolean {
423
- return this._isConnected;
424
- }
425
-
426
- /**
427
- * Creates a middleware that injects authentication headers for all calls.
428
- * This works for both TLS and insecure channels, similar to gRPC interceptors in C#.
429
- */
430
- private createAuthMiddleware(): ClientMiddleware {
431
- const tokenProvider = this.tokenProvider;
432
- const connectionString = this._connectionString;
433
-
434
- return async function* authMiddleware(call, options) {
435
- try {
436
- const token = await tokenProvider.getAccessToken();
437
-
438
- if (token) {
439
- // Create metadata object with the Bearer token
440
- // The Metadata factory function from nice-grpc-common accepts an object
441
- const authMetadata = Metadata({ authorization: `Bearer ${token}` });
442
-
443
- // Merge with existing metadata if present
444
- if (options.metadata) {
445
- const mergedMetadata = Metadata(options.metadata);
446
- mergedMetadata.set('authorization', `Bearer ${token}`);
447
- options.metadata = mergedMetadata;
448
- } else {
449
- options.metadata = authMetadata;
450
- }
451
- } else {
452
- // Fallback to API key if no token
453
- try {
454
- const authMode = connectionString.authenticationMode;
455
- if (authMode === AuthenticationMode.ApiKey && connectionString.apiKey) {
456
- const apiKeyMetadata = Metadata({ 'api-key': connectionString.apiKey });
457
-
458
- if (options.metadata) {
459
- const mergedMetadata = Metadata(options.metadata);
460
- mergedMetadata.set('api-key', connectionString.apiKey);
461
- options.metadata = mergedMetadata;
462
- } else {
463
- options.metadata = apiKeyMetadata;
464
- }
465
- }
466
- } catch {
467
- // No API key configured, continue without additional auth
468
- }
469
- }
470
- } catch (error) {
471
- // If token retrieval fails, continue without additional auth headers
472
- // This allows the connection to proceed with channel-level credentials if available
473
- }
474
-
475
- // Pass through to next middleware/handler, properly returning the response
476
- return yield* call.next(call.request, options);
477
- };
478
- }
479
-
480
- /**
481
- * Connects to the Chronicle Kernel
482
- * @returns Promise that resolves when connected
483
- */
484
- async connect(): Promise<void> {
485
- if (this._isConnected) {
486
- return;
487
- }
488
-
489
- return new Promise<void>((resolve, reject) => {
490
- const deadline = new Date();
491
- deadline.setSeconds(deadline.getSeconds() + 10);
492
-
493
- this.channel.watchConnectivityState(
494
- this.channel.getConnectivityState(true),
495
- deadline,
496
- (error) => {
497
- if (error) {
498
- this._isConnected = false;
499
- reject(error);
500
- } else {
501
- const state = this.channel.getConnectivityState(false);
502
- if (state === grpc.connectivityState.READY) {
503
- this._isConnected = true;
504
- resolve();
505
- } else {
506
- this._isConnected = false;
507
- reject(new Error(`Connection failed with state: ${state}`));
508
- }
509
- }
510
- }
511
- );
512
- });
513
- }
514
-
515
- /**
516
- * Disconnects from the Chronicle Kernel
517
- */
518
- disconnect(): void {
519
- this._isConnected = false;
520
- this.channel.close();
521
- }
522
-
523
- /**
524
- * Disposes the connection and cleans up resources
525
- */
526
- dispose(): void {
527
- this.disconnect();
528
- }
529
- }
530
-