@hyperspan/framework 2.0.0-alpha.7 → 2.0.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.
@@ -0,0 +1,109 @@
1
+ import { html } from "./html.js";
2
+ import { createRoute, returnHTMLResponse } from "./server.js";
3
+ import { assetHash, formDataToJSON } from "./utils.js";
4
+ import { hyperspanActionsScriptTag } from "./layout.js";
5
+ import { validateBody } from "./middleware.js";
6
+ import debug from "debug";
7
+ const log = debug("hyperspan:actions");
8
+ function createAction(params) {
9
+ const { name, schema } = params;
10
+ const path = `/__actions/${assetHash(name)}`;
11
+ let _handler = null;
12
+ let _errorHandler = null;
13
+ function actionResponseOptions(status) {
14
+ return {
15
+ ...route._serverConfig?.responseOptions ?? {},
16
+ ...route._config?.responseOptions ?? {},
17
+ ...status !== void 0 ? { status } : {}
18
+ };
19
+ }
20
+ const route = createRoute({ path, name }).get((c) => api.render(c)).post(
21
+ async (c) => {
22
+ if (!_handler) {
23
+ throw new Error("Action POST handler not set! Every action must have a POST handler.");
24
+ }
25
+ const data = c.vars.body || formDataToJSON(await c.req.formData()) || {};
26
+ log("POST handler", { data });
27
+ const response = await _handler(c, { data });
28
+ log("POST handler response", { response });
29
+ if (response instanceof Response) {
30
+ if ([301, 302, 307, 308].includes(response.status)) {
31
+ response.headers.set("X-Redirect-Location", response.headers.get("Location") || "/");
32
+ response.headers.delete("Location");
33
+ }
34
+ }
35
+ return response;
36
+ },
37
+ { middleware: schema ? [validateBody(schema)] : [] }
38
+ ).errorHandler(async (c, err) => {
39
+ const data = c.vars.body || formDataToJSON(await c.req.formData()) || {};
40
+ const error = err._error || err;
41
+ c.res.status = err._error ? 400 : 500;
42
+ log("errorHandler", { data, error });
43
+ return await returnHTMLResponse(
44
+ c,
45
+ () => {
46
+ return _errorHandler ? _errorHandler(c, { data, error }) : api.render(c, { data, error });
47
+ },
48
+ actionResponseOptions(c.res.status ?? 400)
49
+ );
50
+ });
51
+ route._config.name = name;
52
+ const api = {
53
+ _kind: "hsAction",
54
+ _config: route._config,
55
+ get _serverConfig() {
56
+ return route._serverConfig;
57
+ },
58
+ set _serverConfig(config) {
59
+ route._serverConfig = config;
60
+ },
61
+ _path() {
62
+ return path;
63
+ },
64
+ _form: null,
65
+ /**
66
+ * Form to render
67
+ * This will be wrapped in a <hs-action> web component and submitted via fetch()
68
+ */
69
+ form(_formFn) {
70
+ api._form = _formFn;
71
+ return api;
72
+ },
73
+ /**
74
+ * Process form data
75
+ *
76
+ * Returns result from form processing if successful
77
+ * Re-renders form with data and error information otherwise
78
+ */
79
+ post(handler) {
80
+ _handler = handler;
81
+ return api;
82
+ },
83
+ /**
84
+ * Get form renderer method
85
+ */
86
+ render(c, props) {
87
+ const formContent = api._form ? api._form(c, props || {}) : null;
88
+ return formContent ? html`<hs-action url="${this._path()}">${formContent}</hs-action
89
+ >${hyperspanActionsScriptTag()}` : null;
90
+ },
91
+ errorHandler(handler) {
92
+ _errorHandler = handler;
93
+ return api;
94
+ },
95
+ use(middleware, opts) {
96
+ route.use(middleware, opts);
97
+ return api;
98
+ },
99
+ middleware(middleware, opts) {
100
+ route.middleware(middleware, opts);
101
+ return api;
102
+ },
103
+ fetch: route.fetch
104
+ };
105
+ return api;
106
+ }
107
+ export {
108
+ createAction
109
+ };
@@ -0,0 +1,18 @@
1
+ function callsites() {
2
+ const _prepareStackTrace = Error.prepareStackTrace;
3
+ try {
4
+ let result = [];
5
+ Error.prepareStackTrace = (_, callSites) => {
6
+ const callSitesWithoutCurrent = callSites.slice(1);
7
+ result = callSitesWithoutCurrent;
8
+ return callSitesWithoutCurrent;
9
+ };
10
+ new Error().stack;
11
+ return result;
12
+ } finally {
13
+ Error.prepareStackTrace = _prepareStackTrace;
14
+ }
15
+ }
16
+ export {
17
+ callsites
18
+ };
@@ -0,0 +1,6 @@
1
+ const CSS_PUBLIC_PATH = "/_hs/css";
2
+ const CSS_ROUTE_MAP = /* @__PURE__ */ new Map();
3
+ export {
4
+ CSS_PUBLIC_PATH,
5
+ CSS_ROUTE_MAP
6
+ };
@@ -0,0 +1,314 @@
1
+ var __freeze = Object.freeze;
2
+ var __defProp = Object.defineProperty;
3
+ var __template = (cooked, raw) => __freeze(__defProp(cooked, "raw", { value: __freeze(raw || cooked.slice()) }));
4
+ var _a, _b, _c, _d;
5
+ import { readFileSync, existsSync } from "node:fs";
6
+ import { isAbsolute, join, relative } from "node:path";
7
+ import { fileURLToPath } from "node:url";
8
+ import { html } from "../html.js";
9
+ import { assetHash as assetHashFn } from "../utils.js";
10
+ import { getImportMap, registerImport, resolveImport } from "./manifest.js";
11
+ import { registerImport as registerImport2, resolveImport as resolveImport2, getImportMap as getImportMap2 } from "./manifest.js";
12
+ const JS_PUBLIC_PATH = "/_hs/js";
13
+ const JS_ISLAND_PUBLIC_PATH = "/_hs/js/islands";
14
+ const CLIENT_JS_REGISTRY = /* @__PURE__ */ Symbol.for("@hyperspan/client-js-entries");
15
+ const CLIENT_JS_PATH_IDENTITIES = /* @__PURE__ */ Symbol.for("@hyperspan/client-js-path-identities");
16
+ const PATH_ALIASES = /* @__PURE__ */ Symbol.for("@hyperspan/path-aliases");
17
+ function getPathAliases() {
18
+ const globalAliases = globalThis;
19
+ if (!globalAliases[PATH_ALIASES]) {
20
+ globalAliases[PATH_ALIASES] = {};
21
+ }
22
+ return globalAliases[PATH_ALIASES];
23
+ }
24
+ function registerPathAliases(aliases) {
25
+ Object.assign(getPathAliases(), aliases);
26
+ }
27
+ function resolveWithAliases(specifier) {
28
+ const aliases = getPathAliases();
29
+ const keys = Object.keys(aliases).sort((a, b) => b.length - a.length);
30
+ for (const key of keys) {
31
+ if (specifier === key || specifier.startsWith(key)) {
32
+ const rest = specifier.slice(key.length).replace(/^\//, "");
33
+ return join(aliases[key], rest);
34
+ }
35
+ }
36
+ return void 0;
37
+ }
38
+ function getPathIdentityClientJS() {
39
+ const globalPathIdentities = globalThis;
40
+ if (!globalPathIdentities[CLIENT_JS_PATH_IDENTITIES]) {
41
+ globalPathIdentities[CLIENT_JS_PATH_IDENTITIES] = [];
42
+ }
43
+ return globalPathIdentities[CLIENT_JS_PATH_IDENTITIES];
44
+ }
45
+ function getClientJSRegistry() {
46
+ const globalRegistry = globalThis;
47
+ if (!globalRegistry[CLIENT_JS_REGISTRY]) {
48
+ globalRegistry[CLIENT_JS_REGISTRY] = /* @__PURE__ */ new Map();
49
+ }
50
+ return globalRegistry[CLIENT_JS_REGISTRY];
51
+ }
52
+ const JS_IMPORT_MAP = {
53
+ get size() {
54
+ return Object.keys(getImportMap()).length;
55
+ },
56
+ keys() {
57
+ return Object.keys(getImportMap()).values();
58
+ },
59
+ has(key) {
60
+ return resolveImport(key) !== void 0;
61
+ },
62
+ get(key) {
63
+ return resolveImport(key);
64
+ },
65
+ set(key, value) {
66
+ registerImport(key, value);
67
+ return this;
68
+ },
69
+ entries() {
70
+ return Object.entries(getImportMap()).values();
71
+ },
72
+ [Symbol.iterator]() {
73
+ return Object.entries(getImportMap())[Symbol.iterator]();
74
+ }
75
+ };
76
+ function stableClientSourceKey(absPath) {
77
+ const normalized = absPath.replace(/\\/g, "/");
78
+ const marker = "/node_modules/";
79
+ const idx = normalized.lastIndexOf(marker);
80
+ if (idx !== -1) {
81
+ return normalized.slice(idx + marker.length);
82
+ }
83
+ if (typeof process !== "undefined" && typeof process.cwd === "function") {
84
+ const rel = relative(process.cwd(), absPath).replace(/\\/g, "/");
85
+ if (rel && !rel.startsWith("..") && !isAbsolute(rel)) {
86
+ return rel;
87
+ }
88
+ }
89
+ return normalized;
90
+ }
91
+ function toFilePath(modulePath) {
92
+ return modulePath.startsWith("file://") ? fileURLToPath(modulePath) : modulePath;
93
+ }
94
+ function tryResolveToFile(specifier) {
95
+ try {
96
+ if (typeof import.meta.resolve !== "function") {
97
+ return void 0;
98
+ }
99
+ const resolved = import.meta.resolve(specifier);
100
+ if (typeof resolved === "string" && (resolved.startsWith("file://") || isAbsolute(resolved))) {
101
+ return toFilePath(resolved);
102
+ }
103
+ } catch {
104
+ }
105
+ return void 0;
106
+ }
107
+ function clientPublicPath(esmName) {
108
+ return resolveImport(esmName) ?? `${JS_PUBLIC_PATH}/${esmName}.js`;
109
+ }
110
+ function clientIdentityKey(specifier) {
111
+ if (specifier.startsWith("file://") || isAbsolute(specifier)) {
112
+ return stableClientSourceKey(toFilePath(specifier));
113
+ }
114
+ return specifier;
115
+ }
116
+ function resolveClientAbsPath(specifier) {
117
+ if (specifier.startsWith("file://") || isAbsolute(specifier)) {
118
+ return toFilePath(specifier);
119
+ }
120
+ const aliased = resolveWithAliases(specifier);
121
+ if (aliased) {
122
+ return aliased;
123
+ }
124
+ const cwd = typeof process !== "undefined" && typeof process.cwd === "function" ? process.cwd() : "";
125
+ return tryResolveToFile(specifier) ?? (cwd ? join(cwd, specifier) : specifier);
126
+ }
127
+ function readClientSource(absPath) {
128
+ try {
129
+ if (existsSync(absPath)) {
130
+ return readFileSync(absPath, "utf-8");
131
+ }
132
+ } catch {
133
+ }
134
+ return void 0;
135
+ }
136
+ function getClientJSEntries() {
137
+ return [...getClientJSRegistry().values()];
138
+ }
139
+ function getClientJSEntryByEsmName(esmName) {
140
+ return getClientJSRegistry().get(esmName);
141
+ }
142
+ function resetClientJSEntriesForTests() {
143
+ getClientJSRegistry().clear();
144
+ getPathIdentityClientJS().length = 0;
145
+ const aliases = getPathAliases();
146
+ for (const key of Object.keys(aliases)) {
147
+ delete aliases[key];
148
+ }
149
+ }
150
+ function registerClientJS(modulePathResolved, options = {}) {
151
+ const type = options.type ?? "module";
152
+ const specifier = modulePathResolved.replace(/\\/g, "/");
153
+ if (specifier.startsWith(".")) {
154
+ throw new Error(
155
+ `[Hyperspan] buildClientJS(${JSON.stringify(modulePathResolved)}) got a relative path, which has no stable identity across dev, build, and deploy. Use a tsconfig alias like '~/app/client/file.ts' \u2014 the build resolves it, and every runtime (including Workers, which cannot resolve paths) matches it in the asset manifest.`
156
+ );
157
+ }
158
+ const identityKey = clientIdentityKey(specifier);
159
+ const identityFromPath = identityKey !== specifier;
160
+ const hash = assetHashFn(identityKey);
161
+ const esmName = `client-${hash}`;
162
+ if (identityFromPath) {
163
+ getPathIdentityClientJS().push({ modulePath: modulePathResolved, identityKey });
164
+ }
165
+ let absPath;
166
+ let discovered;
167
+ function currentAbsPath() {
168
+ return absPath ??= resolveClientAbsPath(specifier);
169
+ }
170
+ function currentExports() {
171
+ if (!discovered) {
172
+ const source = readClientSource(currentAbsPath());
173
+ discovered = source ? discoverClientExports(source) : { exports: "* as _module", fnArgs: "_module" };
174
+ }
175
+ return discovered;
176
+ }
177
+ const entry = {
178
+ modulePath: modulePathResolved,
179
+ get absPath() {
180
+ return currentAbsPath();
181
+ },
182
+ identityKey,
183
+ identityFromPath,
184
+ assetHash: hash,
185
+ esmName,
186
+ get publicPath() {
187
+ return clientPublicPath(esmName);
188
+ },
189
+ get exports() {
190
+ return currentExports().exports;
191
+ },
192
+ get fnArgs() {
193
+ return currentExports().fnArgs;
194
+ },
195
+ type
196
+ };
197
+ getClientJSRegistry().set(esmName, entry);
198
+ registerImport(esmName, entry.publicPath);
199
+ return {
200
+ assetHash: hash,
201
+ esmName,
202
+ get publicPath() {
203
+ return clientPublicPath(esmName);
204
+ },
205
+ renderScriptTag: (loadScript) => {
206
+ if (type === "iife") {
207
+ return html(_a || (_a = __template(['<script src="', '"><\/script>'])), clientPublicPath(esmName));
208
+ }
209
+ const t = typeof loadScript;
210
+ const { exports, fnArgs } = currentExports();
211
+ if (t === "string") {
212
+ return html(_b || (_b = __template(['\n <script type="module" data-source-id="', '">\n import ', " from '", "';\n (", ")(", ");\n <\/script>\n "])), hash, exports, esmName, html.raw(loadScript), fnArgs);
213
+ }
214
+ if (t === "function") {
215
+ return html(_c || (_c = __template(['\n <script type="module" data-source-id="', '">\n import ', " from '", "';\n (", ")(", ");\n <\/script>\n "])), hash, exports, esmName, html.raw(functionToString(loadScript)), fnArgs);
216
+ }
217
+ return html(_d || (_d = __template(['\n <script type="module" data-source-id="', `">
218
+ import '`, "';\n <\/script>\n "])), hash, esmName);
219
+ }
220
+ };
221
+ }
222
+ async function buildClientJS(modulePathResolved, options = {}) {
223
+ return registerClientJS(modulePathResolved, options);
224
+ }
225
+ const streamingClient = registerClientJS(
226
+ "@hyperspan/framework/client/_hs/hyperspan-streaming.client.ts",
227
+ { type: "iife" }
228
+ );
229
+ const actionsClient = registerClientJS(
230
+ "@hyperspan/framework/client/_hs/hyperspan-actions.client.ts"
231
+ );
232
+ function discoverClientExports(contents) {
233
+ const bundled = extractExports(contents);
234
+ if (bundled.exports !== "* as _module") {
235
+ return bundled;
236
+ }
237
+ const names = [];
238
+ const seen = /* @__PURE__ */ new Set();
239
+ for (const re of [
240
+ /export\s+(?:async\s+)?function\s+([A-Za-z_$][\w$]*)/g,
241
+ /export\s+const\s+([A-Za-z_$][\w$]*)/g,
242
+ /export\s+class\s+([A-Za-z_$][\w$]*)/g,
243
+ /export\s+let\s+([A-Za-z_$][\w$]*)/g
244
+ ]) {
245
+ let match;
246
+ while ((match = re.exec(contents)) !== null) {
247
+ if (!seen.has(match[1])) {
248
+ names.push(match[1]);
249
+ seen.add(match[1]);
250
+ }
251
+ }
252
+ }
253
+ const exportBlock = /export\s*\{([^}]+)\}/g;
254
+ let block;
255
+ while ((block = exportBlock.exec(contents)) !== null) {
256
+ for (const part of block[1].split(",")) {
257
+ const trimmed = part.trim();
258
+ if (!trimmed || trimmed.startsWith("type ")) continue;
259
+ const asMatch = trimmed.match(/^(?:([\w$]+)\s+as\s+)?([\w$]+)$/);
260
+ const name = asMatch?.[2] ?? trimmed;
261
+ if (name && name !== "default" && !seen.has(name)) {
262
+ names.push(name);
263
+ seen.add(name);
264
+ }
265
+ }
266
+ }
267
+ if (names.length === 0) {
268
+ if (/export\s+default\b/.test(contents)) {
269
+ return { exports: "DefaultExport", fnArgs: "DefaultExport" };
270
+ }
271
+ return { exports: "* as _module", fnArgs: "_module" };
272
+ }
273
+ const exports = `{${names.join(", ")}}`;
274
+ return { exports, fnArgs: exports };
275
+ }
276
+ function extractExports(contents) {
277
+ const exportRegex = /export\{(.*)\}/g;
278
+ const exportLine = exportRegex.exec(contents);
279
+ let exports = "{}";
280
+ let fnArgs = "{}";
281
+ if (exportLine) {
282
+ const exportName = exportLine[1];
283
+ exports = "{" + exportName.split(",").map((name) => name.trim().split(" as ")).map(([name, alias]) => `${alias === "default" ? "default as " + name : alias}`).join(", ") + "}";
284
+ }
285
+ fnArgs = exports.replace(/(\w+)\s*as\s*(\w+)/g, "$1: $2").trim();
286
+ if (exports === "{}" && fnArgs === "{}") {
287
+ exports = "* as _module";
288
+ fnArgs = "_module";
289
+ }
290
+ return { exports, fnArgs };
291
+ }
292
+ function functionToString(fn) {
293
+ return fn.toString().trim();
294
+ }
295
+ export {
296
+ JS_IMPORT_MAP,
297
+ JS_ISLAND_PUBLIC_PATH,
298
+ JS_PUBLIC_PATH,
299
+ actionsClient,
300
+ buildClientJS,
301
+ discoverClientExports,
302
+ extractExports,
303
+ functionToString,
304
+ getClientJSEntries,
305
+ getClientJSEntryByEsmName,
306
+ getImportMap2 as getImportMap,
307
+ getPathIdentityClientJS,
308
+ registerImport2 as registerImport,
309
+ registerPathAliases,
310
+ resetClientJSEntriesForTests,
311
+ resolveImport2 as resolveImport,
312
+ stableClientSourceKey,
313
+ streamingClient
314
+ };
@@ -0,0 +1,55 @@
1
+ const MANIFEST_KEY = /* @__PURE__ */ Symbol.for("@hyperspan/asset-manifest");
2
+ function sharedManifest() {
3
+ const globalStore = globalThis;
4
+ if (!globalStore[MANIFEST_KEY]) {
5
+ globalStore[MANIFEST_KEY] = { imports: {}, css: {}, clients: {} };
6
+ }
7
+ return globalStore[MANIFEST_KEY];
8
+ }
9
+ function setAssetManifest(manifest) {
10
+ const store = sharedManifest();
11
+ store.imports = { ...manifest.imports ?? {} };
12
+ store.css = { ...manifest.css ?? {} };
13
+ store.clients = { ...manifest.clients ?? {} };
14
+ }
15
+ function getAssetManifest() {
16
+ return sharedManifest();
17
+ }
18
+ function resolveImport(name) {
19
+ return sharedManifest().imports[name];
20
+ }
21
+ function getRouteCss(path) {
22
+ return sharedManifest().css[path] ?? [];
23
+ }
24
+ function getImportMap() {
25
+ return { ...sharedManifest().imports };
26
+ }
27
+ function registerImport(name, publicPath) {
28
+ sharedManifest().imports[name] = publicPath;
29
+ }
30
+ function getClientJSFromManifest(moduleId, _exportNames = "default") {
31
+ const publicPath = sharedManifest().clients[moduleId];
32
+ if (!publicPath) {
33
+ throw new Error(
34
+ `[Hyperspan] Client module "${moduleId}" not found in asset manifest. Run hyperspan build or start dev server.`
35
+ );
36
+ }
37
+ const esmName = publicPath.split("/").pop()?.replace(".js", "") ?? moduleId;
38
+ return {
39
+ assetHash: moduleId,
40
+ esmName,
41
+ publicPath,
42
+ renderScriptTag: () => {
43
+ throw new Error("renderScriptTag requires html template - use layout helpers instead");
44
+ }
45
+ };
46
+ }
47
+ export {
48
+ getAssetManifest,
49
+ getClientJSFromManifest,
50
+ getImportMap,
51
+ getRouteCss,
52
+ registerImport,
53
+ resolveImport,
54
+ setAssetManifest
55
+ };
@@ -0,0 +1,142 @@
1
+ const REGEXP_PAIR_SPLIT = /; */;
2
+ const REGEXP_FIELD_CONTENT = /^[\u0009\u0020-\u007e\u0080-\u00ff]+$/;
3
+ class Cookies {
4
+ _req;
5
+ _responseHeaders;
6
+ _parsedCookies = {};
7
+ _encrypt;
8
+ _decrypt;
9
+ constructor(req, responseHeaders = void 0) {
10
+ this._req = req;
11
+ this._responseHeaders = responseHeaders;
12
+ this._parsedCookies = parse(req.headers.get("Cookie") || "");
13
+ }
14
+ get(name) {
15
+ const value = this._parsedCookies[name];
16
+ if (value && this._decrypt) {
17
+ return this._decrypt(value);
18
+ }
19
+ return value;
20
+ }
21
+ set(name, value, options) {
22
+ if (!this._responseHeaders) {
23
+ throw new Error("Set cookies in the response object. Cookies can only be read from the request object.");
24
+ }
25
+ if (this._encrypt) {
26
+ value = this._encrypt(value);
27
+ }
28
+ this._responseHeaders.append("Set-Cookie", serialize(name, value, options));
29
+ }
30
+ delete(name) {
31
+ this.set(name, "", { expires: /* @__PURE__ */ new Date(0) });
32
+ }
33
+ /**
34
+ * Set the encoder and decoder functions for the cookies and re-parse the cookie header
35
+ */
36
+ setEncryption(encrypt, decrypt) {
37
+ this._encrypt = encrypt;
38
+ this._decrypt = decrypt;
39
+ this._parsedCookies = parse(this._req.headers.get("Cookie") || "");
40
+ }
41
+ }
42
+ /*!
43
+ * cookie
44
+ * @source https://github.com/jkohrman/cookie-parse/blob/master/index.js
45
+ * Copyright(c) 2012-2014 Roman Shtylman
46
+ * Copyright(c) 2015 Douglas Christopher Wilson
47
+ * Copyright(c) 2016 Jeff Kohrman
48
+ * MIT Licensed
49
+ */
50
+ function parse(str) {
51
+ if (typeof str !== "string") {
52
+ throw new TypeError("argument str must be a string");
53
+ }
54
+ const obj = {};
55
+ const pairs = str.split(REGEXP_PAIR_SPLIT);
56
+ for (let i = 0; i < pairs.length; i++) {
57
+ const pair = pairs[i];
58
+ let eq_idx = pair.indexOf("=");
59
+ let key;
60
+ let val;
61
+ if (eq_idx < 0) {
62
+ key = pair.trim();
63
+ val = "true";
64
+ } else {
65
+ key = pair.substring(0, eq_idx).trim();
66
+ val = pair.substring(eq_idx + 1, eq_idx + 1 + pair.length).trim();
67
+ }
68
+ ;
69
+ if ('"' == val[0]) {
70
+ val = val.slice(1, -1);
71
+ }
72
+ if (void 0 == obj[key]) {
73
+ obj[key] = tryDecode(val, decodeURIComponent);
74
+ }
75
+ }
76
+ return obj;
77
+ }
78
+ function serialize(name, val, options = {}) {
79
+ const opt = options || {};
80
+ if (!REGEXP_FIELD_CONTENT.test(name)) {
81
+ throw new TypeError("argument name is invalid");
82
+ }
83
+ let value = encodeURIComponent(val);
84
+ if (value && !REGEXP_FIELD_CONTENT.test(value)) {
85
+ throw new TypeError("argument val is invalid");
86
+ }
87
+ let str = name + "=" + value;
88
+ if (null != opt.maxAge) {
89
+ const maxAge = opt.maxAge - 0;
90
+ if (isNaN(maxAge)) throw new Error("maxAge should be a Number");
91
+ str += "; Max-Age=" + Math.floor(maxAge);
92
+ }
93
+ if (opt.domain) {
94
+ if (!REGEXP_FIELD_CONTENT.test(opt.domain)) {
95
+ throw new TypeError("option domain is invalid");
96
+ }
97
+ str += "; Domain=" + opt.domain;
98
+ }
99
+ if (opt.path) {
100
+ if (!REGEXP_FIELD_CONTENT.test(opt.path)) {
101
+ throw new TypeError("option path is invalid");
102
+ }
103
+ str += "; Path=" + opt.path;
104
+ }
105
+ if (opt.expires) {
106
+ if (typeof opt.expires.toUTCString !== "function") {
107
+ throw new TypeError("option expires must be a Date object");
108
+ }
109
+ str += "; Expires=" + opt.expires.toUTCString();
110
+ }
111
+ if (opt.httpOnly) {
112
+ str += "; HttpOnly";
113
+ }
114
+ if (opt.secure) {
115
+ str += "; Secure";
116
+ }
117
+ if (opt.sameSite) {
118
+ const sameSite = typeof opt.sameSite === "string" ? opt.sameSite.toLowerCase() : opt.sameSite;
119
+ switch (sameSite) {
120
+ case true:
121
+ case "strict":
122
+ str += "; SameSite=Strict";
123
+ break;
124
+ case "lax":
125
+ str += "; SameSite=Lax";
126
+ break;
127
+ default:
128
+ throw new TypeError("option sameSite is invalid");
129
+ }
130
+ }
131
+ return str;
132
+ }
133
+ function tryDecode(str, decode) {
134
+ try {
135
+ return decode(str);
136
+ } catch (e) {
137
+ return str;
138
+ }
139
+ }
140
+ export {
141
+ Cookies
142
+ };
@@ -0,0 +1,15 @@
1
+ let devBindings;
2
+ function setDevBindings(env) {
3
+ devBindings = env;
4
+ }
5
+ function getDevBindings() {
6
+ return devBindings;
7
+ }
8
+ function clearDevBindingsForTests() {
9
+ devBindings = void 0;
10
+ }
11
+ export {
12
+ clearDevBindingsForTests,
13
+ getDevBindings,
14
+ setDevBindings
15
+ };