effect-start 0.16.0 → 0.17.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/dist/Commander.d.ts +103 -0
- package/dist/Commander.js +333 -0
- package/dist/ContentNegotiation.d.ts +13 -0
- package/dist/ContentNegotiation.js +364 -0
- package/dist/Development.d.ts +34 -0
- package/dist/Development.js +52 -0
- package/dist/Entity.d.ts +47 -0
- package/dist/Entity.js +224 -0
- package/dist/FileRouter.d.ts +61 -0
- package/dist/FileRouter.js +203 -0
- package/dist/FileRouterCodegen.d.ts +19 -0
- package/dist/FileRouterCodegen.js +176 -0
- package/dist/FileRouterPattern.d.ts +9 -0
- package/dist/FileRouterPattern.js +35 -0
- package/dist/Http.d.ts +37 -0
- package/dist/Http.js +92 -0
- package/dist/HttpAppExtra.d.ts +7 -0
- package/dist/HttpAppExtra.js +320 -0
- package/dist/HttpUtils.d.ts +3 -0
- package/dist/HttpUtils.js +11 -0
- package/dist/PathPattern.d.ts +134 -0
- package/dist/PathPattern.js +415 -0
- package/dist/Random.d.ts +5 -0
- package/dist/Random.js +49 -0
- package/dist/Route.d.ts +98 -0
- package/dist/Route.js +81 -0
- package/dist/RouteBody.d.ts +53 -0
- package/dist/RouteBody.js +67 -0
- package/dist/RouteHook.d.ts +12 -0
- package/dist/RouteHook.js +45 -0
- package/dist/RouteHttp.d.ts +21 -0
- package/dist/RouteHttp.js +260 -0
- package/dist/RouteHttpTracer.d.ts +10 -0
- package/dist/RouteHttpTracer.js +62 -0
- package/dist/RouteMount.d.ts +119 -0
- package/dist/RouteMount.js +77 -0
- package/dist/RouteSchema.d.ts +65 -0
- package/dist/RouteSchema.js +155 -0
- package/dist/RouteSse.d.ts +21 -0
- package/dist/RouteSse.js +85 -0
- package/dist/RouteTree.d.ts +56 -0
- package/dist/RouteTree.js +91 -0
- package/dist/RouteTrie.d.ts +20 -0
- package/dist/RouteTrie.js +157 -0
- package/dist/RouterPattern.d.ts +118 -0
- package/dist/RouterPattern.js +269 -0
- package/dist/SchemaExtra.d.ts +7 -0
- package/dist/SchemaExtra.js +74 -0
- package/dist/Start.d.ts +19 -0
- package/dist/Start.js +23 -0
- package/dist/StartApp.d.ts +19 -0
- package/dist/StartApp.js +21 -0
- package/dist/StreamExtra.d.ts +28 -0
- package/dist/StreamExtra.js +100 -0
- package/dist/TuplePathPattern.d.ts +9 -0
- package/dist/TuplePathPattern.js +63 -0
- package/dist/Values.d.ts +26 -0
- package/dist/Values.js +30 -0
- package/dist/bun/BunBundle.d.ts +12 -0
- package/dist/bun/BunBundle.js +145 -0
- package/dist/bun/BunHttpServer.d.ts +44 -0
- package/dist/bun/BunHttpServer.js +187 -0
- package/dist/bun/BunHttpServer_web.d.ts +60 -0
- package/dist/bun/BunHttpServer_web.js +252 -0
- package/dist/bun/BunImportTrackerPlugin.d.ts +13 -0
- package/dist/bun/BunImportTrackerPlugin.js +71 -0
- package/dist/bun/BunRoute.d.ts +49 -0
- package/dist/bun/BunRoute.js +131 -0
- package/dist/bun/BunRuntime.d.ts +1 -0
- package/dist/bun/BunRuntime.js +26 -0
- package/dist/bun/BunVirtualFilesPlugin.d.ts +4 -0
- package/dist/bun/BunVirtualFilesPlugin.js +40 -0
- package/dist/bun/_BunEnhancedResolve.d.ts +45 -0
- package/dist/bun/_BunEnhancedResolve.js +104 -0
- package/dist/bun/index.d.ts +4 -0
- package/dist/bun/index.js +4 -0
- package/dist/bundler/Bundle.d.ts +60 -0
- package/dist/bundler/Bundle.js +48 -0
- package/dist/bundler/BundleFiles.d.ts +13 -0
- package/dist/bundler/BundleFiles.js +94 -0
- package/dist/bundler/BundleHttp.d.ts +45 -0
- package/dist/bundler/BundleHttp.js +176 -0
- package/dist/client/Overlay.d.ts +2 -0
- package/dist/client/Overlay.js +32 -0
- package/dist/client/ScrollState.d.ts +6 -0
- package/dist/client/ScrollState.js +98 -0
- package/dist/client/index.d.ts +6 -0
- package/dist/client/index.js +81 -0
- package/dist/experimental/EncryptedCookies.d.ts +51 -0
- package/dist/experimental/EncryptedCookies.js +243 -0
- package/dist/experimental/SseHttpResponse.d.ts +7 -0
- package/dist/experimental/SseHttpResponse.js +28 -0
- package/dist/experimental/index.d.ts +2 -0
- package/dist/experimental/index.js +2 -0
- package/dist/hyper/Hyper.d.ts +32 -0
- package/dist/hyper/Hyper.js +34 -0
- package/dist/hyper/HyperHtml.d.ts +23 -0
- package/dist/hyper/HyperHtml.js +144 -0
- package/dist/hyper/HyperNode.d.ts +14 -0
- package/dist/hyper/HyperNode.js +11 -0
- package/dist/hyper/HyperRoute.d.ts +8 -0
- package/dist/hyper/HyperRoute.js +32 -0
- package/dist/hyper/HyperRoute.test.d.ts +1 -0
- package/dist/hyper/HyperRoute.test.js +72 -0
- package/dist/hyper/index.d.ts +4 -0
- package/dist/hyper/index.js +4 -0
- package/dist/hyper/jsx-runtime.d.ts +7 -0
- package/dist/hyper/jsx-runtime.js +8 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +6 -0
- package/dist/inference_check.d.ts +1 -0
- package/dist/inference_check.js +15 -0
- package/dist/middlewares/BasicAuthMiddleware.d.ts +8 -0
- package/dist/middlewares/BasicAuthMiddleware.js +22 -0
- package/dist/middlewares/index.d.ts +1 -0
- package/dist/middlewares/index.js +1 -0
- package/dist/node/FileSystem.d.ts +9 -0
- package/dist/node/FileSystem.js +440 -0
- package/dist/node/Utils.d.ts +1 -0
- package/dist/node/Utils.js +19 -0
- package/dist/repro_fail.d.ts +1 -0
- package/dist/repro_fail.js +14 -0
- package/dist/testing/TestHttpClient.d.ts +13 -0
- package/dist/testing/TestHttpClient.js +68 -0
- package/dist/testing/TestLogger.d.ts +13 -0
- package/dist/testing/TestLogger.js +29 -0
- package/dist/testing/index.d.ts +3 -0
- package/dist/testing/index.js +3 -0
- package/dist/testing/utils.d.ts +9 -0
- package/dist/testing/utils.js +39 -0
- package/dist/x/cloudflare/CloudflareTunnel.d.ts +13 -0
- package/dist/x/cloudflare/CloudflareTunnel.js +43 -0
- package/dist/x/cloudflare/index.d.ts +1 -0
- package/dist/x/cloudflare/index.js +1 -0
- package/dist/x/datastar/Datastar.d.ts +6 -0
- package/dist/x/datastar/Datastar.js +46 -0
- package/dist/x/datastar/index.d.ts +2 -0
- package/dist/x/datastar/index.js +2 -0
- package/dist/x/tailwind/TailwindPlugin.d.ts +23 -0
- package/dist/x/tailwind/TailwindPlugin.js +219 -0
- package/dist/x/tailwind/compile.d.ts +19 -0
- package/dist/x/tailwind/compile.js +156 -0
- package/dist/x/tailwind/plugin.d.ts +2 -0
- package/dist/x/tailwind/plugin.js +15 -0
- package/package.json +67 -14
- package/src/Development.test.ts +119 -0
- package/src/Development.ts +137 -0
- package/src/Entity.test.ts +1 -1
- package/src/Entity.ts +3 -6
- package/src/FileRouter.ts +2 -2
- package/src/Route.ts +4 -0
- package/src/RouteBody.test.ts +43 -45
- package/src/RouteBody.ts +137 -10
- package/src/RouteHttp.test.ts +4 -1
- package/src/RouteHttp.ts +22 -6
- package/src/RouteSse.test.ts +249 -0
- package/src/RouteSse.ts +195 -0
- package/src/Values.ts +9 -7
- package/src/bun/BunBundle.ts +0 -73
- package/src/bun/BunRoute.ts +0 -2
- package/src/hyper/HyperHtml.test.ts +119 -0
- package/src/hyper/HyperHtml.ts +10 -2
- package/src/hyper/HyperNode.ts +2 -0
- package/src/hyper/HyperRoute.test.tsx +199 -0
- package/src/hyper/HyperRoute.ts +61 -0
- package/src/hyper/index.ts +4 -0
- package/src/hyper/jsx.d.ts +15 -0
- package/src/index.ts +1 -0
- package/src/node/FileSystem.ts +8 -0
- package/src/x/tailwind/compile.ts +8 -2
- package/src/FileSystemExtra.test.ts +0 -242
- package/src/FileSystemExtra.ts +0 -66
|
@@ -0,0 +1,364 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* RFC 7231 Content Negotiation compatible with Express/Node.js ecosystem.
|
|
3
|
+
* Based on {@link https://github.com/jshttp/negotiator}
|
|
4
|
+
*/
|
|
5
|
+
const simpleMediaTypeRegExp = /^\s*([^\s\/;]+)\/([^;\s]+)\s*(?:;(.*))?$/;
|
|
6
|
+
const simpleLanguageRegExp = /^\s*([^\s\-;]+)(?:-([^\s;]+))?\s*(?:;(.*))?$/;
|
|
7
|
+
const simpleEncodingRegExp = /^\s*([^\s;]+)\s*(?:;(.*))?$/;
|
|
8
|
+
const simpleCharsetRegExp = /^\s*([^\s;]+)\s*(?:;(.*))?$/;
|
|
9
|
+
function parseQuality(params) {
|
|
10
|
+
if (!params)
|
|
11
|
+
return 1;
|
|
12
|
+
const match = params.match(/q\s*=\s*([0-9.]+)/);
|
|
13
|
+
if (!match)
|
|
14
|
+
return 1;
|
|
15
|
+
const q = parseFloat(match[1]);
|
|
16
|
+
return isNaN(q) ? 1 : Math.min(Math.max(q, 0), 1);
|
|
17
|
+
}
|
|
18
|
+
function splitMediaTypeParams(params) {
|
|
19
|
+
const result = {};
|
|
20
|
+
let q = 1;
|
|
21
|
+
const parts = params.split(";");
|
|
22
|
+
for (const part of parts) {
|
|
23
|
+
const trimmed = part.trim();
|
|
24
|
+
const eqIndex = trimmed.indexOf("=");
|
|
25
|
+
if (eqIndex === -1)
|
|
26
|
+
continue;
|
|
27
|
+
const key = trimmed.slice(0, eqIndex).trim().toLowerCase();
|
|
28
|
+
let value = trimmed.slice(eqIndex + 1).trim();
|
|
29
|
+
if (value.startsWith("\"") && value.endsWith("\"")) {
|
|
30
|
+
value = value.slice(1, -1);
|
|
31
|
+
}
|
|
32
|
+
if (key === "q") {
|
|
33
|
+
q = parseFloat(value);
|
|
34
|
+
if (isNaN(q))
|
|
35
|
+
q = 1;
|
|
36
|
+
q = Math.min(Math.max(q, 0), 1);
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
result[key] = value;
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
return { params: result, q };
|
|
43
|
+
}
|
|
44
|
+
function parseAccept(accept) {
|
|
45
|
+
const specs = [];
|
|
46
|
+
const parts = accept.split(",");
|
|
47
|
+
for (let o = 0; o < parts.length; o++) {
|
|
48
|
+
const part = parts[o].trim();
|
|
49
|
+
if (!part)
|
|
50
|
+
continue;
|
|
51
|
+
const match = simpleMediaTypeRegExp.exec(part);
|
|
52
|
+
if (!match)
|
|
53
|
+
continue;
|
|
54
|
+
const type = match[1].toLowerCase();
|
|
55
|
+
const subtype = match[2].toLowerCase();
|
|
56
|
+
const { params, q } = match[3]
|
|
57
|
+
? splitMediaTypeParams(match[3])
|
|
58
|
+
: { params: {}, q: 1 };
|
|
59
|
+
if (q > 0) {
|
|
60
|
+
specs.push({ type, subtype, params, q, o });
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return specs;
|
|
64
|
+
}
|
|
65
|
+
function specifyMediaType(type, subtype, params, spec) {
|
|
66
|
+
let s = 0;
|
|
67
|
+
if (spec.type === type) {
|
|
68
|
+
s |= 4; // exact match: highest specificity
|
|
69
|
+
}
|
|
70
|
+
else if (type === "*") {
|
|
71
|
+
s |= 0; // server offers wildcard (e.g. */*): matches any client type
|
|
72
|
+
}
|
|
73
|
+
else if (spec.type !== "*") {
|
|
74
|
+
// client is NOT requesting wildcard: no match
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
// client requests wildcard (e.g. Accept: */*)
|
|
78
|
+
if (spec.subtype === subtype) {
|
|
79
|
+
s |= 2; // // exact match: highest specificity
|
|
80
|
+
}
|
|
81
|
+
else if (subtype === "*") {
|
|
82
|
+
s |= 1; // server offers wildcard (e.g. text/*)
|
|
83
|
+
}
|
|
84
|
+
else if (spec.subtype !== "*") {
|
|
85
|
+
return null; // client is NOT requesting wildcard
|
|
86
|
+
}
|
|
87
|
+
// client requests wildcard (e.g. Accept: text/*): matches any server subtype
|
|
88
|
+
const specParams = Object.keys(spec.params);
|
|
89
|
+
if (specParams.length > 0) {
|
|
90
|
+
if (specParams.every((key) => spec.params[key].toLowerCase() === (params[key] || "").toLowerCase())) {
|
|
91
|
+
s |= 1;
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
return null;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return { q: spec.q, s, o: spec.o };
|
|
98
|
+
}
|
|
99
|
+
function getMediaTypePriority(mediaType, accepted, index) {
|
|
100
|
+
let best = null;
|
|
101
|
+
const match = simpleMediaTypeRegExp.exec(mediaType);
|
|
102
|
+
if (!match) {
|
|
103
|
+
return { value: mediaType, q: 0, s: 0, o: -1, i: index };
|
|
104
|
+
}
|
|
105
|
+
const type = match[1].toLowerCase();
|
|
106
|
+
const subtype = match[2].toLowerCase();
|
|
107
|
+
const { params } = match[3]
|
|
108
|
+
? splitMediaTypeParams(match[3])
|
|
109
|
+
: { params: {} };
|
|
110
|
+
for (const spec of accepted) {
|
|
111
|
+
const result = specifyMediaType(type, subtype, params, spec);
|
|
112
|
+
if (result
|
|
113
|
+
&& (best === null
|
|
114
|
+
|| result.s > best.s
|
|
115
|
+
|| (result.s === best.s && result.q > best.q)
|
|
116
|
+
|| (result.s === best.s && result.q === best.q && result.o < best.o))) {
|
|
117
|
+
best = result;
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
value: mediaType,
|
|
122
|
+
q: best?.q ?? 0,
|
|
123
|
+
s: best?.s ?? 0,
|
|
124
|
+
o: best?.o ?? -1,
|
|
125
|
+
i: index,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
function parseAcceptLanguage(accept) {
|
|
129
|
+
const specs = [];
|
|
130
|
+
const parts = accept.split(",");
|
|
131
|
+
for (let o = 0; o < parts.length; o++) {
|
|
132
|
+
const part = parts[o].trim();
|
|
133
|
+
if (!part)
|
|
134
|
+
continue;
|
|
135
|
+
const match = simpleLanguageRegExp.exec(part);
|
|
136
|
+
if (!match)
|
|
137
|
+
continue;
|
|
138
|
+
const prefix = match[1].toLowerCase();
|
|
139
|
+
const suffix = match[2]?.toLowerCase();
|
|
140
|
+
const q = parseQuality(match[3]);
|
|
141
|
+
if (q > 0) {
|
|
142
|
+
specs.push({ prefix, suffix, q, o });
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
return specs;
|
|
146
|
+
}
|
|
147
|
+
function specifyLanguage(language, spec) {
|
|
148
|
+
const match = simpleLanguageRegExp.exec(language);
|
|
149
|
+
if (!match)
|
|
150
|
+
return null;
|
|
151
|
+
const prefix = match[1].toLowerCase();
|
|
152
|
+
const suffix = match[2]?.toLowerCase();
|
|
153
|
+
if (spec.prefix === "*") {
|
|
154
|
+
return { q: spec.q, s: 0, o: spec.o };
|
|
155
|
+
}
|
|
156
|
+
if (spec.prefix !== prefix) {
|
|
157
|
+
return null;
|
|
158
|
+
}
|
|
159
|
+
if (spec.suffix === undefined) {
|
|
160
|
+
return { q: spec.q, s: suffix ? 2 : 4, o: spec.o };
|
|
161
|
+
}
|
|
162
|
+
if (spec.suffix === suffix) {
|
|
163
|
+
return { q: spec.q, s: 4, o: spec.o };
|
|
164
|
+
}
|
|
165
|
+
return null;
|
|
166
|
+
}
|
|
167
|
+
function getLanguagePriority(language, accepted, index) {
|
|
168
|
+
let best = null;
|
|
169
|
+
for (const spec of accepted) {
|
|
170
|
+
const result = specifyLanguage(language, spec);
|
|
171
|
+
if (result
|
|
172
|
+
&& (best === null
|
|
173
|
+
|| result.s > best.s
|
|
174
|
+
|| (result.s === best.s && result.q > best.q)
|
|
175
|
+
|| (result.s === best.s && result.q === best.q && result.o < best.o))) {
|
|
176
|
+
best = result;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
return {
|
|
180
|
+
value: language,
|
|
181
|
+
q: best?.q ?? 0,
|
|
182
|
+
s: best?.s ?? 0,
|
|
183
|
+
o: best?.o ?? -1,
|
|
184
|
+
i: index,
|
|
185
|
+
};
|
|
186
|
+
}
|
|
187
|
+
function parseAcceptEncoding(accept) {
|
|
188
|
+
const specs = [];
|
|
189
|
+
const parts = accept.split(",");
|
|
190
|
+
let hasIdentity = false;
|
|
191
|
+
for (let o = 0; o < parts.length; o++) {
|
|
192
|
+
const part = parts[o].trim();
|
|
193
|
+
if (!part)
|
|
194
|
+
continue;
|
|
195
|
+
const match = simpleEncodingRegExp.exec(part);
|
|
196
|
+
if (!match)
|
|
197
|
+
continue;
|
|
198
|
+
const encoding = match[1].toLowerCase();
|
|
199
|
+
const q = parseQuality(match[2]);
|
|
200
|
+
if (encoding === "identity")
|
|
201
|
+
hasIdentity = true;
|
|
202
|
+
if (encoding === "*")
|
|
203
|
+
hasIdentity = true;
|
|
204
|
+
if (q > 0) {
|
|
205
|
+
specs.push({ encoding, q, o });
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (!hasIdentity) {
|
|
209
|
+
specs.push({ encoding: "identity", q: 0.0001, o: specs.length });
|
|
210
|
+
}
|
|
211
|
+
return specs;
|
|
212
|
+
}
|
|
213
|
+
function specifyEncoding(encoding, spec) {
|
|
214
|
+
const e = encoding.toLowerCase();
|
|
215
|
+
const s = spec.encoding;
|
|
216
|
+
if (s === "*" || s === e) {
|
|
217
|
+
return { q: spec.q, s: s === e ? 1 : 0, o: spec.o };
|
|
218
|
+
}
|
|
219
|
+
return null;
|
|
220
|
+
}
|
|
221
|
+
function getEncodingPriority(encoding, accepted, index) {
|
|
222
|
+
let best = null;
|
|
223
|
+
for (const spec of accepted) {
|
|
224
|
+
const result = specifyEncoding(encoding, spec);
|
|
225
|
+
if (result
|
|
226
|
+
&& (best === null
|
|
227
|
+
|| result.s > best.s
|
|
228
|
+
|| (result.s === best.s && result.q > best.q)
|
|
229
|
+
|| (result.s === best.s && result.q === best.q && result.o < best.o))) {
|
|
230
|
+
best = result;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return {
|
|
234
|
+
value: encoding,
|
|
235
|
+
q: best?.q ?? 0,
|
|
236
|
+
s: best?.s ?? 0,
|
|
237
|
+
o: best?.o ?? -1,
|
|
238
|
+
i: index,
|
|
239
|
+
};
|
|
240
|
+
}
|
|
241
|
+
function parseAcceptCharset(accept) {
|
|
242
|
+
const specs = [];
|
|
243
|
+
const parts = accept.split(",");
|
|
244
|
+
for (let o = 0; o < parts.length; o++) {
|
|
245
|
+
const part = parts[o].trim();
|
|
246
|
+
if (!part)
|
|
247
|
+
continue;
|
|
248
|
+
const match = simpleCharsetRegExp.exec(part);
|
|
249
|
+
if (!match)
|
|
250
|
+
continue;
|
|
251
|
+
const charset = match[1].toLowerCase();
|
|
252
|
+
const q = parseQuality(match[2]);
|
|
253
|
+
if (q > 0) {
|
|
254
|
+
specs.push({ charset, q, o });
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
return specs;
|
|
258
|
+
}
|
|
259
|
+
function specifyCharset(charset, spec) {
|
|
260
|
+
const c = charset.toLowerCase();
|
|
261
|
+
const s = spec.charset;
|
|
262
|
+
if (s === "*" || s === c) {
|
|
263
|
+
return { q: spec.q, s: s === c ? 1 : 0, o: spec.o };
|
|
264
|
+
}
|
|
265
|
+
return null;
|
|
266
|
+
}
|
|
267
|
+
function getCharsetPriority(charset, accepted, index) {
|
|
268
|
+
let best = null;
|
|
269
|
+
for (const spec of accepted) {
|
|
270
|
+
const result = specifyCharset(charset, spec);
|
|
271
|
+
if (result
|
|
272
|
+
&& (best === null
|
|
273
|
+
|| result.s > best.s
|
|
274
|
+
|| (result.s === best.s && result.q > best.q)
|
|
275
|
+
|| (result.s === best.s && result.q === best.q && result.o < best.o))) {
|
|
276
|
+
best = result;
|
|
277
|
+
}
|
|
278
|
+
}
|
|
279
|
+
return {
|
|
280
|
+
value: charset,
|
|
281
|
+
q: best?.q ?? 0,
|
|
282
|
+
s: best?.s ?? 0,
|
|
283
|
+
o: best?.o ?? -1,
|
|
284
|
+
i: index,
|
|
285
|
+
};
|
|
286
|
+
}
|
|
287
|
+
function compareSpecs(a, b) {
|
|
288
|
+
return (b.q - a.q
|
|
289
|
+
|| b.s - a.s
|
|
290
|
+
|| a.o - b.o
|
|
291
|
+
|| a.i - b.i);
|
|
292
|
+
}
|
|
293
|
+
export function media(accept, available) {
|
|
294
|
+
const parsed = parseAccept(accept);
|
|
295
|
+
if (parsed.length === 0) {
|
|
296
|
+
return [];
|
|
297
|
+
}
|
|
298
|
+
if (!available) {
|
|
299
|
+
return parsed.sort((a, b) => b.q - a.q || a.o - b.o).map((p) => `${p.type}/${p.subtype}`);
|
|
300
|
+
}
|
|
301
|
+
const priorities = available.map((t, i) => getMediaTypePriority(t, parsed, i));
|
|
302
|
+
const sorted = priorities.filter((p) => p.q > 0).sort(compareSpecs);
|
|
303
|
+
return sorted.map((p) => p.value);
|
|
304
|
+
}
|
|
305
|
+
export function language(accept, available) {
|
|
306
|
+
const parsed = parseAcceptLanguage(accept);
|
|
307
|
+
if (parsed.length === 0) {
|
|
308
|
+
return [];
|
|
309
|
+
}
|
|
310
|
+
if (!available) {
|
|
311
|
+
return parsed.sort((a, b) => b.q - a.q || a.o - b.o).map((p) => p.suffix ? `${p.prefix}-${p.suffix}` : p.prefix);
|
|
312
|
+
}
|
|
313
|
+
const priorities = available.map((l, i) => getLanguagePriority(l, parsed, i));
|
|
314
|
+
const sorted = priorities.filter((p) => p.q > 0).sort(compareSpecs);
|
|
315
|
+
return sorted.map((p) => p.value);
|
|
316
|
+
}
|
|
317
|
+
export function encoding(accept, available) {
|
|
318
|
+
const parsed = parseAcceptEncoding(accept);
|
|
319
|
+
if (parsed.length === 0) {
|
|
320
|
+
return [];
|
|
321
|
+
}
|
|
322
|
+
if (!available) {
|
|
323
|
+
return parsed.sort((a, b) => b.q - a.q || a.o - b.o).map((p) => p.encoding);
|
|
324
|
+
}
|
|
325
|
+
const priorities = available.map((e, i) => getEncodingPriority(e, parsed, i));
|
|
326
|
+
const sorted = priorities.filter((p) => p.q > 0).sort(compareSpecs);
|
|
327
|
+
return sorted.map((p) => p.value);
|
|
328
|
+
}
|
|
329
|
+
export function charset(accept, available) {
|
|
330
|
+
const parsed = parseAcceptCharset(accept);
|
|
331
|
+
if (parsed.length === 0) {
|
|
332
|
+
return [];
|
|
333
|
+
}
|
|
334
|
+
if (!available) {
|
|
335
|
+
return parsed.sort((a, b) => b.q - a.q || a.o - b.o).map((p) => p.charset);
|
|
336
|
+
}
|
|
337
|
+
const priorities = available.map((c, i) => getCharsetPriority(c, parsed, i));
|
|
338
|
+
const sorted = priorities.filter((p) => p.q > 0).sort(compareSpecs);
|
|
339
|
+
return sorted.map((p) => p.value);
|
|
340
|
+
}
|
|
341
|
+
export function headerMedia(headers, available) {
|
|
342
|
+
const accept = headers["accept"];
|
|
343
|
+
if (!accept)
|
|
344
|
+
return [];
|
|
345
|
+
return media(accept, available);
|
|
346
|
+
}
|
|
347
|
+
export function headerLanguage(headers, available) {
|
|
348
|
+
const accept = headers["accept-language"];
|
|
349
|
+
if (!accept)
|
|
350
|
+
return [];
|
|
351
|
+
return language(accept, available);
|
|
352
|
+
}
|
|
353
|
+
export function headerEncoding(headers, available) {
|
|
354
|
+
const accept = headers["accept-encoding"];
|
|
355
|
+
if (!accept)
|
|
356
|
+
return [];
|
|
357
|
+
return encoding(accept, available);
|
|
358
|
+
}
|
|
359
|
+
export function headerCharset(headers, available) {
|
|
360
|
+
const accept = headers["accept-charset"];
|
|
361
|
+
if (!accept)
|
|
362
|
+
return [];
|
|
363
|
+
return charset(accept, available);
|
|
364
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { Context, Effect, Layer, PubSub, Stream } from "effect";
|
|
2
|
+
import { Error, FileSystem } from "./node/FileSystem.ts";
|
|
3
|
+
export type DevelopmentEvent = FileSystem.WatchEvent | {
|
|
4
|
+
readonly _tag: "Reload";
|
|
5
|
+
};
|
|
6
|
+
/** @internal */
|
|
7
|
+
export declare const _resetForTesting: () => void;
|
|
8
|
+
export type DevelopmentService = {
|
|
9
|
+
events: PubSub.PubSub<DevelopmentEvent>;
|
|
10
|
+
};
|
|
11
|
+
declare const Development_base: Context.TagClass<Development, "effect-start/Development", DevelopmentService>;
|
|
12
|
+
export declare class Development extends Development_base {
|
|
13
|
+
}
|
|
14
|
+
export declare const filterSourceFiles: (event: FileSystem.WatchEvent) => boolean;
|
|
15
|
+
export declare const filterDirectory: (event: FileSystem.WatchEvent) => boolean;
|
|
16
|
+
export declare const watchSource: (opts?: {
|
|
17
|
+
path?: string;
|
|
18
|
+
recursive?: boolean;
|
|
19
|
+
filter?: (event: FileSystem.WatchEvent) => boolean;
|
|
20
|
+
}) => Stream.Stream<FileSystem.WatchEvent, Error.PlatformError, FileSystem.FileSystem>;
|
|
21
|
+
export declare const watch: (opts?: {
|
|
22
|
+
path?: string;
|
|
23
|
+
recursive?: boolean;
|
|
24
|
+
filter?: (event: FileSystem.WatchEvent) => boolean;
|
|
25
|
+
}) => Effect.Effect<{
|
|
26
|
+
events: PubSub.PubSub<DevelopmentEvent>;
|
|
27
|
+
}, never, FileSystem.FileSystem>;
|
|
28
|
+
export declare const layerWatch: (opts?: {
|
|
29
|
+
path?: string;
|
|
30
|
+
recursive?: boolean;
|
|
31
|
+
filter?: (event: FileSystem.WatchEvent) => boolean;
|
|
32
|
+
}) => Layer.Layer<Development, never, FileSystem.FileSystem>;
|
|
33
|
+
export declare const stream: () => Stream.Stream<DevelopmentEvent>;
|
|
34
|
+
export {};
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import { Context, Effect, Function, Layer, Option, pipe, PubSub, Stream, } from "effect";
|
|
2
|
+
import { globalValue } from "effect/GlobalValue";
|
|
3
|
+
import { FileSystem, } from "./node/FileSystem.js";
|
|
4
|
+
const devState = globalValue(Symbol.for("effect-start/Development"), () => ({
|
|
5
|
+
count: 0,
|
|
6
|
+
pubsub: null,
|
|
7
|
+
}));
|
|
8
|
+
/** @internal */
|
|
9
|
+
export const _resetForTesting = () => {
|
|
10
|
+
devState.count = 0;
|
|
11
|
+
devState.pubsub = null;
|
|
12
|
+
};
|
|
13
|
+
export class Development extends Context.Tag("effect-start/Development")() {
|
|
14
|
+
}
|
|
15
|
+
const SOURCE_FILENAME = /\.(tsx?|jsx?|html?|css|json)$/;
|
|
16
|
+
export const filterSourceFiles = (event) => {
|
|
17
|
+
return SOURCE_FILENAME.test(event.path);
|
|
18
|
+
};
|
|
19
|
+
export const filterDirectory = (event) => {
|
|
20
|
+
return event.path.endsWith("/");
|
|
21
|
+
};
|
|
22
|
+
export const watchSource = (opts) => {
|
|
23
|
+
const baseDir = opts?.path ?? process.cwd();
|
|
24
|
+
const customFilter = opts?.filter;
|
|
25
|
+
return Function.pipe(Stream.unwrap(Effect.map(FileSystem.FileSystem, fs => fs.watch(baseDir, { recursive: opts?.recursive ?? true }))), customFilter ? Stream.filter(customFilter) : Function.identity, Stream.rechunk(1), Stream.throttle({
|
|
26
|
+
units: 1,
|
|
27
|
+
cost: () => 1,
|
|
28
|
+
duration: "400 millis",
|
|
29
|
+
strategy: "enforce",
|
|
30
|
+
}));
|
|
31
|
+
};
|
|
32
|
+
export const watch = (opts) => Effect.gen(function* () {
|
|
33
|
+
devState.count++;
|
|
34
|
+
if (devState.count === 1) {
|
|
35
|
+
const pubsub = yield* PubSub.unbounded();
|
|
36
|
+
devState.pubsub = pubsub;
|
|
37
|
+
yield* pipe(watchSource({
|
|
38
|
+
path: opts?.path,
|
|
39
|
+
recursive: opts?.recursive,
|
|
40
|
+
filter: opts?.filter ?? filterSourceFiles,
|
|
41
|
+
}), Stream.runForEach((event) => PubSub.publish(pubsub, event)), Effect.fork);
|
|
42
|
+
}
|
|
43
|
+
else {
|
|
44
|
+
yield* PubSub.publish(devState.pubsub, { _tag: "Reload" });
|
|
45
|
+
}
|
|
46
|
+
return { events: devState.pubsub };
|
|
47
|
+
});
|
|
48
|
+
export const layerWatch = (opts) => Layer.scoped(Development, watch(opts));
|
|
49
|
+
export const stream = () => Stream.unwrap(pipe(Effect.serviceOption(Development), Effect.map(Option.match({
|
|
50
|
+
onNone: () => Stream.empty,
|
|
51
|
+
onSome: (dev) => Stream.fromPubSub(dev.events),
|
|
52
|
+
}))));
|
package/dist/Entity.d.ts
ADDED
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import * as Effect from "effect/Effect";
|
|
2
|
+
import * as ParseResult from "effect/ParseResult";
|
|
3
|
+
import * as Pipeable from "effect/Pipeable";
|
|
4
|
+
import * as Stream from "effect/Stream";
|
|
5
|
+
import * as Values from "./Values.ts";
|
|
6
|
+
export declare const TypeId: unique symbol;
|
|
7
|
+
export type TypeId = typeof TypeId;
|
|
8
|
+
/**
|
|
9
|
+
* Header keys are guaranteed to be lowercase.
|
|
10
|
+
*/
|
|
11
|
+
export type Headers = {
|
|
12
|
+
[header: string]: string | null | undefined;
|
|
13
|
+
};
|
|
14
|
+
export interface Entity<T = unknown, E = never> extends Pipeable.Pipeable {
|
|
15
|
+
readonly [TypeId]: TypeId;
|
|
16
|
+
readonly body: T;
|
|
17
|
+
readonly headers: Headers;
|
|
18
|
+
/**
|
|
19
|
+
* Accepts any valid URI (Uniform Resource Identifier), including URLs
|
|
20
|
+
* (http://, https://, file://), URNs (urn:isbn:...), S3 URIs (s3://bucket/key),
|
|
21
|
+
* data URIs, and other schemes. While commonly called "URL" in many APIs,
|
|
22
|
+
* this property handles URIs as the correct superset term per RFC 3986.
|
|
23
|
+
*/
|
|
24
|
+
readonly url: string | undefined;
|
|
25
|
+
readonly status: number | undefined;
|
|
26
|
+
readonly text: T extends string ? Effect.Effect<T, ParseResult.ParseError | E> : Effect.Effect<string, ParseResult.ParseError | E>;
|
|
27
|
+
readonly json: [T] extends [Effect.Effect<infer A, any, any>] ? Effect.Effect<A extends string | Uint8Array | ArrayBuffer ? unknown : A, ParseResult.ParseError | E> : [T] extends [Stream.Stream<any, any, any>] ? Effect.Effect<unknown, ParseResult.ParseError | E> : [T] extends [string | Uint8Array | ArrayBuffer] ? Effect.Effect<unknown, ParseResult.ParseError | E> : [T] extends [Values.Json] ? Effect.Effect<T, ParseResult.ParseError | E> : Effect.Effect<unknown, ParseResult.ParseError | E>;
|
|
28
|
+
readonly bytes: Effect.Effect<Uint8Array, ParseResult.ParseError | E>;
|
|
29
|
+
readonly stream: T extends Stream.Stream<infer A, infer E1, any> ? Stream.Stream<A, ParseResult.ParseError | E | E1> : Stream.Stream<Uint8Array, ParseResult.ParseError | E>;
|
|
30
|
+
}
|
|
31
|
+
export interface Proto extends Pipeable.Pipeable {
|
|
32
|
+
readonly [TypeId]: TypeId;
|
|
33
|
+
}
|
|
34
|
+
export declare function isEntity(input: unknown): input is Entity;
|
|
35
|
+
interface Options {
|
|
36
|
+
readonly headers?: Headers;
|
|
37
|
+
readonly url?: string;
|
|
38
|
+
readonly status?: number;
|
|
39
|
+
}
|
|
40
|
+
export declare function make<A, E>(body: Effect.Effect<A, E, never>, options?: Options): Entity<Effect.Effect<A, E, never>, E>;
|
|
41
|
+
export declare function make<A extends Uint8Array | string, E>(body: Stream.Stream<A, E, never>, options?: Options): Entity<Stream.Stream<A, E, never>, E>;
|
|
42
|
+
export declare function make<T>(body: T, options?: Options): Entity<T, never>;
|
|
43
|
+
export declare function effect<A, E, R>(body: Effect.Effect<Entity<A> | A, E, R>): Entity<A, E>;
|
|
44
|
+
export declare function resolve<A, E>(entity: Entity<A, E>): Effect.Effect<Entity<A, E>, E, never>;
|
|
45
|
+
export declare function type(self: Entity): string;
|
|
46
|
+
export declare function length(self: Entity): number | undefined;
|
|
47
|
+
export {};
|