@infrascan/shared-types 0.5.1 → 0.6.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.
- package/CHANGELOG.md +12 -0
- package/package.json +1 -1
- package/src/api.ts +11 -2
- package/src/config.ts +4 -5
- package/src/graph.ts +15 -7
- package/src/scan.ts +350 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# @infrascan/shared-types
|
|
2
2
|
|
|
3
|
+
## 0.6.1
|
|
4
|
+
|
|
5
|
+
### Patch Changes
|
|
6
|
+
|
|
7
|
+
- [#101](https://github.com/infrascan/infrascan/pull/101) [`316320a39bfd64a9feab735d83c054031abf2cf0`](https://github.com/infrascan/infrascan/commit/316320a39bfd64a9feab735d83c054031abf2cf0) Thanks [@lfarrel6](https://github.com/lfarrel6)! - Update ECS Task scans to more appropriately label the task nodes, and correct their parent assignment. This release also captures context from the ECS task's attached network interface.
|
|
8
|
+
|
|
9
|
+
## 0.6.0
|
|
10
|
+
|
|
11
|
+
### Minor Changes
|
|
12
|
+
|
|
13
|
+
- [#89](https://github.com/infrascan/infrascan/pull/89) [`913867b73a72791c79a69ebfec8bf94331654c1d`](https://github.com/infrascan/infrascan/commit/913867b73a72791c79a69ebfec8bf94331654c1d) Thanks [@lfarrel6](https://github.com/lfarrel6)! - Migrate graph output to a standard schema for easier search/filter
|
|
14
|
+
|
|
3
15
|
## 0.5.1
|
|
4
16
|
|
|
5
17
|
### Patch Changes
|
package/package.json
CHANGED
package/src/api.ts
CHANGED
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
|
|
7
7
|
import type { SelectedEdge, SelectedNode } from "./graph";
|
|
8
8
|
import type { BaseEdgeResolver } from "./config";
|
|
9
|
+
import type { TranslatedEntity, BaseState } from "./scan";
|
|
9
10
|
|
|
10
11
|
/**
|
|
11
12
|
* Callback to store state from a specific function call
|
|
@@ -116,7 +117,15 @@ export type EntityRoleData = {
|
|
|
116
117
|
};
|
|
117
118
|
type GetIamRoleFn = (stateConnector: Connector) => Promise<EntityRoleData[]>;
|
|
118
119
|
|
|
119
|
-
export interface ServiceModule<
|
|
120
|
+
export interface ServiceModule<
|
|
121
|
+
T,
|
|
122
|
+
P extends Provider,
|
|
123
|
+
E extends TranslatedEntity<BaseState, any, any> = TranslatedEntity<
|
|
124
|
+
BaseState,
|
|
125
|
+
any,
|
|
126
|
+
any
|
|
127
|
+
>,
|
|
128
|
+
> {
|
|
120
129
|
provider: P;
|
|
121
130
|
service: string;
|
|
122
131
|
arnLabel?: string;
|
|
@@ -124,9 +133,9 @@ export interface ServiceModule<T, P extends Provider> {
|
|
|
124
133
|
getClient: ClientBuilder<T, P>;
|
|
125
134
|
callPerRegion: boolean;
|
|
126
135
|
getters: GetterFn<T, P>[];
|
|
127
|
-
nodes?: string[];
|
|
128
136
|
getNodes?: GetNodeFn<P>;
|
|
129
137
|
edges?: BaseEdgeResolver[];
|
|
130
138
|
getEdges?: GetEdgeFn;
|
|
131
139
|
getIamRoles?: GetIamRoleFn;
|
|
140
|
+
entities?: E[];
|
|
132
141
|
}
|
package/src/config.ts
CHANGED
|
@@ -38,8 +38,6 @@ export type BaseScannerDefinition = {
|
|
|
38
38
|
callPerRegion: boolean;
|
|
39
39
|
// Scanner functions for pulling state from a service
|
|
40
40
|
getters: BaseGetter[];
|
|
41
|
-
// Scrapers for pulling Nodes from service state
|
|
42
|
-
nodes?: GenericNodeSelector[];
|
|
43
41
|
// Scrapers for pulling Edges from service state
|
|
44
42
|
edges?: BaseEdgeResolver[];
|
|
45
43
|
// Scrapers for pulling IAM Roles from service state, used to generate permission based edges
|
|
@@ -47,8 +45,10 @@ export type BaseScannerDefinition = {
|
|
|
47
45
|
};
|
|
48
46
|
|
|
49
47
|
type AsCommand<S extends string> = `${S}Command`;
|
|
50
|
-
export type AvailableCommand<
|
|
51
|
-
|
|
48
|
+
export type AvailableCommand<
|
|
49
|
+
Serv extends object,
|
|
50
|
+
Funcs extends string,
|
|
51
|
+
> = AsCommand<Funcs> extends `${infer P}Command` & keyof Serv ? P : never;
|
|
52
52
|
|
|
53
53
|
export type StateSelector<
|
|
54
54
|
ServiceName extends string,
|
|
@@ -124,7 +124,6 @@ export type ScannerDefinition<
|
|
|
124
124
|
skipClientBuilder?: boolean;
|
|
125
125
|
callPerRegion: boolean;
|
|
126
126
|
getters: ServiceGetter<ServiceName, Serv, Funcs>[];
|
|
127
|
-
nodes?: StateSelector<ServiceName, Serv, Funcs>[];
|
|
128
127
|
edges?: EdgeSelector<ServiceName, Serv, Funcs>[];
|
|
129
128
|
iamRoles?: StateSelector<ServiceName, Serv, Funcs>[];
|
|
130
129
|
};
|
package/src/graph.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { BaseState } from "./scan";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* A node returned from a state selector before its been formatted for a graphing library
|
|
3
5
|
*/
|
|
@@ -6,6 +8,7 @@ export interface SelectedNode {
|
|
|
6
8
|
name?: string;
|
|
7
9
|
parent?: string;
|
|
8
10
|
type?: string;
|
|
11
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
9
12
|
rawState?: any;
|
|
10
13
|
}
|
|
11
14
|
|
|
@@ -26,16 +29,19 @@ export type ElementType<ReadType, WriteType> = {
|
|
|
26
29
|
readonly _write: WriteType;
|
|
27
30
|
};
|
|
28
31
|
|
|
32
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
29
33
|
export type ElementRecord<K extends keyof any, R, W> = ElementType<
|
|
30
34
|
Record<K, Readable<R>>,
|
|
31
35
|
Record<K, Writable<W>>
|
|
32
36
|
>;
|
|
33
37
|
|
|
38
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
34
39
|
export type ReadType<T> = T extends ElementType<infer R, any> ? Readable<R> : T;
|
|
35
40
|
export type Readable<T> = {
|
|
36
41
|
[K in keyof T]: ReadType<T[K]>;
|
|
37
42
|
};
|
|
38
43
|
|
|
44
|
+
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
39
45
|
export type WriteType<T> = T extends ElementType<any, infer W>
|
|
40
46
|
? Writable<W>
|
|
41
47
|
: T;
|
|
@@ -43,7 +49,14 @@ export type Writable<T> = {
|
|
|
43
49
|
[K in keyof T]: WriteType<T[K]>;
|
|
44
50
|
};
|
|
45
51
|
|
|
46
|
-
export interface Node {
|
|
52
|
+
export interface Node extends BaseState<unknown> {
|
|
53
|
+
parent?: ElementType<Node, string>;
|
|
54
|
+
children?: ElementRecord<string, Node, string>;
|
|
55
|
+
incomingEdges: ElementRecord<string, Edge, string>;
|
|
56
|
+
outgoingEdges: ElementRecord<string, Edge, string>;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
export interface NodeOld {
|
|
47
60
|
id: string;
|
|
48
61
|
name: string;
|
|
49
62
|
metadata: Record<string, unknown>;
|
|
@@ -66,12 +79,7 @@ export interface Edge {
|
|
|
66
79
|
export interface Graph {
|
|
67
80
|
nodes: Readable<Node>[];
|
|
68
81
|
edges: Readable<Edge>[];
|
|
69
|
-
addNode: (
|
|
70
|
-
node: Pick<
|
|
71
|
-
Writable<Node>,
|
|
72
|
-
"id" | "name" | "metadata" | "parent" | "service" | "type"
|
|
73
|
-
>,
|
|
74
|
-
) => void;
|
|
82
|
+
addNode: (node: BaseState<unknown>) => void;
|
|
75
83
|
addEdge: (
|
|
76
84
|
edge: Pick<Writable<Edge>, "name" | "source" | "target" | "metadata">,
|
|
77
85
|
) => void;
|
package/src/scan.ts
CHANGED
|
@@ -1,12 +1,352 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
1
|
+
import { AwsContext, Connector } from "./api";
|
|
2
|
+
|
|
3
|
+
export interface CommandCallMetadata {
|
|
4
|
+
account: string;
|
|
5
|
+
region: string;
|
|
6
|
+
partition?: string;
|
|
7
|
+
timestamp: number;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export interface State<O, I = unknown> {
|
|
11
|
+
_metadata: CommandCallMetadata;
|
|
12
|
+
_result: O;
|
|
13
|
+
_parameters?: I;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
export type GenericState = State<unknown>;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Metadata for any piece of state generated — when it was scanned, and what version of the state schema it uses
|
|
20
|
+
*/
|
|
21
|
+
export interface StateMetadata {
|
|
22
|
+
version: string;
|
|
23
|
+
/**
|
|
24
|
+
* Epoch value (in ms)
|
|
25
|
+
*/
|
|
26
|
+
timestamp: number;
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
* Coordinates of a node in the graph including an optional position on the Z axis
|
|
31
|
+
*/
|
|
32
|
+
export interface Coordinates {
|
|
33
|
+
x: number;
|
|
34
|
+
y: number;
|
|
35
|
+
z?: number;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* Details about the nodes position in the graph and how it relates to other components
|
|
40
|
+
*/
|
|
41
|
+
export interface GraphInfo {
|
|
42
|
+
/**
|
|
43
|
+
* The unique ID of the node in the graph
|
|
44
|
+
*/
|
|
45
|
+
id: string;
|
|
46
|
+
/**
|
|
47
|
+
* The human readable name of the node in the graph
|
|
48
|
+
*/
|
|
49
|
+
label: string;
|
|
50
|
+
/**
|
|
51
|
+
* The type of the node, used for assigning an icon in the graph
|
|
52
|
+
*/
|
|
53
|
+
nodeType: string;
|
|
54
|
+
/**
|
|
55
|
+
* The ID of the parent node, optional.
|
|
56
|
+
*/
|
|
57
|
+
parent?: string;
|
|
58
|
+
/**
|
|
59
|
+
* The coordinates of the node in the graph, optional.
|
|
60
|
+
*/
|
|
61
|
+
coords?: Coordinates;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* The tenant that the resource has been created in, typically an account or org. Should be defined for every resource.
|
|
66
|
+
*/
|
|
67
|
+
export interface Tenant {
|
|
68
|
+
/**
|
|
69
|
+
* CSP that the state refers to (aws, gcp, azure)
|
|
70
|
+
*/
|
|
71
|
+
provider: string;
|
|
72
|
+
/**
|
|
73
|
+
* The partition of this state e.g. govcloud, cn partitions
|
|
74
|
+
*/
|
|
75
|
+
partition?: string;
|
|
76
|
+
/**
|
|
77
|
+
* The unique ID for the tenant (e.g. account id)
|
|
78
|
+
*/
|
|
79
|
+
tenantId: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* The geo data for a resource tracking where it is deployed to and, if known, which specific zones (i.e. datacenters) its in.
|
|
84
|
+
*/
|
|
85
|
+
export interface Location {
|
|
86
|
+
/**
|
|
87
|
+
* The standard reference name for the region e.g. us-east-1
|
|
88
|
+
*/
|
|
89
|
+
code: string;
|
|
90
|
+
/**
|
|
91
|
+
* The availability zone/datacenter that the resource is in e.g. us-east-1a
|
|
92
|
+
*/
|
|
93
|
+
zone?: string[];
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* Details which identify a resource within the state
|
|
98
|
+
*/
|
|
99
|
+
export interface Resource {
|
|
100
|
+
/**
|
|
101
|
+
* Category tracks whether this resource is a higher level concept like an account, or a service of a resource
|
|
102
|
+
*/
|
|
103
|
+
category: string;
|
|
104
|
+
/**
|
|
105
|
+
* Subcategory tracks the resource's more specific resource type e.g. sub-service entity type. Not set for higher level concepts
|
|
106
|
+
*/
|
|
107
|
+
subcategory?: string;
|
|
108
|
+
/**
|
|
109
|
+
* The unique ID of the resource — either an account number or a resource ID
|
|
110
|
+
*/
|
|
111
|
+
id: string;
|
|
112
|
+
/**
|
|
113
|
+
* The human-readable name of the resource
|
|
114
|
+
*/
|
|
115
|
+
name: string;
|
|
116
|
+
/**
|
|
117
|
+
* The recorded description for the resource
|
|
118
|
+
*/
|
|
119
|
+
description?: string;
|
|
120
|
+
/**
|
|
121
|
+
* The resource level policy which dictates access
|
|
122
|
+
*/
|
|
123
|
+
policy?: string;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
export interface Role {
|
|
127
|
+
arn: string;
|
|
128
|
+
label: string;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
/**
|
|
132
|
+
* The IAM roles associated with a resource. Supports resources with many roles assigned to varying lifecycles
|
|
133
|
+
*/
|
|
134
|
+
export interface IAM {
|
|
135
|
+
roles: Role[];
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* The audit details of any existing resource where available - tracks who created the resource and when.
|
|
140
|
+
*/
|
|
141
|
+
export interface Audit {
|
|
142
|
+
createdAt?: string | Date;
|
|
143
|
+
createdBy?: string;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
/**
|
|
147
|
+
* The domain names that a resource can be accessed at
|
|
148
|
+
*/
|
|
149
|
+
export interface DNS {
|
|
150
|
+
/**
|
|
151
|
+
* List of domain names at which a resource is accessible
|
|
152
|
+
*/
|
|
153
|
+
domains: string[];
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
export type PublicIpStatus = "enabled" | "disabled";
|
|
157
|
+
|
|
158
|
+
/**
|
|
159
|
+
* The network information for a scanned resource which aims to cover both resources being assigned an address
|
|
160
|
+
* and the networking resource itself (VPC, subnet)
|
|
161
|
+
*/
|
|
162
|
+
export interface Network {
|
|
163
|
+
/**
|
|
164
|
+
* Information about the public IP of the resource
|
|
165
|
+
*/
|
|
166
|
+
publicIp?: {
|
|
167
|
+
status?: PublicIpStatus;
|
|
168
|
+
address?: string;
|
|
169
|
+
};
|
|
170
|
+
/**
|
|
171
|
+
* List of security group IDs that are associated with the resource
|
|
172
|
+
*/
|
|
173
|
+
securityGroups?: string[];
|
|
174
|
+
/**
|
|
175
|
+
* The subnets that the resource is deployed into
|
|
176
|
+
*/
|
|
177
|
+
targetSubnets?: string[];
|
|
178
|
+
/**
|
|
179
|
+
* The IPs that have been assigned to the resource within the private network.
|
|
180
|
+
*/
|
|
181
|
+
assignedAddresses?: {
|
|
182
|
+
ipv4?: string;
|
|
183
|
+
ipv6?: string;
|
|
184
|
+
};
|
|
185
|
+
/**
|
|
186
|
+
* The IP ranges reserved for a networking resource (VPC, subnet)
|
|
187
|
+
*/
|
|
188
|
+
reservedAddresses?: [
|
|
189
|
+
{
|
|
190
|
+
family: "ipv4" | "ipv6";
|
|
191
|
+
cidrBlock: string;
|
|
192
|
+
cidrBlockAssociationSets?: [
|
|
193
|
+
{
|
|
194
|
+
associationId: string;
|
|
195
|
+
cidrBlock: string;
|
|
196
|
+
state: string;
|
|
197
|
+
stateMessage: string;
|
|
198
|
+
},
|
|
199
|
+
];
|
|
200
|
+
firstAddress: string;
|
|
201
|
+
lastAddress: string;
|
|
202
|
+
},
|
|
203
|
+
];
|
|
204
|
+
/**
|
|
205
|
+
* The information relating to a specific subnet
|
|
206
|
+
*/
|
|
207
|
+
subnet?: {
|
|
208
|
+
ipv6Only?: boolean;
|
|
209
|
+
availableAddressCount?: number;
|
|
210
|
+
};
|
|
211
|
+
/**
|
|
212
|
+
* The information relating to a specific VPC.
|
|
213
|
+
*/
|
|
214
|
+
vpc?: {
|
|
215
|
+
id?: string;
|
|
216
|
+
dhcpOptionsId?: string;
|
|
217
|
+
state?: string;
|
|
218
|
+
instanceTenancy?: string;
|
|
219
|
+
default?: boolean;
|
|
220
|
+
};
|
|
221
|
+
|
|
222
|
+
attachedEni?: {
|
|
223
|
+
interfaceId?: string;
|
|
224
|
+
macAddress?: string;
|
|
225
|
+
};
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
/**
|
|
229
|
+
* Generic structure for tracking key value datatypes
|
|
230
|
+
*/
|
|
231
|
+
export interface KVPair {
|
|
232
|
+
key?: string;
|
|
233
|
+
value?: string;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Structure for tracking the source of state that was scanned
|
|
238
|
+
*/
|
|
239
|
+
export interface Source<T> {
|
|
240
|
+
command: string;
|
|
241
|
+
parameters?: T;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Structure for representing the relationship between resources and the load balancers that route to them
|
|
246
|
+
*/
|
|
247
|
+
export interface LoadBalancer {
|
|
248
|
+
name?: string;
|
|
249
|
+
port?: number;
|
|
250
|
+
targetGroupArn?: string;
|
|
251
|
+
}
|
|
252
|
+
|
|
253
|
+
export type SizeUnit = "B" | "MB" | "MiB" | "GB" | "GiB";
|
|
254
|
+
|
|
255
|
+
export type TimeUnit = "s" | "ms" | "m" | "h" | "d";
|
|
256
|
+
|
|
257
|
+
export interface QualifiedMeasure<T> {
|
|
258
|
+
unit: T;
|
|
259
|
+
value: number;
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
export interface HealthcheckConfig {
|
|
263
|
+
status?: string;
|
|
264
|
+
gracePeriod?: QualifiedMeasure<TimeUnit>;
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Structure for tracking resources which have an associated encryption key
|
|
269
|
+
*/
|
|
270
|
+
export interface EncryptionConfig {
|
|
271
|
+
keyId?: string;
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
export interface DeadLetterConfig {
|
|
275
|
+
targetId?: string;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
/**
|
|
279
|
+
* Base state type to be extended on a per-service basis with the service specific context to use for linking.
|
|
280
|
+
* Attribute specific information can be found on each type.
|
|
281
|
+
*/
|
|
282
|
+
export interface BaseState<T = unknown> {
|
|
283
|
+
$metadata: StateMetadata;
|
|
284
|
+
$graph: GraphInfo;
|
|
285
|
+
$source?: Source<T>;
|
|
286
|
+
deadLetter?: DeadLetterConfig;
|
|
287
|
+
tenant: Tenant;
|
|
288
|
+
location?: Location;
|
|
289
|
+
loadBalancers?: LoadBalancer[];
|
|
290
|
+
resource: Resource;
|
|
291
|
+
dns?: DNS;
|
|
292
|
+
iam?: IAM;
|
|
293
|
+
healthcheck?: HealthcheckConfig;
|
|
294
|
+
network?: Network;
|
|
295
|
+
audit?: Audit;
|
|
296
|
+
tags?: KVPair[];
|
|
297
|
+
encryption?: EncryptionConfig;
|
|
298
|
+
}
|
|
299
|
+
|
|
300
|
+
/**
|
|
301
|
+
* Generic type signature for any ode responsible for translating between data types
|
|
302
|
+
*/
|
|
303
|
+
type Translate<A, B> = (val: A) => B;
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Definition of a an entity's translators to convert the raw input state into the common schema
|
|
307
|
+
*/
|
|
308
|
+
export type ComponentFactory<Input, Schema = BaseState<unknown>> = {
|
|
309
|
+
[ComponentName in keyof Schema]: Translate<Input, Schema[ComponentName]>;
|
|
9
310
|
};
|
|
10
311
|
|
|
11
|
-
|
|
12
|
-
|
|
312
|
+
export interface CommonEntity<Schema, RawState, TranslatedState = RawState> {
|
|
313
|
+
version: string;
|
|
314
|
+
selector: string;
|
|
315
|
+
debugLabel: string;
|
|
316
|
+
provider: string;
|
|
317
|
+
command: string;
|
|
318
|
+
category: string;
|
|
319
|
+
subcategory: string;
|
|
320
|
+
nodeType: string;
|
|
321
|
+
|
|
322
|
+
getState: (state: Connector, context: AwsContext) => Promise<RawState[]>;
|
|
323
|
+
components: ComponentFactory<TranslatedState, Schema>;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
/**
|
|
327
|
+
* Entity which can act directly on its raw state, and does not require any pre-processing before
|
|
328
|
+
*/
|
|
329
|
+
export interface SimpleEntity<Schema, RawState>
|
|
330
|
+
extends CommonEntity<Schema, RawState> {
|
|
331
|
+
translate?: never;
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Entity which needs to translate its stored raw state before it can produce the standard schema
|
|
336
|
+
*/
|
|
337
|
+
export interface TranslatedEntity<Schema, RawState, TranslatedState>
|
|
338
|
+
extends CommonEntity<Schema, RawState, TranslatedState> {
|
|
339
|
+
translate: Translate<RawState, TranslatedState[]>;
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
/**
|
|
343
|
+
* Discriminated union type for both simple and translated entities
|
|
344
|
+
*/
|
|
345
|
+
export type EntityETL<Schema, RawState, TranslatedState = RawState> =
|
|
346
|
+
| SimpleEntity<Schema, RawState>
|
|
347
|
+
| TranslatedEntity<Schema, RawState, TranslatedState>;
|
|
348
|
+
|
|
349
|
+
export type WithCallContext<T, Input> = T & {
|
|
350
|
+
$metadata: CommandCallMetadata;
|
|
351
|
+
$parameters?: Input;
|
|
352
|
+
};
|