-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Clarify internal/external separation (#135)
- Loading branch information
Showing
7 changed files
with
101 additions
and
26 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,11 @@ | ||
import { z } from 'zod' | ||
|
||
// Core fields that describe either internal event or external message | ||
export const BASE_EVENT_SCHEMA = z.object({ | ||
id: z.string().describe('event unique identifier'), | ||
timestamp: z.string().datetime().describe('iso 8601 datetime'), | ||
type: z.literal<string>('<replace.me>').describe('event type name'), | ||
payload: z.optional(z.object({})).describe('event payload based on type'), | ||
}) | ||
|
||
export type BaseEventType = z.infer<typeof BASE_EVENT_SCHEMA> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,28 +1,28 @@ | ||
import z from 'zod' | ||
|
||
// Core fields that describe event | ||
export const BASE_MESSAGE_SCHEMA = z.object({ | ||
id: z.string().describe('event unique identifier'), | ||
timestamp: z.string().datetime().describe('iso 8601 datetime'), | ||
type: z.literal<string>('<replace.me>').describe('event type name'), | ||
payload: z.optional(z.object({})).describe('event payload based on type'), | ||
}) | ||
import { BASE_EVENT_SCHEMA } from '../events/baseEventSchemas' | ||
|
||
// External message metadata that describe the context in which the message was created, primarily used for debugging purposes | ||
export const MESSAGE_METADATA_SCHEMA = z | ||
.object({ | ||
schemaVersion: z.string().min(1).describe('message schema version'), | ||
// this is always set to a service that created the message | ||
producedBy: z.string().min(1).describe('app/service that produced the message'), | ||
// this is always propagated within the message chain. For the first message in the chain it is equal to "producedBy" | ||
originatedFrom: z | ||
.string() | ||
.min(1) | ||
.describe('app/service that initiated entire workflow that led to creating this message'), | ||
// this is always propagated within the message chain. | ||
correlationId: z.string().describe('unique identifier passed to all events in workflow chain'), | ||
}) | ||
.describe('external message metadata') | ||
|
||
// Extra fields that are optional for the event processing | ||
export const EXTENDED_MESSAGE_SCHEMA = BASE_MESSAGE_SCHEMA.extend({ | ||
metadata: z | ||
.object({ | ||
schemaVersion: z.string().min(1).describe('message schema version'), | ||
producedBy: z.string().min(1).describe('app/service that produced the message'), | ||
originatedFrom: z | ||
.string() | ||
.min(1) | ||
.describe('app/service that initiated entire workflow that led to creating this message'), | ||
correlationId: z | ||
.string() | ||
.describe('unique identifier passed to all events in workflow chain'), | ||
}) | ||
.describe('event metadata'), | ||
export const BASE_MESSAGE_SCHEMA = BASE_EVENT_SCHEMA.extend({ | ||
// For internal domain events that did not originate within a message chain metadata field can be omitted, producer should then assume it is initiating a new chain | ||
metadata: MESSAGE_METADATA_SCHEMA.optional(), | ||
}) | ||
|
||
export type BaseMessageType = z.infer<typeof BASE_MESSAGE_SCHEMA> | ||
|
||
export type MessageMetadataType = z.infer<typeof MESSAGE_METADATA_SCHEMA> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
import { describe, expect, it } from 'vitest' | ||
import { z } from 'zod' | ||
|
||
import { toDatePreprocessor } from './toDateProcessor' | ||
|
||
describe('toDatePreprocessor', () => { | ||
it('converts valid strings to date', () => { | ||
const SCHEMA = z.object({ | ||
createdAt: z.preprocess(toDatePreprocessor, z.date()), | ||
updatedAt: z.preprocess(toDatePreprocessor, z.date()), | ||
}) | ||
|
||
const result = SCHEMA.parse({ | ||
createdAt: '2016-01-01', | ||
updatedAt: '2022-01-12T00:00:00.000Z', | ||
}) | ||
|
||
expect(result).toEqual({ | ||
createdAt: new Date('2016-01-01'), | ||
updatedAt: new Date('2022-01-12T00:00:00.000Z'), | ||
}) | ||
}) | ||
|
||
it('converts valid numbers to date', () => { | ||
const SCHEMA = z.object({ | ||
createdAt: z.preprocess(toDatePreprocessor, z.date()), | ||
updatedAt: z.preprocess(toDatePreprocessor, z.date()), | ||
}) | ||
|
||
const result = SCHEMA.parse({ | ||
createdAt: 166, | ||
updatedAt: 99999, | ||
}) | ||
|
||
expect(result).toEqual({ | ||
createdAt: new Date(166), | ||
updatedAt: new Date(99999), | ||
}) | ||
}) | ||
|
||
it('does not convert function input', () => { | ||
const SCHEMA = z.object({ | ||
createdAt: z.preprocess(toDatePreprocessor, z.date()), | ||
}) | ||
|
||
expect(() => | ||
SCHEMA.parse({ | ||
createdAt: (x: string) => x, | ||
}), | ||
).toThrow(/Expected date, received function/) | ||
}) | ||
}) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
export const toDatePreprocessor = (value: unknown) => { | ||
switch (typeof value) { | ||
case 'string': | ||
case 'number': | ||
return new Date(value) | ||
|
||
default: | ||
return value // could not coerce, return the original and face the consequences during validation | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters