arvo-core 1.2.3 → 2.0.1

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 (33) hide show
  1. package/CHANGELOG.md +4 -0
  2. package/dist/ArvoContract/helpers.d.ts +119 -20
  3. package/dist/ArvoContract/helpers.js +150 -32
  4. package/dist/ArvoContract/index.d.ts +32 -26
  5. package/dist/ArvoContract/index.js +69 -60
  6. package/dist/ArvoContract/types.d.ts +49 -35
  7. package/dist/ArvoEvent/schema.d.ts +2 -2
  8. package/dist/ArvoEventFactory/helpers.d.ts +39 -9
  9. package/dist/ArvoEventFactory/helpers.js +50 -8
  10. package/dist/ArvoEventFactory/index.d.ts +60 -33
  11. package/dist/ArvoEventFactory/index.js +62 -36
  12. package/dist/ArvoOrchestrationSubject/index.d.ts +5 -4
  13. package/dist/ArvoOrchestrationSubject/index.js +2 -2
  14. package/dist/ArvoOrchestrationSubject/schema.d.ts +1 -2
  15. package/dist/ArvoOrchestrationSubject/schema.js +4 -11
  16. package/dist/ArvoOrchestrationSubject/type.d.ts +2 -12
  17. package/dist/ArvoOrchestratorContract/index.d.ts +62 -56
  18. package/dist/ArvoOrchestratorContract/index.js +99 -93
  19. package/dist/ArvoOrchestratorContract/types.d.ts +64 -71
  20. package/dist/index.d.ts +14 -18
  21. package/dist/index.js +12 -14
  22. package/dist/schema.d.ts +1 -0
  23. package/dist/schema.js +6 -1
  24. package/dist/types.d.ts +107 -81
  25. package/dist/utils.d.ts +21 -0
  26. package/dist/utils.js +33 -0
  27. package/package.json +1 -1
  28. package/dist/ArvoContractLibrary/helpers.d.ts +0 -10
  29. package/dist/ArvoContractLibrary/helpers.js +0 -22
  30. package/dist/ArvoContractLibrary/index.d.ts +0 -61
  31. package/dist/ArvoContractLibrary/index.js +0 -87
  32. package/dist/ArvoOrchestratorContract/helpers.d.ts +0 -67
  33. package/dist/ArvoOrchestratorContract/helpers.js +0 -101
package/CHANGELOG.md CHANGED
@@ -68,3 +68,7 @@
68
68
 
69
69
  - Added mandatory parent chaining in orchestration events so the process chaining and orchestration chaining can be traced
70
70
 
71
+ ## [2.0.0] - 2024-11-24
72
+
73
+ - Added version support for contracts and simplified orchestrator contracts
74
+
@@ -1,33 +1,132 @@
1
1
  import { IArvoContract } from './types';
2
2
  import ArvoContract from '.';
3
+ import { ArvoSemanticVersion } from '../types';
4
+ import { z } from 'zod';
3
5
  /**
4
- * Infers the ArvoContract type from a given IArvoContract.
6
+ * Infers the ArvoContract type from a given IArvoContract interface.
7
+ *
8
+ * @template T - The IArvoContract interface to infer from
5
9
  */
6
- export type InferArvoContract<T> = T extends IArvoContract<infer S, infer U, infer V, infer W> ? ArvoContract<S, U, V, W> : never;
10
+ type InferArvoContract<T> = T extends IArvoContract<infer Uri, infer Type, infer Versions> ? ArvoContract<Uri, Type, Versions> : never;
7
11
  /**
8
- * Creates an ArvoContract instance from the given contract specification.
12
+ * Creates and validates an ArvoContract instance from a contract specification.
9
13
  *
10
- * This function provides a convenient way to create and initialize an ArvoContract
11
- * with proper type inference.
14
+ * @template TContract - The contract specification type, must extend IArvoContract
15
+ * @param contract - The contract specification object containing URI, type, and versioned schemas
16
+ * @throws {Error} If any event type uses the reserved orchestrator prefix
17
+ * @throws {Error} If URI or event types fail validation
18
+ * @returns A properly typed ArvoContract instance
12
19
  *
13
- * @template TContract - The type of the contract specification.
20
+ * @example
21
+ * ```typescript
22
+ * const contract = createArvoContract({
23
+ * uri: 'com.example.contract',
24
+ * type: 'input.event',
25
+ * versions: {
26
+ * '0.0.1': {
27
+ * accepts: z.object({ data: z.string() }),
28
+ * emits: {
29
+ * 'output.event': z.object({ result: z.number() })
30
+ * }
31
+ * }
32
+ * }
33
+ * });
34
+ * ```
35
+ */
36
+ export declare const createArvoContract: <const TContract extends IArvoContract>(contract: TContract, isOrchestrationContract?: boolean) => InferArvoContract<TContract>;
37
+ /**
38
+ * Creates a simplified ArvoContract with standardized type prefixes and emit patterns.
39
+ * This is a convenience function that automatically formats event types according to conventions:
40
+ * - Accept types are prefixed with "com."
41
+ * - Emit types are prefixed with "evt." and suffixed with ".success"
42
+ *
43
+ * @template TUri - The URI type for the contract
44
+ * @template TType - The base type name (without prefixes) for the contract
45
+ * @template TVersions - Record of versions containing accept and emit schemas
14
46
  *
15
- * @param contract - The contract specification object.
16
- * This should include the URI, accepts, and emits properties as defined in IArvoContract.
47
+ * @param param - The configuration object for creating the contract
48
+ * @param param.uri - The URI identifying the contract
49
+ * @param param.type - The base type name (will be prefixed with "com.")
50
+ * @param param.versions - Version-specific schema definitions
51
+ * @param param.versions[version].accepts - Zod schema for validating incoming events
52
+ * @param param.versions[version].emits - Zod schema for validating outgoing events
17
53
  *
18
- * @returns The created ArvoContract instance.
19
- * The returned type is inferred from the input contract specification.
54
+ * @returns An ArvoContract instance with standardized type formatting:
55
+ * - Accept type will be "com.[type]"
56
+ * - Emit type will be "evt.[type].success"
20
57
  *
21
58
  * @example
22
- * const myContract = createArvoContract({
23
- * uri: 'https://example.com/contracts/myContract',
24
- * accepts: {
25
- * type: 'com.example.input',
26
- * schema: z.object({ name: z.string() }),
27
- * },
28
- * emits: {
29
- * 'com.example.output': z.object({ result: z.number() }),
30
- * },
59
+ * ```typescript
60
+ * const contract = createSimpleArvoContract({
61
+ * uri: 'example.com/contracts/processor',
62
+ * type: 'document.process',
63
+ * versions: {
64
+ * '1.0.0': {
65
+ * accepts: z.object({
66
+ * documentId: z.string(),
67
+ * options: z.object({ format: z.string() })
68
+ * }),
69
+ * emits: z.object({
70
+ * processedDocument: z.string(),
71
+ * metadata: z.object({ size: z.number() })
72
+ * })
73
+ * }
74
+ * }
31
75
  * });
76
+ *
77
+ * // Results in a contract where:
78
+ * // - Accept type is "com.document.process"
79
+ * // - Emit type is "evt.document.process.success"
80
+ * ```
81
+ *
82
+ * @example
83
+ * ```typescript
84
+ * // Multiple versions example
85
+ * const contract = createSimpleArvoContract({
86
+ * uri: 'api.example/contracts/user',
87
+ * type: 'user.create',
88
+ * versions: {
89
+ * '1.0.0': {
90
+ * accepts: z.object({ name: z.string() }),
91
+ * emits: z.object({ id: z.string() })
92
+ * },
93
+ * '2.0.0': {
94
+ * accepts: z.object({
95
+ * name: z.string(),
96
+ * email: z.string().email()
97
+ * }),
98
+ * emits: z.object({
99
+ * id: z.string(),
100
+ * created: z.date()
101
+ * })
102
+ * }
103
+ * }
104
+ * });
105
+ * ```
106
+ *
107
+ * @remarks
108
+ * This function simplifies contract creation by:
109
+ * 1. Automatically prefixing accept types with "com."
110
+ * 2. Creating a single emit type prefixed with "evt." and suffixed with ".success"
111
+ * 3. Maintaining type safety and schema validation
112
+ *
113
+ * Use this when you have a simple contract pattern with:
114
+ * - A single accept type
115
+ * - A single success emit type
116
+ * - Standard type naming conventions
117
+ *
118
+ * For more complex contracts with multiple emit types or custom type naming,
119
+ * use {@link createArvoContract} instead.
32
120
  */
33
- export declare const createArvoContract: <const TContract extends IArvoContract>(contract: TContract) => InferArvoContract<TContract>;
121
+ export declare const createSimpleArvoContract: <TUri extends string, TType extends string, TVersions extends Record<ArvoSemanticVersion, {
122
+ accepts: z.ZodTypeAny;
123
+ emits: z.ZodTypeAny;
124
+ }>>(param: {
125
+ uri: TUri;
126
+ type: TType;
127
+ versions: TVersions;
128
+ }) => ArvoContract<TUri, `com.${TType}`, { [V in ArvoSemanticVersion & keyof TVersions]: {
129
+ accepts: TVersions[V]["accepts"];
130
+ emits: { [K in `evt.${TType}.succes`]: TVersions[V]["emits"]; };
131
+ }; }>;
132
+ export {};
@@ -3,52 +3,170 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.createArvoContract = void 0;
6
+ exports.createSimpleArvoContract = exports.createArvoContract = void 0;
7
7
  var _1 = __importDefault(require("."));
8
8
  var typegen_1 = require("../ArvoOrchestratorContract/typegen");
9
9
  var utils_1 = require("../utils");
10
+ var validators_1 = require("./validators");
11
+ var schema_1 = require("../schema");
12
+ var ArvoOrchestrationSubject_1 = __importDefault(require("../ArvoOrchestrationSubject"));
10
13
  /**
11
- * Creates an ArvoContract instance from the given contract specification.
14
+ * Creates and validates an ArvoContract instance from a contract specification.
12
15
  *
13
- * This function provides a convenient way to create and initialize an ArvoContract
14
- * with proper type inference.
15
- *
16
- * @template TContract - The type of the contract specification.
17
- *
18
- * @param contract - The contract specification object.
19
- * This should include the URI, accepts, and emits properties as defined in IArvoContract.
20
- *
21
- * @returns The created ArvoContract instance.
22
- * The returned type is inferred from the input contract specification.
16
+ * @template TContract - The contract specification type, must extend IArvoContract
17
+ * @param contract - The contract specification object containing URI, type, and versioned schemas
18
+ * @throws {Error} If any event type uses the reserved orchestrator prefix
19
+ * @throws {Error} If URI or event types fail validation
20
+ * @returns A properly typed ArvoContract instance
23
21
  *
24
22
  * @example
25
- * const myContract = createArvoContract({
26
- * uri: 'https://example.com/contracts/myContract',
27
- * accepts: {
28
- * type: 'com.example.input',
29
- * schema: z.object({ name: z.string() }),
30
- * },
31
- * emits: {
32
- * 'com.example.output': z.object({ result: z.number() }),
33
- * },
23
+ * ```typescript
24
+ * const contract = createArvoContract({
25
+ * uri: 'com.example.contract',
26
+ * type: 'input.event',
27
+ * versions: {
28
+ * '0.0.1': {
29
+ * accepts: z.object({ data: z.string() }),
30
+ * emits: {
31
+ * 'output.event': z.object({ result: z.number() })
32
+ * }
33
+ * }
34
+ * }
34
35
  * });
36
+ * ```
35
37
  */
36
- var createArvoContract = function (contract) {
37
- var createErrorMessage = function (source, type) {
38
- return (0, utils_1.cleanString)("\n In contract (uri=".concat(contract.uri, "), the '").concat(source, "' event (type=").concat(type, ") must not start \n with '").concat(typegen_1.ArvoOrchestratorEventTypeGen.prefix, "' becuase this a reserved pattern \n for Arvo orchestrators.\n "));
38
+ var createArvoContract = function (contract, isOrchestrationContract) {
39
+ if (isOrchestrationContract === void 0) { isOrchestrationContract = false; }
40
+ var createErrorMessage = function (source, type, version) {
41
+ var versionString = version ? ", version=".concat(version) : '';
42
+ return (0, utils_1.cleanString)("\n In contract (uri=".concat(contract.uri).concat(versionString, "), the '").concat(source, "' event (type=").concat(type, ") must not start\n with '").concat(typegen_1.ArvoOrchestratorEventTypeGen.prefix, "' because this is a reserved pattern\n for Arvo orchestrators.\n "));
39
43
  };
40
- var validator = function (value) {
41
- return value.startsWith(typegen_1.ArvoOrchestratorEventTypeGen.prefix);
44
+ var isReservedPrefix = function (value) {
45
+ return !isOrchestrationContract &&
46
+ value.startsWith(typegen_1.ArvoOrchestratorEventTypeGen.prefix);
42
47
  };
43
- if (validator(contract.accepts.type)) {
44
- throw new Error(createErrorMessage('accepts', contract.accepts.type));
48
+ if (isReservedPrefix(contract.type)) {
49
+ throw new Error(createErrorMessage('accepts', contract.type, null));
45
50
  }
46
- for (var _i = 0, _a = Object.keys(contract.emits); _i < _a.length; _i++) {
47
- var item = _a[_i];
48
- if (validator(item)) {
49
- throw new Error(createErrorMessage('emits', item));
51
+ validators_1.ArvoContractValidators.contract.uri.parse(contract.uri);
52
+ for (var _i = 0, _a = Object.entries(contract.versions); _i < _a.length; _i++) {
53
+ var _b = _a[_i], version = _b[0], versionContract = _b[1];
54
+ schema_1.ArvoSemanticVersionSchema.parse(version);
55
+ if (version === ArvoOrchestrationSubject_1.default.WildCardMachineVersion) {
56
+ throw new Error("The version cannot be ".concat(ArvoOrchestrationSubject_1.default.WildCardMachineVersion));
57
+ }
58
+ for (var _c = 0, _d = Object.keys(versionContract.emits); _c < _d.length; _c++) {
59
+ var emitType = _d[_c];
60
+ validators_1.ArvoContractValidators.record.type.parse(emitType);
61
+ if (isReservedPrefix(emitType)) {
62
+ throw new Error(createErrorMessage('emits', emitType, version));
63
+ }
50
64
  }
51
65
  }
52
66
  return new _1.default(contract);
53
67
  };
54
68
  exports.createArvoContract = createArvoContract;
69
+ /**
70
+ * Creates a simplified ArvoContract with standardized type prefixes and emit patterns.
71
+ * This is a convenience function that automatically formats event types according to conventions:
72
+ * - Accept types are prefixed with "com."
73
+ * - Emit types are prefixed with "evt." and suffixed with ".success"
74
+ *
75
+ * @template TUri - The URI type for the contract
76
+ * @template TType - The base type name (without prefixes) for the contract
77
+ * @template TVersions - Record of versions containing accept and emit schemas
78
+ *
79
+ * @param param - The configuration object for creating the contract
80
+ * @param param.uri - The URI identifying the contract
81
+ * @param param.type - The base type name (will be prefixed with "com.")
82
+ * @param param.versions - Version-specific schema definitions
83
+ * @param param.versions[version].accepts - Zod schema for validating incoming events
84
+ * @param param.versions[version].emits - Zod schema for validating outgoing events
85
+ *
86
+ * @returns An ArvoContract instance with standardized type formatting:
87
+ * - Accept type will be "com.[type]"
88
+ * - Emit type will be "evt.[type].success"
89
+ *
90
+ * @example
91
+ * ```typescript
92
+ * const contract = createSimpleArvoContract({
93
+ * uri: 'example.com/contracts/processor',
94
+ * type: 'document.process',
95
+ * versions: {
96
+ * '1.0.0': {
97
+ * accepts: z.object({
98
+ * documentId: z.string(),
99
+ * options: z.object({ format: z.string() })
100
+ * }),
101
+ * emits: z.object({
102
+ * processedDocument: z.string(),
103
+ * metadata: z.object({ size: z.number() })
104
+ * })
105
+ * }
106
+ * }
107
+ * });
108
+ *
109
+ * // Results in a contract where:
110
+ * // - Accept type is "com.document.process"
111
+ * // - Emit type is "evt.document.process.success"
112
+ * ```
113
+ *
114
+ * @example
115
+ * ```typescript
116
+ * // Multiple versions example
117
+ * const contract = createSimpleArvoContract({
118
+ * uri: 'api.example/contracts/user',
119
+ * type: 'user.create',
120
+ * versions: {
121
+ * '1.0.0': {
122
+ * accepts: z.object({ name: z.string() }),
123
+ * emits: z.object({ id: z.string() })
124
+ * },
125
+ * '2.0.0': {
126
+ * accepts: z.object({
127
+ * name: z.string(),
128
+ * email: z.string().email()
129
+ * }),
130
+ * emits: z.object({
131
+ * id: z.string(),
132
+ * created: z.date()
133
+ * })
134
+ * }
135
+ * }
136
+ * });
137
+ * ```
138
+ *
139
+ * @remarks
140
+ * This function simplifies contract creation by:
141
+ * 1. Automatically prefixing accept types with "com."
142
+ * 2. Creating a single emit type prefixed with "evt." and suffixed with ".success"
143
+ * 3. Maintaining type safety and schema validation
144
+ *
145
+ * Use this when you have a simple contract pattern with:
146
+ * - A single accept type
147
+ * - A single success emit type
148
+ * - Standard type naming conventions
149
+ *
150
+ * For more complex contracts with multiple emit types or custom type naming,
151
+ * use {@link createArvoContract} instead.
152
+ */
153
+ var createSimpleArvoContract = function (param) {
154
+ return (0, exports.createArvoContract)({
155
+ uri: param.uri,
156
+ type: "com.".concat(param.type),
157
+ versions: Object.fromEntries(Object.entries(param.versions).map(function (_a) {
158
+ var _b;
159
+ var version = _a[0], contract = _a[1];
160
+ return [
161
+ version,
162
+ {
163
+ accepts: contract.accepts,
164
+ emits: (_b = {},
165
+ _b["evt.".concat(param.type, ".success")] = contract.emits,
166
+ _b),
167
+ },
168
+ ];
169
+ })),
170
+ });
171
+ };
172
+ exports.createSimpleArvoContract = createSimpleArvoContract;
@@ -1,6 +1,7 @@
1
1
  import { z } from 'zod';
2
2
  import { ArvoContractJSONSchema, ArvoContractRecord, IArvoContract } from './types';
3
3
  import { ArvoErrorSchema } from '../schema';
4
+ import { ArvoSemanticVersion } from '../types';
4
5
  /**
5
6
  * ArvoContract class represents a contract with defined input and output schemas.
6
7
  * It provides methods for validating inputs and outputs based on the contract's specifications.
@@ -9,45 +10,64 @@ import { ArvoErrorSchema } from '../schema';
9
10
  *
10
11
  * @template TUri - The URI of the contract
11
12
  * @template TType - The accept type, defaults to string.
12
- * @template TAcceptSchema - The of the data which the contract bound can accept
13
- * @template TEmits - The type of records the contract bound handler emits.
13
+ * @template TVersion - The contract versions
14
14
  */
15
- export default class ArvoContract<TUri extends string = string, TType extends string = string, TAcceptSchema extends z.ZodTypeAny = z.ZodTypeAny, TEmits extends Record<string, z.ZodTypeAny> = Record<string, z.ZodTypeAny>> {
15
+ export default class ArvoContract<TUri extends string = string, TType extends string = string, TVersions extends Record<ArvoSemanticVersion, {
16
+ accepts: z.ZodTypeAny;
17
+ emits: Record<string, z.ZodTypeAny>;
18
+ }> = Record<ArvoSemanticVersion, {
19
+ accepts: z.ZodTypeAny;
20
+ emits: Record<string, z.ZodTypeAny>;
21
+ }>> {
16
22
  private readonly _uri;
17
- private readonly _accepts;
18
- private readonly _emits;
19
- /** (Optional) The Contract description */
23
+ private readonly _type;
24
+ private readonly _versions;
20
25
  readonly description: string | null;
21
26
  /**
22
27
  * Creates an instance of ArvoContract.
23
28
  * @param params - The contract parameters.
24
29
  */
25
- constructor(params: IArvoContract<TUri, TType, TAcceptSchema, TEmits>);
30
+ constructor(params: IArvoContract<TUri, TType, TVersions>);
26
31
  /**
27
32
  * Gets the URI of the contract.
28
33
  */
29
34
  get uri(): TUri;
35
+ /**
36
+ * Get the type of the event the handler
37
+ * bound to the contract accepts
38
+ */
39
+ get type(): TType;
40
+ /**
41
+ * Gets the version of the contract
42
+ */
43
+ get versions(): TVersions;
44
+ /**
45
+ * Get the latest version of the contract
46
+ */
47
+ get latestVersion(): ArvoSemanticVersion | undefined;
30
48
  /**
31
49
  * Gets the type and schema of the event that the contact
32
50
  * bound handler listens to.
33
51
  */
34
- get accepts(): ArvoContractRecord<TType, TAcceptSchema>;
52
+ accepts<V extends ArvoSemanticVersion & keyof TVersions>(version: V): ArvoContractRecord<TType, TVersions[V]['accepts']>;
35
53
  /**
36
54
  * Gets all event types and schemas that can be emitted by the
37
55
  * contract bound handler.
38
56
  */
39
- get emits(): TEmits;
57
+ emits<V extends ArvoSemanticVersion & keyof TVersions>(version: V): TVersions[V]['emits'];
40
58
  get systemError(): ArvoContractRecord<`sys.${TType}.error`, typeof ArvoErrorSchema>;
41
59
  /**
42
60
  * Validates the contract bound handler's input/ accept event against the
43
61
  * contract's accept schema.
44
62
  * @template U - The type of the input to validate.
63
+ * @template V - The version to use
64
+ * @param version - The version to use
45
65
  * @param type - The type of the input event.
46
66
  * @param input - The input data to validate.
47
67
  * @returns The validation result.
48
68
  * @throws If the accept type is not found in the contract.
49
69
  */
50
- validateAccepts<U>(type: TType, input: U): z.SafeParseReturnType<any, any>;
70
+ validateAccepts<V extends ArvoSemanticVersion & keyof TVersions, U>(version: V, type: TType, input: U): z.SafeParseReturnType<any, any>;
51
71
  /**
52
72
  * Validates the contract bound handler's output/ emits against the
53
73
  * contract's emit schema.
@@ -57,28 +77,14 @@ export default class ArvoContract<TUri extends string = string, TType extends st
57
77
  * @returns The validation result.
58
78
  * @throws If the emit type is not found in the contract.
59
79
  */
60
- validateEmits<U extends keyof TEmits>(type: U, output: unknown): z.SafeParseReturnType<any, any>;
61
- /**
62
- * Validates the accepts record.
63
- * @param accepts - The accepts record to validate.
64
- * @returns The validated accepts record.
65
- * @private
66
- */
67
- private _validateAccepts;
68
- /**
69
- * Validates the emits records.
70
- * @param emits - The emits records to validate.
71
- * @returns The validated emits records.
72
- * @private
73
- */
74
- private _validateEmits;
80
+ validateEmits<V extends ArvoSemanticVersion & keyof TVersions, E extends string & keyof TVersions[V]['emits'], U>(version: V, type: E, output: U): z.SafeParseReturnType<any, any>;
75
81
  /**
76
82
  * Exports the ArvoContract instance as a plain object conforming to the IArvoContract interface.
77
83
  * This method can be used to serialize the contract or to create a new instance with the same parameters.
78
84
  *
79
85
  * @returns An object representing the contract, including its URI, accepts, and emits properties.
80
86
  */
81
- export(): IArvoContract<TUri, TType, TAcceptSchema, TEmits>;
87
+ export(): IArvoContract<TUri, TType, TVersions>;
82
88
  /**
83
89
  * Converts the ArvoContract instance to a JSON Schema representation.
84
90
  * This method provides a way to represent the contract's structure and validation rules