@warp-drive/holodeck 0.1.0-beta.0 → 0.1.0-beta.2
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 +139 -0
- package/dist/index.d.ts +56 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +154 -210
- package/dist/index.js.map +1 -0
- package/dist/mock.d.ts +89 -0
- package/dist/mock.d.ts.map +1 -0
- package/dist/mock.js +182 -103
- package/dist/mock.js.map +1 -0
- package/package.json +23 -28
- package/server/bun.js +31 -23
- package/server/node.js +42 -33
- package/server/utils.js +57 -1
- package/declarations/index.d.ts +0 -52
- package/declarations/mock.d.ts +0 -65
package/dist/mock.d.ts
ADDED
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
//#region src/mock.d.ts
|
|
2
|
+
/**
|
|
3
|
+
* @public
|
|
4
|
+
*/
|
|
5
|
+
interface Scaffold {
|
|
6
|
+
status: number;
|
|
7
|
+
statusText?: string;
|
|
8
|
+
headers: Record<string, string>;
|
|
9
|
+
body: Record<string, string> | string | null;
|
|
10
|
+
method: string;
|
|
11
|
+
url: string;
|
|
12
|
+
response: Record<string, unknown>;
|
|
13
|
+
}
|
|
14
|
+
/**
|
|
15
|
+
* @public
|
|
16
|
+
*/
|
|
17
|
+
type ScaffoldGenerator = () => Scaffold;
|
|
18
|
+
/**
|
|
19
|
+
* @public
|
|
20
|
+
*/
|
|
21
|
+
type ResponseGenerator = () => Record<string, unknown>;
|
|
22
|
+
/**
|
|
23
|
+
* Sets up Mocking for a GET request on the mock server
|
|
24
|
+
* for the supplied url.
|
|
25
|
+
*
|
|
26
|
+
* The response body is generated by the supplied response function.
|
|
27
|
+
*
|
|
28
|
+
* Available options:
|
|
29
|
+
* - status: the status code to return (default: 200)
|
|
30
|
+
* - headers: the headers to return (default: {})
|
|
31
|
+
* - body: the body to match against for the request (default: null)
|
|
32
|
+
* - RECORD: whether to record the request (default: false)
|
|
33
|
+
*
|
|
34
|
+
* @param url the url to mock, relative to the mock server host (e.g. `users/1`)
|
|
35
|
+
* @param response a function which generates the response to return
|
|
36
|
+
* @param options status, headers for the response, body to match against for the request, and whether to record the request
|
|
37
|
+
* @return
|
|
38
|
+
*/
|
|
39
|
+
declare function GET(owner: object, url: string, response: ResponseGenerator, options?: Partial<Omit<Scaffold, "response" | "url" | "method">> & {
|
|
40
|
+
RECORD?: boolean;
|
|
41
|
+
}): Promise<void>;
|
|
42
|
+
/**
|
|
43
|
+
* Mock a POST request
|
|
44
|
+
*/
|
|
45
|
+
declare function POST(owner: object, url: string, response: ResponseGenerator, options?: Partial<Omit<Scaffold, "response" | "url" | "method">> & {
|
|
46
|
+
RECORD?: boolean;
|
|
47
|
+
}): Promise<void>;
|
|
48
|
+
/**
|
|
49
|
+
* mock a PUT request
|
|
50
|
+
*/
|
|
51
|
+
declare function PUT(owner: object, url: string, response: ResponseGenerator, options?: Partial<Omit<Scaffold, "response" | "url" | "method">> & {
|
|
52
|
+
RECORD?: boolean;
|
|
53
|
+
}): Promise<void>;
|
|
54
|
+
/**
|
|
55
|
+
* mock a PATCH request
|
|
56
|
+
*
|
|
57
|
+
*/
|
|
58
|
+
declare function PATCH(owner: object, url: string, response: ResponseGenerator, options?: Partial<Omit<Scaffold, "response" | "url" | "method">> & {
|
|
59
|
+
RECORD?: boolean;
|
|
60
|
+
}): Promise<void>;
|
|
61
|
+
/**
|
|
62
|
+
* mock a DELETE request
|
|
63
|
+
*/
|
|
64
|
+
declare function DELETE(owner: object, url: string, response: ResponseGenerator, options?: Partial<Omit<Scaffold, "response" | "url" | "method">> & {
|
|
65
|
+
RECORD?: boolean;
|
|
66
|
+
}): Promise<void>;
|
|
67
|
+
/**
|
|
68
|
+
* Sets up Mocking for a HEAD request on the mock server
|
|
69
|
+
* for the supplied url.
|
|
70
|
+
*
|
|
71
|
+
* The response body is generated by the supplied response function.
|
|
72
|
+
*
|
|
73
|
+
* Available options:
|
|
74
|
+
* - status: the status code to return (default: 200)
|
|
75
|
+
* - headers: the headers to return (default: {})
|
|
76
|
+
* - body: the body to match against for the request (default: null)
|
|
77
|
+
* - RECORD: whether to record the request (default: false)
|
|
78
|
+
*
|
|
79
|
+
* @param url the url to mock, relative to the mock server host (e.g. `users/1`)
|
|
80
|
+
* @param response a function which generates the response to return
|
|
81
|
+
* @param options status, headers for the response, body to match against for the request, and whether to record the request
|
|
82
|
+
* @return
|
|
83
|
+
*/
|
|
84
|
+
declare function HEAD(owner: object, url: string, response: ResponseGenerator, options?: Partial<Omit<Scaffold, "response" | "url" | "method">> & {
|
|
85
|
+
RECORD?: boolean;
|
|
86
|
+
}): Promise<void>;
|
|
87
|
+
//#endregion
|
|
88
|
+
export { DELETE, GET, HEAD, PATCH, POST, PUT, ResponseGenerator, Scaffold, ScaffoldGenerator };
|
|
89
|
+
//# sourceMappingURL=mock.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock.d.ts","names":[],"sources":["../src/mock.ts"],"mappings":";;;;UAKiB;EACf;EACA;EACA,SAAS;EACT,MAAM;EACN;EACA;EACA,UAAU;;;;;KAMA,0BAA0B;;;;KAK1B,0BAA0B;;;;;;;;;;;;;;;;;;iBAmBtB,IACd,eACA,aACA,UAAU,mBACV,UAAU,QAAQ,KAAK;EAA8C;IACpE;;;;iBAmFa,KACd,eACA,aACA,UAAU,mBACV,UAAU,QAAQ,KAAK;EAA8C;IACpE;;;;iBAwBa,IACd,eACA,aACA,UAAU,mBACV,UAAU,QAAQ,KAAK;EAA8C;IACpE;;;;;iBAwBa,MACd,eACA,aACA,UAAU,mBACV,UAAU,QAAQ,KAAK;EAA8C;IACpE;;;;iBAuBa,OACd,eACA,aACA,UAAU,mBACV,UAAU,QAAQ,KAAK;EAA8C;IACpE;;;;;;;;;;;;;;;;;;iBAsCa,KACd,eACA,aACA,UAAU,mBAIV,UAAU,QAAQ,KAAK;EAA8C;IACpE"}
|
package/dist/mock.js
CHANGED
|
@@ -1,120 +1,199 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getIsRecording, mock } from "./index.js";
|
|
2
2
|
|
|
3
|
+
//#region src/mock.ts
|
|
3
4
|
/**
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
*
|
|
21
|
-
* Available options:
|
|
22
|
-
* - status: the status code to return (default: 200)
|
|
23
|
-
* - headers: the headers to return (default: {})
|
|
24
|
-
* - body: the body to match against for the request (default: null)
|
|
25
|
-
* - RECORD: whether to record the request (default: false)
|
|
26
|
-
*
|
|
27
|
-
* @param url the url to mock, relative to the mock server host (e.g. `users/1`)
|
|
28
|
-
* @param response a function which generates the response to return
|
|
29
|
-
* @param options status, headers for the response, body to match against for the request, and whether to record the request
|
|
30
|
-
* @return
|
|
31
|
-
*/
|
|
5
|
+
* Sets up Mocking for a GET request on the mock server
|
|
6
|
+
* for the supplied url.
|
|
7
|
+
*
|
|
8
|
+
* The response body is generated by the supplied response function.
|
|
9
|
+
*
|
|
10
|
+
* Available options:
|
|
11
|
+
* - status: the status code to return (default: 200)
|
|
12
|
+
* - headers: the headers to return (default: {})
|
|
13
|
+
* - body: the body to match against for the request (default: null)
|
|
14
|
+
* - RECORD: whether to record the request (default: false)
|
|
15
|
+
*
|
|
16
|
+
* @param url the url to mock, relative to the mock server host (e.g. `users/1`)
|
|
17
|
+
* @param response a function which generates the response to return
|
|
18
|
+
* @param options status, headers for the response, body to match against for the request, and whether to record the request
|
|
19
|
+
* @return
|
|
20
|
+
*/
|
|
32
21
|
function GET(owner, url, response, options) {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
22
|
+
return mock(owner, () => ({
|
|
23
|
+
status: options?.status ?? 200,
|
|
24
|
+
statusText: options?.statusText ?? "OK",
|
|
25
|
+
headers: options?.headers ?? {},
|
|
26
|
+
body: options?.body ?? null,
|
|
27
|
+
method: "GET",
|
|
28
|
+
url,
|
|
29
|
+
response: response()
|
|
30
|
+
}), getIsRecording() || (options?.RECORD ?? false));
|
|
42
31
|
}
|
|
43
|
-
const STATUS_TEXT_FOR = new Map([
|
|
44
|
-
|
|
32
|
+
const STATUS_TEXT_FOR = /* @__PURE__ */ new Map([
|
|
33
|
+
[200, "OK"],
|
|
34
|
+
[201, "Created"],
|
|
35
|
+
[202, "Accepted"],
|
|
36
|
+
[203, "Non-Authoritative Information"],
|
|
37
|
+
[204, "No Content"],
|
|
38
|
+
[205, "Reset Content"],
|
|
39
|
+
[206, "Partial Content"],
|
|
40
|
+
[207, "Multi-Status"],
|
|
41
|
+
[208, "Already Reported"],
|
|
42
|
+
[226, "IM Used"],
|
|
43
|
+
[300, "Multiple Choices"],
|
|
44
|
+
[301, "Moved Permanently"],
|
|
45
|
+
[302, "Found"],
|
|
46
|
+
[303, "See Other"],
|
|
47
|
+
[304, "Not Modified"],
|
|
48
|
+
[307, "Temporary Redirect"],
|
|
49
|
+
[308, "Permanent Redirect"],
|
|
50
|
+
[400, "Bad Request"],
|
|
51
|
+
[401, "Unauthorized"],
|
|
52
|
+
[402, "Payment Required"],
|
|
53
|
+
[403, "Forbidden"],
|
|
54
|
+
[404, "Not Found"],
|
|
55
|
+
[405, "Method Not Allowed"],
|
|
56
|
+
[406, "Not Acceptable"],
|
|
57
|
+
[407, "Proxy Authentication Required"],
|
|
58
|
+
[408, "Request Timeout"],
|
|
59
|
+
[409, "Conflict"],
|
|
60
|
+
[410, "Gone"],
|
|
61
|
+
[411, "Length Required"],
|
|
62
|
+
[412, "Precondition Failed"],
|
|
63
|
+
[413, "Payload Too Large"],
|
|
64
|
+
[414, "URI Too Long"],
|
|
65
|
+
[415, "Unsupported Media Type"],
|
|
66
|
+
[416, "Range Not Satisfiable"],
|
|
67
|
+
[417, "Expectation Failed"],
|
|
68
|
+
[419, "Page Expired"],
|
|
69
|
+
[420, "Enhance Your Calm"],
|
|
70
|
+
[421, "Misdirected Request"],
|
|
71
|
+
[422, "Unprocessable Entity"],
|
|
72
|
+
[423, "Locked"],
|
|
73
|
+
[424, "Failed Dependency"],
|
|
74
|
+
[425, "Too Early"],
|
|
75
|
+
[426, "Upgrade Required"],
|
|
76
|
+
[428, "Precondition Required"],
|
|
77
|
+
[429, "Too Many Requests"],
|
|
78
|
+
[430, "Request Header Fields Too Large"],
|
|
79
|
+
[431, "Request Header Fields Too Large"],
|
|
80
|
+
[450, "Blocked By Windows Parental Controls"],
|
|
81
|
+
[451, "Unavailable For Legal Reasons"],
|
|
82
|
+
[500, "Internal Server Error"],
|
|
83
|
+
[501, "Not Implemented"],
|
|
84
|
+
[502, "Bad Gateway"],
|
|
85
|
+
[503, "Service Unavailable"],
|
|
86
|
+
[504, "Gateway Timeout"],
|
|
87
|
+
[505, "HTTP Version Not Supported"],
|
|
88
|
+
[506, "Variant Also Negotiates"],
|
|
89
|
+
[507, "Insufficient Storage"],
|
|
90
|
+
[508, "Loop Detected"],
|
|
91
|
+
[509, "Bandwidth Limit Exceeded"],
|
|
92
|
+
[510, "Not Extended"],
|
|
93
|
+
[511, "Network Authentication Required"]
|
|
94
|
+
]);
|
|
45
95
|
/**
|
|
46
|
-
|
|
47
|
-
|
|
96
|
+
* Mock a POST request
|
|
97
|
+
*/
|
|
48
98
|
function POST(owner, url, response, options) {
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
99
|
+
return mock(owner, () => {
|
|
100
|
+
const body = response();
|
|
101
|
+
const status = options?.status ?? (body ? 201 : 204);
|
|
102
|
+
return {
|
|
103
|
+
status,
|
|
104
|
+
statusText: options?.statusText ?? STATUS_TEXT_FOR.get(status) ?? "",
|
|
105
|
+
headers: options?.headers ?? {},
|
|
106
|
+
body: options?.body ?? null,
|
|
107
|
+
method: "POST",
|
|
108
|
+
url,
|
|
109
|
+
response: body
|
|
110
|
+
};
|
|
111
|
+
}, getIsRecording() || (options?.RECORD ?? false));
|
|
62
112
|
}
|
|
63
|
-
|
|
64
113
|
/**
|
|
65
|
-
|
|
66
|
-
|
|
114
|
+
* mock a PUT request
|
|
115
|
+
*/
|
|
67
116
|
function PUT(owner, url, response, options) {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
117
|
+
return mock(owner, () => {
|
|
118
|
+
const body = response();
|
|
119
|
+
const status = options?.status ?? (body ? 200 : 204);
|
|
120
|
+
return {
|
|
121
|
+
status,
|
|
122
|
+
statusText: options?.statusText ?? STATUS_TEXT_FOR.get(status) ?? "",
|
|
123
|
+
headers: options?.headers ?? {},
|
|
124
|
+
body: options?.body ?? null,
|
|
125
|
+
method: "PUT",
|
|
126
|
+
url,
|
|
127
|
+
response: body
|
|
128
|
+
};
|
|
129
|
+
}, getIsRecording() || (options?.RECORD ?? false));
|
|
81
130
|
}
|
|
82
131
|
/**
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
132
|
+
* mock a PATCH request
|
|
133
|
+
*
|
|
134
|
+
*/
|
|
86
135
|
function PATCH(owner, url, response, options) {
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
136
|
+
return mock(owner, () => {
|
|
137
|
+
const body = response();
|
|
138
|
+
const status = options?.status ?? (body ? 200 : 204);
|
|
139
|
+
return {
|
|
140
|
+
status,
|
|
141
|
+
statusText: options?.statusText ?? STATUS_TEXT_FOR.get(status) ?? "",
|
|
142
|
+
headers: options?.headers ?? {},
|
|
143
|
+
body: options?.body ?? null,
|
|
144
|
+
method: "PATCH",
|
|
145
|
+
url,
|
|
146
|
+
response: body
|
|
147
|
+
};
|
|
148
|
+
}, getIsRecording() || (options?.RECORD ?? false));
|
|
100
149
|
}
|
|
101
150
|
/**
|
|
102
|
-
|
|
103
|
-
|
|
151
|
+
* mock a DELETE request
|
|
152
|
+
*/
|
|
104
153
|
function DELETE(owner, url, response, options) {
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
154
|
+
return mock(owner, () => {
|
|
155
|
+
const body = response();
|
|
156
|
+
const status = options?.status ?? (body ? 200 : 204);
|
|
157
|
+
return {
|
|
158
|
+
status,
|
|
159
|
+
statusText: options?.statusText ?? STATUS_TEXT_FOR.get(status) ?? "",
|
|
160
|
+
headers: options?.headers ?? {},
|
|
161
|
+
body: options?.body ?? null,
|
|
162
|
+
method: "DELETE",
|
|
163
|
+
url,
|
|
164
|
+
response: body
|
|
165
|
+
};
|
|
166
|
+
}, getIsRecording() || (options?.RECORD ?? false));
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* Sets up Mocking for a HEAD request on the mock server
|
|
170
|
+
* for the supplied url.
|
|
171
|
+
*
|
|
172
|
+
* The response body is generated by the supplied response function.
|
|
173
|
+
*
|
|
174
|
+
* Available options:
|
|
175
|
+
* - status: the status code to return (default: 200)
|
|
176
|
+
* - headers: the headers to return (default: {})
|
|
177
|
+
* - body: the body to match against for the request (default: null)
|
|
178
|
+
* - RECORD: whether to record the request (default: false)
|
|
179
|
+
*
|
|
180
|
+
* @param url the url to mock, relative to the mock server host (e.g. `users/1`)
|
|
181
|
+
* @param response a function which generates the response to return
|
|
182
|
+
* @param options status, headers for the response, body to match against for the request, and whether to record the request
|
|
183
|
+
* @return
|
|
184
|
+
*/
|
|
185
|
+
function HEAD(owner, url, response, options) {
|
|
186
|
+
return mock(owner, () => ({
|
|
187
|
+
status: options?.status ?? 200,
|
|
188
|
+
statusText: options?.statusText ?? "OK",
|
|
189
|
+
headers: options?.headers ?? {},
|
|
190
|
+
body: options?.body ?? null,
|
|
191
|
+
method: "HEAD",
|
|
192
|
+
url,
|
|
193
|
+
response: response()
|
|
194
|
+
}), getIsRecording() || (options?.RECORD ?? false));
|
|
118
195
|
}
|
|
119
196
|
|
|
120
|
-
|
|
197
|
+
//#endregion
|
|
198
|
+
export { DELETE, GET, HEAD, PATCH, POST, PUT };
|
|
199
|
+
//# sourceMappingURL=mock.js.map
|
package/dist/mock.js.map
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock.js","names":[],"sources":["../src/mock.ts"],"sourcesContent":["import { getIsRecording, mock } from '.';\n\n/**\n * @public\n */\nexport interface Scaffold {\n status: number;\n statusText?: string;\n headers: Record<string, string>;\n body: Record<string, string> | string | null;\n method: string;\n url: string;\n response: Record<string, unknown>;\n}\n\n/**\n * @public\n */\nexport type ScaffoldGenerator = () => Scaffold;\n\n/**\n * @public\n */\nexport type ResponseGenerator = () => Record<string, unknown>;\n\n/**\n * Sets up Mocking for a GET request on the mock server\n * for the supplied url.\n *\n * The response body is generated by the supplied response function.\n *\n * Available options:\n * - status: the status code to return (default: 200)\n * - headers: the headers to return (default: {})\n * - body: the body to match against for the request (default: null)\n * - RECORD: whether to record the request (default: false)\n *\n * @param url the url to mock, relative to the mock server host (e.g. `users/1`)\n * @param response a function which generates the response to return\n * @param options status, headers for the response, body to match against for the request, and whether to record the request\n * @return\n */\nexport function GET(\n owner: object,\n url: string,\n response: ResponseGenerator,\n options?: Partial<Omit<Scaffold, 'response' | 'url' | 'method'>> & { RECORD?: boolean }\n): Promise<void> {\n return mock(\n owner,\n () => ({\n status: options?.status ?? 200,\n statusText: options?.statusText ?? 'OK',\n headers: options?.headers ?? {},\n body: options?.body ?? null,\n method: 'GET',\n url,\n response: response(),\n }),\n getIsRecording() || (options?.RECORD ?? false)\n );\n}\n\nconst STATUS_TEXT_FOR = new Map([\n [200, 'OK'],\n [201, 'Created'],\n [202, 'Accepted'],\n [203, 'Non-Authoritative Information'],\n [204, 'No Content'],\n [205, 'Reset Content'],\n [206, 'Partial Content'],\n [207, 'Multi-Status'],\n [208, 'Already Reported'],\n [226, 'IM Used'],\n [300, 'Multiple Choices'],\n [301, 'Moved Permanently'],\n [302, 'Found'],\n [303, 'See Other'],\n [304, 'Not Modified'],\n [307, 'Temporary Redirect'],\n [308, 'Permanent Redirect'],\n [400, 'Bad Request'],\n [401, 'Unauthorized'],\n [402, 'Payment Required'],\n [403, 'Forbidden'],\n [404, 'Not Found'],\n [405, 'Method Not Allowed'],\n [406, 'Not Acceptable'],\n [407, 'Proxy Authentication Required'],\n [408, 'Request Timeout'],\n [409, 'Conflict'],\n [410, 'Gone'],\n [411, 'Length Required'],\n [412, 'Precondition Failed'],\n [413, 'Payload Too Large'],\n [414, 'URI Too Long'],\n [415, 'Unsupported Media Type'],\n [416, 'Range Not Satisfiable'],\n [417, 'Expectation Failed'],\n [419, 'Page Expired'],\n [420, 'Enhance Your Calm'],\n [421, 'Misdirected Request'],\n [422, 'Unprocessable Entity'],\n [423, 'Locked'],\n [424, 'Failed Dependency'],\n [425, 'Too Early'],\n [426, 'Upgrade Required'],\n [428, 'Precondition Required'],\n [429, 'Too Many Requests'],\n [430, 'Request Header Fields Too Large'],\n [431, 'Request Header Fields Too Large'],\n [450, 'Blocked By Windows Parental Controls'],\n [451, 'Unavailable For Legal Reasons'],\n [500, 'Internal Server Error'],\n [501, 'Not Implemented'],\n [502, 'Bad Gateway'],\n [503, 'Service Unavailable'],\n [504, 'Gateway Timeout'],\n [505, 'HTTP Version Not Supported'],\n [506, 'Variant Also Negotiates'],\n [507, 'Insufficient Storage'],\n [508, 'Loop Detected'],\n [509, 'Bandwidth Limit Exceeded'],\n [510, 'Not Extended'],\n [511, 'Network Authentication Required'],\n]);\n\n/**\n * Mock a POST request\n */\nexport function POST(\n owner: object,\n url: string,\n response: ResponseGenerator,\n options?: Partial<Omit<Scaffold, 'response' | 'url' | 'method'>> & { RECORD?: boolean }\n): Promise<void> {\n return mock(\n owner,\n () => {\n const body = response();\n const status = options?.status ?? (body ? 201 : 204);\n\n return {\n status: status,\n statusText: options?.statusText ?? STATUS_TEXT_FOR.get(status) ?? '',\n headers: options?.headers ?? {},\n body: options?.body ?? null,\n method: 'POST',\n url,\n response: body,\n };\n },\n getIsRecording() || (options?.RECORD ?? false)\n );\n}\n\n/**\n * mock a PUT request\n */\nexport function PUT(\n owner: object,\n url: string,\n response: ResponseGenerator,\n options?: Partial<Omit<Scaffold, 'response' | 'url' | 'method'>> & { RECORD?: boolean }\n): Promise<void> {\n return mock(\n owner,\n () => {\n const body = response();\n const status = options?.status ?? (body ? 200 : 204);\n\n return {\n status: status,\n statusText: options?.statusText ?? STATUS_TEXT_FOR.get(status) ?? '',\n headers: options?.headers ?? {},\n body: options?.body ?? null,\n method: 'PUT',\n url,\n response: body,\n };\n },\n getIsRecording() || (options?.RECORD ?? false)\n );\n}\n/**\n * mock a PATCH request\n *\n */\nexport function PATCH(\n owner: object,\n url: string,\n response: ResponseGenerator,\n options?: Partial<Omit<Scaffold, 'response' | 'url' | 'method'>> & { RECORD?: boolean }\n): Promise<void> {\n return mock(\n owner,\n () => {\n const body = response();\n const status = options?.status ?? (body ? 200 : 204);\n\n return {\n status: status,\n statusText: options?.statusText ?? STATUS_TEXT_FOR.get(status) ?? '',\n headers: options?.headers ?? {},\n body: options?.body ?? null,\n method: 'PATCH',\n url,\n response: body,\n };\n },\n getIsRecording() || (options?.RECORD ?? false)\n );\n}\n/**\n * mock a DELETE request\n */\nexport function DELETE(\n owner: object,\n url: string,\n response: ResponseGenerator,\n options?: Partial<Omit<Scaffold, 'response' | 'url' | 'method'>> & { RECORD?: boolean }\n): Promise<void> {\n return mock(\n owner,\n () => {\n const body = response();\n const status = options?.status ?? (body ? 200 : 204);\n\n return {\n status: status,\n statusText: options?.statusText ?? STATUS_TEXT_FOR.get(status) ?? '',\n headers: options?.headers ?? {},\n body: options?.body ?? null,\n method: 'DELETE',\n url,\n response: body,\n };\n },\n getIsRecording() || (options?.RECORD ?? false)\n );\n}\n\n/**\n * Sets up Mocking for a HEAD request on the mock server\n * for the supplied url.\n *\n * The response body is generated by the supplied response function.\n *\n * Available options:\n * - status: the status code to return (default: 200)\n * - headers: the headers to return (default: {})\n * - body: the body to match against for the request (default: null)\n * - RECORD: whether to record the request (default: false)\n *\n * @param url the url to mock, relative to the mock server host (e.g. `users/1`)\n * @param response a function which generates the response to return\n * @param options status, headers for the response, body to match against for the request, and whether to record the request\n * @return\n */\nexport function HEAD(\n owner: object,\n url: string,\n response: ResponseGenerator,\n // TODO: should we omit the `body` as well?\n // It does _seem_ possible for HEAD requests to have a body, but it should be ignored.\n // From MDN: Warning: If a response to a HEAD request has a body, the response body must be ignored.\n options?: Partial<Omit<Scaffold, 'response' | 'url' | 'method'>> & { RECORD?: boolean }\n): Promise<void> {\n return mock(\n owner,\n () => ({\n status: options?.status ?? 200,\n statusText: options?.statusText ?? 'OK',\n headers: options?.headers ?? {},\n body: options?.body ?? null,\n method: 'HEAD',\n url,\n response: response(),\n }),\n getIsRecording() || (options?.RECORD ?? false)\n );\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@warp-drive/holodeck",
|
|
3
3
|
"description": "⚡️ Simple, Fast HTTP Mocking for Tests",
|
|
4
|
-
"version": "0.1.0-beta.
|
|
4
|
+
"version": "0.1.0-beta.2",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Chris Thoburn <runspired@users.noreply.github.com>",
|
|
7
7
|
"repository": {
|
|
@@ -12,17 +12,13 @@
|
|
|
12
12
|
"homepage": "https://github.com/warp-drive-data/warp-drive",
|
|
13
13
|
"bugs": "https://github.com/warp-drive-data/warp-drive/issues",
|
|
14
14
|
"engines": {
|
|
15
|
-
"node": ">=
|
|
15
|
+
"node": ">= 24.20.0"
|
|
16
16
|
},
|
|
17
17
|
"keywords": [
|
|
18
18
|
"http-mock"
|
|
19
19
|
],
|
|
20
|
-
"volta": {
|
|
21
|
-
"extends": "../../package.json"
|
|
22
|
-
},
|
|
23
20
|
"dependencies": {
|
|
24
|
-
"
|
|
25
|
-
"hono": "^4.9.4",
|
|
21
|
+
"hono": "^4.13.5",
|
|
26
22
|
"@hono/node-server": "^1.19.0"
|
|
27
23
|
},
|
|
28
24
|
"type": "module",
|
|
@@ -32,16 +28,15 @@
|
|
|
32
28
|
"README.md",
|
|
33
29
|
"LICENSE.md",
|
|
34
30
|
"server",
|
|
35
|
-
"declarations",
|
|
36
31
|
"logos"
|
|
37
32
|
],
|
|
38
33
|
"bin": {
|
|
39
34
|
"ensure-cert": "./server/ensure-cert.js"
|
|
40
35
|
},
|
|
41
36
|
"peerDependencies": {
|
|
42
|
-
"@warp-drive/utilities": "5.9.0-beta.
|
|
43
|
-
"@warp-drive/legacy": "5.9.0-beta.
|
|
44
|
-
"@warp-drive/core": "5.9.0-beta.
|
|
37
|
+
"@warp-drive/utilities": "5.9.0-beta.2",
|
|
38
|
+
"@warp-drive/legacy": "5.9.0-beta.2",
|
|
39
|
+
"@warp-drive/core": "5.9.0-beta.2"
|
|
45
40
|
},
|
|
46
41
|
"peerDependenciesMeta": {
|
|
47
42
|
"@warp-drive/utilities": {
|
|
@@ -52,16 +47,17 @@
|
|
|
52
47
|
}
|
|
53
48
|
},
|
|
54
49
|
"devDependencies": {
|
|
55
|
-
"@babel/core": "^7.
|
|
56
|
-
"@babel/plugin-transform-typescript": "^7.
|
|
57
|
-
"@babel/preset-env": "^7.
|
|
58
|
-
"@babel/preset-typescript": "^7.
|
|
59
|
-
"@babel/runtime": "^7.
|
|
60
|
-
"@warp-drive/utilities": "5.9.0-beta.
|
|
61
|
-
"@warp-drive/legacy": "5.9.0-beta.
|
|
62
|
-
"@warp-drive/core": "5.9.0-beta.
|
|
63
|
-
"@warp-drive/internal-config": "5.9.0-beta.
|
|
64
|
-
"
|
|
50
|
+
"@babel/core": "^7.29.7",
|
|
51
|
+
"@babel/plugin-transform-typescript": "^7.29.7",
|
|
52
|
+
"@babel/preset-env": "^7.29.7",
|
|
53
|
+
"@babel/preset-typescript": "^7.29.7",
|
|
54
|
+
"@babel/runtime": "^7.29.7",
|
|
55
|
+
"@warp-drive/utilities": "5.9.0-beta.2",
|
|
56
|
+
"@warp-drive/legacy": "5.9.0-beta.2",
|
|
57
|
+
"@warp-drive/core": "5.9.0-beta.2",
|
|
58
|
+
"@warp-drive/internal-config": "5.9.0-beta.2",
|
|
59
|
+
"tsdown": "^0.22.14",
|
|
60
|
+
"typescript-7": "npm:typescript@7.1.0-dev.20260828.1"
|
|
65
61
|
},
|
|
66
62
|
"exports": {
|
|
67
63
|
".": {
|
|
@@ -69,25 +65,24 @@
|
|
|
69
65
|
"bun": "./server/index.js",
|
|
70
66
|
"deno": "./server/index.js",
|
|
71
67
|
"browser": {
|
|
72
|
-
"types": "./
|
|
68
|
+
"types": "./dist/index.d.ts",
|
|
73
69
|
"default": "./dist/index.js"
|
|
74
70
|
},
|
|
75
71
|
"import": {
|
|
76
|
-
"types": "./
|
|
72
|
+
"types": "./dist/index.d.ts",
|
|
77
73
|
"default": "./dist/index.js"
|
|
78
74
|
},
|
|
79
75
|
"default": "./server/index.js"
|
|
80
76
|
},
|
|
81
77
|
"./mock": {
|
|
82
|
-
"types": "./
|
|
78
|
+
"types": "./dist/mock.d.ts",
|
|
83
79
|
"default": "./dist/mock.js"
|
|
84
80
|
}
|
|
85
81
|
},
|
|
86
82
|
"scripts": {
|
|
87
|
-
"check:
|
|
88
|
-
"build:pkg": "
|
|
83
|
+
"check:types": "node ./node_modules/typescript-7/bin/tsc --noEmit",
|
|
84
|
+
"build:pkg": "node node_modules/tsdown/dist/run.mjs",
|
|
89
85
|
"sync": "echo \"syncing\"",
|
|
90
|
-
"
|
|
91
|
-
"start": "vite"
|
|
86
|
+
"start": "node node_modules/tsdown/dist/run.mjs --watch"
|
|
92
87
|
}
|
|
93
88
|
}
|
package/server/bun.js
CHANGED
|
@@ -1,13 +1,15 @@
|
|
|
1
|
-
import chalk from 'chalk';
|
|
2
1
|
import { Hono } from 'hono';
|
|
3
|
-
import { createSecureServer } from 'node:http2';
|
|
4
|
-
import { logger } from 'hono/logger';
|
|
5
|
-
import { HTTPException } from 'hono/http-exception';
|
|
6
2
|
import { cors } from 'hono/cors';
|
|
3
|
+
import { HTTPException } from 'hono/http-exception';
|
|
4
|
+
import { logger } from 'hono/logger';
|
|
7
5
|
import fs from 'node:fs';
|
|
8
|
-
import
|
|
6
|
+
import { createSecureServer } from 'node:http2';
|
|
7
|
+
import { styleText } from 'node:util';
|
|
9
8
|
import { Worker, threadId, parentPort } from 'node:worker_threads';
|
|
9
|
+
import path from 'path';
|
|
10
|
+
|
|
10
11
|
import {
|
|
12
|
+
bindWithRetry,
|
|
11
13
|
compress,
|
|
12
14
|
createCloseHandler,
|
|
13
15
|
DEFAULT_PORT,
|
|
@@ -307,18 +309,20 @@ async function _createServer(options) {
|
|
|
307
309
|
hostname: options.hostname ?? 'localhost',
|
|
308
310
|
};
|
|
309
311
|
|
|
310
|
-
const server =
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
312
|
+
const server = await bindWithRetry(() =>
|
|
313
|
+
Bun.serve({
|
|
314
|
+
fetch: app.fetch,
|
|
315
|
+
tls: {
|
|
316
|
+
key: KEY,
|
|
317
|
+
cert: CERT,
|
|
318
|
+
},
|
|
319
|
+
port: location.port,
|
|
320
|
+
hostname: location.hostname,
|
|
321
|
+
})
|
|
322
|
+
);
|
|
319
323
|
|
|
320
324
|
console.log(
|
|
321
|
-
`\tServing Holodeck HTTP Mocks from ${
|
|
325
|
+
`\tServing Holodeck HTTP Mocks from ${styleText('yellow', 'https://') + styleText('magenta', location.hostname + ':') + styleText('yellow', String(location.port))}\n`
|
|
322
326
|
);
|
|
323
327
|
|
|
324
328
|
if (typeof threadId === 'number' && threadId !== 0) {
|
|
@@ -357,25 +361,29 @@ export async function launchProgram(config = {}) {
|
|
|
357
361
|
}
|
|
358
362
|
const options = { name, projectRoot, ...config };
|
|
359
363
|
console.log(
|
|
360
|
-
|
|
361
|
-
|
|
364
|
+
styleText(
|
|
365
|
+
'grey',
|
|
366
|
+
`\n\t@${styleText('greenBright', 'warp-drive')}/${styleText(
|
|
367
|
+
'magentaBright',
|
|
362
368
|
'holodeck'
|
|
363
369
|
)} 🌅\n\t=================================\n`
|
|
364
370
|
) +
|
|
365
|
-
|
|
366
|
-
|
|
371
|
+
styleText(
|
|
372
|
+
'grey',
|
|
373
|
+
`\n\tHolodeck Access Granted\n\t\tprogram: ${styleText('magenta', name)}\n\t\tsettings: ${styleText(
|
|
374
|
+
'green',
|
|
367
375
|
JSON.stringify(config).split('\n').join(' ')
|
|
368
|
-
)}\n\t\tdirectory: ${
|
|
376
|
+
)}\n\t\tdirectory: ${styleText('cyan', projectRoot)}\n\t\tengine: ${styleText('cyan', 'bun')}@${styleText('yellow', Bun.version)}\n`
|
|
369
377
|
)
|
|
370
378
|
);
|
|
371
|
-
console.log(
|
|
379
|
+
console.log(styleText('grey', `\n\tStarting Holodeck Subroutines`));
|
|
372
380
|
|
|
373
381
|
const project = await createServer(options);
|
|
374
382
|
|
|
375
383
|
async function shutdown() {
|
|
376
|
-
console.log(
|
|
384
|
+
console.log(styleText('grey', `\n\tEnding Holodeck Subroutines`));
|
|
377
385
|
project.close();
|
|
378
|
-
console.log(
|
|
386
|
+
console.log(styleText('grey', `\n\tHolodeck program ended`));
|
|
379
387
|
}
|
|
380
388
|
|
|
381
389
|
const endProgram = createCloseHandler(shutdown);
|