@magek/common 0.0.7 → 0.0.8

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/config.d.ts CHANGED
@@ -61,6 +61,10 @@ export declare class MagekConfig {
61
61
  enableSubscriptions: boolean;
62
62
  readonly nonExposedGraphQLMetadataKey: Record<string, Array<string>>;
63
63
  dispatchedEventsTtl: number;
64
+ /** Interval in milliseconds between event polling cycles. Default: 1000ms */
65
+ eventPollingIntervalMs: number;
66
+ /** Number of events to process per polling cycle. Default: 100 */
67
+ eventProcessingBatchSize: number;
64
68
  traceConfiguration: TraceConfiguration;
65
69
  eventStreamConfiguration: EventStreamConfiguration;
66
70
  /** Environment variables to set when running the application */
package/dist/config.js CHANGED
@@ -67,6 +67,10 @@ class MagekConfig {
67
67
  nonExposedGraphQLMetadataKey = {};
68
68
  // TTL for events stored in dispatched events table. Default to 5 minutes (i.e., 300 seconds).
69
69
  dispatchedEventsTtl = 300;
70
+ /** Interval in milliseconds between event polling cycles. Default: 1000ms */
71
+ eventPollingIntervalMs = 1000;
72
+ /** Number of events to process per polling cycle. Default: 100 */
73
+ eventProcessingBatchSize = 100;
70
74
  traceConfiguration = {
71
75
  enableTraceNotification: false,
72
76
  includeInternal: false,
@@ -39,9 +39,17 @@ export interface NonPersistedEventEnvelope extends EventStoreEntryEnvelope {
39
39
  createdAt: string;
40
40
  }
41
41
  export interface EventEnvelope extends NonPersistedEventEnvelope {
42
+ /** Unique identifier assigned by the event store after persistence. */
42
43
  id?: string;
44
+ /** ISO timestamp when the event was created. */
43
45
  createdAt: string;
46
+ /** ISO timestamp when the event was soft-deleted, if applicable. */
44
47
  deletedAt?: string;
48
+ /**
49
+ * ISO timestamp when the event was processed by async event processing.
50
+ * Used for filtering unprocessed events and as an audit marker.
51
+ */
52
+ processedAt?: string;
45
53
  }
46
54
  export interface NonPersistedEntitySnapshotEnvelope extends EventStoreEntryEnvelope {
47
55
  kind: 'snapshot';
@@ -10,8 +10,32 @@ export interface EventStoreAdapter {
10
10
  * @returns An array of EventEnvelope objects
11
11
  */
12
12
  rawToEnvelopes(rawEvents: unknown): Array<EventEnvelope>;
13
+ /**
14
+ * Converts raw stream data into an array of EventEnvelope objects.
15
+ *
16
+ * @param config - The Magek configuration object
17
+ * @param context - The context from the raw stream
18
+ * @param dedupEventStream - The deduplicated event stream
19
+ * @returns An array of EventEnvelope objects
20
+ */
13
21
  rawStreamToEnvelopes(config: MagekConfig, context: unknown, dedupEventStream: EventStream): Array<EventEnvelope>;
22
+ /**
23
+ * Deduplicates raw events and returns them as an EventStream.
24
+ *
25
+ * @param config - The Magek configuration object
26
+ * @param rawEvents - The raw events data to deduplicate
27
+ * @returns A promise that resolves to a deduplicated EventStream
28
+ */
14
29
  dedupEventStream(config: MagekConfig, rawEvents: unknown): Promise<EventStream>;
30
+ /**
31
+ * Produces events to an external event stream (e.g., Kafka).
32
+ *
33
+ * @param entityName - The name of the entity type
34
+ * @param entityID - The unique identifier of the entity
35
+ * @param eventEnvelopes - The array of EventEnvelope objects to produce
36
+ * @param config - The Magek configuration object
37
+ * @returns A promise that resolves when events are produced
38
+ */
15
39
  produce(entityName: string, entityID: UUID, eventEnvelopes: Array<EventEnvelope>, config: MagekConfig): Promise<void>;
16
40
  /**
17
41
  * Retrieves events for a specific entity since a given time
@@ -76,48 +100,79 @@ export interface EventStoreAdapter {
76
100
  */
77
101
  storeDispatched(eventEnvelope: EventEnvelope, config: MagekConfig): Promise<boolean>;
78
102
  /**
79
- * Find all events to be removed based on the parameters
103
+ * Finds all events matching the deletion criteria.
80
104
  *
81
- * @param config
82
- * @param parameters
105
+ * @param config - The Magek configuration object
106
+ * @param parameters - The parameters specifying which events to find for deletion
107
+ * @returns A promise that resolves to an array of EventEnvelopeFromDatabase objects
83
108
  */
84
109
  findDeletableEvent(config: MagekConfig, parameters: EventDeleteParameters): Promise<Array<EventEnvelopeFromDatabase>>;
85
110
  /**
86
- * Find all snapshots to be removed based on the parameters
111
+ * Finds all snapshots matching the deletion criteria.
87
112
  *
88
- * @param config
89
- * @param parameters
113
+ * @param config - The Magek configuration object
114
+ * @param parameters - The parameters specifying which snapshots to find for deletion
115
+ * @returns A promise that resolves to an array of EntitySnapshotEnvelopeFromDatabase objects
90
116
  */
91
117
  findDeletableSnapshot(config: MagekConfig, parameters: SnapshotDeleteParameters): Promise<Array<EntitySnapshotEnvelopeFromDatabase>>;
92
118
  /**
93
- * Delete events
119
+ * Soft-deletes events by marking them with a deletedAt timestamp.
94
120
  *
95
- * @param config
96
- * @param events
121
+ * @param config - The Magek configuration object
122
+ * @param events - The array of events to delete
123
+ * @returns A promise that resolves when the events are deleted
97
124
  */
98
125
  deleteEvent(config: MagekConfig, events: Array<EventEnvelopeFromDatabase>): Promise<void>;
99
126
  /**
100
- * Delete snapshots
127
+ * Soft-deletes snapshots by marking them with a deletedAt timestamp.
101
128
  *
102
- * @param config
103
- * @param snapshots
129
+ * @param config - The Magek configuration object
130
+ * @param snapshots - The array of snapshots to delete
131
+ * @returns A promise that resolves when the snapshots are deleted
104
132
  */
105
133
  deleteSnapshot(config: MagekConfig, snapshots: Array<EntitySnapshotEnvelopeFromDatabase>): Promise<void>;
106
134
  /**
107
- * Health check methods for the event store
135
+ * Health check methods for the event store.
108
136
  */
109
137
  healthCheck?: {
110
138
  /**
111
- * Check if the event store is up and running
139
+ * Checks if the event store is up and running.
140
+ *
141
+ * @param config - The Magek configuration object
142
+ * @returns A promise that resolves to true if the event store is healthy
112
143
  */
113
144
  isUp(config: MagekConfig): Promise<boolean>;
114
145
  /**
115
- * Get detailed health information about the event store
146
+ * Gets detailed health information about the event store.
147
+ *
148
+ * @param config - The Magek configuration object
149
+ * @returns A promise that resolves to health details
116
150
  */
117
151
  details(config: MagekConfig): Promise<unknown>;
118
152
  /**
119
- * Get the URLs/endpoints of the event store
153
+ * Gets the URLs/endpoints of the event store.
154
+ *
155
+ * @param config - The Magek configuration object
156
+ * @returns A promise that resolves to an array of URL strings
120
157
  */
121
158
  urls(config: MagekConfig): Promise<Array<string>>;
122
159
  };
160
+ /**
161
+ * Fetches the next batch of unprocessed events.
162
+ * The adapter manages the cursor internally to track processing position.
163
+ * Batch size is read from config.eventProcessingBatchSize.
164
+ *
165
+ * @param config - The Magek configuration object
166
+ * @returns A promise that resolves to an array of EventEnvelope objects
167
+ */
168
+ fetchUnprocessedEvents?(config: MagekConfig): Promise<Array<EventEnvelope>>;
169
+ /**
170
+ * Marks a single event as processed and advances the internal cursor.
171
+ * Should be called after each event has been successfully dispatched.
172
+ *
173
+ * @param config - The Magek configuration object
174
+ * @param eventId - The ID of the event that was processed
175
+ * @returns A promise that resolves when the event is marked and cursor is updated
176
+ */
177
+ markEventProcessed?(config: MagekConfig, eventId: UUID): Promise<void>;
123
178
  }
package/dist/index.d.ts CHANGED
@@ -1,30 +1,27 @@
1
- export * from './groups';
2
- export * from './promises';
3
- export * from './retrier';
4
- export * from './instances';
5
- export * from './run-command';
6
- export * from './logger';
7
- export * from './http-service';
8
1
  export * from './app';
9
- export * from './envelope';
10
2
  export * from './config';
11
3
  export * from './concepts';
12
- export * from './typelevel';
4
+ export * from './envelope';
13
5
  export * from './errors';
14
6
  export * from './errors/index';
15
- export * from './user-app';
7
+ export * from './logger';
16
8
  export * from './searcher';
17
- export * from './graphql-websocket-messages';
18
- export * from './schedule';
19
- export * from './data-migration-parameters';
20
- export * from './super-kind';
21
- export * from './instrumentation/trace-types';
22
- export * from './sensor/health-indicator-configuration';
23
- export * from './internal-info';
24
- export * from './stream-types';
25
- export * from './runtime';
26
9
  export * from './event-store-adapter';
27
10
  export * from './read-model-store-adapter';
28
11
  export * from './session-store-adapter';
29
- export * from './metadata-types';
12
+ export * from './retrier';
30
13
  export * from './timestamp-generator';
14
+ export * from './instances';
15
+ export * from './groups';
16
+ export * from './stream-types';
17
+ export * from './typelevel';
18
+ export * from './runtime';
19
+ export * from './user-app';
20
+ export * from './metadata-types';
21
+ export * from './super-kind';
22
+ export * from './schedule';
23
+ export * from './data-migration-parameters';
24
+ export * from './graphql-websocket-messages';
25
+ export * from './http-service';
26
+ export * from './instrumentation/trace-types';
27
+ export * from './sensor/health-indicator-configuration';
package/dist/index.js CHANGED
@@ -1,33 +1,43 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
- tslib_1.__exportStar(require("./groups"), exports);
5
- tslib_1.__exportStar(require("./promises"), exports);
6
- tslib_1.__exportStar(require("./retrier"), exports);
7
- tslib_1.__exportStar(require("./instances"), exports);
8
- tslib_1.__exportStar(require("./run-command"), exports);
9
- tslib_1.__exportStar(require("./logger"), exports);
10
- tslib_1.__exportStar(require("./http-service"), exports);
4
+ // =============================================================================
5
+ // PUBLIC API - Core Framework Types
6
+ // These are the primary exports for framework users building Magek applications
7
+ // =============================================================================
11
8
  tslib_1.__exportStar(require("./app"), exports);
12
- tslib_1.__exportStar(require("./envelope"), exports);
13
9
  tslib_1.__exportStar(require("./config"), exports);
14
10
  tslib_1.__exportStar(require("./concepts"), exports);
15
- tslib_1.__exportStar(require("./typelevel"), exports);
11
+ tslib_1.__exportStar(require("./envelope"), exports);
16
12
  tslib_1.__exportStar(require("./errors"), exports);
17
13
  tslib_1.__exportStar(require("./errors/index"), exports);
18
- tslib_1.__exportStar(require("./user-app"), exports);
14
+ tslib_1.__exportStar(require("./logger"), exports);
19
15
  tslib_1.__exportStar(require("./searcher"), exports);
20
- tslib_1.__exportStar(require("./graphql-websocket-messages"), exports);
21
- tslib_1.__exportStar(require("./schedule"), exports);
22
- tslib_1.__exportStar(require("./data-migration-parameters"), exports);
23
- tslib_1.__exportStar(require("./super-kind"), exports);
24
- tslib_1.__exportStar(require("./instrumentation/trace-types"), exports);
25
- tslib_1.__exportStar(require("./sensor/health-indicator-configuration"), exports);
26
- tslib_1.__exportStar(require("./internal-info"), exports);
27
- tslib_1.__exportStar(require("./stream-types"), exports);
28
- tslib_1.__exportStar(require("./runtime"), exports);
16
+ // =============================================================================
17
+ // ADAPTER DEVELOPMENT
18
+ // Types and utilities for building custom adapters (event stores, read models, etc.)
19
+ // =============================================================================
29
20
  tslib_1.__exportStar(require("./event-store-adapter"), exports);
30
21
  tslib_1.__exportStar(require("./read-model-store-adapter"), exports);
31
22
  tslib_1.__exportStar(require("./session-store-adapter"), exports);
32
- tslib_1.__exportStar(require("./metadata-types"), exports);
23
+ tslib_1.__exportStar(require("./retrier"), exports);
33
24
  tslib_1.__exportStar(require("./timestamp-generator"), exports);
25
+ tslib_1.__exportStar(require("./instances"), exports);
26
+ tslib_1.__exportStar(require("./groups"), exports);
27
+ tslib_1.__exportStar(require("./stream-types"), exports);
28
+ // =============================================================================
29
+ // FRAMEWORK INTERNALS
30
+ // Used by @magek/core, @magek/server, and other framework packages
31
+ // These may change between versions - use with caution in user code
32
+ // =============================================================================
33
+ tslib_1.__exportStar(require("./typelevel"), exports);
34
+ tslib_1.__exportStar(require("./runtime"), exports);
35
+ tslib_1.__exportStar(require("./user-app"), exports);
36
+ tslib_1.__exportStar(require("./metadata-types"), exports);
37
+ tslib_1.__exportStar(require("./super-kind"), exports);
38
+ tslib_1.__exportStar(require("./schedule"), exports);
39
+ tslib_1.__exportStar(require("./data-migration-parameters"), exports);
40
+ tslib_1.__exportStar(require("./graphql-websocket-messages"), exports);
41
+ tslib_1.__exportStar(require("./http-service"), exports);
42
+ tslib_1.__exportStar(require("./instrumentation/trace-types"), exports);
43
+ tslib_1.__exportStar(require("./sensor/health-indicator-configuration"), exports);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@magek/common",
3
- "version": "0.0.7",
3
+ "version": "0.0.8",
4
4
  "description": "Contains Magek common helpers used by the core and provider packages",
5
5
  "keywords": [
6
6
  "framework-common-helpers"
@@ -33,7 +33,7 @@
33
33
  "uuid": "^13.0.0"
34
34
  },
35
35
  "devDependencies": {
36
- "@magek/eslint-config": "^0.0.7",
36
+ "@magek/eslint-config": "^0.0.8",
37
37
  "@types/chai": "5.2.3",
38
38
  "@types/chai-as-promised": "8.0.2",
39
39
  "@types/mocha": "10.0.10",
@@ -1,2 +0,0 @@
1
- export declare const MAGEK_LOCAL_PORT = "INTERNAL_LOCAL_PORT";
2
- export declare const localPort: () => string;
@@ -1,6 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.localPort = exports.MAGEK_LOCAL_PORT = void 0;
4
- exports.MAGEK_LOCAL_PORT = 'INTERNAL_LOCAL_PORT';
5
- const localPort = () => process.env[exports.MAGEK_LOCAL_PORT] || '3000';
6
- exports.localPort = localPort;
@@ -1,25 +0,0 @@
1
- export declare class Promises {
2
- /**
3
- * Waits until all the passed promise-like values are settled, no matter if they were fulfilled or rejected.
4
- * If some rejected were found, an array with all the rejected promises is thrown.
5
- * If all were fulfilled, an array of PromiseFulfilledResult is returned
6
- * @param values Array of promise-like values to be wait for
7
- * @throws an array of PromiseRejectedResult with all the rejected promises, if any
8
- *
9
- * Comparison with other similar Promise methods:
10
- * - `Promise.all`: This has an "all-or-nothing" behavior. As long as one of the promises is rejected, the result is
11
- * rejected. More importantly, **it does not wait for al the promises to finish**, which could lead to undesired behaviors
12
- * - `Promise.allSettled`: This method waits for all the promises to finish and then returns an array of results. Some
13
- * of them will be fulfilled and some rejected. More importantly, **it never throws an error**, which could lead to
14
- * unexpected consequences. For example if you do "await Promise.allSettle(...)" expecting it to throw if some of them
15
- * failed, you won't get that.
16
- *
17
- * In brief, `Promises.allSettledAndFulfilled` behaves exactly the same way as `Promise.allSettle` but it throws with
18
- * an array of the failed promises, only if there are any.
19
- */
20
- static allSettledAndFulfilled<TValue>(values: Iterable<TValue>): ReturnType<PromiseConstructor['allSettled']>;
21
- }
22
- export declare class PromisesError extends Error {
23
- readonly failedReasons: Array<unknown>;
24
- constructor(rejectedResults: Array<PromiseRejectedResult>);
25
- }
package/dist/promises.js DELETED
@@ -1,43 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PromisesError = exports.Promises = void 0;
4
- class Promises {
5
- /**
6
- * Waits until all the passed promise-like values are settled, no matter if they were fulfilled or rejected.
7
- * If some rejected were found, an array with all the rejected promises is thrown.
8
- * If all were fulfilled, an array of PromiseFulfilledResult is returned
9
- * @param values Array of promise-like values to be wait for
10
- * @throws an array of PromiseRejectedResult with all the rejected promises, if any
11
- *
12
- * Comparison with other similar Promise methods:
13
- * - `Promise.all`: This has an "all-or-nothing" behavior. As long as one of the promises is rejected, the result is
14
- * rejected. More importantly, **it does not wait for al the promises to finish**, which could lead to undesired behaviors
15
- * - `Promise.allSettled`: This method waits for all the promises to finish and then returns an array of results. Some
16
- * of them will be fulfilled and some rejected. More importantly, **it never throws an error**, which could lead to
17
- * unexpected consequences. For example if you do "await Promise.allSettle(...)" expecting it to throw if some of them
18
- * failed, you won't get that.
19
- *
20
- * In brief, `Promises.allSettledAndFulfilled` behaves exactly the same way as `Promise.allSettle` but it throws with
21
- * an array of the failed promises, only if there are any.
22
- */
23
- static async allSettledAndFulfilled(values) {
24
- const results = await Promise.allSettled(values); // Promise.allSettled never throws
25
- // Get all the failed promises
26
- const failed = results.filter((result) => result.status === 'rejected');
27
- // Throw if we found any failed ones
28
- if (failed.length > 0) {
29
- throw new PromisesError(failed);
30
- }
31
- return results;
32
- }
33
- }
34
- exports.Promises = Promises;
35
- class PromisesError extends Error {
36
- failedReasons;
37
- constructor(rejectedResults) {
38
- const reasons = rejectedResults.map((res) => res.reason);
39
- super(reasons.join('. '));
40
- this.failedReasons = reasons;
41
- }
42
- }
43
- exports.PromisesError = PromisesError;
@@ -1,5 +0,0 @@
1
- import { ChildProcessWithoutNullStreams } from 'child_process';
2
- /** Spawn a CLI command and optionally printing the logs and error messages */
3
- export declare function runCommandAsync(path: string, command: string, ignoreLogs?: boolean): ChildProcessWithoutNullStreams;
4
- /** Synchronously run a CLI command and return the stdout, optionally printing the logs and error messages */
5
- export declare function runCommand(path: string, command: string, ignoreLogs?: boolean): Promise<string>;
@@ -1,48 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.runCommandAsync = runCommandAsync;
4
- exports.runCommand = runCommand;
5
- const child_process_1 = require("child_process");
6
- /** Spawn a CLI command and optionally printing the logs and error messages */
7
- function runCommandAsync(path, command, ignoreLogs = false) {
8
- // Split the command into an array of arguments
9
- const args = command.split(' ');
10
- // Use the first argument as the command name
11
- const subprocess = (0, child_process_1.spawn)(args[0], args.slice(1), {
12
- cwd: path,
13
- stdio: 'pipe',
14
- });
15
- if (!ignoreLogs) {
16
- subprocess.stdout.on('data', (data) => {
17
- console.log(data.toString());
18
- });
19
- subprocess.stderr.on('data', (data) => {
20
- console.error(data.toString());
21
- });
22
- }
23
- return subprocess;
24
- }
25
- /** Synchronously run a CLI command and return the stdout, optionally printing the logs and error messages */
26
- function runCommand(path, command, ignoreLogs = false) {
27
- return new Promise((resolve, reject) => {
28
- const subprocess = runCommandAsync(path, command, ignoreLogs);
29
- let stdout = '';
30
- let stderr = '';
31
- if (subprocess) {
32
- subprocess.stdout.on('data', (data) => {
33
- stdout += data.toString();
34
- });
35
- subprocess.stderr.on('data', (data) => {
36
- stderr += data.toString();
37
- });
38
- subprocess.on('close', (code) => {
39
- if (code === 0) {
40
- resolve(stdout);
41
- }
42
- else {
43
- reject(stderr);
44
- }
45
- });
46
- }
47
- });
48
- }