@prismicio/simulator 0.1.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/LICENSE +202 -0
- package/README.md +98 -0
- package/dist/SimulatorAPI.cjs +50 -0
- package/dist/SimulatorAPI.cjs.map +1 -0
- package/dist/SimulatorAPI.d.ts +12 -0
- package/dist/SimulatorAPI.js +50 -0
- package/dist/SimulatorAPI.js.map +1 -0
- package/dist/SimulatorClient.cjs +54 -0
- package/dist/SimulatorClient.cjs.map +1 -0
- package/dist/SimulatorClient.d.ts +10 -0
- package/dist/SimulatorClient.js +54 -0
- package/dist/SimulatorClient.js.map +1 -0
- package/dist/channel/ChannelEmitter.cjs +146 -0
- package/dist/channel/ChannelEmitter.cjs.map +1 -0
- package/dist/channel/ChannelEmitter.d.ts +38 -0
- package/dist/channel/ChannelEmitter.js +146 -0
- package/dist/channel/ChannelEmitter.js.map +1 -0
- package/dist/channel/ChannelNetwork.cjs +112 -0
- package/dist/channel/ChannelNetwork.cjs.map +1 -0
- package/dist/channel/ChannelNetwork.d.ts +24 -0
- package/dist/channel/ChannelNetwork.js +112 -0
- package/dist/channel/ChannelNetwork.js.map +1 -0
- package/dist/channel/ChannelReceiver.cjs +95 -0
- package/dist/channel/ChannelReceiver.cjs.map +1 -0
- package/dist/channel/ChannelReceiver.d.ts +20 -0
- package/dist/channel/ChannelReceiver.js +95 -0
- package/dist/channel/ChannelReceiver.js.map +1 -0
- package/dist/channel/errors.cjs +54 -0
- package/dist/channel/errors.cjs.map +1 -0
- package/dist/channel/errors.d.ts +25 -0
- package/dist/channel/errors.js +54 -0
- package/dist/channel/errors.js.map +1 -0
- package/dist/channel/index.d.ts +10 -0
- package/dist/channel/messages.cjs +66 -0
- package/dist/channel/messages.cjs.map +1 -0
- package/dist/channel/messages.d.ts +10 -0
- package/dist/channel/messages.js +66 -0
- package/dist/channel/messages.js.map +1 -0
- package/dist/channel/types.cjs +11 -0
- package/dist/channel/types.cjs.map +1 -0
- package/dist/channel/types.d.ts +61 -0
- package/dist/channel/types.js +13 -0
- package/dist/channel/types.js.map +1 -0
- package/dist/index.cjs +33 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.js +27 -0
- package/dist/index.js.map +1 -0
- package/dist/kit/SimulatorManager.cjs +140 -0
- package/dist/kit/SimulatorManager.cjs.map +1 -0
- package/dist/kit/SimulatorManager.d.ts +15 -0
- package/dist/kit/SimulatorManager.js +140 -0
- package/dist/kit/SimulatorManager.js.map +1 -0
- package/dist/kit/State.cjs +82 -0
- package/dist/kit/State.cjs.map +1 -0
- package/dist/kit/State.d.ts +25 -0
- package/dist/kit/State.js +82 -0
- package/dist/kit/State.js.map +1 -0
- package/dist/kit/domHelpers.cjs +53 -0
- package/dist/kit/domHelpers.cjs.map +1 -0
- package/dist/kit/domHelpers.d.ts +9 -0
- package/dist/kit/domHelpers.js +53 -0
- package/dist/kit/domHelpers.js.map +1 -0
- package/dist/kit/eventHandlers.cjs +15 -0
- package/dist/kit/eventHandlers.cjs.map +1 -0
- package/dist/kit/eventHandlers.d.ts +4 -0
- package/dist/kit/eventHandlers.js +15 -0
- package/dist/kit/eventHandlers.js.map +1 -0
- package/dist/kit/getDefault.cjs +16 -0
- package/dist/kit/getDefault.cjs.map +1 -0
- package/dist/kit/getDefault.d.ts +8 -0
- package/dist/kit/getDefault.js +16 -0
- package/dist/kit/getDefault.js.map +1 -0
- package/dist/kit/index.cjs +26 -0
- package/dist/kit/index.cjs.map +1 -0
- package/dist/kit/index.d.ts +8 -0
- package/dist/kit/index.js +23 -0
- package/dist/kit/index.js.map +1 -0
- package/dist/kit/messages.cjs +29 -0
- package/dist/kit/messages.cjs.map +1 -0
- package/dist/kit/messages.d.ts +1 -0
- package/dist/kit/messages.js +29 -0
- package/dist/kit/messages.js.map +1 -0
- package/dist/kit/types.cjs +9 -0
- package/dist/kit/types.cjs.map +1 -0
- package/dist/kit/types.d.ts +23 -0
- package/dist/kit/types.js +10 -0
- package/dist/kit/types.js.map +1 -0
- package/dist/lib/EventEmitter.cjs +27 -0
- package/dist/lib/EventEmitter.cjs.map +1 -0
- package/dist/lib/EventEmitter.d.ts +10 -0
- package/dist/lib/EventEmitter.js +27 -0
- package/dist/lib/EventEmitter.js.map +1 -0
- package/dist/lib/__PRODUCTION__.d.ts +7 -0
- package/dist/lib/throttle.cjs +24 -0
- package/dist/lib/throttle.cjs.map +1 -0
- package/dist/lib/throttle.d.ts +1 -0
- package/dist/lib/throttle.js +24 -0
- package/dist/lib/throttle.js.map +1 -0
- package/dist/types.cjs +14 -0
- package/dist/types.cjs.map +1 -0
- package/dist/types.d.ts +34 -0
- package/dist/types.js +16 -0
- package/dist/types.js.map +1 -0
- package/package.json +99 -0
- package/src/SimulatorAPI.ts +90 -0
- package/src/SimulatorClient.ts +96 -0
- package/src/channel/ChannelEmitter.ts +278 -0
- package/src/channel/ChannelNetwork.ts +216 -0
- package/src/channel/ChannelReceiver.ts +184 -0
- package/src/channel/errors.ts +53 -0
- package/src/channel/index.ts +75 -0
- package/src/channel/messages.ts +115 -0
- package/src/channel/types.ts +138 -0
- package/src/index.ts +42 -0
- package/src/kit/SimulatorManager.ts +199 -0
- package/src/kit/State.ts +113 -0
- package/src/kit/domHelpers.ts +75 -0
- package/src/kit/eventHandlers.ts +16 -0
- package/src/kit/getDefault.ts +18 -0
- package/src/kit/index.ts +33 -0
- package/src/kit/messages.ts +25 -0
- package/src/kit/types.ts +30 -0
- package/src/lib/EventEmitter.ts +41 -0
- package/src/lib/__PRODUCTION__.ts +12 -0
- package/src/lib/throttle.ts +26 -0
- package/src/types.ts +57 -0
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
import { UnknownErrorResponseMessage } from ".";
|
|
2
|
+
|
|
3
|
+
import { UnknownRequestMessage } from "./types";
|
|
4
|
+
|
|
5
|
+
export class ResponseError<
|
|
6
|
+
TErrorResponse extends UnknownErrorResponseMessage,
|
|
7
|
+
> extends Error {
|
|
8
|
+
public response: TErrorResponse;
|
|
9
|
+
|
|
10
|
+
constructor(errorResponse: TErrorResponse) {
|
|
11
|
+
super(errorResponse.msg);
|
|
12
|
+
|
|
13
|
+
this.response = errorResponse;
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
export class ConnectionTimeoutError extends Error {
|
|
18
|
+
constructor() {
|
|
19
|
+
super("Connection timed out");
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
export class TooManyConcurrentRequestsError extends Error {
|
|
23
|
+
public request: UnknownRequestMessage;
|
|
24
|
+
|
|
25
|
+
constructor(request: UnknownRequestMessage) {
|
|
26
|
+
super(`Too many concurrent requests`);
|
|
27
|
+
|
|
28
|
+
this.request = request;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
export class RequestTimeoutError<
|
|
32
|
+
TRequest extends UnknownRequestMessage,
|
|
33
|
+
> extends Error {
|
|
34
|
+
public request: UnknownRequestMessage;
|
|
35
|
+
|
|
36
|
+
constructor(request: TRequest) {
|
|
37
|
+
super(`Request \`${request.requestID}\` timed out`);
|
|
38
|
+
|
|
39
|
+
this.request = request;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
export class NotReadyError extends Error {}
|
|
44
|
+
export class PortNotSetError extends Error {
|
|
45
|
+
constructor() {
|
|
46
|
+
super("Port is not set");
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
export class ChannelNotSetError extends Error {
|
|
50
|
+
constructor() {
|
|
51
|
+
super("Channel is not set");
|
|
52
|
+
}
|
|
53
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
export { ChannelNetwork, channelNetworkDefaultOptions } from "./ChannelNetwork";
|
|
2
|
+
export type {
|
|
3
|
+
PostRequestOptions,
|
|
4
|
+
ChannelNetworkOptions,
|
|
5
|
+
} from "./ChannelNetwork";
|
|
6
|
+
|
|
7
|
+
export { ChannelEmitter, channelEmitterDefaultOptions } from "./ChannelEmitter";
|
|
8
|
+
export type {
|
|
9
|
+
ChannelEmitterOptions,
|
|
10
|
+
AllChannelEmitterOptions,
|
|
11
|
+
} from "./ChannelEmitter";
|
|
12
|
+
|
|
13
|
+
export {
|
|
14
|
+
ChannelReceiver,
|
|
15
|
+
channelReceiverDefaultOptions,
|
|
16
|
+
} from "./ChannelReceiver";
|
|
17
|
+
export type {
|
|
18
|
+
ChannelReceiverOptions,
|
|
19
|
+
AllChannelReceiverOptions,
|
|
20
|
+
} from "./ChannelReceiver";
|
|
21
|
+
|
|
22
|
+
export {
|
|
23
|
+
createRequestMessage,
|
|
24
|
+
createSuccessResponseMessage,
|
|
25
|
+
createErrorResponseMessage,
|
|
26
|
+
validateMessage,
|
|
27
|
+
isRequestMessage,
|
|
28
|
+
isResponseMessage,
|
|
29
|
+
isSuccessResponseMessage,
|
|
30
|
+
isErrorResponseMessage,
|
|
31
|
+
} from "./messages";
|
|
32
|
+
|
|
33
|
+
export {
|
|
34
|
+
ResponseError,
|
|
35
|
+
ConnectionTimeoutError,
|
|
36
|
+
TooManyConcurrentRequestsError,
|
|
37
|
+
RequestTimeoutError,
|
|
38
|
+
NotReadyError,
|
|
39
|
+
PortNotSetError,
|
|
40
|
+
ChannelNotSetError,
|
|
41
|
+
} from "./errors";
|
|
42
|
+
|
|
43
|
+
export {
|
|
44
|
+
InternalEmitterRequestType,
|
|
45
|
+
InternalReceiverRequestType,
|
|
46
|
+
} from "./types";
|
|
47
|
+
export type {
|
|
48
|
+
// Messages
|
|
49
|
+
RequestMessage,
|
|
50
|
+
ResponseMessage,
|
|
51
|
+
ErrorResponseMessage,
|
|
52
|
+
SuccessResponseMessage,
|
|
53
|
+
ExtractSuccessResponseMessage,
|
|
54
|
+
ExtractErrorResponseMessage,
|
|
55
|
+
// Unknown messages
|
|
56
|
+
UnknownRequestMessage,
|
|
57
|
+
UnknownSuccessResponseMessage,
|
|
58
|
+
UnknownErrorResponseMessage,
|
|
59
|
+
UnknownResponseMessage,
|
|
60
|
+
UnknownMessage,
|
|
61
|
+
// Transactions
|
|
62
|
+
Transaction,
|
|
63
|
+
TransactionMethod,
|
|
64
|
+
TransactionHandler,
|
|
65
|
+
TransactionsMethods,
|
|
66
|
+
TransactionsHandlers,
|
|
67
|
+
// Unknown transactions
|
|
68
|
+
UnknownTransaction,
|
|
69
|
+
UnknownTransactionMethod,
|
|
70
|
+
UnknownTransactionHandler,
|
|
71
|
+
// Emitter
|
|
72
|
+
InternalEmitterTransactions,
|
|
73
|
+
// Receiver
|
|
74
|
+
InternalReceiverTransactions,
|
|
75
|
+
} from "./types";
|
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
import statuses from "statuses";
|
|
2
|
+
|
|
3
|
+
import {
|
|
4
|
+
ErrorResponseMessage,
|
|
5
|
+
RequestMessage,
|
|
6
|
+
SuccessResponseMessage,
|
|
7
|
+
UnknownErrorResponseMessage,
|
|
8
|
+
UnknownMessage,
|
|
9
|
+
UnknownRequestMessage,
|
|
10
|
+
UnknownResponseMessage,
|
|
11
|
+
UnknownSuccessResponseMessage,
|
|
12
|
+
} from "./types";
|
|
13
|
+
|
|
14
|
+
let requestID = 0;
|
|
15
|
+
|
|
16
|
+
export const createRequestMessage = <
|
|
17
|
+
TType extends string = string,
|
|
18
|
+
TData = undefined,
|
|
19
|
+
>(
|
|
20
|
+
type: TType,
|
|
21
|
+
data: TData,
|
|
22
|
+
prefix = "",
|
|
23
|
+
): RequestMessage<TType, TData> => {
|
|
24
|
+
return {
|
|
25
|
+
requestID: `${prefix}${requestID++}`,
|
|
26
|
+
type,
|
|
27
|
+
data,
|
|
28
|
+
};
|
|
29
|
+
};
|
|
30
|
+
|
|
31
|
+
export const createSuccessResponseMessage = <TData = undefined>(
|
|
32
|
+
requestID: string,
|
|
33
|
+
data: TData,
|
|
34
|
+
status: keyof typeof statuses.message = 200,
|
|
35
|
+
): SuccessResponseMessage<TData> => {
|
|
36
|
+
if (status >= 400) {
|
|
37
|
+
throw new TypeError(
|
|
38
|
+
`Invalid success status code, expected status to be within \`[100;400[\`, got \`${status}\``,
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
return {
|
|
43
|
+
requestID,
|
|
44
|
+
status,
|
|
45
|
+
msg: statuses.message[status]?.replace(/\.$/, "").toLowerCase() ?? "",
|
|
46
|
+
data,
|
|
47
|
+
};
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
export const createErrorResponseMessage = <TError = undefined>(
|
|
51
|
+
requestID: string,
|
|
52
|
+
error: TError,
|
|
53
|
+
status: keyof typeof statuses.message = 400,
|
|
54
|
+
): ErrorResponseMessage<TError> => {
|
|
55
|
+
if (status < 400) {
|
|
56
|
+
throw new TypeError(
|
|
57
|
+
`Invalid error status code, expected status to be within \`[500;600[\`, got \`${status}\``,
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return {
|
|
62
|
+
requestID,
|
|
63
|
+
status,
|
|
64
|
+
msg: statuses.message[status]?.replace(/\.$/, "").toLowerCase() ?? "",
|
|
65
|
+
error,
|
|
66
|
+
};
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export const validateMessage = (message: unknown): UnknownMessage => {
|
|
70
|
+
if (typeof message !== "object" || message === null) {
|
|
71
|
+
throw new TypeError(
|
|
72
|
+
`Invalid message received, expected message to be of type \`object\`, got \`${typeof message}\``,
|
|
73
|
+
);
|
|
74
|
+
} else if (
|
|
75
|
+
!Object.keys(message).every((key) =>
|
|
76
|
+
["requestID", "type", "data", "status", "msg", "error"].includes(key),
|
|
77
|
+
)
|
|
78
|
+
) {
|
|
79
|
+
throw new TypeError(`Invalid message received: ${JSON.stringify(message)}`);
|
|
80
|
+
} else if (
|
|
81
|
+
typeof (message as Record<string, unknown>).requestID !== "string"
|
|
82
|
+
) {
|
|
83
|
+
throw new TypeError(
|
|
84
|
+
`Invalid message received, expected \`message.requestID\` to be of type \`string\`, got \`${typeof (
|
|
85
|
+
message as Record<string, unknown>
|
|
86
|
+
).id}\``,
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
return message as UnknownMessage;
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
export const isRequestMessage = (
|
|
94
|
+
message: UnknownMessage,
|
|
95
|
+
): message is UnknownRequestMessage => {
|
|
96
|
+
return "type" in message;
|
|
97
|
+
};
|
|
98
|
+
|
|
99
|
+
export const isResponseMessage = (
|
|
100
|
+
message: UnknownMessage,
|
|
101
|
+
): message is UnknownResponseMessage => {
|
|
102
|
+
return !("type" in message);
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
export const isSuccessResponseMessage = (
|
|
106
|
+
message: UnknownMessage,
|
|
107
|
+
): message is UnknownSuccessResponseMessage => {
|
|
108
|
+
return isResponseMessage(message) && !("error" in message);
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
export const isErrorResponseMessage = (
|
|
112
|
+
message: UnknownMessage,
|
|
113
|
+
): message is UnknownErrorResponseMessage => {
|
|
114
|
+
return isResponseMessage(message) && !("data" in message);
|
|
115
|
+
};
|
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
// Messages
|
|
2
|
+
export type MessageBase = {
|
|
3
|
+
requestID: string;
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export type RequestMessage<TType extends string = string, TData = void> = {
|
|
7
|
+
type: TType;
|
|
8
|
+
data: TData;
|
|
9
|
+
} & MessageBase;
|
|
10
|
+
|
|
11
|
+
export type ResponseMessageBase = {
|
|
12
|
+
status: number;
|
|
13
|
+
msg: string;
|
|
14
|
+
} & MessageBase;
|
|
15
|
+
|
|
16
|
+
export type SuccessResponseMessage<TData = void> = {
|
|
17
|
+
data: TData;
|
|
18
|
+
error?: never;
|
|
19
|
+
} & ResponseMessageBase;
|
|
20
|
+
|
|
21
|
+
export type ErrorResponseMessage<TError = unknown> = {
|
|
22
|
+
data?: never;
|
|
23
|
+
error: unknown | TError;
|
|
24
|
+
} & ResponseMessageBase;
|
|
25
|
+
|
|
26
|
+
export type ResponseMessage<TData = void, TError = unknown> =
|
|
27
|
+
| SuccessResponseMessage<TData>
|
|
28
|
+
| ErrorResponseMessage<TError>;
|
|
29
|
+
|
|
30
|
+
export type ExtractSuccessResponseMessage<
|
|
31
|
+
TResponse extends UnknownResponseMessage,
|
|
32
|
+
> = Extract<TResponse, { error?: never }>;
|
|
33
|
+
|
|
34
|
+
export type ExtractErrorResponseMessage<
|
|
35
|
+
TResponse extends UnknownResponseMessage,
|
|
36
|
+
> = Extract<TResponse, { data?: never }>;
|
|
37
|
+
|
|
38
|
+
// Unknown messages
|
|
39
|
+
export type UnknownRequestMessage = RequestMessage<string, unknown>;
|
|
40
|
+
|
|
41
|
+
export type UnknownSuccessResponseMessage = SuccessResponseMessage<unknown>;
|
|
42
|
+
|
|
43
|
+
export type UnknownErrorResponseMessage = ErrorResponseMessage<unknown>;
|
|
44
|
+
|
|
45
|
+
export type UnknownResponseMessage =
|
|
46
|
+
| UnknownSuccessResponseMessage
|
|
47
|
+
| UnknownErrorResponseMessage;
|
|
48
|
+
|
|
49
|
+
export type UnknownMessage = UnknownRequestMessage | UnknownResponseMessage;
|
|
50
|
+
|
|
51
|
+
// Transactions
|
|
52
|
+
export type Transaction<
|
|
53
|
+
TRequest extends UnknownRequestMessage,
|
|
54
|
+
TResponse extends UnknownResponseMessage = ResponseMessage<void>,
|
|
55
|
+
> = {
|
|
56
|
+
request: TRequest;
|
|
57
|
+
response: TResponse;
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
export type TransactionMethod<
|
|
61
|
+
TTransaction extends Transaction<
|
|
62
|
+
UnknownRequestMessage,
|
|
63
|
+
UnknownResponseMessage
|
|
64
|
+
>,
|
|
65
|
+
> = (
|
|
66
|
+
data: TTransaction["request"]["data"],
|
|
67
|
+
) => Promise<ExtractSuccessResponseMessage<TTransaction["response"]>>;
|
|
68
|
+
|
|
69
|
+
export type TransactionHandler<
|
|
70
|
+
TTransaction extends Transaction<
|
|
71
|
+
UnknownRequestMessage,
|
|
72
|
+
UnknownResponseMessage
|
|
73
|
+
>,
|
|
74
|
+
> = (
|
|
75
|
+
request: TTransaction["request"],
|
|
76
|
+
response: {
|
|
77
|
+
success: (
|
|
78
|
+
data: ExtractSuccessResponseMessage<TTransaction["response"]>["data"],
|
|
79
|
+
status?: number,
|
|
80
|
+
) => ExtractSuccessResponseMessage<TTransaction["response"]>;
|
|
81
|
+
error: (
|
|
82
|
+
error: ExtractErrorResponseMessage<TTransaction["response"]>["error"],
|
|
83
|
+
status?: number,
|
|
84
|
+
) => ExtractErrorResponseMessage<TTransaction["response"]>;
|
|
85
|
+
},
|
|
86
|
+
) => Promise<TTransaction["response"]> | TTransaction["response"];
|
|
87
|
+
|
|
88
|
+
export type TransactionsMethods<
|
|
89
|
+
TTransactions extends Record<string, UnknownTransaction>,
|
|
90
|
+
> = {
|
|
91
|
+
[Key in keyof TTransactions]: TransactionMethod<TTransactions[Key]>;
|
|
92
|
+
};
|
|
93
|
+
|
|
94
|
+
export type TransactionsHandlers<
|
|
95
|
+
TTransactions extends Record<string, UnknownTransaction>,
|
|
96
|
+
> = {
|
|
97
|
+
[Key in keyof TTransactions]: TransactionHandler<TTransactions[Key]>;
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// Unknown transactions
|
|
101
|
+
export type UnknownTransaction = Transaction<
|
|
102
|
+
UnknownRequestMessage,
|
|
103
|
+
UnknownResponseMessage
|
|
104
|
+
>;
|
|
105
|
+
|
|
106
|
+
export type UnknownTransactionMethod = TransactionMethod<UnknownTransaction>;
|
|
107
|
+
|
|
108
|
+
export type UnknownTransactionHandler = TransactionHandler<UnknownTransaction>;
|
|
109
|
+
|
|
110
|
+
// Emitter
|
|
111
|
+
export enum InternalEmitterRequestType {
|
|
112
|
+
Connect = "connect",
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
export type InternalEmitterTransactions<
|
|
116
|
+
TReceiverOptions extends Record<string, unknown> = Record<string, unknown>,
|
|
117
|
+
> = {
|
|
118
|
+
[InternalEmitterRequestType.Connect]: Transaction<
|
|
119
|
+
RequestMessage<
|
|
120
|
+
InternalEmitterRequestType.Connect,
|
|
121
|
+
| Partial<
|
|
122
|
+
Omit<TReceiverOptions, "debug" | "requestIDPrefix" | "readyTimeout">
|
|
123
|
+
>
|
|
124
|
+
| undefined
|
|
125
|
+
>
|
|
126
|
+
>;
|
|
127
|
+
};
|
|
128
|
+
|
|
129
|
+
// Receiver
|
|
130
|
+
export enum InternalReceiverRequestType {
|
|
131
|
+
Ready = "ready",
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
export type InternalReceiverTransactions = {
|
|
135
|
+
[InternalReceiverRequestType.Ready]: Transaction<
|
|
136
|
+
RequestMessage<InternalReceiverRequestType.Ready>
|
|
137
|
+
>;
|
|
138
|
+
};
|
package/src/index.ts
ADDED
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
export {
|
|
2
|
+
SimulatorClient,
|
|
3
|
+
simulatorClientDefaultOptions,
|
|
4
|
+
} from "./SimulatorClient";
|
|
5
|
+
|
|
6
|
+
export { SimulatorAPI, simulatorAPIDefaultOptions } from "./SimulatorAPI";
|
|
7
|
+
export type { SimulatorAPIOptions } from "./SimulatorAPI";
|
|
8
|
+
|
|
9
|
+
export {
|
|
10
|
+
// Validators
|
|
11
|
+
validateMessage,
|
|
12
|
+
isRequestMessage,
|
|
13
|
+
isResponseMessage,
|
|
14
|
+
isSuccessResponseMessage,
|
|
15
|
+
isErrorResponseMessage,
|
|
16
|
+
// Error classes
|
|
17
|
+
ResponseError,
|
|
18
|
+
ConnectionTimeoutError,
|
|
19
|
+
TooManyConcurrentRequestsError,
|
|
20
|
+
RequestTimeoutError,
|
|
21
|
+
NotReadyError,
|
|
22
|
+
PortNotSetError,
|
|
23
|
+
ChannelNotSetError,
|
|
24
|
+
} from "./channel";
|
|
25
|
+
export type {
|
|
26
|
+
RequestMessage,
|
|
27
|
+
ResponseMessage,
|
|
28
|
+
ErrorResponseMessage,
|
|
29
|
+
SuccessResponseMessage,
|
|
30
|
+
AllChannelEmitterOptions,
|
|
31
|
+
AllChannelReceiverOptions,
|
|
32
|
+
} from "./channel";
|
|
33
|
+
|
|
34
|
+
export { APIRequestType, ClientRequestType } from "./types";
|
|
35
|
+
export type {
|
|
36
|
+
ActiveSlice,
|
|
37
|
+
VariationSummary,
|
|
38
|
+
SliceSummary,
|
|
39
|
+
LibrarySummary,
|
|
40
|
+
APITransactions,
|
|
41
|
+
ClientTransactions,
|
|
42
|
+
} from "./types";
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import type { SliceZone } from "@prismicio/client";
|
|
2
|
+
|
|
3
|
+
import { throttle } from "../lib/throttle";
|
|
4
|
+
|
|
5
|
+
import { ClientRequestType } from "../types";
|
|
6
|
+
import { StateEventType } from "./types";
|
|
7
|
+
|
|
8
|
+
import { SimulatorAPI } from "../SimulatorAPI";
|
|
9
|
+
import { ResponseError } from "../channel";
|
|
10
|
+
|
|
11
|
+
import { State } from "./State";
|
|
12
|
+
import {
|
|
13
|
+
getSimulatorDOM,
|
|
14
|
+
getSimulatorRootDOM,
|
|
15
|
+
getSliceZoneDOM,
|
|
16
|
+
} from "./domHelpers";
|
|
17
|
+
import { sliceSimulatorAccessedDirectly } from "./messages";
|
|
18
|
+
|
|
19
|
+
type ManagerConstructorArgs = {
|
|
20
|
+
slices?: SliceZone;
|
|
21
|
+
};
|
|
22
|
+
|
|
23
|
+
export class SimulatorManager {
|
|
24
|
+
public state: State;
|
|
25
|
+
private _api: SimulatorAPI | null;
|
|
26
|
+
private _initialized: boolean;
|
|
27
|
+
|
|
28
|
+
constructor(args?: ManagerConstructorArgs) {
|
|
29
|
+
this.state = new State(args);
|
|
30
|
+
this._api = null;
|
|
31
|
+
this._initialized = false;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async init(): Promise<void> {
|
|
35
|
+
if (this._initialized) {
|
|
36
|
+
return;
|
|
37
|
+
} else {
|
|
38
|
+
this._initialized = true;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// Init state manager
|
|
42
|
+
await this.state.init();
|
|
43
|
+
|
|
44
|
+
// Init API
|
|
45
|
+
try {
|
|
46
|
+
await this._initAPI();
|
|
47
|
+
} catch (error) {
|
|
48
|
+
if (
|
|
49
|
+
error instanceof Error &&
|
|
50
|
+
error.message === "Receiver is currently not embedded as an iframe" &&
|
|
51
|
+
!this.state.slices.length
|
|
52
|
+
) {
|
|
53
|
+
// Catch not embedded error and display message
|
|
54
|
+
this.state.message = sliceSimulatorAccessedDirectly;
|
|
55
|
+
}
|
|
56
|
+
console.error(error);
|
|
57
|
+
|
|
58
|
+
return;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Init listeners
|
|
62
|
+
this._initListeners();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
private async _initAPI(): Promise<void> {
|
|
66
|
+
// Register SimulatorAPI request handlers
|
|
67
|
+
this._api = new SimulatorAPI({
|
|
68
|
+
[ClientRequestType.SetSliceZone]: (req, res) => {
|
|
69
|
+
this.state.setSliceZone(req.data);
|
|
70
|
+
|
|
71
|
+
return res.success();
|
|
72
|
+
},
|
|
73
|
+
[ClientRequestType.ScrollToSlice]: (req, res) => {
|
|
74
|
+
// Error if `sliceIndex` is invalid
|
|
75
|
+
if (req.data.sliceIndex < 0) {
|
|
76
|
+
return res.error("`sliceIndex` must be > 0", 400);
|
|
77
|
+
} else if (req.data.sliceIndex >= this.state.slices.length) {
|
|
78
|
+
return res.error(
|
|
79
|
+
`\`sliceIndex\` must be < ${this.state.slices.length} (\`<SliceZone />\` current length)`,
|
|
80
|
+
400,
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
const $sliceZone = getSliceZoneDOM(this.state.slices.length);
|
|
85
|
+
if (!$sliceZone) {
|
|
86
|
+
return res.error("Failed to find `<SliceZone />`", 500);
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// Destroy existing active slice as we're about to scroll
|
|
90
|
+
this.state.activeSlice = null;
|
|
91
|
+
|
|
92
|
+
const $slice = $sliceZone.children[req.data.sliceIndex];
|
|
93
|
+
if (!$slice) {
|
|
94
|
+
return res.error(
|
|
95
|
+
`Failed fo find slice at index $\`{req.data.sliceIndex}\` in \`<SliceZone />\``,
|
|
96
|
+
500,
|
|
97
|
+
);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Scroll to Slice
|
|
101
|
+
$slice.scrollIntoView({
|
|
102
|
+
behavior: req.data.behavior,
|
|
103
|
+
block: req.data.block,
|
|
104
|
+
inline: req.data.inline,
|
|
105
|
+
});
|
|
106
|
+
|
|
107
|
+
// Update active slice after scrolling
|
|
108
|
+
this._api?.options.activeSliceAPI &&
|
|
109
|
+
setTimeout(this.state.setActiveSlice, 750);
|
|
110
|
+
|
|
111
|
+
return res.success();
|
|
112
|
+
},
|
|
113
|
+
});
|
|
114
|
+
|
|
115
|
+
// Mark API as ready
|
|
116
|
+
await this._api.ready();
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
private _initListeners(): void {
|
|
120
|
+
if (this._api?.options.activeSliceAPI) {
|
|
121
|
+
// Update active slice on mouse move
|
|
122
|
+
window.addEventListener("mousemove", () => {
|
|
123
|
+
this.state.setActiveSlice();
|
|
124
|
+
});
|
|
125
|
+
// Update active slice on events impacting slices rendering
|
|
126
|
+
window.addEventListener("resize", () => {
|
|
127
|
+
this.state.setActiveSlice();
|
|
128
|
+
});
|
|
129
|
+
window.addEventListener("mousewheel", () => {
|
|
130
|
+
this._api?.options.activeSliceAPI &&
|
|
131
|
+
setTimeout(this.state.setActiveSlice, 200);
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Update active slice when slices are set
|
|
135
|
+
this.state.on(StateEventType.Slices, () => {
|
|
136
|
+
this.state.setActiveSlice();
|
|
137
|
+
});
|
|
138
|
+
// Send active slices to renderer
|
|
139
|
+
this.state.on(StateEventType.ActiveSlice, async (activeSlice) => {
|
|
140
|
+
if (this._api) {
|
|
141
|
+
try {
|
|
142
|
+
await this._api.setActiveSlice(activeSlice);
|
|
143
|
+
} catch (error) {
|
|
144
|
+
// Just log bad requests, throw everything else
|
|
145
|
+
if (
|
|
146
|
+
error instanceof ResponseError &&
|
|
147
|
+
error.response.status === 400
|
|
148
|
+
) {
|
|
149
|
+
console.error(error.response);
|
|
150
|
+
} else {
|
|
151
|
+
throw error;
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
});
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
if (this._api?.options.sliceZoneSizeAPI) {
|
|
159
|
+
// Monitor Simulator root node size
|
|
160
|
+
const resizeObserver = new ResizeObserver(
|
|
161
|
+
throttle(async (entries) => {
|
|
162
|
+
const [entry] = entries;
|
|
163
|
+
|
|
164
|
+
if (this._api && entry) {
|
|
165
|
+
try {
|
|
166
|
+
await this._api.setSliceZoneSize({ rect: entry.contentRect });
|
|
167
|
+
} catch (error) {
|
|
168
|
+
// Just log bad requests, throw everything else
|
|
169
|
+
if (
|
|
170
|
+
error instanceof ResponseError &&
|
|
171
|
+
error.response.status === 400
|
|
172
|
+
) {
|
|
173
|
+
console.error(error.response);
|
|
174
|
+
} else {
|
|
175
|
+
throw error;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
}, 16),
|
|
180
|
+
);
|
|
181
|
+
const observeSimulatorRoot = () => {
|
|
182
|
+
const simulatorRootDOM = getSimulatorRootDOM();
|
|
183
|
+
if (simulatorRootDOM) {
|
|
184
|
+
resizeObserver.disconnect();
|
|
185
|
+
resizeObserver.observe(simulatorRootDOM);
|
|
186
|
+
}
|
|
187
|
+
};
|
|
188
|
+
|
|
189
|
+
// Monitor Simulator root node in DOM
|
|
190
|
+
const mutationObserver = new MutationObserver(observeSimulatorRoot);
|
|
191
|
+
// We want it to fail if not found
|
|
192
|
+
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
|
|
193
|
+
mutationObserver.observe(getSimulatorDOM()!, {
|
|
194
|
+
subtree: false,
|
|
195
|
+
childList: true,
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
}
|