@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/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 { mock, getIsRecording } from './index.js';
1
+ import { getIsRecording, mock } from "./index.js";
2
2
 
3
+ //#region src/mock.ts
3
4
  /**
4
- * @public
5
- */
6
-
7
- /**
8
- * @public
9
- */
10
-
11
- /**
12
- * @public
13
- */
14
-
15
- /**
16
- * Sets up Mocking for a GET request on the mock server
17
- * for the supplied url.
18
- *
19
- * The response body is generated by the supplied response function.
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
- return mock(owner, () => ({
34
- status: options?.status ?? 200,
35
- statusText: options?.statusText ?? 'OK',
36
- headers: options?.headers ?? {},
37
- body: options?.body ?? null,
38
- method: 'GET',
39
- url,
40
- response: response()
41
- }), getIsRecording() || (options?.RECORD ?? false));
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([[200, 'OK'], [201, 'Created'], [202, 'Accepted'], [203, 'Non-Authoritative Information'], [204, 'No Content'], [205, 'Reset Content'], [206, 'Partial Content'], [207, 'Multi-Status'], [208, 'Already Reported'], [226, 'IM Used'], [300, 'Multiple Choices'], [301, 'Moved Permanently'], [302, 'Found'], [303, 'See Other'], [304, 'Not Modified'], [307, 'Temporary Redirect'], [308, 'Permanent Redirect'], [400, 'Bad Request'], [401, 'Unauthorized'], [402, 'Payment Required'], [403, 'Forbidden'], [404, 'Not Found'], [405, 'Method Not Allowed'], [406, 'Not Acceptable'], [407, 'Proxy Authentication Required'], [408, 'Request Timeout'], [409, 'Conflict'], [410, 'Gone'], [411, 'Length Required'], [412, 'Precondition Failed'], [413, 'Payload Too Large'], [414, 'URI Too Long'], [415, 'Unsupported Media Type'], [416, 'Range Not Satisfiable'], [417, 'Expectation Failed'], [419, 'Page Expired'], [420, 'Enhance Your Calm'], [421, 'Misdirected Request'], [422, 'Unprocessable Entity'], [423, 'Locked'], [424, 'Failed Dependency'], [425, 'Too Early'], [426, 'Upgrade Required'], [428, 'Precondition Required'], [429, 'Too Many Requests'], [430, 'Request Header Fields Too Large'], [431, 'Request Header Fields Too Large'], [450, 'Blocked By Windows Parental Controls'], [451, 'Unavailable For Legal Reasons'], [500, 'Internal Server Error'], [501, 'Not Implemented'], [502, 'Bad Gateway'], [503, 'Service Unavailable'], [504, 'Gateway Timeout'], [505, 'HTTP Version Not Supported'], [506, 'Variant Also Negotiates'], [507, 'Insufficient Storage'], [508, 'Loop Detected'], [509, 'Bandwidth Limit Exceeded'], [510, 'Not Extended'], [511, 'Network Authentication Required']]);
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
- * Mock a POST request
47
- */
96
+ * Mock a POST request
97
+ */
48
98
  function POST(owner, url, response, options) {
49
- return mock(owner, () => {
50
- const body = response();
51
- const status = options?.status ?? (body ? 201 : 204);
52
- return {
53
- status: status,
54
- statusText: options?.statusText ?? STATUS_TEXT_FOR.get(status) ?? '',
55
- headers: options?.headers ?? {},
56
- body: options?.body ?? null,
57
- method: 'POST',
58
- url,
59
- response: body
60
- };
61
- }, getIsRecording() || (options?.RECORD ?? false));
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
- * mock a PUT request
66
- */
114
+ * mock a PUT request
115
+ */
67
116
  function PUT(owner, url, response, options) {
68
- return mock(owner, () => {
69
- const body = response();
70
- const status = options?.status ?? (body ? 200 : 204);
71
- return {
72
- status: status,
73
- statusText: options?.statusText ?? STATUS_TEXT_FOR.get(status) ?? '',
74
- headers: options?.headers ?? {},
75
- body: options?.body ?? null,
76
- method: 'PUT',
77
- url,
78
- response: body
79
- };
80
- }, getIsRecording() || (options?.RECORD ?? false));
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
- * mock a PATCH request
84
- *
85
- */
132
+ * mock a PATCH request
133
+ *
134
+ */
86
135
  function PATCH(owner, url, response, options) {
87
- return mock(owner, () => {
88
- const body = response();
89
- const status = options?.status ?? (body ? 200 : 204);
90
- return {
91
- status: status,
92
- statusText: options?.statusText ?? STATUS_TEXT_FOR.get(status) ?? '',
93
- headers: options?.headers ?? {},
94
- body: options?.body ?? null,
95
- method: 'PATCH',
96
- url,
97
- response: body
98
- };
99
- }, getIsRecording() || (options?.RECORD ?? false));
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
- * mock a DELETE request
103
- */
151
+ * mock a DELETE request
152
+ */
104
153
  function DELETE(owner, url, response, options) {
105
- return mock(owner, () => {
106
- const body = response();
107
- const status = options?.status ?? (body ? 200 : 204);
108
- return {
109
- status: status,
110
- statusText: options?.statusText ?? STATUS_TEXT_FOR.get(status) ?? '',
111
- headers: options?.headers ?? {},
112
- body: options?.body ?? null,
113
- method: 'DELETE',
114
- url,
115
- response: body
116
- };
117
- }, getIsRecording() || (options?.RECORD ?? false));
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
- export { DELETE, GET, PATCH, POST, PUT };
197
+ //#endregion
198
+ export { DELETE, GET, HEAD, PATCH, POST, PUT };
199
+ //# sourceMappingURL=mock.js.map
@@ -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.0",
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": ">= 18.20.8"
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
- "chalk": "^5.5.0",
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.0",
43
- "@warp-drive/legacy": "5.9.0-beta.0",
44
- "@warp-drive/core": "5.9.0-beta.0"
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.28.3",
56
- "@babel/plugin-transform-typescript": "^7.28.0",
57
- "@babel/preset-env": "^7.28.3",
58
- "@babel/preset-typescript": "^7.27.1",
59
- "@babel/runtime": "^7.28.3",
60
- "@warp-drive/utilities": "5.9.0-beta.0",
61
- "@warp-drive/legacy": "5.9.0-beta.0",
62
- "@warp-drive/core": "5.9.0-beta.0",
63
- "@warp-drive/internal-config": "5.9.0-beta.0",
64
- "vite": "^7.1.3"
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": "./declarations/index.d.ts",
68
+ "types": "./dist/index.d.ts",
73
69
  "default": "./dist/index.js"
74
70
  },
75
71
  "import": {
76
- "types": "./declarations/index.d.ts",
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": "./declarations/mock.d.ts",
78
+ "types": "./dist/mock.d.ts",
83
79
  "default": "./dist/mock.js"
84
80
  }
85
81
  },
86
82
  "scripts": {
87
- "check:pkg-types": "tsc --noEmit",
88
- "build:pkg": "vite build;",
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
- "_temporarily_deactivated_lint": "eslint . --quiet --cache --cache-strategy=content",
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 path from 'path';
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 = Bun.serve({
311
- fetch: app.fetch,
312
- tls: {
313
- key: KEY,
314
- cert: CERT,
315
- },
316
- port: location.port,
317
- hostname: location.hostname,
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 ${chalk.yellow('https://') + chalk.magenta(location.hostname + ':') + chalk.yellow(location.port)}\n`
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
- chalk.grey(
361
- `\n\t@${chalk.greenBright('warp-drive')}/${chalk.magentaBright(
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
- chalk.grey(
366
- `\n\tHolodeck Access Granted\n\t\tprogram: ${chalk.magenta(name)}\n\t\tsettings: ${chalk.green(
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: ${chalk.cyan(projectRoot)}\n\t\tengine: ${chalk.cyan('bun')}@${chalk.yellow(Bun.version)}\n`
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(chalk.grey(`\n\tStarting Holodeck Subroutines`));
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(chalk.grey(`\n\tEnding Holodeck Subroutines`));
384
+ console.log(styleText('grey', `\n\tEnding Holodeck Subroutines`));
377
385
  project.close();
378
- console.log(chalk.grey(`\n\tHolodeck program ended`));
386
+ console.log(styleText('grey', `\n\tHolodeck program ended`));
379
387
  }
380
388
 
381
389
  const endProgram = createCloseHandler(shutdown);