hexok 1.0.1 → 2.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.
- package/README.md +4 -26
- package/dist/adapter.d.ts +18 -0
- package/dist/adapter.d.ts.map +1 -0
- package/dist/adapter.js +21 -0
- package/dist/adapter.js.map +1 -0
- package/dist/catalog.d.ts +88 -0
- package/dist/catalog.d.ts.map +1 -0
- package/dist/catalog.js +79 -0
- package/dist/catalog.js.map +1 -0
- package/dist/{core/coded-error.d.ts → coded-error.d.ts} +9 -4
- package/dist/coded-error.d.ts.map +1 -0
- package/dist/{core/coded-error.js → coded-error.js} +9 -4
- package/dist/coded-error.js.map +1 -0
- package/dist/cow-draft.d.ts.map +1 -0
- package/dist/cow-draft.js.map +1 -0
- package/dist/entity.d.ts +63 -0
- package/dist/entity.d.ts.map +1 -0
- package/dist/{domain/entity.js → entity.js} +52 -80
- package/dist/entity.js.map +1 -0
- package/dist/error-map.d.ts +22 -0
- package/dist/error-map.d.ts.map +1 -0
- package/dist/error-map.js +2 -0
- package/dist/error-map.js.map +1 -0
- package/dist/errors.d.ts +85 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +85 -0
- package/dist/errors.js.map +1 -0
- package/dist/event-handler.d.ts +31 -0
- package/dist/event-handler.d.ts.map +1 -0
- package/dist/event-handler.js +28 -0
- package/dist/event-handler.js.map +1 -0
- package/dist/event.d.ts +37 -0
- package/dist/event.d.ts.map +1 -0
- package/dist/event.js +44 -0
- package/dist/event.js.map +1 -0
- package/dist/index.d.ts +16 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +14 -0
- package/dist/index.js.map +1 -0
- package/dist/mapper.d.ts +100 -0
- package/dist/mapper.d.ts.map +1 -0
- package/dist/mapper.js +167 -0
- package/dist/mapper.js.map +1 -0
- package/dist/port.d.ts +20 -0
- package/dist/port.d.ts.map +1 -0
- package/dist/port.js +25 -0
- package/dist/port.js.map +1 -0
- package/dist/result.d.ts.map +1 -0
- package/dist/result.js.map +1 -0
- package/dist/schema.d.ts +37 -0
- package/dist/schema.d.ts.map +1 -0
- package/dist/schema.js +50 -0
- package/dist/schema.js.map +1 -0
- package/dist/{core/standard-schema.d.ts → standard-schema.d.ts} +1 -1
- package/dist/standard-schema.d.ts.map +1 -0
- package/dist/standard-schema.js.map +1 -0
- package/dist/use-case.d.ts +183 -0
- package/dist/use-case.d.ts.map +1 -0
- package/dist/use-case.js +221 -0
- package/dist/use-case.js.map +1 -0
- package/dist/{core/schema.d.ts → validate.d.ts} +1 -1
- package/dist/validate.d.ts.map +1 -0
- package/dist/{core/schema.js → validate.js} +1 -1
- package/dist/validate.js.map +1 -0
- package/package.json +5 -25
- package/dist/app/callable-use-case.d.ts +0 -34
- package/dist/app/callable-use-case.d.ts.map +0 -1
- package/dist/app/callable-use-case.js +0 -41
- package/dist/app/callable-use-case.js.map +0 -1
- package/dist/app/contract.d.ts +0 -46
- package/dist/app/contract.d.ts.map +0 -1
- package/dist/app/contract.js +0 -28
- package/dist/app/contract.js.map +0 -1
- package/dist/app/error-factory.d.ts +0 -9
- package/dist/app/error-factory.d.ts.map +0 -1
- package/dist/app/error-factory.js +0 -30
- package/dist/app/error-factory.js.map +0 -1
- package/dist/app/event-channel.d.ts +0 -133
- package/dist/app/event-channel.d.ts.map +0 -1
- package/dist/app/event-channel.js +0 -49
- package/dist/app/event-channel.js.map +0 -1
- package/dist/app/event-use-case.d.ts +0 -47
- package/dist/app/event-use-case.d.ts.map +0 -1
- package/dist/app/event-use-case.js +0 -54
- package/dist/app/event-use-case.js.map +0 -1
- package/dist/app/execute-ctx.d.ts +0 -92
- package/dist/app/execute-ctx.d.ts.map +0 -1
- package/dist/app/execute-ctx.js +0 -2
- package/dist/app/execute-ctx.js.map +0 -1
- package/dist/app/external-use-case.d.ts +0 -25
- package/dist/app/external-use-case.d.ts.map +0 -1
- package/dist/app/external-use-case.js +0 -25
- package/dist/app/external-use-case.js.map +0 -1
- package/dist/app/index.d.ts +0 -9
- package/dist/app/index.d.ts.map +0 -1
- package/dist/app/index.js +0 -8
- package/dist/app/index.js.map +0 -1
- package/dist/app/internal-use-case.d.ts +0 -26
- package/dist/app/internal-use-case.d.ts.map +0 -1
- package/dist/app/internal-use-case.js +0 -26
- package/dist/app/internal-use-case.js.map +0 -1
- package/dist/app/nest.d.ts +0 -9
- package/dist/app/nest.d.ts.map +0 -1
- package/dist/app/nest.js +0 -28
- package/dist/app/nest.js.map +0 -1
- package/dist/app/types.d.ts +0 -153
- package/dist/app/types.d.ts.map +0 -1
- package/dist/app/types.js +0 -17
- package/dist/app/types.js.map +0 -1
- package/dist/core/coded-error.d.ts.map +0 -1
- package/dist/core/coded-error.js.map +0 -1
- package/dist/core/error-map.d.ts +0 -21
- package/dist/core/error-map.d.ts.map +0 -1
- package/dist/core/error-map.js +0 -5
- package/dist/core/error-map.js.map +0 -1
- package/dist/core/index.d.ts +0 -6
- package/dist/core/index.d.ts.map +0 -1
- package/dist/core/index.js +0 -5
- package/dist/core/index.js.map +0 -1
- package/dist/core/result.d.ts.map +0 -1
- package/dist/core/result.js.map +0 -1
- package/dist/core/schema.d.ts.map +0 -1
- package/dist/core/schema.js.map +0 -1
- package/dist/core/standard-schema.d.ts.map +0 -1
- package/dist/core/standard-schema.js.map +0 -1
- package/dist/domain/capabilities.d.ts +0 -42
- package/dist/domain/capabilities.d.ts.map +0 -1
- package/dist/domain/capabilities.js +0 -2
- package/dist/domain/capabilities.js.map +0 -1
- package/dist/domain/catalog.d.ts +0 -46
- package/dist/domain/catalog.d.ts.map +0 -1
- package/dist/domain/catalog.js +0 -114
- package/dist/domain/catalog.js.map +0 -1
- package/dist/domain/channel.d.ts +0 -36
- package/dist/domain/channel.d.ts.map +0 -1
- package/dist/domain/channel.js +0 -2
- package/dist/domain/channel.js.map +0 -1
- package/dist/domain/cow-draft.d.ts.map +0 -1
- package/dist/domain/cow-draft.js.map +0 -1
- package/dist/domain/entity.d.ts +0 -120
- package/dist/domain/entity.d.ts.map +0 -1
- package/dist/domain/entity.js.map +0 -1
- package/dist/domain/envelope.d.ts +0 -59
- package/dist/domain/envelope.d.ts.map +0 -1
- package/dist/domain/envelope.js +0 -2
- package/dist/domain/envelope.js.map +0 -1
- package/dist/domain/event.d.ts +0 -44
- package/dist/domain/event.d.ts.map +0 -1
- package/dist/domain/event.js +0 -21
- package/dist/domain/event.js.map +0 -1
- package/dist/domain/index.d.ts +0 -8
- package/dist/domain/index.d.ts.map +0 -1
- package/dist/domain/index.js +0 -5
- package/dist/domain/index.js.map +0 -1
- package/dist/domain/port.d.ts +0 -45
- package/dist/domain/port.d.ts.map +0 -1
- package/dist/domain/port.js +0 -41
- package/dist/domain/port.js.map +0 -1
- package/dist/infra/adapter.d.ts +0 -22
- package/dist/infra/adapter.d.ts.map +0 -1
- package/dist/infra/adapter.js +0 -18
- package/dist/infra/adapter.js.map +0 -1
- package/dist/infra/index.d.ts +0 -3
- package/dist/infra/index.d.ts.map +0 -1
- package/dist/infra/index.js +0 -3
- package/dist/infra/index.js.map +0 -1
- package/dist/infra/mapper.d.ts +0 -48
- package/dist/infra/mapper.d.ts.map +0 -1
- package/dist/infra/mapper.js +0 -77
- package/dist/infra/mapper.js.map +0 -1
- package/dist/runtime/app.d.ts +0 -100
- package/dist/runtime/app.d.ts.map +0 -1
- package/dist/runtime/app.js +0 -292
- package/dist/runtime/app.js.map +0 -1
- package/dist/runtime/channel.d.ts +0 -34
- package/dist/runtime/channel.d.ts.map +0 -1
- package/dist/runtime/channel.js +0 -110
- package/dist/runtime/channel.js.map +0 -1
- package/dist/runtime/client.d.ts +0 -21
- package/dist/runtime/client.d.ts.map +0 -1
- package/dist/runtime/client.js +0 -2
- package/dist/runtime/client.js.map +0 -1
- package/dist/runtime/completeness.d.ts +0 -89
- package/dist/runtime/completeness.d.ts.map +0 -1
- package/dist/runtime/completeness.js +0 -2
- package/dist/runtime/completeness.js.map +0 -1
- package/dist/runtime/envelope.d.ts +0 -7
- package/dist/runtime/envelope.d.ts.map +0 -1
- package/dist/runtime/envelope.js +0 -69
- package/dist/runtime/envelope.js.map +0 -1
- package/dist/runtime/events.d.ts +0 -6
- package/dist/runtime/events.d.ts.map +0 -1
- package/dist/runtime/events.js +0 -48
- package/dist/runtime/events.js.map +0 -1
- package/dist/runtime/http-status.d.ts +0 -3
- package/dist/runtime/http-status.d.ts.map +0 -1
- package/dist/runtime/http-status.js +0 -11
- package/dist/runtime/http-status.js.map +0 -1
- package/dist/runtime/http.d.ts +0 -4
- package/dist/runtime/http.d.ts.map +0 -1
- package/dist/runtime/http.js +0 -58
- package/dist/runtime/http.js.map +0 -1
- package/dist/runtime/index.d.ts +0 -10
- package/dist/runtime/index.d.ts.map +0 -1
- package/dist/runtime/index.js +0 -6
- package/dist/runtime/index.js.map +0 -1
- package/dist/runtime/interceptor.d.ts +0 -61
- package/dist/runtime/interceptor.d.ts.map +0 -1
- package/dist/runtime/interceptor.js +0 -7
- package/dist/runtime/interceptor.js.map +0 -1
- package/dist/runtime/invoke.d.ts +0 -34
- package/dist/runtime/invoke.d.ts.map +0 -1
- package/dist/runtime/invoke.js +0 -235
- package/dist/runtime/invoke.js.map +0 -1
- package/dist/runtime/middleware.d.ts +0 -20
- package/dist/runtime/middleware.d.ts.map +0 -1
- package/dist/runtime/middleware.js +0 -2
- package/dist/runtime/middleware.js.map +0 -1
- package/dist/runtime/rpc.d.ts +0 -24
- package/dist/runtime/rpc.d.ts.map +0 -1
- package/dist/runtime/rpc.js +0 -16
- package/dist/runtime/rpc.js.map +0 -1
- package/dist/testing/app-test.d.ts +0 -77
- package/dist/testing/app-test.d.ts.map +0 -1
- package/dist/testing/app-test.js +0 -109
- package/dist/testing/app-test.js.map +0 -1
- package/dist/testing/in-memory-bus.d.ts +0 -19
- package/dist/testing/in-memory-bus.d.ts.map +0 -1
- package/dist/testing/in-memory-bus.js +0 -31
- package/dist/testing/in-memory-bus.js.map +0 -1
- package/dist/testing/in-memory-channel.d.ts +0 -32
- package/dist/testing/in-memory-channel.d.ts.map +0 -1
- package/dist/testing/in-memory-channel.js +0 -65
- package/dist/testing/in-memory-channel.js.map +0 -1
- package/dist/testing/in-memory-queue.d.ts +0 -24
- package/dist/testing/in-memory-queue.d.ts.map +0 -1
- package/dist/testing/in-memory-queue.js +0 -66
- package/dist/testing/in-memory-queue.js.map +0 -1
- package/dist/testing/in-memory-repository.d.ts +0 -44
- package/dist/testing/in-memory-repository.d.ts.map +0 -1
- package/dist/testing/in-memory-repository.js +0 -60
- package/dist/testing/in-memory-repository.js.map +0 -1
- package/dist/testing/index.d.ts +0 -6
- package/dist/testing/index.d.ts.map +0 -1
- package/dist/testing/index.js +0 -6
- package/dist/testing/index.js.map +0 -1
- /package/dist/{domain/cow-draft.d.ts → cow-draft.d.ts} +0 -0
- /package/dist/{domain/cow-draft.js → cow-draft.js} +0 -0
- /package/dist/{core/result.d.ts → result.d.ts} +0 -0
- /package/dist/{core/result.js → result.js} +0 -0
- /package/dist/{core/standard-schema.js → standard-schema.js} +0 -0
|
@@ -1,46 +1,38 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { validationError } from './coded-error.js';
|
|
2
2
|
import { applyCowDraft, cloneValue, frozenSnapshot, isPlainObject, } from './cow-draft.js';
|
|
3
|
+
import { schemaDefinition, } from './schema.js';
|
|
4
|
+
import { validate } from './validate.js';
|
|
3
5
|
const EMPTY_CHANGED_KEYS = Object.freeze([]);
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
* }
|
|
25
|
-
* }
|
|
26
|
-
* ```
|
|
27
|
-
*/
|
|
28
|
-
export class Entity {
|
|
29
|
-
/** Entity name used in validation and undeclared-error messages. Declare on each subclass. */
|
|
30
|
-
static key;
|
|
31
|
-
/** Standard Schema for `create` / `parse` / `set` / `validate()`. Declare on each subclass. */
|
|
6
|
+
export function Entity(token, schema) {
|
|
7
|
+
const definition = schemaDefinition(schema);
|
|
8
|
+
class EntityClass extends EntityBase {
|
|
9
|
+
/** Entity name. Literal type of the string passed to {@link Entity}. */
|
|
10
|
+
static token = token;
|
|
11
|
+
/** Schema used by `create`, `parse`, `set`, and `validate`. */
|
|
12
|
+
static schema = definition;
|
|
13
|
+
/** Nominal marker. Each `Entity(...)` call is a distinct class. */
|
|
14
|
+
#brand = true;
|
|
15
|
+
constructor(props) {
|
|
16
|
+
super(props);
|
|
17
|
+
void this.#brand;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return EntityClass;
|
|
21
|
+
}
|
|
22
|
+
class EntityBase {
|
|
23
|
+
/** Entity name used in validation messages. */
|
|
24
|
+
static token;
|
|
25
|
+
/** Schema for `create` / `parse` / `set` / `validate()`. */
|
|
32
26
|
static schema;
|
|
33
|
-
/** Declared refusal codes. Keys are the `error()` union. Declare on each subclass. */
|
|
34
|
-
static errors;
|
|
35
27
|
#isNew = false;
|
|
36
28
|
#validated = false;
|
|
37
29
|
#original = undefined;
|
|
38
30
|
#owned = undefined;
|
|
39
31
|
#snapshot = undefined;
|
|
40
|
-
|
|
32
|
+
#props;
|
|
41
33
|
/** Live props. Read-only; write through `set`. */
|
|
42
34
|
get props() {
|
|
43
|
-
return this
|
|
35
|
+
return this.#props;
|
|
44
36
|
}
|
|
45
37
|
/** True after `create` until `commit`. `restore` / `parse` start false. */
|
|
46
38
|
get isNew() {
|
|
@@ -59,22 +51,22 @@ export class Entity {
|
|
|
59
51
|
*/
|
|
60
52
|
get original() {
|
|
61
53
|
if (this.#original === undefined ||
|
|
62
|
-
Object.is(this
|
|
54
|
+
Object.is(this.#props, this.#original)) {
|
|
63
55
|
return undefined;
|
|
64
56
|
}
|
|
65
57
|
return this.#original;
|
|
66
58
|
}
|
|
67
59
|
constructor(props) {
|
|
68
|
-
this
|
|
60
|
+
this.#props = props;
|
|
69
61
|
}
|
|
70
|
-
/** Copy-on-write mutate. Edit `draft` and return `this`. Re-validates
|
|
62
|
+
/** Copy-on-write mutate. Edit `draft` and return `this`. Re-validates after a write. */
|
|
71
63
|
set(producer) {
|
|
72
|
-
const previousRoot = this
|
|
73
|
-
const backup = cloneValue(this
|
|
64
|
+
const previousRoot = this.#props;
|
|
65
|
+
const backup = cloneValue(this.#props);
|
|
74
66
|
const previousSnapshot = this.#snapshot;
|
|
75
|
-
const wasOwned = this.#owned?.has(this
|
|
76
|
-
const result = applyCowDraft(this
|
|
77
|
-
this
|
|
67
|
+
const wasOwned = this.#owned?.has(this.#props) === true;
|
|
68
|
+
const result = applyCowDraft(this.#props, this.#owned, producer);
|
|
69
|
+
this.#props = result.root;
|
|
78
70
|
this.#owned = result.owned;
|
|
79
71
|
if (result.wrote) {
|
|
80
72
|
this.#snapshot = undefined;
|
|
@@ -82,7 +74,7 @@ export class Entity {
|
|
|
82
74
|
this.#assertSchema();
|
|
83
75
|
}
|
|
84
76
|
catch (error) {
|
|
85
|
-
this
|
|
77
|
+
this.#props = wasOwned ? backup : previousRoot;
|
|
86
78
|
this.#owned = wasOwned ? new WeakSet([backup]) : undefined;
|
|
87
79
|
this.#snapshot = previousSnapshot;
|
|
88
80
|
throw error;
|
|
@@ -105,18 +97,18 @@ export class Entity {
|
|
|
105
97
|
}
|
|
106
98
|
getChangedKeys(opts) {
|
|
107
99
|
if (!this.#isNew &&
|
|
108
|
-
(this.#original === undefined || Object.is(this
|
|
100
|
+
(this.#original === undefined || Object.is(this.#props, this.#original))) {
|
|
109
101
|
return EMPTY_CHANGED_KEYS;
|
|
110
102
|
}
|
|
111
103
|
if (opts?.deep) {
|
|
112
104
|
const out = [];
|
|
113
|
-
diffDeep(this
|
|
105
|
+
diffDeep(this.#props, this.#isNew ? undefined : this.#original, '', out);
|
|
114
106
|
return out.length === 0 ? EMPTY_CHANGED_KEYS : out;
|
|
115
107
|
}
|
|
116
108
|
if (this.#isNew) {
|
|
117
|
-
return Object.keys(this
|
|
109
|
+
return Object.keys(this.#props);
|
|
118
110
|
}
|
|
119
|
-
const current = this
|
|
111
|
+
const current = this.#props;
|
|
120
112
|
const original = this.#original;
|
|
121
113
|
const keys = new Set([
|
|
122
114
|
...Object.keys(current),
|
|
@@ -134,9 +126,9 @@ export class Entity {
|
|
|
134
126
|
isDirty() {
|
|
135
127
|
return this.#isNew || this.getChangedKeys().length > 0;
|
|
136
128
|
}
|
|
137
|
-
/** Accept current props as original; `isNew` becomes false.
|
|
129
|
+
/** Accept current props as original; `isNew` becomes false. */
|
|
138
130
|
commit() {
|
|
139
|
-
this.#original = this
|
|
131
|
+
this.#original = this.#props;
|
|
140
132
|
this.#isNew = false;
|
|
141
133
|
this.#owned = undefined;
|
|
142
134
|
return this;
|
|
@@ -144,7 +136,7 @@ export class Entity {
|
|
|
144
136
|
/** Deep frozen snapshot for persistence and use-case output. Reused until the next `set`. */
|
|
145
137
|
toProps() {
|
|
146
138
|
if (this.#snapshot === undefined) {
|
|
147
|
-
this.#snapshot = frozenSnapshot(this
|
|
139
|
+
this.#snapshot = frozenSnapshot(this.#props);
|
|
148
140
|
}
|
|
149
141
|
return this.#snapshot;
|
|
150
142
|
}
|
|
@@ -152,15 +144,6 @@ export class Entity {
|
|
|
152
144
|
toJSON() {
|
|
153
145
|
return this.toProps();
|
|
154
146
|
}
|
|
155
|
-
/**
|
|
156
|
-
* Throw a declared entity error. Codes are the keys of the subclass
|
|
157
|
-
* `static errors` when called as `Incident.error('ALREADY_CLOSED')`.
|
|
158
|
-
* An undeclared code is a type error on that call, and a programming
|
|
159
|
-
* error at runtime.
|
|
160
|
-
*/
|
|
161
|
-
static error(code, data) {
|
|
162
|
-
throwEntityError(this, code, data);
|
|
163
|
-
}
|
|
164
147
|
/**
|
|
165
148
|
* Validate typed props and construct a new instance (`isNew: true`).
|
|
166
149
|
* Throws `CodedError` `VALIDATION` if the schema rejects the props.
|
|
@@ -173,8 +156,8 @@ export class Entity {
|
|
|
173
156
|
}
|
|
174
157
|
/**
|
|
175
158
|
* Reconstruct an existing instance (`isNew: false`) without running the
|
|
176
|
-
* schema. Props are stored as given
|
|
177
|
-
*
|
|
159
|
+
* schema. Props are stored as given. `isValidated` starts false until
|
|
160
|
+
* `set` writes or `validate()` runs.
|
|
178
161
|
*/
|
|
179
162
|
static restore(props) {
|
|
180
163
|
const instance = construct(this, props);
|
|
@@ -182,8 +165,8 @@ export class Entity {
|
|
|
182
165
|
return instance;
|
|
183
166
|
}
|
|
184
167
|
/**
|
|
185
|
-
* Trust boundary for untyped input. Validates like `create
|
|
186
|
-
*
|
|
168
|
+
* Trust boundary for untyped input. Validates like `create`.
|
|
169
|
+
* Tracking matches `restore` (`isNew: false`).
|
|
187
170
|
* Throws `CodedError` `VALIDATION` if the schema rejects the value.
|
|
188
171
|
*/
|
|
189
172
|
static parse(value) {
|
|
@@ -193,31 +176,31 @@ export class Entity {
|
|
|
193
176
|
return instance;
|
|
194
177
|
}
|
|
195
178
|
#markNew() {
|
|
196
|
-
this
|
|
179
|
+
this.#props = { ...this.#props };
|
|
197
180
|
this.#original = undefined;
|
|
198
181
|
this.#isNew = true;
|
|
199
182
|
this.#owned = new WeakSet();
|
|
200
|
-
this.#owned.add(this
|
|
183
|
+
this.#owned.add(this.#props);
|
|
201
184
|
this.#snapshot = undefined;
|
|
202
185
|
}
|
|
203
186
|
#markRestored() {
|
|
204
|
-
this.#original = this
|
|
187
|
+
this.#original = this.#props;
|
|
205
188
|
this.#isNew = false;
|
|
206
189
|
this.#owned = undefined;
|
|
207
190
|
this.#snapshot = undefined;
|
|
208
191
|
}
|
|
209
192
|
#assertSchema() {
|
|
210
|
-
const
|
|
211
|
-
const parsed = validate(
|
|
193
|
+
const ctor = this.constructor;
|
|
194
|
+
const parsed = validate(ctor.schema, this.#props);
|
|
212
195
|
if (!parsed.ok) {
|
|
213
|
-
throw validationError(`hexok: ${
|
|
196
|
+
throw validationError(`hexok: ${ctor.token} validation failed`, parsed.issues);
|
|
214
197
|
}
|
|
215
198
|
}
|
|
216
199
|
}
|
|
217
200
|
function instantiate(Ctor, value) {
|
|
218
201
|
const parsed = validate(Ctor.schema, value);
|
|
219
202
|
if (!parsed.ok) {
|
|
220
|
-
throw validationError(`hexok: ${Ctor.
|
|
203
|
+
throw validationError(`hexok: ${Ctor.token} validation failed`, parsed.issues);
|
|
221
204
|
}
|
|
222
205
|
return construct(Ctor, parsed.value);
|
|
223
206
|
}
|
|
@@ -249,15 +232,4 @@ function diffDeep(current, original, path, out) {
|
|
|
249
232
|
if (path)
|
|
250
233
|
out.push(path);
|
|
251
234
|
}
|
|
252
|
-
function throwEntityError(ctor, code, data) {
|
|
253
|
-
const def = ctor.errors[code];
|
|
254
|
-
if (def === undefined) {
|
|
255
|
-
throw new Error(`hexok: undeclared error "${code}" on ${ctor.key}`);
|
|
256
|
-
}
|
|
257
|
-
throw new CodedError({
|
|
258
|
-
code,
|
|
259
|
-
message: def.message ?? code,
|
|
260
|
-
...(data !== undefined ? { data } : {}),
|
|
261
|
-
});
|
|
262
|
-
}
|
|
263
235
|
//# sourceMappingURL=entity.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"entity.js","sourceRoot":"","sources":["../src/entity.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { StandardSchemaV1 } from './standard-schema.js';
|
|
2
|
+
/**
|
|
3
|
+
* One code in an {@link Errors} catalog. The key of an {@link ErrorMap} is the code.
|
|
4
|
+
*
|
|
5
|
+
* ```ts
|
|
6
|
+
* const defs = {
|
|
7
|
+
* UserExists: { message: 'User already exists' },
|
|
8
|
+
* }
|
|
9
|
+
* ```
|
|
10
|
+
*/
|
|
11
|
+
export interface ErrorDef {
|
|
12
|
+
/**
|
|
13
|
+
* Default message. The factory uses the code when this is omitted.
|
|
14
|
+
* A call may override it by passing a string first.
|
|
15
|
+
*/
|
|
16
|
+
message?: string;
|
|
17
|
+
/** Payload schema. The member factory requires this schema's output. */
|
|
18
|
+
data?: StandardSchemaV1;
|
|
19
|
+
}
|
|
20
|
+
/** Definition map passed to {@link Errors}. Keys are the member codes. */
|
|
21
|
+
export type ErrorMap = Record<string, ErrorDef>;
|
|
22
|
+
//# sourceMappingURL=error-map.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-map.d.ts","sourceRoot":"","sources":["../src/error-map.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D;;;;;;;;GAQG;AACH,MAAM,WAAW,QAAQ;IACvB;;;OAGG;IACH,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wEAAwE;IACxE,IAAI,CAAC,EAAE,gBAAgB,CAAC;CACzB;AAED,0EAA0E;AAC1E,MAAM,MAAM,QAAQ,GAAG,MAAM,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"error-map.js","sourceRoot":"","sources":["../src/error-map.ts"],"names":[],"mappings":""}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
import type { ErrorMap } from './error-map.js';
|
|
2
|
+
import type { StandardSchemaV1 } from './standard-schema.js';
|
|
3
|
+
import type { Infer } from './validate.js';
|
|
4
|
+
/**
|
|
5
|
+
* Nominal catalog brand. The symbol is shared. The type argument is the
|
|
6
|
+
* catalog token, so two catalogs are not the same error.
|
|
7
|
+
*/
|
|
8
|
+
export declare const catalogBrand: unique symbol;
|
|
9
|
+
type MessageOf<Code extends string, Def> = Def extends {
|
|
10
|
+
readonly message: infer M extends string;
|
|
11
|
+
} ? M : Code;
|
|
12
|
+
type DataOf<Def> = Def extends {
|
|
13
|
+
readonly data: infer S extends StandardSchemaV1;
|
|
14
|
+
} ? Infer<S> : undefined;
|
|
15
|
+
/** One member. `code` and `data` are the pair a gateway matches on. */
|
|
16
|
+
export type CatalogMember<Token extends string, Code extends string, Message extends string, Data> = Error & {
|
|
17
|
+
readonly [catalogBrand]: Token;
|
|
18
|
+
readonly catalog: Token;
|
|
19
|
+
readonly code: Code;
|
|
20
|
+
readonly message: Message;
|
|
21
|
+
readonly data: Data;
|
|
22
|
+
};
|
|
23
|
+
/** Discriminated union of every member. Returned by {@link ErrorsHandle.is}. */
|
|
24
|
+
export type CatalogUnion<Token extends string, M> = {
|
|
25
|
+
[K in keyof M & string]: CatalogMember<Token, K, string, DataOf<M[K]>>;
|
|
26
|
+
}[keyof M & string];
|
|
27
|
+
/**
|
|
28
|
+
* One object type so `class X extends Errors(...)` is legal.
|
|
29
|
+
* A union here is TS2509. Payloads are discriminated by `is()`.
|
|
30
|
+
*/
|
|
31
|
+
export interface CatalogInstance<Token extends string, M extends ErrorMap> extends Error {
|
|
32
|
+
readonly [catalogBrand]: Token;
|
|
33
|
+
readonly catalog: Token;
|
|
34
|
+
readonly code: keyof M & string;
|
|
35
|
+
readonly data: unknown;
|
|
36
|
+
}
|
|
37
|
+
type MatchReturns<Keys extends string> = Record<Keys, any>;
|
|
38
|
+
type Matchers<Token extends string, M, R extends MatchReturns<keyof M & string>> = {
|
|
39
|
+
[K in keyof M & string]: (error: CatalogMember<Token, K, string, DataOf<M[K]>>) => R[K];
|
|
40
|
+
};
|
|
41
|
+
/**
|
|
42
|
+
* Message, when passed, is the first argument. The catalog message is the default.
|
|
43
|
+
* With `data`: `(data)` or `(message, data)`. Without `data`: `()` or `(message)`.
|
|
44
|
+
*/
|
|
45
|
+
type Factory<Token extends string, Code extends string, Def> = Def extends {
|
|
46
|
+
readonly data: infer S extends StandardSchemaV1;
|
|
47
|
+
} ? {
|
|
48
|
+
<M extends string>(message: M, data: Infer<S>): CatalogMember<Token, Code, M, Infer<S>>;
|
|
49
|
+
(data: Infer<S>): CatalogMember<Token, Code, MessageOf<Code, Def>, Infer<S>>;
|
|
50
|
+
} : {
|
|
51
|
+
(): CatalogMember<Token, Code, MessageOf<Code, Def>, undefined>;
|
|
52
|
+
<M extends string>(message: M): CatalogMember<Token, Code, M, undefined>;
|
|
53
|
+
};
|
|
54
|
+
/**
|
|
55
|
+
* Abstract constructor, `is`, `match`, and one static factory per code.
|
|
56
|
+
* Factories return the error. The caller throws.
|
|
57
|
+
* `init: never` blocks `new DomainError()`.
|
|
58
|
+
*/
|
|
59
|
+
export type ErrorsHandle<Token extends string, M extends ErrorMap> = {
|
|
60
|
+
readonly token: Token;
|
|
61
|
+
readonly prototype: CatalogInstance<Token, M>;
|
|
62
|
+
is(error: unknown): error is CatalogUnion<Token, M>;
|
|
63
|
+
match<R extends MatchReturns<keyof M & string>>(error: CatalogUnion<Token, M>, cases: Matchers<Token, M, R>): R[keyof R & keyof M & string];
|
|
64
|
+
} & {
|
|
65
|
+
[K in keyof M & string]: Factory<Token, K, M[K]>;
|
|
66
|
+
} & (abstract new (init: never) => CatalogInstance<Token, M>);
|
|
67
|
+
/**
|
|
68
|
+
* Branded error catalog. Throw a member from any layer. A gateway imports
|
|
69
|
+
* the catalog and maps it. The catalog does not know about HTTP.
|
|
70
|
+
*
|
|
71
|
+
* ```ts
|
|
72
|
+
* class DomainError extends Errors('domain', {
|
|
73
|
+
* BlankName: { message: 'Name is blank' },
|
|
74
|
+
* UserExists: { message: 'User already exists', data: z.object({ id: z.string() }) },
|
|
75
|
+
* }) {}
|
|
76
|
+
*
|
|
77
|
+
* throw DomainError.BlankName()
|
|
78
|
+
* throw DomainError.BlankName('Name cannot be empty')
|
|
79
|
+
* throw DomainError.UserExists({ id })
|
|
80
|
+
* throw DomainError.UserExists('User ada already exists', { id })
|
|
81
|
+
* ```
|
|
82
|
+
*/
|
|
83
|
+
export declare function Errors<const Token extends string, const M extends ErrorMap>(token: Token, defs: M): ErrorsHandle<Token, M>;
|
|
84
|
+
export {};
|
|
85
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
package/dist/errors.js
ADDED
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Nominal catalog brand. The symbol is shared. The type argument is the
|
|
3
|
+
* catalog token, so two catalogs are not the same error.
|
|
4
|
+
*/
|
|
5
|
+
export const catalogBrand = Symbol('hexok.catalog');
|
|
6
|
+
const RESERVED = new Set(['is', 'match', 'prototype', 'token']);
|
|
7
|
+
/**
|
|
8
|
+
* Branded error catalog. Throw a member from any layer. A gateway imports
|
|
9
|
+
* the catalog and maps it. The catalog does not know about HTTP.
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* class DomainError extends Errors('domain', {
|
|
13
|
+
* BlankName: { message: 'Name is blank' },
|
|
14
|
+
* UserExists: { message: 'User already exists', data: z.object({ id: z.string() }) },
|
|
15
|
+
* }) {}
|
|
16
|
+
*
|
|
17
|
+
* throw DomainError.BlankName()
|
|
18
|
+
* throw DomainError.BlankName('Name cannot be empty')
|
|
19
|
+
* throw DomainError.UserExists({ id })
|
|
20
|
+
* throw DomainError.UserExists('User ada already exists', { id })
|
|
21
|
+
* ```
|
|
22
|
+
*/
|
|
23
|
+
export function Errors(token, defs) {
|
|
24
|
+
for (const code of Object.keys(defs)) {
|
|
25
|
+
if (RESERVED.has(code)) {
|
|
26
|
+
throw new Error(`hexok: error code "${code}" is reserved`);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
class CatalogError extends Error {
|
|
30
|
+
/** Catalog name. Literal type of the string passed to {@link Errors}. */
|
|
31
|
+
static token = token;
|
|
32
|
+
catalog = token;
|
|
33
|
+
code;
|
|
34
|
+
data;
|
|
35
|
+
[catalogBrand];
|
|
36
|
+
/** Per-call class identity. Public nominality is `catalogBrand`. */
|
|
37
|
+
#brand = true;
|
|
38
|
+
constructor(code, message, data) {
|
|
39
|
+
super(message);
|
|
40
|
+
this.name = `${token}.${code}`;
|
|
41
|
+
this.code = code;
|
|
42
|
+
this.data = data;
|
|
43
|
+
this[catalogBrand] = token;
|
|
44
|
+
void this.#brand;
|
|
45
|
+
}
|
|
46
|
+
/** True when `error` is a member of this catalog. */
|
|
47
|
+
static is(error) {
|
|
48
|
+
return error instanceof this;
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Run the handler for `error.code`. A missing handler is a type error.
|
|
52
|
+
* An unknown code at runtime is a programming error.
|
|
53
|
+
*/
|
|
54
|
+
static match(error, cases) {
|
|
55
|
+
const handler = cases[error.code];
|
|
56
|
+
if (handler === undefined) {
|
|
57
|
+
throw new Error(`hexok: unmatched ${token}.${error.code}`);
|
|
58
|
+
}
|
|
59
|
+
return handler(error);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
for (const code of Object.keys(defs)) {
|
|
63
|
+
const def = defs[code];
|
|
64
|
+
if (def === undefined)
|
|
65
|
+
continue;
|
|
66
|
+
const fallback = def.message ?? code;
|
|
67
|
+
const withData = def.data !== undefined;
|
|
68
|
+
Object.defineProperty(CatalogError, code, {
|
|
69
|
+
enumerable: true,
|
|
70
|
+
configurable: true,
|
|
71
|
+
writable: true,
|
|
72
|
+
value(...args) {
|
|
73
|
+
if (!withData) {
|
|
74
|
+
return new this(code, args.length === 0 ? fallback : args[0], undefined);
|
|
75
|
+
}
|
|
76
|
+
if (args.length > 1) {
|
|
77
|
+
return new this(code, args[0], args[1]);
|
|
78
|
+
}
|
|
79
|
+
return new this(code, fallback, args[0]);
|
|
80
|
+
},
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
return CatalogError;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=errors.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { EventConstructor } from './catalog.js';
|
|
2
|
+
type EventInstanceOf<Event> = Event extends abstract new (...args: never[]) => infer Instance ? Instance : never;
|
|
3
|
+
/**
|
|
4
|
+
* Application service for one event. Pass ports through the constructor.
|
|
5
|
+
* `handle` is required; the compiler errors on the class when it is missing.
|
|
6
|
+
* Annotate the event parameter with the event class.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* class OnUserCreated extends EventHandler('on.user.created', UserCreated) {
|
|
10
|
+
* handle(event: UserCreated): void {
|
|
11
|
+
* event.payload.email
|
|
12
|
+
* }
|
|
13
|
+
* }
|
|
14
|
+
* ```
|
|
15
|
+
*/
|
|
16
|
+
export declare function EventHandler<const Token extends string, E extends EventConstructor>(token: Token, event: E): (abstract new () => {
|
|
17
|
+
/** Nominal marker. Each `EventHandler(...)` call is a distinct class. */
|
|
18
|
+
readonly "__#private@#brand": true;
|
|
19
|
+
/**
|
|
20
|
+
* Required. Annotate `event` with the event class passed to
|
|
21
|
+
* {@link EventHandler}. Return `void` or `Promise<void>`.
|
|
22
|
+
*/
|
|
23
|
+
handle(event: EventInstanceOf<E>): Promise<void> | void;
|
|
24
|
+
}) & {
|
|
25
|
+
/** Handler name. Literal type of the string passed to {@link EventHandler}. */
|
|
26
|
+
readonly token: Token;
|
|
27
|
+
/** Event class this handler receives. */
|
|
28
|
+
readonly event: E;
|
|
29
|
+
};
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=event-handler.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-handler.d.ts","sourceRoot":"","sources":["../src/event-handler.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAErD,KAAK,eAAe,CAAC,KAAK,IAAI,KAAK,SAAS,QAAQ,MAClD,GAAG,IAAI,EAAE,KAAK,EAAE,KACb,MAAM,QAAQ,GACf,QAAQ,GACR,KAAK,CAAC;AAEV;;;;;;;;;;;;GAYG;AACH,wBAAgB,YAAY,CAC1B,KAAK,CAAC,KAAK,SAAS,MAAM,EAC1B,CAAC,SAAS,gBAAgB,EAC1B,KAAK,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;IAQpB,yEAAyE;kCACvD,IAAI;IAMtB;;;OAGG;uCAC+B,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI;;IAftD,+EAA+E;oBACxD,KAAK;IAC5B,yCAAyC;oBAClB,CAAC;EAgB3B"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Application service for one event. Pass ports through the constructor.
|
|
3
|
+
* `handle` is required; the compiler errors on the class when it is missing.
|
|
4
|
+
* Annotate the event parameter with the event class.
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* class OnUserCreated extends EventHandler('on.user.created', UserCreated) {
|
|
8
|
+
* handle(event: UserCreated): void {
|
|
9
|
+
* event.payload.email
|
|
10
|
+
* }
|
|
11
|
+
* }
|
|
12
|
+
* ```
|
|
13
|
+
*/
|
|
14
|
+
export function EventHandler(token, event) {
|
|
15
|
+
class HandlerClass {
|
|
16
|
+
/** Handler name. Literal type of the string passed to {@link EventHandler}. */
|
|
17
|
+
static token = token;
|
|
18
|
+
/** Event class this handler receives. */
|
|
19
|
+
static event = event;
|
|
20
|
+
/** Nominal marker. Each `EventHandler(...)` call is a distinct class. */
|
|
21
|
+
#brand = true;
|
|
22
|
+
constructor() {
|
|
23
|
+
void this.#brand;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
return HandlerClass;
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=event-handler.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event-handler.js","sourceRoot":"","sources":["../src/event-handler.ts"],"names":[],"mappings":"AAQA;;;;;;;;;;;;GAYG;AACH,MAAM,UAAU,YAAY,CAG1B,KAAY,EAAE,KAAQ;IAGtB,MAAe,YAAY;QACzB,+EAA+E;QAC/E,MAAM,CAAU,KAAK,GAAU,KAAK,CAAC;QACrC,yCAAyC;QACzC,MAAM,CAAU,KAAK,GAAM,KAAK,CAAC;QACjC,yEAAyE;QAChE,MAAM,GAAG,IAAI,CAAC;QAEvB;YACE,KAAK,IAAI,CAAC,MAAM,CAAC;QACnB,CAAC;;IASH,OAAO,YAAY,CAAC;AACtB,CAAC"}
|
package/dist/event.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { type InferSchema, type ResolvedSchema, type SchemaSource } from './schema.js';
|
|
2
|
+
/**
|
|
3
|
+
* A fact the domain records. The token and payload schema are arguments.
|
|
4
|
+
* `new` trusts an already-typed payload. `parse` validates unknown input.
|
|
5
|
+
*
|
|
6
|
+
* ```ts
|
|
7
|
+
* class UserCreated extends Event('user.created', userSchema) {}
|
|
8
|
+
* ```
|
|
9
|
+
*/
|
|
10
|
+
export declare function Event<const Token extends string, S extends SchemaSource>(token: Token, schema: S): {
|
|
11
|
+
new (payload: InferSchema<S>): {
|
|
12
|
+
/** Nominal marker. Each `Event(...)` call is a distinct class. */
|
|
13
|
+
readonly "__#private@#brand": true;
|
|
14
|
+
/** Event name. Same literal as the static token. */
|
|
15
|
+
readonly token: Token;
|
|
16
|
+
/** Typed payload. Not validated in the constructor. */
|
|
17
|
+
readonly payload: InferSchema<S>;
|
|
18
|
+
};
|
|
19
|
+
/** Event name. Literal type of the string passed to {@link Event}. */
|
|
20
|
+
readonly token: Token;
|
|
21
|
+
/** Payload schema. A Schema class is stored as its definition. */
|
|
22
|
+
readonly schema: ResolvedSchema<S>;
|
|
23
|
+
/**
|
|
24
|
+
* Validate `value` and construct an event.
|
|
25
|
+
* Throws `CodedError` `VALIDATION` when the schema rejects it.
|
|
26
|
+
* A subclass receives its own instance. Override to customize the boundary.
|
|
27
|
+
*/
|
|
28
|
+
parse<T extends {
|
|
29
|
+
/** Nominal marker. Each `Event(...)` call is a distinct class. */
|
|
30
|
+
readonly "__#private@#brand": true;
|
|
31
|
+
/** Event name. Same literal as the static token. */
|
|
32
|
+
readonly token: Token;
|
|
33
|
+
/** Typed payload. Not validated in the constructor. */
|
|
34
|
+
readonly payload: InferSchema<S>;
|
|
35
|
+
}>(this: new (payload: InferSchema<S>) => T, value: unknown): T;
|
|
36
|
+
};
|
|
37
|
+
//# sourceMappingURL=event.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event.d.ts","sourceRoot":"","sources":["../src/event.ts"],"names":[],"mappings":"AACA,OAAO,EACL,KAAK,WAAW,EAChB,KAAK,cAAc,EACnB,KAAK,YAAY,EAElB,MAAM,aAAa,CAAC;AAGrB;;;;;;;GAOG;AACH,wBAAgB,KAAK,CAAC,KAAK,CAAC,KAAK,SAAS,MAAM,EAAE,CAAC,SAAS,YAAY,EACtE,KAAK,EAAE,KAAK,EACZ,MAAM,EAAE,CAAC;kBAiBc,WAAW,CAAC,CAAC,CAAC;QAPnC,kEAAkE;sCAChD,IAAI;QACtB,oDAAoD;wBACpC,KAAK;QACrB,uDAAuD;0BACrC,WAAW,CAAC,CAAC,CAAC;;IAVhC,sEAAsE;oBAC/C,KAAK;IAC5B,kEAAkE;qBAC1C,cAAc,CAAC,CAAC,CAAC;IAczC;;;;OAIG;UACU,CAAC;QAjBd,kEAAkE;sCAChD,IAAI;QACtB,oDAAoD;wBACpC,KAAK;QACrB,uDAAuD;0BACrC,WAAW,CAAC,CAAC,CAAC;aAaxB,KACJ,OAAO,EAAE,WAAW,CAAC,CAAC,CAAC,KACpB,CAAC,SACC,OAAO,GACb,CAAC;EAaP"}
|
package/dist/event.js
ADDED
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { validationError } from './coded-error.js';
|
|
2
|
+
import { schemaDefinition, } from './schema.js';
|
|
3
|
+
import { validate } from './validate.js';
|
|
4
|
+
/**
|
|
5
|
+
* A fact the domain records. The token and payload schema are arguments.
|
|
6
|
+
* `new` trusts an already-typed payload. `parse` validates unknown input.
|
|
7
|
+
*
|
|
8
|
+
* ```ts
|
|
9
|
+
* class UserCreated extends Event('user.created', userSchema) {}
|
|
10
|
+
* ```
|
|
11
|
+
*/
|
|
12
|
+
export function Event(token, schema) {
|
|
13
|
+
const definition = schemaDefinition(schema);
|
|
14
|
+
class EventClass {
|
|
15
|
+
/** Event name. Literal type of the string passed to {@link Event}. */
|
|
16
|
+
static token = token;
|
|
17
|
+
/** Payload schema. A Schema class is stored as its definition. */
|
|
18
|
+
static schema = definition;
|
|
19
|
+
/** Nominal marker. Each `Event(...)` call is a distinct class. */
|
|
20
|
+
#brand = true;
|
|
21
|
+
/** Event name. Same literal as the static token. */
|
|
22
|
+
token = token;
|
|
23
|
+
/** Typed payload. Not validated in the constructor. */
|
|
24
|
+
payload;
|
|
25
|
+
constructor(payload) {
|
|
26
|
+
this.payload = payload;
|
|
27
|
+
void this.#brand;
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Validate `value` and construct an event.
|
|
31
|
+
* Throws `CodedError` `VALIDATION` when the schema rejects it.
|
|
32
|
+
* A subclass receives its own instance. Override to customize the boundary.
|
|
33
|
+
*/
|
|
34
|
+
static parse(value) {
|
|
35
|
+
const parsed = validate(definition, value);
|
|
36
|
+
if (!parsed.ok) {
|
|
37
|
+
throw validationError(`hexok: ${token} validation failed`, parsed.issues);
|
|
38
|
+
}
|
|
39
|
+
return new this(parsed.value);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return EventClass;
|
|
43
|
+
}
|
|
44
|
+
//# sourceMappingURL=event.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"event.js","sourceRoot":"","sources":["../src/event.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,eAAe,EAAE,MAAM,kBAAkB,CAAC;AACnD,OAAO,EAIL,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,QAAQ,EAAE,MAAM,eAAe,CAAC;AAEzC;;;;;;;GAOG;AACH,MAAM,UAAU,KAAK,CACnB,KAAY,EACZ,MAAS;IAET,MAAM,UAAU,GAAG,gBAAgB,CAAC,MAAM,CAAC,CAAC;IAE5C,MAAM,UAAU;QACd,sEAAsE;QACtE,MAAM,CAAU,KAAK,GAAU,KAAK,CAAC;QACrC,kEAAkE;QAClE,MAAM,CAAU,MAAM,GAAsB,UAAU,CAAC;QAEvD,kEAAkE;QACzD,MAAM,GAAG,IAAI,CAAC;QACvB,oDAAoD;QAC3C,KAAK,GAAU,KAAK,CAAC;QAC9B,uDAAuD;QAC9C,OAAO,CAAiB;QAEjC,YAAY,OAAuB;YACjC,IAAI,CAAC,OAAO,GAAG,OAAO,CAAC;YACvB,KAAK,IAAI,CAAC,MAAM,CAAC;QACnB,CAAC;QAED;;;;WAIG;QACH,MAAM,CAAC,KAAK,CAIV,KAAc;YAEd,MAAM,MAAM,GAAG,QAAQ,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;YAC3C,IAAI,CAAC,MAAM,CAAC,EAAE,EAAE,CAAC;gBACf,MAAM,eAAe,CACnB,UAAU,KAAK,oBAAoB,EACnC,MAAM,CAAC,MAAM,CACd,CAAC;YACJ,CAAC;YACD,OAAO,IAAI,IAAI,CAAC,MAAM,CAAC,KAAuB,CAAC,CAAC;QAClD,CAAC;;IAGH,OAAO,UAAU,CAAC;AACpB,CAAC"}
|