codebay 0.0.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.mochi/import-css/index-0nwv3654.css +18 -0
- package/.mochi/import-css/index-xndx4980.css +54 -0
- package/.mochi/manifest.json +1608 -0
- package/.mochi/server-island.js +1 -0
- package/.mochi/svelte-client/HydratableIsland-ps09gjy2.js +1 -0
- package/.mochi/svelte-client/_hydrate-AppShell_2rtnxn6pgp2rh-62w5zwww.js +2 -0
- package/.mochi/svelte-client/_hydrate-AvatarsView_257s9yq1wwr4f-jmm501zf.js +13 -0
- package/.mochi/svelte-client/_hydrate-InstanceView_2ma45l9bybfhl-ewk4n2c0.js +1 -0
- package/.mochi/svelte-client/_hydrate-SettingsView_8hmarwmf8onq-e7e89md0.js +23 -0
- package/.mochi/svelte-client/chunk-jx5cekhh.js +2 -0
- package/.mochi/svelte-client/chunk-k3my1snp.js +2 -0
- package/.mochi/svelte-client/chunk-kgn1b2t1.js +4 -0
- package/.mochi/svelte-client/chunk-ry7q5zk5.js +1 -0
- package/.mochi/svelte-client/chunk-x843txjc.js +2 -0
- package/.mochi/svelte-client/chunk-zjcg8kw5.js +2 -0
- package/.mochi/svelte-compile/App-8k1gyxdc.server.js +1167 -0
- package/.mochi/svelte-compile/Avatars-f7c6rp96.server.js +351 -0
- package/.mochi/svelte-compile/ClientStats-z3tn9ad6.server.js +99 -0
- package/.mochi/svelte-compile/DefaultError-wh77vebf.server.js +52 -0
- package/.mochi/svelte-compile/Instance-yvps12zg.server.js +355 -0
- package/.mochi/svelte-compile/Settings-jwg3httb.server.js +1169 -0
- package/.mochi/svelte-compile/chunk-4kwy539a.js +14 -0
- package/.mochi/svelte-compile/chunk-9bjk7yx6.js +81 -0
- package/.mochi/svelte-compile/chunk-dqgstte4.js +52 -0
- package/.mochi/svelte-compile/chunk-sxqys3nw.js +1668 -0
- package/.mochi/svelte-compile/chunk-v6796ga4.js +3295 -0
- package/.mochi/svelte-compile/chunk-we0ggtws.js +34 -0
- package/.mochi/svelte-css/AppBar-3bxinv4pabv8l.css +1 -0
- package/.mochi/svelte-css/AppShell-36mpg5smnbmuw.css +1 -0
- package/.mochi/svelte-css/Avatar-24th63awm9mna.css +1 -0
- package/.mochi/svelte-css/AvatarEditor-1ryrs1md5g36y.css +1 -0
- package/.mochi/svelte-css/AvatarsView-3hq37u4dgtljn.css +1 -0
- package/.mochi/svelte-css/BackLink-2wlu0eovz9j86.css +1 -0
- package/.mochi/svelte-css/BranchBox-1yqu1q2mgnjwz.css +1 -0
- package/.mochi/svelte-css/Brand-1la7zw5uhcbl4.css +1 -0
- package/.mochi/svelte-css/Button-2vtbrzb5kgu25.css +1 -0
- package/.mochi/svelte-css/CheckmarkIcon-3qlazj2oc50jc.css +1 -0
- package/.mochi/svelte-css/ClientStats-19qzckq40p2q9.css +1 -0
- package/.mochi/svelte-css/CoinButton-1rej3sh3tkjud.css +1 -0
- package/.mochi/svelte-css/CredMenu-9hwgeptp7crb.css +1 -0
- package/.mochi/svelte-css/DashboardView-1cy4xpqhja9sx.css +1 -0
- package/.mochi/svelte-css/DefaultError-2b0daamydxgb2.css +1 -0
- package/.mochi/svelte-css/ErrorIcon-2x0tzsqxskw28.css +1 -0
- package/.mochi/svelte-css/FolderBrowser-1x428zb3f2kti.css +1 -0
- package/.mochi/svelte-css/HealthBox-er2her0jukwl.css +1 -0
- package/.mochi/svelte-css/IdeBar-2qoqi2ya9zdn3.css +1 -0
- package/.mochi/svelte-css/IdeLoader-26rlko8e00j3g.css +1 -0
- package/.mochi/svelte-css/InstanceCard-16f77aysm7lgp.css +1 -0
- package/.mochi/svelte-css/InstanceView-wq85bxtusont.css +1 -0
- package/.mochi/svelte-css/LoaderIcon-soq5wt3p05ye.css +1 -0
- package/.mochi/svelte-css/PortsBox-1t25b5yg7jva3.css +1 -0
- package/.mochi/svelte-css/SettingsCog-jftyadvo64qo.css +1 -0
- package/.mochi/svelte-css/SettingsView-3bbkzsvnrth3v.css +1 -0
- package/.mochi/svelte-css/Skeleton-8k69usiju43h.css +1 -0
- package/.mochi/svelte-css/StatusBadge-3mq0j7z6aq4j.css +1 -0
- package/.mochi/svelte-css/ThemePicker-1ir8jyocm8mvi.css +1 -0
- package/.mochi/svelte-css/ToastBar-3havgkmtofntq.css +1 -0
- package/.mochi/svelte-css/ToastIcon-2z5wrkc95khg0.css +1 -0
- package/.mochi/svelte-css/ToastMessage-2jfwb2og2lfa8.css +1 -0
- package/.mochi/svelte-css/ToastWrapper-1fbnym10rm2nv.css +1 -0
- package/.mochi/svelte-css/Toaster-kk60j193854n.css +1 -0
- package/.mochi/svelte-css/TopBar-2q87li6yt8ids.css +1 -0
- package/LICENSE +21 -0
- package/README.md +33 -3
- package/bin/codebay.ts +22 -0
- package/migrations/0001_init.sql +20 -0
- package/migrations/0002_port_forwards.sql +9 -0
- package/migrations/0003_options.sql +4 -0
- package/migrations/0004_instance_image.sql +1 -0
- package/package.json +87 -9
- package/public/sounds/done.wav +0 -0
- package/public/sounds/waiting.wav +0 -0
- package/src/__fixtures__/HelloWorld.svelte +4 -0
- package/src/additional-svelte-typings.d.ts +1 -0
- package/src/api.ts +61 -0
- package/src/avatars/anchor.ts +17 -0
- package/src/avatars/bear.ts +17 -0
- package/src/avatars/bee.ts +17 -0
- package/src/avatars/bob-marley.ts +17 -0
- package/src/avatars/car.ts +17 -0
- package/src/avatars/carpathians.ts +17 -0
- package/src/avatars/cat-body.ts +17 -0
- package/src/avatars/cat-sits.ts +17 -0
- package/src/avatars/cat.ts +17 -0
- package/src/avatars/celtic-cross.ts +17 -0
- package/src/avatars/cherry.ts +17 -0
- package/src/avatars/cotton.ts +17 -0
- package/src/avatars/crab.ts +17 -0
- package/src/avatars/crown.ts +17 -0
- package/src/avatars/diamond.ts +17 -0
- package/src/avatars/dog.ts +17 -0
- package/src/avatars/elephant.ts +17 -0
- package/src/avatars/fish.ts +17 -0
- package/src/avatars/fleur-de-lis.ts +17 -0
- package/src/avatars/flower.ts +17 -0
- package/src/avatars/fox.ts +17 -0
- package/src/avatars/frog.ts +17 -0
- package/src/avatars/ghost.ts +17 -0
- package/src/avatars/giraffe.ts +17 -0
- package/src/avatars/glasses.ts +17 -0
- package/src/avatars/heart.ts +17 -0
- package/src/avatars/index.ts +128 -0
- package/src/avatars/invader.ts +17 -0
- package/src/avatars/kangaroo.ts +17 -0
- package/src/avatars/key.ts +17 -0
- package/src/avatars/lightning.ts +17 -0
- package/src/avatars/mushroom.ts +17 -0
- package/src/avatars/octopus.ts +17 -0
- package/src/avatars/owl.ts +17 -0
- package/src/avatars/penguin.ts +17 -0
- package/src/avatars/planet.ts +17 -0
- package/src/avatars/rabbit.ts +17 -0
- package/src/avatars/rat.ts +17 -0
- package/src/avatars/robot.ts +17 -0
- package/src/avatars/rocket.ts +17 -0
- package/src/avatars/sea.ts +17 -0
- package/src/avatars/serialize.ts +65 -0
- package/src/avatars/skull.ts +17 -0
- package/src/avatars/snail.ts +17 -0
- package/src/avatars/snake.ts +17 -0
- package/src/avatars/snakegame.ts +17 -0
- package/src/avatars/star.ts +17 -0
- package/src/avatars/svelte.ts +17 -0
- package/src/avatars/target.ts +17 -0
- package/src/avatars/tree.ts +17 -0
- package/src/avatars/types.ts +24 -0
- package/src/avatars/ukraine.ts +17 -0
- package/src/avatars/whale.ts +17 -0
- package/src/avatars/wheat.ts +17 -0
- package/src/avatars/yinyan.ts +17 -0
- package/src/components/AppBar.svelte +35 -0
- package/src/components/AppShell.svelte +302 -0
- package/src/components/Avatar.svelte +235 -0
- package/src/components/AvatarEditor.svelte +321 -0
- package/src/components/AvatarsView.svelte +113 -0
- package/src/components/BranchBox.svelte +32 -0
- package/src/components/Brand.svelte +41 -0
- package/src/components/Button.svelte +161 -0
- package/src/components/CoinButton.svelte +121 -0
- package/src/components/CredMenu.svelte +171 -0
- package/src/components/DashboardView.svelte +198 -0
- package/src/components/FolderBrowser.svelte +635 -0
- package/src/components/HealthBox.svelte +161 -0
- package/src/components/IdeBar.svelte +186 -0
- package/src/components/IdeLoader.svelte +135 -0
- package/src/components/InstanceCard.svelte +220 -0
- package/src/components/InstanceView.svelte +565 -0
- package/src/components/PortsBox.svelte +73 -0
- package/src/components/SettingsCog.svelte +22 -0
- package/src/components/SettingsView.svelte +1484 -0
- package/src/components/Skeleton.svelte +43 -0
- package/src/components/StatusBadge.svelte +54 -0
- package/src/components/ThemePicker.svelte +77 -0
- package/src/components/TopBar.svelte +64 -0
- package/src/components/UiShowcase.svelte +578 -0
- package/src/components/ui-showcase/ComponentDemo.svelte +85 -0
- package/src/container-injections/attention-hooks.ts +117 -0
- package/src/container-injections/claude-aliases.ts +43 -0
- package/src/container-injections/claude-code-credentials.ts +145 -0
- package/src/container-injections/claude-code-custom.ts +125 -0
- package/src/container-injections/claude-no-coauthor.ts +35 -0
- package/src/container-injections/claude-skip-permissions.ts +38 -0
- package/src/container-injections/claude-statusline.ts +109 -0
- package/src/container-injections/git-identity.ts +63 -0
- package/src/container-injections/git-safe-directory.ts +18 -0
- package/src/container-injections/github-credentials.ts +162 -0
- package/src/container-injections/host-env-vars.ts +108 -0
- package/src/container-injections/tmux.ts +67 -0
- package/src/fontsource.d.ts +3 -0
- package/src/index.ts +81 -0
- package/src/lib/auth.server.ts +95 -0
- package/src/lib/bridge.server.ts +34 -0
- package/src/lib/config.server.ts +122 -0
- package/src/lib/crypto.server.ts +12 -0
- package/src/lib/db.server.ts +196 -0
- package/src/lib/devcontainer.server.ts +503 -0
- package/src/lib/docker-client.server.ts +61 -0
- package/src/lib/docker.server.ts +139 -0
- package/src/lib/exec.server.ts +92 -0
- package/src/lib/git.server.ts +68 -0
- package/src/lib/health.server.ts +105 -0
- package/src/lib/injections.server.ts +72 -0
- package/src/lib/instances.server.ts +552 -0
- package/src/lib/picker.server.ts +46 -0
- package/src/lib/ports.server.ts +9 -0
- package/src/lib/proxy.server.ts +170 -0
- package/src/lib/repo-url.ts +60 -0
- package/src/lib/spawn.server.ts +14 -0
- package/src/lib/theme.server.ts +22 -0
- package/src/live.ts +50 -0
- package/src/pages/App.svelte +14 -0
- package/src/pages/Avatars.svelte +7 -0
- package/src/pages/Instance.svelte +9 -0
- package/src/pages/Settings.svelte +73 -0
- package/src/pages/UI.svelte +10 -0
- package/src/routes.ts +440 -0
- package/src/settings.ts +14 -0
- package/src/shell.html +100 -0
- package/src/sound.ts +69 -0
- package/src/theme.ts +24 -0
- package/src/types.ts +79 -0
- package/svelte.config.js +5 -0
|
@@ -0,0 +1,3295 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
__commonJS,
|
|
4
|
+
__toESM
|
|
5
|
+
} from "./chunk-we0ggtws.js";
|
|
6
|
+
|
|
7
|
+
// node_modules/ipaddr.js/lib/ipaddr.js
|
|
8
|
+
var require_ipaddr = __commonJS((exports, module) => {
|
|
9
|
+
(function(root) {
|
|
10
|
+
const ipv4Part = "(0?\\d+|0x[a-f0-9]+)";
|
|
11
|
+
const ipv4Regexes = {
|
|
12
|
+
fourOctet: new RegExp(`^${ipv4Part}\\.${ipv4Part}\\.${ipv4Part}\\.${ipv4Part}$`, "i"),
|
|
13
|
+
threeOctet: new RegExp(`^${ipv4Part}\\.${ipv4Part}\\.${ipv4Part}$`, "i"),
|
|
14
|
+
twoOctet: new RegExp(`^${ipv4Part}\\.${ipv4Part}$`, "i"),
|
|
15
|
+
longValue: new RegExp(`^${ipv4Part}$`, "i")
|
|
16
|
+
};
|
|
17
|
+
const octalRegex = new RegExp(`^0[0-7]+$`, "i");
|
|
18
|
+
const hexRegex = new RegExp(`^0x[a-f0-9]+$`, "i");
|
|
19
|
+
const zoneIndex = "%[0-9a-z]{1,}";
|
|
20
|
+
const ipv6Part = "(?:[0-9a-f]+::?)+";
|
|
21
|
+
const ipv6Regexes = {
|
|
22
|
+
zoneIndex: new RegExp(zoneIndex, "i"),
|
|
23
|
+
native: new RegExp(`^(::)?(${ipv6Part})?([0-9a-f]+)?(::)?(${zoneIndex})?$`, "i"),
|
|
24
|
+
deprecatedTransitional: new RegExp(`^(?:::)(${ipv4Part}\\.${ipv4Part}\\.${ipv4Part}\\.${ipv4Part}(${zoneIndex})?)$`, "i"),
|
|
25
|
+
transitional: new RegExp(`^((?:${ipv6Part})|(?:::)(?:${ipv6Part})?)${ipv4Part}\\.${ipv4Part}\\.${ipv4Part}\\.${ipv4Part}(${zoneIndex})?$`, "i")
|
|
26
|
+
};
|
|
27
|
+
function expandIPv6(string, parts) {
|
|
28
|
+
if (string.indexOf("::") !== string.lastIndexOf("::")) {
|
|
29
|
+
return null;
|
|
30
|
+
}
|
|
31
|
+
let colonCount = 0;
|
|
32
|
+
let lastColon = -1;
|
|
33
|
+
let zoneId = (string.match(ipv6Regexes.zoneIndex) || [])[0];
|
|
34
|
+
let replacement, replacementCount;
|
|
35
|
+
if (zoneId) {
|
|
36
|
+
zoneId = zoneId.substring(1);
|
|
37
|
+
string = string.replace(/%.+$/, "");
|
|
38
|
+
}
|
|
39
|
+
while ((lastColon = string.indexOf(":", lastColon + 1)) >= 0) {
|
|
40
|
+
colonCount++;
|
|
41
|
+
}
|
|
42
|
+
if (string.substr(0, 2) === "::") {
|
|
43
|
+
colonCount--;
|
|
44
|
+
}
|
|
45
|
+
if (string.substr(-2, 2) === "::") {
|
|
46
|
+
colonCount--;
|
|
47
|
+
}
|
|
48
|
+
if (colonCount > parts) {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
replacementCount = parts - colonCount;
|
|
52
|
+
replacement = ":";
|
|
53
|
+
while (replacementCount--) {
|
|
54
|
+
replacement += "0:";
|
|
55
|
+
}
|
|
56
|
+
string = string.replace("::", replacement);
|
|
57
|
+
if (string[0] === ":") {
|
|
58
|
+
string = string.slice(1);
|
|
59
|
+
}
|
|
60
|
+
if (string[string.length - 1] === ":") {
|
|
61
|
+
string = string.slice(0, -1);
|
|
62
|
+
}
|
|
63
|
+
parts = function() {
|
|
64
|
+
const ref = string.split(":");
|
|
65
|
+
const results = [];
|
|
66
|
+
for (let i = 0;i < ref.length; i++) {
|
|
67
|
+
results.push(parseInt(ref[i], 16));
|
|
68
|
+
}
|
|
69
|
+
return results;
|
|
70
|
+
}();
|
|
71
|
+
return {
|
|
72
|
+
parts,
|
|
73
|
+
zoneId
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function matchCIDR(first, second, partSize, cidrBits) {
|
|
77
|
+
if (first.length !== second.length) {
|
|
78
|
+
throw new Error("ipaddr: cannot match CIDR for objects with different lengths");
|
|
79
|
+
}
|
|
80
|
+
let part = 0;
|
|
81
|
+
let shift;
|
|
82
|
+
while (cidrBits > 0) {
|
|
83
|
+
shift = partSize - cidrBits;
|
|
84
|
+
if (shift < 0) {
|
|
85
|
+
shift = 0;
|
|
86
|
+
}
|
|
87
|
+
if (first[part] >> shift !== second[part] >> shift) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
cidrBits -= partSize;
|
|
91
|
+
part += 1;
|
|
92
|
+
}
|
|
93
|
+
return true;
|
|
94
|
+
}
|
|
95
|
+
function parseIntAuto(string) {
|
|
96
|
+
if (hexRegex.test(string)) {
|
|
97
|
+
return parseInt(string, 16);
|
|
98
|
+
}
|
|
99
|
+
if (string[0] === "0" && !isNaN(parseInt(string[1], 10))) {
|
|
100
|
+
if (octalRegex.test(string)) {
|
|
101
|
+
return parseInt(string, 8);
|
|
102
|
+
}
|
|
103
|
+
throw new Error(`ipaddr: cannot parse ${string} as octal`);
|
|
104
|
+
}
|
|
105
|
+
return parseInt(string, 10);
|
|
106
|
+
}
|
|
107
|
+
function padPart(part, length) {
|
|
108
|
+
while (part.length < length) {
|
|
109
|
+
part = `0${part}`;
|
|
110
|
+
}
|
|
111
|
+
return part;
|
|
112
|
+
}
|
|
113
|
+
const ipaddr = {};
|
|
114
|
+
ipaddr.IPv4 = function() {
|
|
115
|
+
function IPv4(octets) {
|
|
116
|
+
if (octets.length !== 4) {
|
|
117
|
+
throw new Error("ipaddr: ipv4 octet count should be 4");
|
|
118
|
+
}
|
|
119
|
+
let i, octet;
|
|
120
|
+
for (i = 0;i < octets.length; i++) {
|
|
121
|
+
octet = octets[i];
|
|
122
|
+
if (!(0 <= octet && octet <= 255)) {
|
|
123
|
+
throw new Error("ipaddr: ipv4 octet should fit in 8 bits");
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
this.octets = octets;
|
|
127
|
+
}
|
|
128
|
+
IPv4.prototype.SpecialRanges = {
|
|
129
|
+
unspecified: [[new IPv4([0, 0, 0, 0]), 8]],
|
|
130
|
+
broadcast: [[new IPv4([255, 255, 255, 255]), 32]],
|
|
131
|
+
multicast: [[new IPv4([224, 0, 0, 0]), 4]],
|
|
132
|
+
linkLocal: [[new IPv4([169, 254, 0, 0]), 16]],
|
|
133
|
+
loopback: [[new IPv4([127, 0, 0, 0]), 8]],
|
|
134
|
+
carrierGradeNat: [[new IPv4([100, 64, 0, 0]), 10]],
|
|
135
|
+
private: [
|
|
136
|
+
[new IPv4([10, 0, 0, 0]), 8],
|
|
137
|
+
[new IPv4([172, 16, 0, 0]), 12],
|
|
138
|
+
[new IPv4([192, 168, 0, 0]), 16]
|
|
139
|
+
],
|
|
140
|
+
reserved: [
|
|
141
|
+
[new IPv4([192, 0, 0, 0]), 24],
|
|
142
|
+
[new IPv4([192, 0, 2, 0]), 24],
|
|
143
|
+
[new IPv4([192, 88, 99, 0]), 24],
|
|
144
|
+
[new IPv4([198, 18, 0, 0]), 15],
|
|
145
|
+
[new IPv4([198, 51, 100, 0]), 24],
|
|
146
|
+
[new IPv4([203, 0, 113, 0]), 24],
|
|
147
|
+
[new IPv4([240, 0, 0, 0]), 4]
|
|
148
|
+
],
|
|
149
|
+
as112: [
|
|
150
|
+
[new IPv4([192, 175, 48, 0]), 24],
|
|
151
|
+
[new IPv4([192, 31, 196, 0]), 24]
|
|
152
|
+
],
|
|
153
|
+
amt: [
|
|
154
|
+
[new IPv4([192, 52, 193, 0]), 24]
|
|
155
|
+
]
|
|
156
|
+
};
|
|
157
|
+
IPv4.prototype.kind = function() {
|
|
158
|
+
return "ipv4";
|
|
159
|
+
};
|
|
160
|
+
IPv4.prototype.match = function(other, cidrRange) {
|
|
161
|
+
let ref;
|
|
162
|
+
if (cidrRange === undefined) {
|
|
163
|
+
ref = other;
|
|
164
|
+
other = ref[0];
|
|
165
|
+
cidrRange = ref[1];
|
|
166
|
+
}
|
|
167
|
+
if (other.kind() !== "ipv4") {
|
|
168
|
+
throw new Error("ipaddr: cannot match ipv4 address with non-ipv4 one");
|
|
169
|
+
}
|
|
170
|
+
return matchCIDR(this.octets, other.octets, 8, cidrRange);
|
|
171
|
+
};
|
|
172
|
+
IPv4.prototype.prefixLengthFromSubnetMask = function() {
|
|
173
|
+
let cidr = 0;
|
|
174
|
+
let stop = false;
|
|
175
|
+
const zerotable = {
|
|
176
|
+
0: 8,
|
|
177
|
+
128: 7,
|
|
178
|
+
192: 6,
|
|
179
|
+
224: 5,
|
|
180
|
+
240: 4,
|
|
181
|
+
248: 3,
|
|
182
|
+
252: 2,
|
|
183
|
+
254: 1,
|
|
184
|
+
255: 0
|
|
185
|
+
};
|
|
186
|
+
let i, octet, zeros;
|
|
187
|
+
for (i = 3;i >= 0; i -= 1) {
|
|
188
|
+
octet = this.octets[i];
|
|
189
|
+
if (octet in zerotable) {
|
|
190
|
+
zeros = zerotable[octet];
|
|
191
|
+
if (stop && zeros !== 0) {
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
if (zeros !== 8) {
|
|
195
|
+
stop = true;
|
|
196
|
+
}
|
|
197
|
+
cidr += zeros;
|
|
198
|
+
} else {
|
|
199
|
+
return null;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
return 32 - cidr;
|
|
203
|
+
};
|
|
204
|
+
IPv4.prototype.range = function() {
|
|
205
|
+
return ipaddr.subnetMatch(this, this.SpecialRanges);
|
|
206
|
+
};
|
|
207
|
+
IPv4.prototype.toByteArray = function() {
|
|
208
|
+
return this.octets.slice(0);
|
|
209
|
+
};
|
|
210
|
+
IPv4.prototype.toIPv4MappedAddress = function() {
|
|
211
|
+
return ipaddr.IPv6.parse(`::ffff:${this.toString()}`);
|
|
212
|
+
};
|
|
213
|
+
IPv4.prototype.toNormalizedString = function() {
|
|
214
|
+
return this.toString();
|
|
215
|
+
};
|
|
216
|
+
IPv4.prototype.toString = function() {
|
|
217
|
+
return this.octets.join(".");
|
|
218
|
+
};
|
|
219
|
+
return IPv4;
|
|
220
|
+
}();
|
|
221
|
+
ipaddr.IPv4.broadcastAddressFromCIDR = function(string) {
|
|
222
|
+
try {
|
|
223
|
+
const cidr = this.parseCIDR(string);
|
|
224
|
+
const ipInterfaceOctets = cidr[0].toByteArray();
|
|
225
|
+
const subnetMaskOctets = this.subnetMaskFromPrefixLength(cidr[1]).toByteArray();
|
|
226
|
+
const octets = [];
|
|
227
|
+
let i = 0;
|
|
228
|
+
while (i < 4) {
|
|
229
|
+
octets.push(parseInt(ipInterfaceOctets[i], 10) | parseInt(subnetMaskOctets[i], 10) ^ 255);
|
|
230
|
+
i++;
|
|
231
|
+
}
|
|
232
|
+
return new this(octets);
|
|
233
|
+
} catch (e) {
|
|
234
|
+
throw new Error("ipaddr: the address does not have IPv4 CIDR format");
|
|
235
|
+
}
|
|
236
|
+
};
|
|
237
|
+
ipaddr.IPv4.isIPv4 = function(string) {
|
|
238
|
+
return this.parser(string) !== null;
|
|
239
|
+
};
|
|
240
|
+
ipaddr.IPv4.isValid = function(string) {
|
|
241
|
+
try {
|
|
242
|
+
new this(this.parser(string));
|
|
243
|
+
return true;
|
|
244
|
+
} catch (e) {
|
|
245
|
+
return false;
|
|
246
|
+
}
|
|
247
|
+
};
|
|
248
|
+
ipaddr.IPv4.isValidCIDR = function(string) {
|
|
249
|
+
try {
|
|
250
|
+
this.parseCIDR(string);
|
|
251
|
+
return true;
|
|
252
|
+
} catch (e) {
|
|
253
|
+
return false;
|
|
254
|
+
}
|
|
255
|
+
};
|
|
256
|
+
ipaddr.IPv4.isValidFourPartDecimal = function(string) {
|
|
257
|
+
if (ipaddr.IPv4.isValid(string) && string.match(/^(0|[1-9]\d*)(\.(0|[1-9]\d*)){3}$/)) {
|
|
258
|
+
return true;
|
|
259
|
+
} else {
|
|
260
|
+
return false;
|
|
261
|
+
}
|
|
262
|
+
};
|
|
263
|
+
ipaddr.IPv4.isValidCIDRFourPartDecimal = function(string) {
|
|
264
|
+
const match = string.match(/^(.+)\/(\d+)$/);
|
|
265
|
+
if (!ipaddr.IPv4.isValidCIDR(string) || !match) {
|
|
266
|
+
return false;
|
|
267
|
+
}
|
|
268
|
+
return ipaddr.IPv4.isValidFourPartDecimal(match[1]);
|
|
269
|
+
};
|
|
270
|
+
ipaddr.IPv4.networkAddressFromCIDR = function(string) {
|
|
271
|
+
let cidr, i, ipInterfaceOctets, octets, subnetMaskOctets;
|
|
272
|
+
try {
|
|
273
|
+
cidr = this.parseCIDR(string);
|
|
274
|
+
ipInterfaceOctets = cidr[0].toByteArray();
|
|
275
|
+
subnetMaskOctets = this.subnetMaskFromPrefixLength(cidr[1]).toByteArray();
|
|
276
|
+
octets = [];
|
|
277
|
+
i = 0;
|
|
278
|
+
while (i < 4) {
|
|
279
|
+
octets.push(parseInt(ipInterfaceOctets[i], 10) & parseInt(subnetMaskOctets[i], 10));
|
|
280
|
+
i++;
|
|
281
|
+
}
|
|
282
|
+
return new this(octets);
|
|
283
|
+
} catch (e) {
|
|
284
|
+
throw new Error("ipaddr: the address does not have IPv4 CIDR format");
|
|
285
|
+
}
|
|
286
|
+
};
|
|
287
|
+
ipaddr.IPv4.parse = function(string) {
|
|
288
|
+
const parts = this.parser(string);
|
|
289
|
+
if (parts === null) {
|
|
290
|
+
throw new Error("ipaddr: string is not formatted like an IPv4 Address");
|
|
291
|
+
}
|
|
292
|
+
return new this(parts);
|
|
293
|
+
};
|
|
294
|
+
ipaddr.IPv4.parseCIDR = function(string) {
|
|
295
|
+
let match;
|
|
296
|
+
if (match = string.match(/^(.+)\/(\d+)$/)) {
|
|
297
|
+
const maskLength = parseInt(match[2]);
|
|
298
|
+
if (maskLength >= 0 && maskLength <= 32) {
|
|
299
|
+
const parsed = [this.parse(match[1]), maskLength];
|
|
300
|
+
Object.defineProperty(parsed, "toString", {
|
|
301
|
+
value: function() {
|
|
302
|
+
return this.join("/");
|
|
303
|
+
}
|
|
304
|
+
});
|
|
305
|
+
return parsed;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
throw new Error("ipaddr: string is not formatted like an IPv4 CIDR range");
|
|
309
|
+
};
|
|
310
|
+
ipaddr.IPv4.parser = function(string) {
|
|
311
|
+
let match, part, value;
|
|
312
|
+
if (match = string.match(ipv4Regexes.fourOctet)) {
|
|
313
|
+
return function() {
|
|
314
|
+
const ref = match.slice(1, 6);
|
|
315
|
+
const results = [];
|
|
316
|
+
for (let i = 0;i < ref.length; i++) {
|
|
317
|
+
part = ref[i];
|
|
318
|
+
results.push(parseIntAuto(part));
|
|
319
|
+
}
|
|
320
|
+
return results;
|
|
321
|
+
}();
|
|
322
|
+
} else if (match = string.match(ipv4Regexes.longValue)) {
|
|
323
|
+
value = parseIntAuto(match[1]);
|
|
324
|
+
if (value > 4294967295 || value < 0) {
|
|
325
|
+
throw new Error("ipaddr: address outside defined range");
|
|
326
|
+
}
|
|
327
|
+
return function() {
|
|
328
|
+
const results = [];
|
|
329
|
+
let shift;
|
|
330
|
+
for (shift = 0;shift <= 24; shift += 8) {
|
|
331
|
+
results.push(value >> shift & 255);
|
|
332
|
+
}
|
|
333
|
+
return results;
|
|
334
|
+
}().reverse();
|
|
335
|
+
} else if (match = string.match(ipv4Regexes.twoOctet)) {
|
|
336
|
+
return function() {
|
|
337
|
+
const ref = match.slice(1, 4);
|
|
338
|
+
const results = [];
|
|
339
|
+
value = parseIntAuto(ref[1]);
|
|
340
|
+
if (value > 16777215 || value < 0) {
|
|
341
|
+
throw new Error("ipaddr: address outside defined range");
|
|
342
|
+
}
|
|
343
|
+
results.push(parseIntAuto(ref[0]));
|
|
344
|
+
results.push(value >> 16 & 255);
|
|
345
|
+
results.push(value >> 8 & 255);
|
|
346
|
+
results.push(value & 255);
|
|
347
|
+
return results;
|
|
348
|
+
}();
|
|
349
|
+
} else if (match = string.match(ipv4Regexes.threeOctet)) {
|
|
350
|
+
return function() {
|
|
351
|
+
const ref = match.slice(1, 5);
|
|
352
|
+
const results = [];
|
|
353
|
+
value = parseIntAuto(ref[2]);
|
|
354
|
+
if (value > 65535 || value < 0) {
|
|
355
|
+
throw new Error("ipaddr: address outside defined range");
|
|
356
|
+
}
|
|
357
|
+
results.push(parseIntAuto(ref[0]));
|
|
358
|
+
results.push(parseIntAuto(ref[1]));
|
|
359
|
+
results.push(value >> 8 & 255);
|
|
360
|
+
results.push(value & 255);
|
|
361
|
+
return results;
|
|
362
|
+
}();
|
|
363
|
+
} else {
|
|
364
|
+
return null;
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
ipaddr.IPv4.subnetMaskFromPrefixLength = function(prefix) {
|
|
368
|
+
prefix = parseInt(prefix);
|
|
369
|
+
if (prefix < 0 || prefix > 32) {
|
|
370
|
+
throw new Error("ipaddr: invalid IPv4 prefix length");
|
|
371
|
+
}
|
|
372
|
+
const octets = [0, 0, 0, 0];
|
|
373
|
+
let j = 0;
|
|
374
|
+
const filledOctetCount = Math.floor(prefix / 8);
|
|
375
|
+
while (j < filledOctetCount) {
|
|
376
|
+
octets[j] = 255;
|
|
377
|
+
j++;
|
|
378
|
+
}
|
|
379
|
+
if (filledOctetCount < 4) {
|
|
380
|
+
octets[filledOctetCount] = Math.pow(2, prefix % 8) - 1 << 8 - prefix % 8;
|
|
381
|
+
}
|
|
382
|
+
return new this(octets);
|
|
383
|
+
};
|
|
384
|
+
ipaddr.IPv6 = function() {
|
|
385
|
+
function IPv6(parts, zoneId) {
|
|
386
|
+
let i, part;
|
|
387
|
+
if (parts.length === 16) {
|
|
388
|
+
this.parts = [];
|
|
389
|
+
for (i = 0;i <= 14; i += 2) {
|
|
390
|
+
this.parts.push(parts[i] << 8 | parts[i + 1]);
|
|
391
|
+
}
|
|
392
|
+
} else if (parts.length === 8) {
|
|
393
|
+
this.parts = parts;
|
|
394
|
+
} else {
|
|
395
|
+
throw new Error("ipaddr: ipv6 part count should be 8 or 16");
|
|
396
|
+
}
|
|
397
|
+
for (i = 0;i < this.parts.length; i++) {
|
|
398
|
+
part = this.parts[i];
|
|
399
|
+
if (!(0 <= part && part <= 65535)) {
|
|
400
|
+
throw new Error("ipaddr: ipv6 part should fit in 16 bits");
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
if (zoneId) {
|
|
404
|
+
this.zoneId = zoneId;
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
IPv6.prototype.SpecialRanges = {
|
|
408
|
+
unspecified: [new IPv6([0, 0, 0, 0, 0, 0, 0, 0]), 128],
|
|
409
|
+
linkLocal: [new IPv6([65152, 0, 0, 0, 0, 0, 0, 0]), 10],
|
|
410
|
+
multicast: [new IPv6([65280, 0, 0, 0, 0, 0, 0, 0]), 8],
|
|
411
|
+
loopback: [new IPv6([0, 0, 0, 0, 0, 0, 0, 1]), 128],
|
|
412
|
+
uniqueLocal: [new IPv6([64512, 0, 0, 0, 0, 0, 0, 0]), 7],
|
|
413
|
+
ipv4Mapped: [new IPv6([0, 0, 0, 0, 0, 65535, 0, 0]), 96],
|
|
414
|
+
deprecatedSiteLocal: [new IPv6([65216, 0, 0, 0, 0, 0, 0, 0]), 10],
|
|
415
|
+
discard: [new IPv6([256, 0, 0, 0, 0, 0, 0, 0]), 64],
|
|
416
|
+
rfc6145: [new IPv6([0, 0, 0, 0, 65535, 0, 0, 0]), 96],
|
|
417
|
+
rfc6052: [
|
|
418
|
+
[new IPv6([100, 65435, 0, 0, 0, 0, 0, 0]), 96],
|
|
419
|
+
[new IPv6([100, 65435, 1, 0, 0, 0, 0, 0]), 48]
|
|
420
|
+
],
|
|
421
|
+
"6to4": [new IPv6([8194, 0, 0, 0, 0, 0, 0, 0]), 16],
|
|
422
|
+
teredo: [new IPv6([8193, 0, 0, 0, 0, 0, 0, 0]), 32],
|
|
423
|
+
benchmarking: [new IPv6([8193, 2, 0, 0, 0, 0, 0, 0]), 48],
|
|
424
|
+
amt: [new IPv6([8193, 3, 0, 0, 0, 0, 0, 0]), 32],
|
|
425
|
+
as112v6: [
|
|
426
|
+
[new IPv6([8193, 4, 274, 0, 0, 0, 0, 0]), 48],
|
|
427
|
+
[new IPv6([9760, 79, 32768, 0, 0, 0, 0, 0]), 48]
|
|
428
|
+
],
|
|
429
|
+
deprecatedOrchid: [new IPv6([8193, 16, 0, 0, 0, 0, 0, 0]), 28],
|
|
430
|
+
orchid2: [new IPv6([8193, 32, 0, 0, 0, 0, 0, 0]), 28],
|
|
431
|
+
droneRemoteIdProtocolEntityTags: [new IPv6([8193, 48, 0, 0, 0, 0, 0, 0]), 28],
|
|
432
|
+
segmentRouting: [new IPv6([24320, 0, 0, 0, 0, 0, 0, 0]), 16],
|
|
433
|
+
reserved: [
|
|
434
|
+
[new IPv6([8193, 0, 0, 0, 0, 0, 0, 0]), 23],
|
|
435
|
+
[new IPv6([8193, 3512, 0, 0, 0, 0, 0, 0]), 32],
|
|
436
|
+
[new IPv6([16383, 0, 0, 0, 0, 0, 0, 0]), 20]
|
|
437
|
+
]
|
|
438
|
+
};
|
|
439
|
+
IPv6.prototype.isIPv4MappedAddress = function() {
|
|
440
|
+
return this.range() === "ipv4Mapped";
|
|
441
|
+
};
|
|
442
|
+
IPv6.prototype.kind = function() {
|
|
443
|
+
return "ipv6";
|
|
444
|
+
};
|
|
445
|
+
IPv6.prototype.match = function(other, cidrRange) {
|
|
446
|
+
let ref;
|
|
447
|
+
if (cidrRange === undefined) {
|
|
448
|
+
ref = other;
|
|
449
|
+
other = ref[0];
|
|
450
|
+
cidrRange = ref[1];
|
|
451
|
+
}
|
|
452
|
+
if (other.kind() !== "ipv6") {
|
|
453
|
+
throw new Error("ipaddr: cannot match ipv6 address with non-ipv6 one");
|
|
454
|
+
}
|
|
455
|
+
return matchCIDR(this.parts, other.parts, 16, cidrRange);
|
|
456
|
+
};
|
|
457
|
+
IPv6.prototype.prefixLengthFromSubnetMask = function() {
|
|
458
|
+
let cidr = 0;
|
|
459
|
+
let stop = false;
|
|
460
|
+
const zerotable = {
|
|
461
|
+
0: 16,
|
|
462
|
+
32768: 15,
|
|
463
|
+
49152: 14,
|
|
464
|
+
57344: 13,
|
|
465
|
+
61440: 12,
|
|
466
|
+
63488: 11,
|
|
467
|
+
64512: 10,
|
|
468
|
+
65024: 9,
|
|
469
|
+
65280: 8,
|
|
470
|
+
65408: 7,
|
|
471
|
+
65472: 6,
|
|
472
|
+
65504: 5,
|
|
473
|
+
65520: 4,
|
|
474
|
+
65528: 3,
|
|
475
|
+
65532: 2,
|
|
476
|
+
65534: 1,
|
|
477
|
+
65535: 0
|
|
478
|
+
};
|
|
479
|
+
let part, zeros;
|
|
480
|
+
for (let i = 7;i >= 0; i -= 1) {
|
|
481
|
+
part = this.parts[i];
|
|
482
|
+
if (part in zerotable) {
|
|
483
|
+
zeros = zerotable[part];
|
|
484
|
+
if (stop && zeros !== 0) {
|
|
485
|
+
return null;
|
|
486
|
+
}
|
|
487
|
+
if (zeros !== 16) {
|
|
488
|
+
stop = true;
|
|
489
|
+
}
|
|
490
|
+
cidr += zeros;
|
|
491
|
+
} else {
|
|
492
|
+
return null;
|
|
493
|
+
}
|
|
494
|
+
}
|
|
495
|
+
return 128 - cidr;
|
|
496
|
+
};
|
|
497
|
+
IPv6.prototype.range = function() {
|
|
498
|
+
return ipaddr.subnetMatch(this, this.SpecialRanges);
|
|
499
|
+
};
|
|
500
|
+
IPv6.prototype.toByteArray = function() {
|
|
501
|
+
let part;
|
|
502
|
+
const bytes = [];
|
|
503
|
+
const ref = this.parts;
|
|
504
|
+
for (let i = 0;i < ref.length; i++) {
|
|
505
|
+
part = ref[i];
|
|
506
|
+
bytes.push(part >> 8);
|
|
507
|
+
bytes.push(part & 255);
|
|
508
|
+
}
|
|
509
|
+
return bytes;
|
|
510
|
+
};
|
|
511
|
+
IPv6.prototype.toFixedLengthString = function() {
|
|
512
|
+
const addr = function() {
|
|
513
|
+
const results = [];
|
|
514
|
+
for (let i = 0;i < this.parts.length; i++) {
|
|
515
|
+
results.push(padPart(this.parts[i].toString(16), 4));
|
|
516
|
+
}
|
|
517
|
+
return results;
|
|
518
|
+
}.call(this).join(":");
|
|
519
|
+
let suffix = "";
|
|
520
|
+
if (this.zoneId) {
|
|
521
|
+
suffix = `%${this.zoneId}`;
|
|
522
|
+
}
|
|
523
|
+
return addr + suffix;
|
|
524
|
+
};
|
|
525
|
+
IPv6.prototype.toIPv4Address = function() {
|
|
526
|
+
if (!this.isIPv4MappedAddress()) {
|
|
527
|
+
throw new Error("ipaddr: trying to convert a generic ipv6 address to ipv4");
|
|
528
|
+
}
|
|
529
|
+
const ref = this.parts.slice(-2);
|
|
530
|
+
const high = ref[0];
|
|
531
|
+
const low = ref[1];
|
|
532
|
+
return new ipaddr.IPv4([high >> 8, high & 255, low >> 8, low & 255]);
|
|
533
|
+
};
|
|
534
|
+
IPv6.prototype.toNormalizedString = function() {
|
|
535
|
+
const addr = function() {
|
|
536
|
+
const results = [];
|
|
537
|
+
for (let i = 0;i < this.parts.length; i++) {
|
|
538
|
+
results.push(this.parts[i].toString(16));
|
|
539
|
+
}
|
|
540
|
+
return results;
|
|
541
|
+
}.call(this).join(":");
|
|
542
|
+
let suffix = "";
|
|
543
|
+
if (this.zoneId) {
|
|
544
|
+
suffix = `%${this.zoneId}`;
|
|
545
|
+
}
|
|
546
|
+
return addr + suffix;
|
|
547
|
+
};
|
|
548
|
+
IPv6.prototype.toRFC5952String = function() {
|
|
549
|
+
const regex = /((^|:)(0(:|$)){2,})/g;
|
|
550
|
+
const string = this.toNormalizedString();
|
|
551
|
+
let bestMatchIndex = 0;
|
|
552
|
+
let bestMatchLength = -1;
|
|
553
|
+
let match;
|
|
554
|
+
while (match = regex.exec(string)) {
|
|
555
|
+
if (match[0].length > bestMatchLength) {
|
|
556
|
+
bestMatchIndex = match.index;
|
|
557
|
+
bestMatchLength = match[0].length;
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
if (bestMatchLength < 0) {
|
|
561
|
+
return string;
|
|
562
|
+
}
|
|
563
|
+
return `${string.substring(0, bestMatchIndex)}::${string.substring(bestMatchIndex + bestMatchLength)}`;
|
|
564
|
+
};
|
|
565
|
+
IPv6.prototype.toString = function() {
|
|
566
|
+
return this.toRFC5952String();
|
|
567
|
+
};
|
|
568
|
+
return IPv6;
|
|
569
|
+
}();
|
|
570
|
+
ipaddr.IPv6.broadcastAddressFromCIDR = function(string) {
|
|
571
|
+
try {
|
|
572
|
+
const cidr = this.parseCIDR(string);
|
|
573
|
+
const ipInterfaceOctets = cidr[0].toByteArray();
|
|
574
|
+
const subnetMaskOctets = this.subnetMaskFromPrefixLength(cidr[1]).toByteArray();
|
|
575
|
+
const octets = [];
|
|
576
|
+
let i = 0;
|
|
577
|
+
while (i < 16) {
|
|
578
|
+
octets.push(parseInt(ipInterfaceOctets[i], 10) | parseInt(subnetMaskOctets[i], 10) ^ 255);
|
|
579
|
+
i++;
|
|
580
|
+
}
|
|
581
|
+
return new this(octets);
|
|
582
|
+
} catch (e) {
|
|
583
|
+
throw new Error(`ipaddr: the address does not have IPv6 CIDR format (${e})`);
|
|
584
|
+
}
|
|
585
|
+
};
|
|
586
|
+
ipaddr.IPv6.isIPv6 = function(string) {
|
|
587
|
+
return this.parser(string) !== null;
|
|
588
|
+
};
|
|
589
|
+
ipaddr.IPv6.isValid = function(string) {
|
|
590
|
+
if (typeof string === "string" && string.indexOf(":") === -1) {
|
|
591
|
+
return false;
|
|
592
|
+
}
|
|
593
|
+
try {
|
|
594
|
+
const addr = this.parser(string);
|
|
595
|
+
new this(addr.parts, addr.zoneId);
|
|
596
|
+
return true;
|
|
597
|
+
} catch (e) {
|
|
598
|
+
return false;
|
|
599
|
+
}
|
|
600
|
+
};
|
|
601
|
+
ipaddr.IPv6.isValidCIDR = function(string) {
|
|
602
|
+
if (typeof string === "string" && string.indexOf(":") === -1) {
|
|
603
|
+
return false;
|
|
604
|
+
}
|
|
605
|
+
try {
|
|
606
|
+
this.parseCIDR(string);
|
|
607
|
+
return true;
|
|
608
|
+
} catch (e) {
|
|
609
|
+
return false;
|
|
610
|
+
}
|
|
611
|
+
};
|
|
612
|
+
ipaddr.IPv6.networkAddressFromCIDR = function(string) {
|
|
613
|
+
let cidr, i, ipInterfaceOctets, octets, subnetMaskOctets;
|
|
614
|
+
try {
|
|
615
|
+
cidr = this.parseCIDR(string);
|
|
616
|
+
ipInterfaceOctets = cidr[0].toByteArray();
|
|
617
|
+
subnetMaskOctets = this.subnetMaskFromPrefixLength(cidr[1]).toByteArray();
|
|
618
|
+
octets = [];
|
|
619
|
+
i = 0;
|
|
620
|
+
while (i < 16) {
|
|
621
|
+
octets.push(parseInt(ipInterfaceOctets[i], 10) & parseInt(subnetMaskOctets[i], 10));
|
|
622
|
+
i++;
|
|
623
|
+
}
|
|
624
|
+
return new this(octets);
|
|
625
|
+
} catch (e) {
|
|
626
|
+
throw new Error(`ipaddr: the address does not have IPv6 CIDR format (${e})`);
|
|
627
|
+
}
|
|
628
|
+
};
|
|
629
|
+
ipaddr.IPv6.parse = function(string) {
|
|
630
|
+
const addr = this.parser(string);
|
|
631
|
+
if (addr.parts === null) {
|
|
632
|
+
throw new Error("ipaddr: string is not formatted like an IPv6 Address");
|
|
633
|
+
}
|
|
634
|
+
return new this(addr.parts, addr.zoneId);
|
|
635
|
+
};
|
|
636
|
+
ipaddr.IPv6.parseCIDR = function(string) {
|
|
637
|
+
let maskLength, match, parsed;
|
|
638
|
+
if (match = string.match(/^(.+)\/(\d+)$/)) {
|
|
639
|
+
maskLength = parseInt(match[2]);
|
|
640
|
+
if (maskLength >= 0 && maskLength <= 128) {
|
|
641
|
+
parsed = [this.parse(match[1]), maskLength];
|
|
642
|
+
Object.defineProperty(parsed, "toString", {
|
|
643
|
+
value: function() {
|
|
644
|
+
return this.join("/");
|
|
645
|
+
}
|
|
646
|
+
});
|
|
647
|
+
return parsed;
|
|
648
|
+
}
|
|
649
|
+
}
|
|
650
|
+
throw new Error("ipaddr: string is not formatted like an IPv6 CIDR range");
|
|
651
|
+
};
|
|
652
|
+
ipaddr.IPv6.parser = function(string) {
|
|
653
|
+
let addr, i, match, octet, octets, zoneId;
|
|
654
|
+
if (match = string.match(ipv6Regexes.deprecatedTransitional)) {
|
|
655
|
+
return this.parser(`::ffff:${match[1]}`);
|
|
656
|
+
}
|
|
657
|
+
if (ipv6Regexes.native.test(string)) {
|
|
658
|
+
return expandIPv6(string, 8);
|
|
659
|
+
}
|
|
660
|
+
if (match = string.match(ipv6Regexes.transitional)) {
|
|
661
|
+
zoneId = match[6] || "";
|
|
662
|
+
addr = match[1];
|
|
663
|
+
if (!match[1].endsWith("::")) {
|
|
664
|
+
addr = addr.slice(0, -1);
|
|
665
|
+
}
|
|
666
|
+
addr = expandIPv6(addr + zoneId, 6);
|
|
667
|
+
if (addr.parts) {
|
|
668
|
+
octets = [
|
|
669
|
+
parseInt(match[2]),
|
|
670
|
+
parseInt(match[3]),
|
|
671
|
+
parseInt(match[4]),
|
|
672
|
+
parseInt(match[5])
|
|
673
|
+
];
|
|
674
|
+
for (i = 0;i < octets.length; i++) {
|
|
675
|
+
octet = octets[i];
|
|
676
|
+
if (!(0 <= octet && octet <= 255)) {
|
|
677
|
+
return null;
|
|
678
|
+
}
|
|
679
|
+
}
|
|
680
|
+
addr.parts.push(octets[0] << 8 | octets[1]);
|
|
681
|
+
addr.parts.push(octets[2] << 8 | octets[3]);
|
|
682
|
+
return {
|
|
683
|
+
parts: addr.parts,
|
|
684
|
+
zoneId: addr.zoneId
|
|
685
|
+
};
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
return null;
|
|
689
|
+
};
|
|
690
|
+
ipaddr.IPv6.subnetMaskFromPrefixLength = function(prefix) {
|
|
691
|
+
prefix = parseInt(prefix);
|
|
692
|
+
if (prefix < 0 || prefix > 128) {
|
|
693
|
+
throw new Error("ipaddr: invalid IPv6 prefix length");
|
|
694
|
+
}
|
|
695
|
+
const octets = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
|
|
696
|
+
let j = 0;
|
|
697
|
+
const filledOctetCount = Math.floor(prefix / 8);
|
|
698
|
+
while (j < filledOctetCount) {
|
|
699
|
+
octets[j] = 255;
|
|
700
|
+
j++;
|
|
701
|
+
}
|
|
702
|
+
if (filledOctetCount < 16) {
|
|
703
|
+
octets[filledOctetCount] = Math.pow(2, prefix % 8) - 1 << 8 - prefix % 8;
|
|
704
|
+
}
|
|
705
|
+
return new this(octets);
|
|
706
|
+
};
|
|
707
|
+
ipaddr.fromByteArray = function(bytes) {
|
|
708
|
+
const length = bytes.length;
|
|
709
|
+
if (length === 4) {
|
|
710
|
+
return new ipaddr.IPv4(bytes);
|
|
711
|
+
} else if (length === 16) {
|
|
712
|
+
return new ipaddr.IPv6(bytes);
|
|
713
|
+
} else {
|
|
714
|
+
throw new Error("ipaddr: the binary input is neither an IPv6 nor IPv4 address");
|
|
715
|
+
}
|
|
716
|
+
};
|
|
717
|
+
ipaddr.isValid = function(string) {
|
|
718
|
+
return ipaddr.IPv6.isValid(string) || ipaddr.IPv4.isValid(string);
|
|
719
|
+
};
|
|
720
|
+
ipaddr.isValidCIDR = function(string) {
|
|
721
|
+
return ipaddr.IPv6.isValidCIDR(string) || ipaddr.IPv4.isValidCIDR(string);
|
|
722
|
+
};
|
|
723
|
+
ipaddr.parse = function(string) {
|
|
724
|
+
if (ipaddr.IPv6.isValid(string)) {
|
|
725
|
+
return ipaddr.IPv6.parse(string);
|
|
726
|
+
} else if (ipaddr.IPv4.isValid(string)) {
|
|
727
|
+
return ipaddr.IPv4.parse(string);
|
|
728
|
+
} else {
|
|
729
|
+
throw new Error("ipaddr: the address has neither IPv6 nor IPv4 format");
|
|
730
|
+
}
|
|
731
|
+
};
|
|
732
|
+
ipaddr.parseCIDR = function(string) {
|
|
733
|
+
try {
|
|
734
|
+
return ipaddr.IPv6.parseCIDR(string);
|
|
735
|
+
} catch (e) {
|
|
736
|
+
try {
|
|
737
|
+
return ipaddr.IPv4.parseCIDR(string);
|
|
738
|
+
} catch (e2) {
|
|
739
|
+
throw new Error("ipaddr: the address has neither IPv6 nor IPv4 CIDR format");
|
|
740
|
+
}
|
|
741
|
+
}
|
|
742
|
+
};
|
|
743
|
+
ipaddr.process = function(string) {
|
|
744
|
+
const addr = this.parse(string);
|
|
745
|
+
if (addr.kind() === "ipv6" && addr.isIPv4MappedAddress()) {
|
|
746
|
+
return addr.toIPv4Address();
|
|
747
|
+
} else {
|
|
748
|
+
return addr;
|
|
749
|
+
}
|
|
750
|
+
};
|
|
751
|
+
ipaddr.subnetMatch = function(address, rangeList, defaultName) {
|
|
752
|
+
let i, rangeName, rangeSubnets, subnet;
|
|
753
|
+
if (defaultName === undefined || defaultName === null) {
|
|
754
|
+
defaultName = "unicast";
|
|
755
|
+
}
|
|
756
|
+
for (rangeName in rangeList) {
|
|
757
|
+
if (Object.prototype.hasOwnProperty.call(rangeList, rangeName)) {
|
|
758
|
+
rangeSubnets = rangeList[rangeName];
|
|
759
|
+
if (rangeSubnets[0] && !(rangeSubnets[0] instanceof Array)) {
|
|
760
|
+
rangeSubnets = [rangeSubnets];
|
|
761
|
+
}
|
|
762
|
+
for (i = 0;i < rangeSubnets.length; i++) {
|
|
763
|
+
subnet = rangeSubnets[i];
|
|
764
|
+
if (address.kind() === subnet[0].kind() && address.match.apply(address, subnet)) {
|
|
765
|
+
return rangeName;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
return defaultName;
|
|
771
|
+
};
|
|
772
|
+
if (typeof module !== "undefined" && module.exports) {
|
|
773
|
+
module.exports = ipaddr;
|
|
774
|
+
} else {
|
|
775
|
+
root.ipaddr = ipaddr;
|
|
776
|
+
}
|
|
777
|
+
})(exports);
|
|
778
|
+
});
|
|
779
|
+
|
|
780
|
+
// node_modules/negotiator/lib/charset.js
|
|
781
|
+
var require_charset = __commonJS((exports, module) => {
|
|
782
|
+
module.exports = preferredCharsets;
|
|
783
|
+
module.exports.preferredCharsets = preferredCharsets;
|
|
784
|
+
var simpleCharsetRegExp = /^\s*([^\s;]+)\s*(?:;(.*))?$/;
|
|
785
|
+
function parseAcceptCharset(accept) {
|
|
786
|
+
var accepts = accept.split(",");
|
|
787
|
+
for (var i = 0, j = 0;i < accepts.length; i++) {
|
|
788
|
+
var charset = parseCharset(accepts[i].trim(), i);
|
|
789
|
+
if (charset) {
|
|
790
|
+
accepts[j++] = charset;
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
accepts.length = j;
|
|
794
|
+
return accepts;
|
|
795
|
+
}
|
|
796
|
+
function parseCharset(str, i) {
|
|
797
|
+
var match = simpleCharsetRegExp.exec(str);
|
|
798
|
+
if (!match)
|
|
799
|
+
return null;
|
|
800
|
+
var charset = match[1];
|
|
801
|
+
var q = 1;
|
|
802
|
+
if (match[2]) {
|
|
803
|
+
var params = match[2].split(";");
|
|
804
|
+
for (var j = 0;j < params.length; j++) {
|
|
805
|
+
var p = params[j].trim().split("=");
|
|
806
|
+
if (p[0] === "q") {
|
|
807
|
+
q = parseFloat(p[1]);
|
|
808
|
+
break;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
}
|
|
812
|
+
return {
|
|
813
|
+
charset,
|
|
814
|
+
q,
|
|
815
|
+
i
|
|
816
|
+
};
|
|
817
|
+
}
|
|
818
|
+
function getCharsetPriority(charset, accepted, index) {
|
|
819
|
+
var priority = { o: -1, q: 0, s: 0 };
|
|
820
|
+
for (var i = 0;i < accepted.length; i++) {
|
|
821
|
+
var spec = specify(charset, accepted[i], index);
|
|
822
|
+
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
|
|
823
|
+
priority = spec;
|
|
824
|
+
}
|
|
825
|
+
}
|
|
826
|
+
return priority;
|
|
827
|
+
}
|
|
828
|
+
function specify(charset, spec, index) {
|
|
829
|
+
var s = 0;
|
|
830
|
+
if (spec.charset.toLowerCase() === charset.toLowerCase()) {
|
|
831
|
+
s |= 1;
|
|
832
|
+
} else if (spec.charset !== "*") {
|
|
833
|
+
return null;
|
|
834
|
+
}
|
|
835
|
+
return {
|
|
836
|
+
i: index,
|
|
837
|
+
o: spec.i,
|
|
838
|
+
q: spec.q,
|
|
839
|
+
s
|
|
840
|
+
};
|
|
841
|
+
}
|
|
842
|
+
function preferredCharsets(accept, provided) {
|
|
843
|
+
var accepts = parseAcceptCharset(accept === undefined ? "*" : accept || "");
|
|
844
|
+
if (!provided) {
|
|
845
|
+
return accepts.filter(isQuality).sort(compareSpecs).map(getFullCharset);
|
|
846
|
+
}
|
|
847
|
+
var priorities = provided.map(function getPriority(type, index) {
|
|
848
|
+
return getCharsetPriority(type, accepts, index);
|
|
849
|
+
});
|
|
850
|
+
return priorities.filter(isQuality).sort(compareSpecs).map(function getCharset(priority) {
|
|
851
|
+
return provided[priorities.indexOf(priority)];
|
|
852
|
+
});
|
|
853
|
+
}
|
|
854
|
+
function compareSpecs(a, b) {
|
|
855
|
+
return b.q - a.q || b.s - a.s || a.o - b.o || a.i - b.i || 0;
|
|
856
|
+
}
|
|
857
|
+
function getFullCharset(spec) {
|
|
858
|
+
return spec.charset;
|
|
859
|
+
}
|
|
860
|
+
function isQuality(spec) {
|
|
861
|
+
return spec.q > 0;
|
|
862
|
+
}
|
|
863
|
+
});
|
|
864
|
+
|
|
865
|
+
// node_modules/negotiator/lib/encoding.js
|
|
866
|
+
var require_encoding = __commonJS((exports, module) => {
|
|
867
|
+
module.exports = preferredEncodings;
|
|
868
|
+
module.exports.preferredEncodings = preferredEncodings;
|
|
869
|
+
var simpleEncodingRegExp = /^\s*([^\s;]+)\s*(?:;(.*))?$/;
|
|
870
|
+
function parseAcceptEncoding(accept) {
|
|
871
|
+
var accepts = accept.split(",");
|
|
872
|
+
var hasIdentity = false;
|
|
873
|
+
var minQuality = 1;
|
|
874
|
+
for (var i = 0, j = 0;i < accepts.length; i++) {
|
|
875
|
+
var encoding = parseEncoding(accepts[i].trim(), i);
|
|
876
|
+
if (encoding) {
|
|
877
|
+
accepts[j++] = encoding;
|
|
878
|
+
hasIdentity = hasIdentity || specify("identity", encoding);
|
|
879
|
+
minQuality = Math.min(minQuality, encoding.q || 1);
|
|
880
|
+
}
|
|
881
|
+
}
|
|
882
|
+
if (!hasIdentity) {
|
|
883
|
+
accepts[j++] = {
|
|
884
|
+
encoding: "identity",
|
|
885
|
+
q: minQuality,
|
|
886
|
+
i
|
|
887
|
+
};
|
|
888
|
+
}
|
|
889
|
+
accepts.length = j;
|
|
890
|
+
return accepts;
|
|
891
|
+
}
|
|
892
|
+
function parseEncoding(str, i) {
|
|
893
|
+
var match = simpleEncodingRegExp.exec(str);
|
|
894
|
+
if (!match)
|
|
895
|
+
return null;
|
|
896
|
+
var encoding = match[1];
|
|
897
|
+
var q = 1;
|
|
898
|
+
if (match[2]) {
|
|
899
|
+
var params = match[2].split(";");
|
|
900
|
+
for (var j = 0;j < params.length; j++) {
|
|
901
|
+
var p = params[j].trim().split("=");
|
|
902
|
+
if (p[0] === "q") {
|
|
903
|
+
q = parseFloat(p[1]);
|
|
904
|
+
break;
|
|
905
|
+
}
|
|
906
|
+
}
|
|
907
|
+
}
|
|
908
|
+
return {
|
|
909
|
+
encoding,
|
|
910
|
+
q,
|
|
911
|
+
i
|
|
912
|
+
};
|
|
913
|
+
}
|
|
914
|
+
function getEncodingPriority(encoding, accepted, index) {
|
|
915
|
+
var priority = { encoding, o: -1, q: 0, s: 0 };
|
|
916
|
+
for (var i = 0;i < accepted.length; i++) {
|
|
917
|
+
var spec = specify(encoding, accepted[i], index);
|
|
918
|
+
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
|
|
919
|
+
priority = spec;
|
|
920
|
+
}
|
|
921
|
+
}
|
|
922
|
+
return priority;
|
|
923
|
+
}
|
|
924
|
+
function specify(encoding, spec, index) {
|
|
925
|
+
var s = 0;
|
|
926
|
+
if (spec.encoding.toLowerCase() === encoding.toLowerCase()) {
|
|
927
|
+
s |= 1;
|
|
928
|
+
} else if (spec.encoding !== "*") {
|
|
929
|
+
return null;
|
|
930
|
+
}
|
|
931
|
+
return {
|
|
932
|
+
encoding,
|
|
933
|
+
i: index,
|
|
934
|
+
o: spec.i,
|
|
935
|
+
q: spec.q,
|
|
936
|
+
s
|
|
937
|
+
};
|
|
938
|
+
}
|
|
939
|
+
function preferredEncodings(accept, provided, preferred) {
|
|
940
|
+
var accepts = parseAcceptEncoding(accept || "");
|
|
941
|
+
var comparator = preferred ? function comparator2(a, b) {
|
|
942
|
+
if (a.q !== b.q) {
|
|
943
|
+
return b.q - a.q;
|
|
944
|
+
}
|
|
945
|
+
var aPreferred = preferred.indexOf(a.encoding);
|
|
946
|
+
var bPreferred = preferred.indexOf(b.encoding);
|
|
947
|
+
if (aPreferred === -1 && bPreferred === -1) {
|
|
948
|
+
return b.s - a.s || a.o - b.o || a.i - b.i;
|
|
949
|
+
}
|
|
950
|
+
if (aPreferred !== -1 && bPreferred !== -1) {
|
|
951
|
+
return aPreferred - bPreferred;
|
|
952
|
+
}
|
|
953
|
+
return aPreferred === -1 ? 1 : -1;
|
|
954
|
+
} : compareSpecs;
|
|
955
|
+
if (!provided) {
|
|
956
|
+
return accepts.filter(isQuality).sort(comparator).map(getFullEncoding);
|
|
957
|
+
}
|
|
958
|
+
var priorities = provided.map(function getPriority(type, index) {
|
|
959
|
+
return getEncodingPriority(type, accepts, index);
|
|
960
|
+
});
|
|
961
|
+
return priorities.filter(isQuality).sort(comparator).map(function getEncoding(priority) {
|
|
962
|
+
return provided[priorities.indexOf(priority)];
|
|
963
|
+
});
|
|
964
|
+
}
|
|
965
|
+
function compareSpecs(a, b) {
|
|
966
|
+
return b.q - a.q || b.s - a.s || a.o - b.o || a.i - b.i;
|
|
967
|
+
}
|
|
968
|
+
function getFullEncoding(spec) {
|
|
969
|
+
return spec.encoding;
|
|
970
|
+
}
|
|
971
|
+
function isQuality(spec) {
|
|
972
|
+
return spec.q > 0;
|
|
973
|
+
}
|
|
974
|
+
});
|
|
975
|
+
|
|
976
|
+
// node_modules/negotiator/lib/language.js
|
|
977
|
+
var require_language = __commonJS((exports, module) => {
|
|
978
|
+
module.exports = preferredLanguages;
|
|
979
|
+
module.exports.preferredLanguages = preferredLanguages;
|
|
980
|
+
var simpleLanguageRegExp = /^\s*([^\s\-;]+)(?:-([^\s;]+))?\s*(?:;(.*))?$/;
|
|
981
|
+
function parseAcceptLanguage(accept) {
|
|
982
|
+
var accepts = accept.split(",");
|
|
983
|
+
for (var i = 0, j = 0;i < accepts.length; i++) {
|
|
984
|
+
var language = parseLanguage(accepts[i].trim(), i);
|
|
985
|
+
if (language) {
|
|
986
|
+
accepts[j++] = language;
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
accepts.length = j;
|
|
990
|
+
return accepts;
|
|
991
|
+
}
|
|
992
|
+
function parseLanguage(str, i) {
|
|
993
|
+
var match = simpleLanguageRegExp.exec(str);
|
|
994
|
+
if (!match)
|
|
995
|
+
return null;
|
|
996
|
+
var prefix = match[1];
|
|
997
|
+
var suffix = match[2];
|
|
998
|
+
var full = prefix;
|
|
999
|
+
if (suffix)
|
|
1000
|
+
full += "-" + suffix;
|
|
1001
|
+
var q = 1;
|
|
1002
|
+
if (match[3]) {
|
|
1003
|
+
var params = match[3].split(";");
|
|
1004
|
+
for (var j = 0;j < params.length; j++) {
|
|
1005
|
+
var p = params[j].split("=");
|
|
1006
|
+
if (p[0] === "q")
|
|
1007
|
+
q = parseFloat(p[1]);
|
|
1008
|
+
}
|
|
1009
|
+
}
|
|
1010
|
+
return {
|
|
1011
|
+
prefix,
|
|
1012
|
+
suffix,
|
|
1013
|
+
q,
|
|
1014
|
+
i,
|
|
1015
|
+
full
|
|
1016
|
+
};
|
|
1017
|
+
}
|
|
1018
|
+
function getLanguagePriority(language, accepted, index) {
|
|
1019
|
+
var priority = { o: -1, q: 0, s: 0 };
|
|
1020
|
+
for (var i = 0;i < accepted.length; i++) {
|
|
1021
|
+
var spec = specify(language, accepted[i], index);
|
|
1022
|
+
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
|
|
1023
|
+
priority = spec;
|
|
1024
|
+
}
|
|
1025
|
+
}
|
|
1026
|
+
return priority;
|
|
1027
|
+
}
|
|
1028
|
+
function specify(language, spec, index) {
|
|
1029
|
+
var p = parseLanguage(language);
|
|
1030
|
+
if (!p)
|
|
1031
|
+
return null;
|
|
1032
|
+
var s = 0;
|
|
1033
|
+
if (spec.full.toLowerCase() === p.full.toLowerCase()) {
|
|
1034
|
+
s |= 4;
|
|
1035
|
+
} else if (spec.prefix.toLowerCase() === p.full.toLowerCase()) {
|
|
1036
|
+
s |= 2;
|
|
1037
|
+
} else if (spec.full.toLowerCase() === p.prefix.toLowerCase()) {
|
|
1038
|
+
s |= 1;
|
|
1039
|
+
} else if (spec.full !== "*") {
|
|
1040
|
+
return null;
|
|
1041
|
+
}
|
|
1042
|
+
return {
|
|
1043
|
+
i: index,
|
|
1044
|
+
o: spec.i,
|
|
1045
|
+
q: spec.q,
|
|
1046
|
+
s
|
|
1047
|
+
};
|
|
1048
|
+
}
|
|
1049
|
+
function preferredLanguages(accept, provided) {
|
|
1050
|
+
var accepts = parseAcceptLanguage(accept === undefined ? "*" : accept || "");
|
|
1051
|
+
if (!provided) {
|
|
1052
|
+
return accepts.filter(isQuality).sort(compareSpecs).map(getFullLanguage);
|
|
1053
|
+
}
|
|
1054
|
+
var priorities = provided.map(function getPriority(type, index) {
|
|
1055
|
+
return getLanguagePriority(type, accepts, index);
|
|
1056
|
+
});
|
|
1057
|
+
return priorities.filter(isQuality).sort(compareSpecs).map(function getLanguage(priority) {
|
|
1058
|
+
return provided[priorities.indexOf(priority)];
|
|
1059
|
+
});
|
|
1060
|
+
}
|
|
1061
|
+
function compareSpecs(a, b) {
|
|
1062
|
+
return b.q - a.q || b.s - a.s || a.o - b.o || a.i - b.i || 0;
|
|
1063
|
+
}
|
|
1064
|
+
function getFullLanguage(spec) {
|
|
1065
|
+
return spec.full;
|
|
1066
|
+
}
|
|
1067
|
+
function isQuality(spec) {
|
|
1068
|
+
return spec.q > 0;
|
|
1069
|
+
}
|
|
1070
|
+
});
|
|
1071
|
+
|
|
1072
|
+
// node_modules/negotiator/lib/mediaType.js
|
|
1073
|
+
var require_mediaType = __commonJS((exports, module) => {
|
|
1074
|
+
module.exports = preferredMediaTypes;
|
|
1075
|
+
module.exports.preferredMediaTypes = preferredMediaTypes;
|
|
1076
|
+
var simpleMediaTypeRegExp = /^\s*([^\s\/;]+)\/([^;\s]+)\s*(?:;(.*))?$/;
|
|
1077
|
+
function parseAccept(accept) {
|
|
1078
|
+
var accepts = splitMediaTypes(accept);
|
|
1079
|
+
for (var i = 0, j = 0;i < accepts.length; i++) {
|
|
1080
|
+
var mediaType = parseMediaType(accepts[i].trim(), i);
|
|
1081
|
+
if (mediaType) {
|
|
1082
|
+
accepts[j++] = mediaType;
|
|
1083
|
+
}
|
|
1084
|
+
}
|
|
1085
|
+
accepts.length = j;
|
|
1086
|
+
return accepts;
|
|
1087
|
+
}
|
|
1088
|
+
function parseMediaType(str, i) {
|
|
1089
|
+
var match = simpleMediaTypeRegExp.exec(str);
|
|
1090
|
+
if (!match)
|
|
1091
|
+
return null;
|
|
1092
|
+
var params = Object.create(null);
|
|
1093
|
+
var q = 1;
|
|
1094
|
+
var subtype = match[2];
|
|
1095
|
+
var type = match[1];
|
|
1096
|
+
if (match[3]) {
|
|
1097
|
+
var kvps = splitParameters(match[3]).map(splitKeyValuePair);
|
|
1098
|
+
for (var j = 0;j < kvps.length; j++) {
|
|
1099
|
+
var pair = kvps[j];
|
|
1100
|
+
var key = pair[0].toLowerCase();
|
|
1101
|
+
var val = pair[1];
|
|
1102
|
+
var value = val && val[0] === '"' && val[val.length - 1] === '"' ? val.slice(1, -1) : val;
|
|
1103
|
+
if (key === "q") {
|
|
1104
|
+
q = parseFloat(value);
|
|
1105
|
+
break;
|
|
1106
|
+
}
|
|
1107
|
+
params[key] = value;
|
|
1108
|
+
}
|
|
1109
|
+
}
|
|
1110
|
+
return {
|
|
1111
|
+
type,
|
|
1112
|
+
subtype,
|
|
1113
|
+
params,
|
|
1114
|
+
q,
|
|
1115
|
+
i
|
|
1116
|
+
};
|
|
1117
|
+
}
|
|
1118
|
+
function getMediaTypePriority(type, accepted, index) {
|
|
1119
|
+
var priority = { o: -1, q: 0, s: 0 };
|
|
1120
|
+
for (var i = 0;i < accepted.length; i++) {
|
|
1121
|
+
var spec = specify(type, accepted[i], index);
|
|
1122
|
+
if (spec && (priority.s - spec.s || priority.q - spec.q || priority.o - spec.o) < 0) {
|
|
1123
|
+
priority = spec;
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
return priority;
|
|
1127
|
+
}
|
|
1128
|
+
function specify(type, spec, index) {
|
|
1129
|
+
var p = parseMediaType(type);
|
|
1130
|
+
var s = 0;
|
|
1131
|
+
if (!p) {
|
|
1132
|
+
return null;
|
|
1133
|
+
}
|
|
1134
|
+
if (spec.type.toLowerCase() == p.type.toLowerCase()) {
|
|
1135
|
+
s |= 4;
|
|
1136
|
+
} else if (spec.type != "*") {
|
|
1137
|
+
return null;
|
|
1138
|
+
}
|
|
1139
|
+
if (spec.subtype.toLowerCase() == p.subtype.toLowerCase()) {
|
|
1140
|
+
s |= 2;
|
|
1141
|
+
} else if (spec.subtype != "*") {
|
|
1142
|
+
return null;
|
|
1143
|
+
}
|
|
1144
|
+
var keys = Object.keys(spec.params);
|
|
1145
|
+
if (keys.length > 0) {
|
|
1146
|
+
if (keys.every(function(k) {
|
|
1147
|
+
return spec.params[k] == "*" || (spec.params[k] || "").toLowerCase() == (p.params[k] || "").toLowerCase();
|
|
1148
|
+
})) {
|
|
1149
|
+
s |= 1;
|
|
1150
|
+
} else {
|
|
1151
|
+
return null;
|
|
1152
|
+
}
|
|
1153
|
+
}
|
|
1154
|
+
return {
|
|
1155
|
+
i: index,
|
|
1156
|
+
o: spec.i,
|
|
1157
|
+
q: spec.q,
|
|
1158
|
+
s
|
|
1159
|
+
};
|
|
1160
|
+
}
|
|
1161
|
+
function preferredMediaTypes(accept, provided) {
|
|
1162
|
+
var accepts = parseAccept(accept === undefined ? "*/*" : accept || "");
|
|
1163
|
+
if (!provided) {
|
|
1164
|
+
return accepts.filter(isQuality).sort(compareSpecs).map(getFullType);
|
|
1165
|
+
}
|
|
1166
|
+
var priorities = provided.map(function getPriority(type, index) {
|
|
1167
|
+
return getMediaTypePriority(type, accepts, index);
|
|
1168
|
+
});
|
|
1169
|
+
return priorities.filter(isQuality).sort(compareSpecs).map(function getType(priority) {
|
|
1170
|
+
return provided[priorities.indexOf(priority)];
|
|
1171
|
+
});
|
|
1172
|
+
}
|
|
1173
|
+
function compareSpecs(a, b) {
|
|
1174
|
+
return b.q - a.q || b.s - a.s || a.o - b.o || a.i - b.i || 0;
|
|
1175
|
+
}
|
|
1176
|
+
function getFullType(spec) {
|
|
1177
|
+
return spec.type + "/" + spec.subtype;
|
|
1178
|
+
}
|
|
1179
|
+
function isQuality(spec) {
|
|
1180
|
+
return spec.q > 0;
|
|
1181
|
+
}
|
|
1182
|
+
function quoteCount(string) {
|
|
1183
|
+
var count = 0;
|
|
1184
|
+
var index = 0;
|
|
1185
|
+
while ((index = string.indexOf('"', index)) !== -1) {
|
|
1186
|
+
count++;
|
|
1187
|
+
index++;
|
|
1188
|
+
}
|
|
1189
|
+
return count;
|
|
1190
|
+
}
|
|
1191
|
+
function splitKeyValuePair(str) {
|
|
1192
|
+
var index = str.indexOf("=");
|
|
1193
|
+
var key;
|
|
1194
|
+
var val;
|
|
1195
|
+
if (index === -1) {
|
|
1196
|
+
key = str;
|
|
1197
|
+
} else {
|
|
1198
|
+
key = str.slice(0, index);
|
|
1199
|
+
val = str.slice(index + 1);
|
|
1200
|
+
}
|
|
1201
|
+
return [key, val];
|
|
1202
|
+
}
|
|
1203
|
+
function splitMediaTypes(accept) {
|
|
1204
|
+
var accepts = accept.split(",");
|
|
1205
|
+
for (var i = 1, j = 0;i < accepts.length; i++) {
|
|
1206
|
+
if (quoteCount(accepts[j]) % 2 == 0) {
|
|
1207
|
+
accepts[++j] = accepts[i];
|
|
1208
|
+
} else {
|
|
1209
|
+
accepts[j] += "," + accepts[i];
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
accepts.length = j + 1;
|
|
1213
|
+
return accepts;
|
|
1214
|
+
}
|
|
1215
|
+
function splitParameters(str) {
|
|
1216
|
+
var parameters = str.split(";");
|
|
1217
|
+
for (var i = 1, j = 0;i < parameters.length; i++) {
|
|
1218
|
+
if (quoteCount(parameters[j]) % 2 == 0) {
|
|
1219
|
+
parameters[++j] = parameters[i];
|
|
1220
|
+
} else {
|
|
1221
|
+
parameters[j] += ";" + parameters[i];
|
|
1222
|
+
}
|
|
1223
|
+
}
|
|
1224
|
+
parameters.length = j + 1;
|
|
1225
|
+
for (var i = 0;i < parameters.length; i++) {
|
|
1226
|
+
parameters[i] = parameters[i].trim();
|
|
1227
|
+
}
|
|
1228
|
+
return parameters;
|
|
1229
|
+
}
|
|
1230
|
+
});
|
|
1231
|
+
|
|
1232
|
+
// node_modules/negotiator/index.js
|
|
1233
|
+
var require_negotiator = __commonJS((exports, module) => {
|
|
1234
|
+
/*!
|
|
1235
|
+
* negotiator
|
|
1236
|
+
* Copyright(c) 2012 Federico Romero
|
|
1237
|
+
* Copyright(c) 2012-2014 Isaac Z. Schlueter
|
|
1238
|
+
* Copyright(c) 2015 Douglas Christopher Wilson
|
|
1239
|
+
* MIT Licensed
|
|
1240
|
+
*/
|
|
1241
|
+
var preferredCharsets = require_charset();
|
|
1242
|
+
var preferredEncodings = require_encoding();
|
|
1243
|
+
var preferredLanguages = require_language();
|
|
1244
|
+
var preferredMediaTypes = require_mediaType();
|
|
1245
|
+
module.exports = Negotiator;
|
|
1246
|
+
module.exports.Negotiator = Negotiator;
|
|
1247
|
+
function Negotiator(request) {
|
|
1248
|
+
if (!(this instanceof Negotiator)) {
|
|
1249
|
+
return new Negotiator(request);
|
|
1250
|
+
}
|
|
1251
|
+
this.request = request;
|
|
1252
|
+
}
|
|
1253
|
+
Negotiator.prototype.charset = function charset(available) {
|
|
1254
|
+
var set = this.charsets(available);
|
|
1255
|
+
return set && set[0];
|
|
1256
|
+
};
|
|
1257
|
+
Negotiator.prototype.charsets = function charsets(available) {
|
|
1258
|
+
return preferredCharsets(this.request.headers["accept-charset"], available);
|
|
1259
|
+
};
|
|
1260
|
+
Negotiator.prototype.encoding = function encoding(available, opts) {
|
|
1261
|
+
var set = this.encodings(available, opts);
|
|
1262
|
+
return set && set[0];
|
|
1263
|
+
};
|
|
1264
|
+
Negotiator.prototype.encodings = function encodings(available, options) {
|
|
1265
|
+
var opts = options || {};
|
|
1266
|
+
return preferredEncodings(this.request.headers["accept-encoding"], available, opts.preferred);
|
|
1267
|
+
};
|
|
1268
|
+
Negotiator.prototype.language = function language(available) {
|
|
1269
|
+
var set = this.languages(available);
|
|
1270
|
+
return set && set[0];
|
|
1271
|
+
};
|
|
1272
|
+
Negotiator.prototype.languages = function languages(available) {
|
|
1273
|
+
return preferredLanguages(this.request.headers["accept-language"], available);
|
|
1274
|
+
};
|
|
1275
|
+
Negotiator.prototype.mediaType = function mediaType(available) {
|
|
1276
|
+
var set = this.mediaTypes(available);
|
|
1277
|
+
return set && set[0];
|
|
1278
|
+
};
|
|
1279
|
+
Negotiator.prototype.mediaTypes = function mediaTypes(available) {
|
|
1280
|
+
return preferredMediaTypes(this.request.headers.accept, available);
|
|
1281
|
+
};
|
|
1282
|
+
Negotiator.prototype.preferredCharset = Negotiator.prototype.charset;
|
|
1283
|
+
Negotiator.prototype.preferredCharsets = Negotiator.prototype.charsets;
|
|
1284
|
+
Negotiator.prototype.preferredEncoding = Negotiator.prototype.encoding;
|
|
1285
|
+
Negotiator.prototype.preferredEncodings = Negotiator.prototype.encodings;
|
|
1286
|
+
Negotiator.prototype.preferredLanguage = Negotiator.prototype.language;
|
|
1287
|
+
Negotiator.prototype.preferredLanguages = Negotiator.prototype.languages;
|
|
1288
|
+
Negotiator.prototype.preferredMediaType = Negotiator.prototype.mediaType;
|
|
1289
|
+
Negotiator.prototype.preferredMediaTypes = Negotiator.prototype.mediaTypes;
|
|
1290
|
+
});
|
|
1291
|
+
// node_modules/devalue/src/base64.js
|
|
1292
|
+
function encode_native(array_buffer) {
|
|
1293
|
+
return new Uint8Array(array_buffer).toBase64();
|
|
1294
|
+
}
|
|
1295
|
+
function encode_buffer(array_buffer) {
|
|
1296
|
+
return Buffer.from(array_buffer).toString("base64");
|
|
1297
|
+
}
|
|
1298
|
+
function encode_legacy(array_buffer) {
|
|
1299
|
+
const array = new Uint8Array(array_buffer);
|
|
1300
|
+
let binary = "";
|
|
1301
|
+
const chunk_size = 32768;
|
|
1302
|
+
for (let i = 0;i < array.length; i += chunk_size) {
|
|
1303
|
+
const chunk = array.subarray(i, i + chunk_size);
|
|
1304
|
+
binary += String.fromCharCode.apply(null, chunk);
|
|
1305
|
+
}
|
|
1306
|
+
return btoa(binary);
|
|
1307
|
+
}
|
|
1308
|
+
var native = typeof Uint8Array.fromBase64 === "function";
|
|
1309
|
+
var buffer = typeof process === "object" && process.versions?.node !== undefined;
|
|
1310
|
+
var encode64 = native ? encode_native : buffer ? encode_buffer : encode_legacy;
|
|
1311
|
+
|
|
1312
|
+
// node_modules/devalue/src/constants.js
|
|
1313
|
+
var UNDEFINED = -1;
|
|
1314
|
+
var HOLE = -2;
|
|
1315
|
+
var NAN = -3;
|
|
1316
|
+
var POSITIVE_INFINITY = -4;
|
|
1317
|
+
var NEGATIVE_INFINITY = -5;
|
|
1318
|
+
var NEGATIVE_ZERO = -6;
|
|
1319
|
+
var SPARSE = -7;
|
|
1320
|
+
var MAX_ARRAY_LEN = 2 ** 32 - 1;
|
|
1321
|
+
var MAX_ARRAY_INDEX = MAX_ARRAY_LEN - 1;
|
|
1322
|
+
|
|
1323
|
+
// node_modules/devalue/src/utils.js
|
|
1324
|
+
class DevalueError extends Error {
|
|
1325
|
+
constructor(message, keys, value, root) {
|
|
1326
|
+
super(message);
|
|
1327
|
+
this.name = "DevalueError";
|
|
1328
|
+
this.path = keys.join("");
|
|
1329
|
+
this.value = value;
|
|
1330
|
+
this.root = root;
|
|
1331
|
+
}
|
|
1332
|
+
}
|
|
1333
|
+
function is_primitive(thing) {
|
|
1334
|
+
return thing === null || typeof thing !== "object" && typeof thing !== "function";
|
|
1335
|
+
}
|
|
1336
|
+
var object_proto_names = /* @__PURE__ */ Object.getOwnPropertyNames(Object.prototype).sort().join("\x00");
|
|
1337
|
+
function is_plain_object(thing) {
|
|
1338
|
+
const proto = Object.getPrototypeOf(thing);
|
|
1339
|
+
return proto === Object.prototype || proto === null || Object.getPrototypeOf(proto) === null || Object.getOwnPropertyNames(proto).sort().join("\x00") === object_proto_names;
|
|
1340
|
+
}
|
|
1341
|
+
function get_type(thing) {
|
|
1342
|
+
return Object.prototype.toString.call(thing).slice(8, -1);
|
|
1343
|
+
}
|
|
1344
|
+
function get_escaped_char(char) {
|
|
1345
|
+
switch (char) {
|
|
1346
|
+
case '"':
|
|
1347
|
+
return "\\\"";
|
|
1348
|
+
case "<":
|
|
1349
|
+
return "\\u003C";
|
|
1350
|
+
case "\\":
|
|
1351
|
+
return "\\\\";
|
|
1352
|
+
case `
|
|
1353
|
+
`:
|
|
1354
|
+
return "\\n";
|
|
1355
|
+
case "\r":
|
|
1356
|
+
return "\\r";
|
|
1357
|
+
case "\t":
|
|
1358
|
+
return "\\t";
|
|
1359
|
+
case "\b":
|
|
1360
|
+
return "\\b";
|
|
1361
|
+
case "\f":
|
|
1362
|
+
return "\\f";
|
|
1363
|
+
case "\u2028":
|
|
1364
|
+
return "\\u2028";
|
|
1365
|
+
case "\u2029":
|
|
1366
|
+
return "\\u2029";
|
|
1367
|
+
default:
|
|
1368
|
+
return char < " " ? `\\u${char.charCodeAt(0).toString(16).padStart(4, "0")}` : "";
|
|
1369
|
+
}
|
|
1370
|
+
}
|
|
1371
|
+
function stringify_string(str) {
|
|
1372
|
+
let result = "";
|
|
1373
|
+
let last_pos = 0;
|
|
1374
|
+
const len = str.length;
|
|
1375
|
+
for (let i = 0;i < len; i += 1) {
|
|
1376
|
+
const char = str[i];
|
|
1377
|
+
const replacement = get_escaped_char(char);
|
|
1378
|
+
if (replacement) {
|
|
1379
|
+
result += str.slice(last_pos, i) + replacement;
|
|
1380
|
+
last_pos = i + 1;
|
|
1381
|
+
}
|
|
1382
|
+
}
|
|
1383
|
+
return `"${last_pos === 0 ? str : result + str.slice(last_pos)}"`;
|
|
1384
|
+
}
|
|
1385
|
+
function enumerable_symbols(object) {
|
|
1386
|
+
return Object.getOwnPropertySymbols(object).filter((symbol) => Object.getOwnPropertyDescriptor(object, symbol).enumerable);
|
|
1387
|
+
}
|
|
1388
|
+
var is_identifier = /^[a-zA-Z_$][a-zA-Z_$0-9]*$/;
|
|
1389
|
+
function stringify_key(key) {
|
|
1390
|
+
return is_identifier.test(key) ? "." + key : "[" + JSON.stringify(key) + "]";
|
|
1391
|
+
}
|
|
1392
|
+
function is_valid_array_index(n) {
|
|
1393
|
+
if (!Number.isInteger(n))
|
|
1394
|
+
return false;
|
|
1395
|
+
if (n < 0)
|
|
1396
|
+
return false;
|
|
1397
|
+
if (n > MAX_ARRAY_INDEX)
|
|
1398
|
+
return false;
|
|
1399
|
+
return true;
|
|
1400
|
+
}
|
|
1401
|
+
function is_valid_array_index_string(s) {
|
|
1402
|
+
if (s.length === 0)
|
|
1403
|
+
return false;
|
|
1404
|
+
if (s.length > 1 && s.charCodeAt(0) === 48)
|
|
1405
|
+
return false;
|
|
1406
|
+
for (let i = 0;i < s.length; i++) {
|
|
1407
|
+
const c = s.charCodeAt(i);
|
|
1408
|
+
if (c < 48 || c > 57)
|
|
1409
|
+
return false;
|
|
1410
|
+
}
|
|
1411
|
+
return is_valid_array_index(+s);
|
|
1412
|
+
}
|
|
1413
|
+
function valid_array_indices(array) {
|
|
1414
|
+
const keys = Object.keys(array);
|
|
1415
|
+
for (var i = keys.length - 1;i >= 0; i--) {
|
|
1416
|
+
if (is_valid_array_index_string(keys[i])) {
|
|
1417
|
+
break;
|
|
1418
|
+
}
|
|
1419
|
+
}
|
|
1420
|
+
keys.length = i + 1;
|
|
1421
|
+
return keys;
|
|
1422
|
+
}
|
|
1423
|
+
|
|
1424
|
+
// node_modules/devalue/src/stringify.js
|
|
1425
|
+
function stringify(value, reducers) {
|
|
1426
|
+
const stringified = run(false, value, reducers);
|
|
1427
|
+
return typeof stringified === "string" ? stringified : `[${stringified.join(",")}]`;
|
|
1428
|
+
}
|
|
1429
|
+
function run(async, value, reducers) {
|
|
1430
|
+
const stringified = [];
|
|
1431
|
+
const indexes = new Map;
|
|
1432
|
+
const custom = [];
|
|
1433
|
+
if (reducers) {
|
|
1434
|
+
for (const key of Object.getOwnPropertyNames(reducers)) {
|
|
1435
|
+
custom.push({ key, fn: reducers[key] });
|
|
1436
|
+
}
|
|
1437
|
+
}
|
|
1438
|
+
const keys = [];
|
|
1439
|
+
let p = 0;
|
|
1440
|
+
function flatten(thing, index2) {
|
|
1441
|
+
if (thing === undefined)
|
|
1442
|
+
return UNDEFINED;
|
|
1443
|
+
if (Number.isNaN(thing))
|
|
1444
|
+
return NAN;
|
|
1445
|
+
if (thing === Infinity)
|
|
1446
|
+
return POSITIVE_INFINITY;
|
|
1447
|
+
if (thing === -Infinity)
|
|
1448
|
+
return NEGATIVE_INFINITY;
|
|
1449
|
+
if (thing === 0 && 1 / thing < 0)
|
|
1450
|
+
return NEGATIVE_ZERO;
|
|
1451
|
+
if (indexes.has(thing))
|
|
1452
|
+
return indexes.get(thing);
|
|
1453
|
+
index2 ??= p++;
|
|
1454
|
+
indexes.set(thing, index2);
|
|
1455
|
+
for (const { key, fn } of custom) {
|
|
1456
|
+
const value2 = fn(thing);
|
|
1457
|
+
if (value2) {
|
|
1458
|
+
stringified[index2] = `["${key}",${flatten(value2)}]`;
|
|
1459
|
+
return index2;
|
|
1460
|
+
}
|
|
1461
|
+
}
|
|
1462
|
+
if (typeof thing === "function") {
|
|
1463
|
+
throw new DevalueError(`Cannot stringify a function`, keys, thing, value);
|
|
1464
|
+
} else if (typeof thing === "symbol") {
|
|
1465
|
+
throw new DevalueError(`Cannot stringify a Symbol primitive`, keys, thing, value);
|
|
1466
|
+
}
|
|
1467
|
+
let str = "";
|
|
1468
|
+
if (is_primitive(thing)) {
|
|
1469
|
+
str = stringify_primitive(thing);
|
|
1470
|
+
} else if (typeof thing.then === "function") {
|
|
1471
|
+
if (!async) {
|
|
1472
|
+
throw new DevalueError(`Cannot stringify a Promise or thenable \u2014 use stringifyAsync instead`, keys, thing, value);
|
|
1473
|
+
}
|
|
1474
|
+
str = Promise.resolve(thing).then((value2) => {
|
|
1475
|
+
const i = flatten(value2, index2);
|
|
1476
|
+
if (i < 0)
|
|
1477
|
+
stringified[index2] = i;
|
|
1478
|
+
});
|
|
1479
|
+
} else {
|
|
1480
|
+
const type = get_type(thing);
|
|
1481
|
+
switch (type) {
|
|
1482
|
+
case "Number":
|
|
1483
|
+
case "String":
|
|
1484
|
+
case "Boolean":
|
|
1485
|
+
case "BigInt":
|
|
1486
|
+
str = `["Object",${flatten(thing.valueOf())}]`;
|
|
1487
|
+
break;
|
|
1488
|
+
case "Date":
|
|
1489
|
+
const valid = !isNaN(thing.getDate());
|
|
1490
|
+
str = `["Date","${valid ? thing.toISOString() : ""}"]`;
|
|
1491
|
+
break;
|
|
1492
|
+
case "URL":
|
|
1493
|
+
str = `["URL",${stringify_string(thing.toString())}]`;
|
|
1494
|
+
break;
|
|
1495
|
+
case "URLSearchParams":
|
|
1496
|
+
str = `["URLSearchParams",${stringify_string(thing.toString())}]`;
|
|
1497
|
+
break;
|
|
1498
|
+
case "RegExp":
|
|
1499
|
+
const { source, flags } = thing;
|
|
1500
|
+
str = flags ? `["RegExp",${stringify_string(source)},"${flags}"]` : `["RegExp",${stringify_string(source)}]`;
|
|
1501
|
+
break;
|
|
1502
|
+
case "Array": {
|
|
1503
|
+
let mostly_dense = false;
|
|
1504
|
+
str = "[";
|
|
1505
|
+
for (let i = 0;i < thing.length; i += 1) {
|
|
1506
|
+
if (i > 0)
|
|
1507
|
+
str += ",";
|
|
1508
|
+
if (Object.hasOwn(thing, i)) {
|
|
1509
|
+
keys.push(`[${i}]`);
|
|
1510
|
+
str += flatten(thing[i]);
|
|
1511
|
+
keys.pop();
|
|
1512
|
+
} else if (mostly_dense) {
|
|
1513
|
+
str += HOLE;
|
|
1514
|
+
} else {
|
|
1515
|
+
const populated_keys = valid_array_indices(thing);
|
|
1516
|
+
const population = populated_keys.length;
|
|
1517
|
+
const d = String(thing.length).length;
|
|
1518
|
+
const hole_cost = (thing.length - population) * 3;
|
|
1519
|
+
const sparse_cost = 4 + d + population * (d + 1);
|
|
1520
|
+
if (hole_cost > sparse_cost) {
|
|
1521
|
+
str = "[" + SPARSE + "," + thing.length;
|
|
1522
|
+
for (let j = 0;j < populated_keys.length; j++) {
|
|
1523
|
+
const key = populated_keys[j];
|
|
1524
|
+
keys.push(`[${key}]`);
|
|
1525
|
+
str += "," + key + "," + flatten(thing[key]);
|
|
1526
|
+
keys.pop();
|
|
1527
|
+
}
|
|
1528
|
+
break;
|
|
1529
|
+
} else {
|
|
1530
|
+
mostly_dense = true;
|
|
1531
|
+
str += HOLE;
|
|
1532
|
+
}
|
|
1533
|
+
}
|
|
1534
|
+
}
|
|
1535
|
+
str += "]";
|
|
1536
|
+
break;
|
|
1537
|
+
}
|
|
1538
|
+
case "Set":
|
|
1539
|
+
str = '["Set"';
|
|
1540
|
+
for (const value2 of thing) {
|
|
1541
|
+
str += `,${flatten(value2)}`;
|
|
1542
|
+
}
|
|
1543
|
+
str += "]";
|
|
1544
|
+
break;
|
|
1545
|
+
case "Map":
|
|
1546
|
+
str = '["Map"';
|
|
1547
|
+
for (const [key, value2] of thing) {
|
|
1548
|
+
keys.push(`.get(${is_primitive(key) ? stringify_primitive(key) : "..."})`);
|
|
1549
|
+
str += `,${flatten(key)},${flatten(value2)}`;
|
|
1550
|
+
keys.pop();
|
|
1551
|
+
}
|
|
1552
|
+
str += "]";
|
|
1553
|
+
break;
|
|
1554
|
+
case "Int8Array":
|
|
1555
|
+
case "Uint8Array":
|
|
1556
|
+
case "Uint8ClampedArray":
|
|
1557
|
+
case "Int16Array":
|
|
1558
|
+
case "Uint16Array":
|
|
1559
|
+
case "Float16Array":
|
|
1560
|
+
case "Int32Array":
|
|
1561
|
+
case "Uint32Array":
|
|
1562
|
+
case "Float32Array":
|
|
1563
|
+
case "Float64Array":
|
|
1564
|
+
case "BigInt64Array":
|
|
1565
|
+
case "BigUint64Array": {
|
|
1566
|
+
const typedArray = thing;
|
|
1567
|
+
str = '["' + type + '",' + flatten(typedArray.buffer);
|
|
1568
|
+
if (typedArray.byteLength !== typedArray.buffer.byteLength) {
|
|
1569
|
+
str += `,${typedArray.byteOffset},${typedArray.length}`;
|
|
1570
|
+
}
|
|
1571
|
+
str += "]";
|
|
1572
|
+
break;
|
|
1573
|
+
}
|
|
1574
|
+
case "DataView": {
|
|
1575
|
+
const view = thing;
|
|
1576
|
+
str = '["' + type + '",' + flatten(view.buffer);
|
|
1577
|
+
if (view.byteLength !== view.buffer.byteLength) {
|
|
1578
|
+
str += `,${view.byteOffset},${view.byteLength}`;
|
|
1579
|
+
}
|
|
1580
|
+
str += "]";
|
|
1581
|
+
break;
|
|
1582
|
+
}
|
|
1583
|
+
case "ArrayBuffer": {
|
|
1584
|
+
const arraybuffer = thing;
|
|
1585
|
+
const base64 = encode64(arraybuffer);
|
|
1586
|
+
str = `["ArrayBuffer","${base64}"]`;
|
|
1587
|
+
break;
|
|
1588
|
+
}
|
|
1589
|
+
case "Temporal.Duration":
|
|
1590
|
+
case "Temporal.Instant":
|
|
1591
|
+
case "Temporal.PlainDate":
|
|
1592
|
+
case "Temporal.PlainTime":
|
|
1593
|
+
case "Temporal.PlainDateTime":
|
|
1594
|
+
case "Temporal.PlainMonthDay":
|
|
1595
|
+
case "Temporal.PlainYearMonth":
|
|
1596
|
+
case "Temporal.ZonedDateTime":
|
|
1597
|
+
str = `["${type}",${stringify_string(thing.toString())}]`;
|
|
1598
|
+
break;
|
|
1599
|
+
default:
|
|
1600
|
+
if (!is_plain_object(thing)) {
|
|
1601
|
+
throw new DevalueError(`Cannot stringify arbitrary non-POJOs`, keys, thing, value);
|
|
1602
|
+
}
|
|
1603
|
+
if (enumerable_symbols(thing).length > 0) {
|
|
1604
|
+
throw new DevalueError(`Cannot stringify POJOs with symbolic keys`, keys, thing, value);
|
|
1605
|
+
}
|
|
1606
|
+
if (Object.getPrototypeOf(thing) === null) {
|
|
1607
|
+
str = '["null"';
|
|
1608
|
+
for (const key of Object.keys(thing)) {
|
|
1609
|
+
if (key === "__proto__") {
|
|
1610
|
+
throw new DevalueError(`Cannot stringify objects with __proto__ keys`, keys, thing, value);
|
|
1611
|
+
}
|
|
1612
|
+
keys.push(stringify_key(key));
|
|
1613
|
+
str += `,${stringify_string(key)},${flatten(thing[key])}`;
|
|
1614
|
+
keys.pop();
|
|
1615
|
+
}
|
|
1616
|
+
str += "]";
|
|
1617
|
+
} else {
|
|
1618
|
+
str = "{";
|
|
1619
|
+
let started = false;
|
|
1620
|
+
for (const key of Object.keys(thing)) {
|
|
1621
|
+
if (key === "__proto__") {
|
|
1622
|
+
throw new DevalueError(`Cannot stringify objects with __proto__ keys`, keys, thing, value);
|
|
1623
|
+
}
|
|
1624
|
+
if (started)
|
|
1625
|
+
str += ",";
|
|
1626
|
+
started = true;
|
|
1627
|
+
keys.push(stringify_key(key));
|
|
1628
|
+
str += `${stringify_string(key)}:${flatten(thing[key])}`;
|
|
1629
|
+
keys.pop();
|
|
1630
|
+
}
|
|
1631
|
+
str += "}";
|
|
1632
|
+
}
|
|
1633
|
+
}
|
|
1634
|
+
}
|
|
1635
|
+
stringified[index2] = str;
|
|
1636
|
+
return index2;
|
|
1637
|
+
}
|
|
1638
|
+
const index = flatten(value);
|
|
1639
|
+
if (index < 0)
|
|
1640
|
+
return `${index}`;
|
|
1641
|
+
return stringified;
|
|
1642
|
+
}
|
|
1643
|
+
function stringify_primitive(thing) {
|
|
1644
|
+
const type = typeof thing;
|
|
1645
|
+
if (type === "string")
|
|
1646
|
+
return stringify_string(thing);
|
|
1647
|
+
if (thing === undefined)
|
|
1648
|
+
return UNDEFINED.toString();
|
|
1649
|
+
if (thing === 0 && 1 / thing < 0)
|
|
1650
|
+
return NEGATIVE_ZERO.toString();
|
|
1651
|
+
if (type === "bigint")
|
|
1652
|
+
return `["BigInt","${thing}"]`;
|
|
1653
|
+
return String(thing);
|
|
1654
|
+
}
|
|
1655
|
+
// node_modules/mochi-framework/src/runtime/requestContext.ts
|
|
1656
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
1657
|
+
|
|
1658
|
+
// node_modules/mochi-framework/src/utils/globalState.ts
|
|
1659
|
+
function pinGlobal(key, factory) {
|
|
1660
|
+
const slot = globalThis;
|
|
1661
|
+
slot[key] ??= factory();
|
|
1662
|
+
return slot[key];
|
|
1663
|
+
}
|
|
1664
|
+
|
|
1665
|
+
// node_modules/mochi-framework/src/utils/serverOnly.ts
|
|
1666
|
+
var IS_CLIENT_BUNDLE = typeof MOCHI_CLIENT !== "undefined" && MOCHI_CLIENT === true;
|
|
1667
|
+
function assertServerOnly(api, why) {
|
|
1668
|
+
if (IS_CLIENT_BUNDLE) {
|
|
1669
|
+
throw new Error(`[mochi] ${api} was called in the browser. ${why}`);
|
|
1670
|
+
}
|
|
1671
|
+
}
|
|
1672
|
+
|
|
1673
|
+
// node_modules/mochi-framework/src/runtime/requestContext.ts
|
|
1674
|
+
var requestContext = pinGlobal("__mochi_request_context__", () => new AsyncLocalStorage);
|
|
1675
|
+
var SERVER_ONLY_REASON = "The request context is server-only. Read what you need during SSR and pass it down as a prop, or through Svelte\u2019s hydratable().";
|
|
1676
|
+
function getRequestContext() {
|
|
1677
|
+
assertServerOnly("getRequestContext()", SERVER_ONLY_REASON);
|
|
1678
|
+
const ctx = requestContext.getStore();
|
|
1679
|
+
if (!ctx) {
|
|
1680
|
+
throw new Error("getRequestContext() called outside of a request. " + "It is only available in server-side code running within a Mochi request handler.");
|
|
1681
|
+
}
|
|
1682
|
+
return ctx;
|
|
1683
|
+
}
|
|
1684
|
+
|
|
1685
|
+
// node_modules/mochi-framework/src/islands/islandPropsRegistry.ts
|
|
1686
|
+
function emitIslandProps(value) {
|
|
1687
|
+
const json = stringify(value);
|
|
1688
|
+
const ctx = getRequestContext();
|
|
1689
|
+
let entry = ctx.islandProps.get(json);
|
|
1690
|
+
if (!entry) {
|
|
1691
|
+
entry = { id: `mochi-props-${ctx.islandProps.size}`, emitCount: 0 };
|
|
1692
|
+
ctx.islandProps.set(json, entry);
|
|
1693
|
+
}
|
|
1694
|
+
entry.emitCount++;
|
|
1695
|
+
return entry.id;
|
|
1696
|
+
}
|
|
1697
|
+
|
|
1698
|
+
// node_modules/mochi-framework/src/utils/log.ts
|
|
1699
|
+
var LEVELS = {
|
|
1700
|
+
silent: 0,
|
|
1701
|
+
error: 1,
|
|
1702
|
+
warn: 2,
|
|
1703
|
+
info: 3,
|
|
1704
|
+
log: 4,
|
|
1705
|
+
debug: 5
|
|
1706
|
+
};
|
|
1707
|
+
var PREFIX = "[mochi]";
|
|
1708
|
+
var red = (s) => `\x1B[31m${s}\x1B[39m`;
|
|
1709
|
+
var yellow = (s) => `\x1B[33m${s}\x1B[39m`;
|
|
1710
|
+
var green = (s) => `\x1B[32m${s}\x1B[39m`;
|
|
1711
|
+
var dim = (s) => `\x1B[2m${s}\x1B[22m`;
|
|
1712
|
+
var DEFAULT_LOG_LEVEL = "warn";
|
|
1713
|
+
var state = pinGlobal("__mochi_log_state__", () => ({ level: DEFAULT_LOG_LEVEL }));
|
|
1714
|
+
var logger = {
|
|
1715
|
+
error: (...args) => {
|
|
1716
|
+
if (LEVELS[state.level] < LEVELS.error) {
|
|
1717
|
+
return;
|
|
1718
|
+
}
|
|
1719
|
+
console.error(red(PREFIX), ...args);
|
|
1720
|
+
},
|
|
1721
|
+
warn: (...args) => {
|
|
1722
|
+
if (LEVELS[state.level] < LEVELS.warn) {
|
|
1723
|
+
return;
|
|
1724
|
+
}
|
|
1725
|
+
console.warn(yellow(PREFIX), ...args);
|
|
1726
|
+
},
|
|
1727
|
+
info: (...args) => {
|
|
1728
|
+
if (LEVELS[state.level] < LEVELS.info) {
|
|
1729
|
+
return;
|
|
1730
|
+
}
|
|
1731
|
+
console.info(green(PREFIX), ...args);
|
|
1732
|
+
},
|
|
1733
|
+
log: (...args) => {
|
|
1734
|
+
if (LEVELS[state.level] < LEVELS.log) {
|
|
1735
|
+
return;
|
|
1736
|
+
}
|
|
1737
|
+
console.log(dim(PREFIX), ...args);
|
|
1738
|
+
},
|
|
1739
|
+
debug: (...args) => {
|
|
1740
|
+
if (LEVELS[state.level] < LEVELS.debug) {
|
|
1741
|
+
return;
|
|
1742
|
+
}
|
|
1743
|
+
console.debug(dim(PREFIX), ...args);
|
|
1744
|
+
}
|
|
1745
|
+
};
|
|
1746
|
+
// node_modules/mochi-framework/src/islands/isHydratable.ts
|
|
1747
|
+
import { getContext } from "svelte";
|
|
1748
|
+
var HYDRATABLE_CONTEXT_KEY = Symbol.for("mochi:hydratable");
|
|
1749
|
+
// node_modules/mitt/dist/mitt.mjs
|
|
1750
|
+
function mitt_default(n) {
|
|
1751
|
+
return { all: n = n || new Map, on: function(t, e) {
|
|
1752
|
+
var i = n.get(t);
|
|
1753
|
+
i ? i.push(e) : n.set(t, [e]);
|
|
1754
|
+
}, off: function(t, e) {
|
|
1755
|
+
var i = n.get(t);
|
|
1756
|
+
i && (e ? i.splice(i.indexOf(e) >>> 0, 1) : n.set(t, []));
|
|
1757
|
+
}, emit: function(t, e) {
|
|
1758
|
+
var i = n.get(t);
|
|
1759
|
+
i && i.slice().map(function(n2) {
|
|
1760
|
+
n2(e);
|
|
1761
|
+
}), (i = n.get("*")) && i.slice().map(function(n2) {
|
|
1762
|
+
n2(t, e);
|
|
1763
|
+
});
|
|
1764
|
+
} };
|
|
1765
|
+
}
|
|
1766
|
+
|
|
1767
|
+
// node_modules/mochi-framework/src/cache/cache.ts
|
|
1768
|
+
import { randomUUID } from "crypto";
|
|
1769
|
+
|
|
1770
|
+
// node_modules/mochi-framework/src/cache/cache-storage.ts
|
|
1771
|
+
import { mkdirSync, rmSync } from "fs";
|
|
1772
|
+
import { mkdir, open, readdir, rename, rm, stat, unlink } from "fs/promises";
|
|
1773
|
+
import { join, relative } from "path";
|
|
1774
|
+
|
|
1775
|
+
// node_modules/mochi-framework/src/events.ts
|
|
1776
|
+
var mochiEvents = pinGlobal("__mochi_events__", () => {
|
|
1777
|
+
const base = mitt_default();
|
|
1778
|
+
const byName = new Map;
|
|
1779
|
+
base.setHandler = (name, type, handler) => {
|
|
1780
|
+
const prior = byName.get(name);
|
|
1781
|
+
if (prior) {
|
|
1782
|
+
base.off(prior.type, prior.handler);
|
|
1783
|
+
}
|
|
1784
|
+
byName.set(name, {
|
|
1785
|
+
type,
|
|
1786
|
+
handler
|
|
1787
|
+
});
|
|
1788
|
+
base.on(type, handler);
|
|
1789
|
+
};
|
|
1790
|
+
base.removeHandler = (name) => {
|
|
1791
|
+
const prior = byName.get(name);
|
|
1792
|
+
if (!prior) {
|
|
1793
|
+
return;
|
|
1794
|
+
}
|
|
1795
|
+
base.off(prior.type, prior.handler);
|
|
1796
|
+
byName.delete(name);
|
|
1797
|
+
};
|
|
1798
|
+
return base;
|
|
1799
|
+
});
|
|
1800
|
+
|
|
1801
|
+
// node_modules/mochi-framework/src/cache/cache-storage.ts
|
|
1802
|
+
function isBlobRef(value) {
|
|
1803
|
+
return typeof value === "object" && value !== null && value.__mochiBlobRef === true;
|
|
1804
|
+
}
|
|
1805
|
+
async function readBlobRef(ref) {
|
|
1806
|
+
return new Uint8Array(await Bun.file(ref.path).arrayBuffer());
|
|
1807
|
+
}
|
|
1808
|
+
function isBinary(value) {
|
|
1809
|
+
return value instanceof Uint8Array;
|
|
1810
|
+
}
|
|
1811
|
+
function isBlobPointer(value) {
|
|
1812
|
+
return typeof value === "object" && value !== null && typeof value.__mochiBlob === "string";
|
|
1813
|
+
}
|
|
1814
|
+
function isInlineBinary(value) {
|
|
1815
|
+
return typeof value === "object" && value !== null && typeof value.__mochiBinary === "string";
|
|
1816
|
+
}
|
|
1817
|
+
function isKeyedEnvelope(value) {
|
|
1818
|
+
return typeof value === "object" && value !== null && "__mochiValue" in value && typeof value.__mochiKey === "string";
|
|
1819
|
+
}
|
|
1820
|
+
|
|
1821
|
+
class MemoryStorage {
|
|
1822
|
+
store = new Map;
|
|
1823
|
+
maxAge;
|
|
1824
|
+
intervalTimer;
|
|
1825
|
+
constructor(options = {}) {
|
|
1826
|
+
this.maxAge = options.maxAge;
|
|
1827
|
+
if (options.purgeInterval && options.purgeInterval > 0) {
|
|
1828
|
+
this.startSweeper(options.purgeInterval);
|
|
1829
|
+
}
|
|
1830
|
+
}
|
|
1831
|
+
getItem(key) {
|
|
1832
|
+
return this.store.get(key)?.value ?? null;
|
|
1833
|
+
}
|
|
1834
|
+
setItem(key, value) {
|
|
1835
|
+
this.store.set(key, { value, writtenAt: Date.now() });
|
|
1836
|
+
}
|
|
1837
|
+
removeItem(key) {
|
|
1838
|
+
this.store.delete(key);
|
|
1839
|
+
}
|
|
1840
|
+
clear() {
|
|
1841
|
+
this.store.clear();
|
|
1842
|
+
}
|
|
1843
|
+
count() {
|
|
1844
|
+
return this.store.size;
|
|
1845
|
+
}
|
|
1846
|
+
keys() {
|
|
1847
|
+
return [...this.store.keys()];
|
|
1848
|
+
}
|
|
1849
|
+
sweep(now = Date.now(), options = {}) {
|
|
1850
|
+
if (this.maxAge === undefined) {
|
|
1851
|
+
return options.reportKeys ? { removed: 0, removedKeys: [] } : { removed: 0 };
|
|
1852
|
+
}
|
|
1853
|
+
const removedKeys = [];
|
|
1854
|
+
let removed = 0;
|
|
1855
|
+
for (const [key, entry] of this.store) {
|
|
1856
|
+
if (now - entry.writtenAt > this.maxAge) {
|
|
1857
|
+
this.store.delete(key);
|
|
1858
|
+
removed++;
|
|
1859
|
+
if (options.reportKeys) {
|
|
1860
|
+
removedKeys.push(key);
|
|
1861
|
+
}
|
|
1862
|
+
}
|
|
1863
|
+
}
|
|
1864
|
+
return options.reportKeys ? { removed, removedKeys } : { removed };
|
|
1865
|
+
}
|
|
1866
|
+
dispose() {
|
|
1867
|
+
if (this.intervalTimer) {
|
|
1868
|
+
clearInterval(this.intervalTimer);
|
|
1869
|
+
}
|
|
1870
|
+
this.intervalTimer = undefined;
|
|
1871
|
+
}
|
|
1872
|
+
startSweeper(intervalMs) {
|
|
1873
|
+
this.intervalTimer = setInterval(() => {
|
|
1874
|
+
const start = Date.now();
|
|
1875
|
+
const { removed } = this.sweep(start);
|
|
1876
|
+
mochiEvents.emit("cache:sweep", { removed, durationMs: Date.now() - start });
|
|
1877
|
+
}, intervalMs);
|
|
1878
|
+
this.intervalTimer.unref?.();
|
|
1879
|
+
}
|
|
1880
|
+
}
|
|
1881
|
+
var isENOENT = (err) => err?.code === "ENOENT";
|
|
1882
|
+
async function writeFileDurable(path, data) {
|
|
1883
|
+
const fh = await open(path, "w");
|
|
1884
|
+
try {
|
|
1885
|
+
await fh.write(data);
|
|
1886
|
+
await fh.sync();
|
|
1887
|
+
} finally {
|
|
1888
|
+
await fh.close();
|
|
1889
|
+
}
|
|
1890
|
+
}
|
|
1891
|
+
var RENAME_RETRY_CODES = new Set(["EPERM", "EACCES", "EBUSY", "ENOENT"]);
|
|
1892
|
+
async function renameWithRetry(from, to) {
|
|
1893
|
+
if (process.platform !== "win32") {
|
|
1894
|
+
return rename(from, to);
|
|
1895
|
+
}
|
|
1896
|
+
for (let attempt = 0;; attempt++) {
|
|
1897
|
+
try {
|
|
1898
|
+
return await rename(from, to);
|
|
1899
|
+
} catch (err) {
|
|
1900
|
+
const code = err.code ?? "";
|
|
1901
|
+
if (attempt >= 50 || !RENAME_RETRY_CODES.has(code)) {
|
|
1902
|
+
throw err;
|
|
1903
|
+
}
|
|
1904
|
+
await Bun.sleep(Math.min(100, 10 * (attempt + 1)));
|
|
1905
|
+
}
|
|
1906
|
+
}
|
|
1907
|
+
}
|
|
1908
|
+
var DIR_FSYNC_UNSUPPORTED = new Set(["EINVAL", "ENOTSUP", "EPERM", "EISDIR"]);
|
|
1909
|
+
async function fsyncDir(dir) {
|
|
1910
|
+
let fh;
|
|
1911
|
+
try {
|
|
1912
|
+
fh = await open(dir, "r");
|
|
1913
|
+
await fh.sync();
|
|
1914
|
+
} catch (err) {
|
|
1915
|
+
if (!DIR_FSYNC_UNSUPPORTED.has(err.code ?? "")) {
|
|
1916
|
+
throw err;
|
|
1917
|
+
}
|
|
1918
|
+
} finally {
|
|
1919
|
+
await fh?.close();
|
|
1920
|
+
}
|
|
1921
|
+
}
|
|
1922
|
+
var ORPHAN_BLOB_GRACE_MS = 1e4;
|
|
1923
|
+
|
|
1924
|
+
class FileStorage {
|
|
1925
|
+
directory;
|
|
1926
|
+
maxAge;
|
|
1927
|
+
offloadBinary;
|
|
1928
|
+
initialTimer;
|
|
1929
|
+
intervalTimer;
|
|
1930
|
+
constructor(options) {
|
|
1931
|
+
this.directory = options.directory;
|
|
1932
|
+
this.maxAge = options.maxAge ?? 600000;
|
|
1933
|
+
this.offloadBinary = options.offloadBinary ?? false;
|
|
1934
|
+
if (options.purgeOnInit) {
|
|
1935
|
+
rmSync(this.directory, { recursive: true, force: true });
|
|
1936
|
+
}
|
|
1937
|
+
mkdirSync(this.directory, { recursive: true });
|
|
1938
|
+
const purgeInterval = options.purgeInterval ?? 60000;
|
|
1939
|
+
if (purgeInterval > 0) {
|
|
1940
|
+
this.startSweeper(purgeInterval);
|
|
1941
|
+
}
|
|
1942
|
+
}
|
|
1943
|
+
async getItem(key) {
|
|
1944
|
+
let text;
|
|
1945
|
+
try {
|
|
1946
|
+
text = await Bun.file(this.pathFor(key)).text();
|
|
1947
|
+
} catch (err) {
|
|
1948
|
+
if (isENOENT(err)) {
|
|
1949
|
+
return null;
|
|
1950
|
+
}
|
|
1951
|
+
throw err;
|
|
1952
|
+
}
|
|
1953
|
+
const parsed = JSON.parse(text);
|
|
1954
|
+
if (!isKeyedEnvelope(parsed)) {
|
|
1955
|
+
return null;
|
|
1956
|
+
}
|
|
1957
|
+
return this.decodeBlobs(parsed.__mochiValue);
|
|
1958
|
+
}
|
|
1959
|
+
async setItem(key, value) {
|
|
1960
|
+
const hash = this.hashKey(key);
|
|
1961
|
+
const path = join(this.directory, `${hash}.json`);
|
|
1962
|
+
const blobs = [];
|
|
1963
|
+
const json = this.encodeBlobs(value, hash, blobs);
|
|
1964
|
+
if (blobs.length > 0) {
|
|
1965
|
+
const blobDir = join(this.directory, hash);
|
|
1966
|
+
await mkdir(blobDir, { recursive: true });
|
|
1967
|
+
for (const b of blobs) {
|
|
1968
|
+
const blobPath = join(this.directory, b.relPath);
|
|
1969
|
+
if (await Bun.file(blobPath).exists()) {
|
|
1970
|
+
continue;
|
|
1971
|
+
}
|
|
1972
|
+
const blobTmp = `${blobPath}.${crypto.randomUUID()}.tmp`;
|
|
1973
|
+
await writeFileDurable(blobTmp, b.data);
|
|
1974
|
+
await renameWithRetry(blobTmp, blobPath);
|
|
1975
|
+
}
|
|
1976
|
+
await fsyncDir(blobDir);
|
|
1977
|
+
}
|
|
1978
|
+
const tmp = `${path}.${crypto.randomUUID()}.tmp`;
|
|
1979
|
+
const envelope = { __mochiKey: key, __mochiValue: json };
|
|
1980
|
+
await writeFileDurable(tmp, new TextEncoder().encode(JSON.stringify(envelope)));
|
|
1981
|
+
await renameWithRetry(tmp, path);
|
|
1982
|
+
await fsyncDir(this.directory);
|
|
1983
|
+
}
|
|
1984
|
+
async removeItem(key) {
|
|
1985
|
+
const hash = this.hashKey(key);
|
|
1986
|
+
try {
|
|
1987
|
+
await unlink(join(this.directory, `${hash}.json`));
|
|
1988
|
+
} catch (err) {
|
|
1989
|
+
if (!isENOENT(err)) {
|
|
1990
|
+
throw err;
|
|
1991
|
+
}
|
|
1992
|
+
}
|
|
1993
|
+
await rm(join(this.directory, hash), { recursive: true, force: true });
|
|
1994
|
+
}
|
|
1995
|
+
async clear() {
|
|
1996
|
+
const entries = await readdir(this.directory, { withFileTypes: true }).catch((err) => {
|
|
1997
|
+
if (isENOENT(err)) {
|
|
1998
|
+
return [];
|
|
1999
|
+
}
|
|
2000
|
+
throw err;
|
|
2001
|
+
});
|
|
2002
|
+
await Promise.all(entries.map((entry) => {
|
|
2003
|
+
const p = join(this.directory, entry.name);
|
|
2004
|
+
if (entry.isDirectory()) {
|
|
2005
|
+
return rm(p, { recursive: true, force: true });
|
|
2006
|
+
}
|
|
2007
|
+
if (entry.name.endsWith(".json") || entry.name.endsWith(".tmp")) {
|
|
2008
|
+
return unlink(p).catch((err) => isENOENT(err) ? undefined : Promise.reject(err));
|
|
2009
|
+
}
|
|
2010
|
+
return;
|
|
2011
|
+
}));
|
|
2012
|
+
}
|
|
2013
|
+
async count() {
|
|
2014
|
+
const entries = await readdir(this.directory, { withFileTypes: true }).catch((err) => {
|
|
2015
|
+
if (isENOENT(err)) {
|
|
2016
|
+
return [];
|
|
2017
|
+
}
|
|
2018
|
+
throw err;
|
|
2019
|
+
});
|
|
2020
|
+
return entries.filter((entry) => !entry.isDirectory() && entry.name.endsWith(".json")).length;
|
|
2021
|
+
}
|
|
2022
|
+
async keys() {
|
|
2023
|
+
const entries = await readdir(this.directory, { withFileTypes: true }).catch((err) => {
|
|
2024
|
+
if (isENOENT(err)) {
|
|
2025
|
+
return [];
|
|
2026
|
+
}
|
|
2027
|
+
throw err;
|
|
2028
|
+
});
|
|
2029
|
+
const files = entries.filter((entry) => !entry.isDirectory() && entry.name.endsWith(".json"));
|
|
2030
|
+
const keys = await Promise.all(files.map((entry) => this.readKey(join(this.directory, entry.name))));
|
|
2031
|
+
return keys.filter((key) => key !== null);
|
|
2032
|
+
}
|
|
2033
|
+
async sweep(now = Date.now(), options = {}) {
|
|
2034
|
+
const entries = await readdir(this.directory, { withFileTypes: true }).catch((err) => {
|
|
2035
|
+
if (isENOENT(err)) {
|
|
2036
|
+
return [];
|
|
2037
|
+
}
|
|
2038
|
+
throw err;
|
|
2039
|
+
});
|
|
2040
|
+
let removed = 0;
|
|
2041
|
+
const removedKeys = [];
|
|
2042
|
+
await Promise.all(entries.filter((entry) => !entry.isDirectory() && (entry.name.endsWith(".json") || entry.name.endsWith(".tmp"))).map(async (entry) => {
|
|
2043
|
+
const filePath = join(this.directory, entry.name);
|
|
2044
|
+
const threshold = entry.name.endsWith(".tmp") ? ORPHAN_BLOB_GRACE_MS : this.maxAge;
|
|
2045
|
+
try {
|
|
2046
|
+
const info = await stat(filePath);
|
|
2047
|
+
if (now - info.mtimeMs > threshold) {
|
|
2048
|
+
if (options.reportKeys && entry.name.endsWith(".json")) {
|
|
2049
|
+
const key = await this.readKey(filePath);
|
|
2050
|
+
if (key !== null) {
|
|
2051
|
+
removedKeys.push(key);
|
|
2052
|
+
}
|
|
2053
|
+
}
|
|
2054
|
+
await unlink(filePath);
|
|
2055
|
+
removed++;
|
|
2056
|
+
if (entry.name.endsWith(".json")) {
|
|
2057
|
+
const blobDir = join(this.directory, entry.name.slice(0, -".json".length));
|
|
2058
|
+
await rm(blobDir, { recursive: true, force: true });
|
|
2059
|
+
}
|
|
2060
|
+
}
|
|
2061
|
+
} catch (err) {
|
|
2062
|
+
if (!isENOENT(err)) {
|
|
2063
|
+
throw err;
|
|
2064
|
+
}
|
|
2065
|
+
}
|
|
2066
|
+
}));
|
|
2067
|
+
await Promise.all(entries.filter((entry) => entry.isDirectory()).map(async (entry) => {
|
|
2068
|
+
const ownerExists = await Bun.file(join(this.directory, `${entry.name}.json`)).exists();
|
|
2069
|
+
if (!ownerExists) {
|
|
2070
|
+
const dir = join(this.directory, entry.name);
|
|
2071
|
+
try {
|
|
2072
|
+
if (now - (await stat(dir)).mtimeMs <= ORPHAN_BLOB_GRACE_MS) {
|
|
2073
|
+
return;
|
|
2074
|
+
}
|
|
2075
|
+
} catch {
|
|
2076
|
+
return;
|
|
2077
|
+
}
|
|
2078
|
+
await rm(dir, { recursive: true, force: true });
|
|
2079
|
+
}
|
|
2080
|
+
}));
|
|
2081
|
+
return options.reportKeys ? { removed, removedKeys } : { removed };
|
|
2082
|
+
}
|
|
2083
|
+
dispose() {
|
|
2084
|
+
if (this.initialTimer) {
|
|
2085
|
+
clearTimeout(this.initialTimer);
|
|
2086
|
+
}
|
|
2087
|
+
if (this.intervalTimer) {
|
|
2088
|
+
clearInterval(this.intervalTimer);
|
|
2089
|
+
}
|
|
2090
|
+
this.initialTimer = undefined;
|
|
2091
|
+
this.intervalTimer = undefined;
|
|
2092
|
+
}
|
|
2093
|
+
async readKey(filePath) {
|
|
2094
|
+
try {
|
|
2095
|
+
const parsed = JSON.parse(await Bun.file(filePath).text());
|
|
2096
|
+
return isKeyedEnvelope(parsed) ? parsed.__mochiKey : null;
|
|
2097
|
+
} catch {
|
|
2098
|
+
return null;
|
|
2099
|
+
}
|
|
2100
|
+
}
|
|
2101
|
+
hashKey(key) {
|
|
2102
|
+
return new Bun.CryptoHasher("sha256").update(key).digest("hex");
|
|
2103
|
+
}
|
|
2104
|
+
pathFor(key) {
|
|
2105
|
+
return join(this.directory, `${this.hashKey(key)}.json`);
|
|
2106
|
+
}
|
|
2107
|
+
pathForKey(key) {
|
|
2108
|
+
return this.pathFor(key);
|
|
2109
|
+
}
|
|
2110
|
+
encodeBlobs(value, hash, blobs) {
|
|
2111
|
+
if (isBinary(value)) {
|
|
2112
|
+
if (!this.offloadBinary) {
|
|
2113
|
+
return { __mochiBinary: Buffer.from(value).toString("base64") };
|
|
2114
|
+
}
|
|
2115
|
+
const digest = new Bun.CryptoHasher("sha256").update(value).digest("hex");
|
|
2116
|
+
const relPath = `${hash}/${digest}.bin`;
|
|
2117
|
+
blobs.push({ relPath, data: value });
|
|
2118
|
+
return { __mochiBlob: relPath, bytes: value.byteLength };
|
|
2119
|
+
}
|
|
2120
|
+
if (isBlobRef(value)) {
|
|
2121
|
+
const relPath = relative(this.directory, value.path);
|
|
2122
|
+
return { __mochiBlob: relPath, bytes: value.bytes };
|
|
2123
|
+
}
|
|
2124
|
+
if (Array.isArray(value)) {
|
|
2125
|
+
return value.map((v) => this.encodeBlobs(v, hash, blobs));
|
|
2126
|
+
}
|
|
2127
|
+
if (value !== null && typeof value === "object") {
|
|
2128
|
+
const out = {};
|
|
2129
|
+
for (const [k, v] of Object.entries(value)) {
|
|
2130
|
+
out[k] = this.encodeBlobs(v, hash, blobs);
|
|
2131
|
+
}
|
|
2132
|
+
return out;
|
|
2133
|
+
}
|
|
2134
|
+
return value;
|
|
2135
|
+
}
|
|
2136
|
+
decodeBlobs(value) {
|
|
2137
|
+
if (isBlobPointer(value)) {
|
|
2138
|
+
return { __mochiBlobRef: true, path: join(this.directory, value.__mochiBlob), bytes: value.bytes };
|
|
2139
|
+
}
|
|
2140
|
+
if (isInlineBinary(value)) {
|
|
2141
|
+
return new Uint8Array(Buffer.from(value.__mochiBinary, "base64"));
|
|
2142
|
+
}
|
|
2143
|
+
if (Array.isArray(value)) {
|
|
2144
|
+
return value.map((v) => this.decodeBlobs(v));
|
|
2145
|
+
}
|
|
2146
|
+
if (value !== null && typeof value === "object") {
|
|
2147
|
+
const out = {};
|
|
2148
|
+
for (const [k, v] of Object.entries(value)) {
|
|
2149
|
+
out[k] = this.decodeBlobs(v);
|
|
2150
|
+
}
|
|
2151
|
+
return out;
|
|
2152
|
+
}
|
|
2153
|
+
return value;
|
|
2154
|
+
}
|
|
2155
|
+
startSweeper(intervalMs) {
|
|
2156
|
+
const run2 = async () => {
|
|
2157
|
+
const start = Date.now();
|
|
2158
|
+
try {
|
|
2159
|
+
const { removed } = await this.sweep(start);
|
|
2160
|
+
mochiEvents.emit("cache:sweep", { removed, durationMs: Date.now() - start });
|
|
2161
|
+
} catch (err) {
|
|
2162
|
+
logger.warn(`Cache sweep failed: ${err instanceof Error ? err.message : String(err)}`);
|
|
2163
|
+
}
|
|
2164
|
+
};
|
|
2165
|
+
this.initialTimer = setTimeout(run2, 1000);
|
|
2166
|
+
this.intervalTimer = setInterval(run2, intervalMs);
|
|
2167
|
+
this.initialTimer.unref?.();
|
|
2168
|
+
this.intervalTimer.unref?.();
|
|
2169
|
+
}
|
|
2170
|
+
}
|
|
2171
|
+
|
|
2172
|
+
// node_modules/mochi-framework/src/cache/cache.ts
|
|
2173
|
+
var identity = (value) => value;
|
|
2174
|
+
function withTimeout(work, ms, key) {
|
|
2175
|
+
let timer;
|
|
2176
|
+
const timeout = new Promise((_, reject) => {
|
|
2177
|
+
timer = setTimeout(() => reject(new Error(`MochiCache: recompute for "${key}" timed out after ${ms}ms`)), ms);
|
|
2178
|
+
});
|
|
2179
|
+
return Promise.race([work, timeout]).finally(() => clearTimeout(timer));
|
|
2180
|
+
}
|
|
2181
|
+
|
|
2182
|
+
class MochiCache {
|
|
2183
|
+
storage;
|
|
2184
|
+
minTimeToStale;
|
|
2185
|
+
maxTimeToLive;
|
|
2186
|
+
serialize;
|
|
2187
|
+
deserialize;
|
|
2188
|
+
inflightTimeout;
|
|
2189
|
+
crossProcessInflight;
|
|
2190
|
+
inflight = new Map;
|
|
2191
|
+
constructor(options = {}) {
|
|
2192
|
+
this.storage = options.storage ?? new MemoryStorage;
|
|
2193
|
+
this.minTimeToStale = options.minTimeToStale ?? 5000;
|
|
2194
|
+
this.maxTimeToLive = options.maxTimeToLive ?? 600000;
|
|
2195
|
+
this.serialize = options.serialize ?? identity;
|
|
2196
|
+
this.deserialize = options.deserialize ?? identity;
|
|
2197
|
+
this.inflightTimeout = options.inflightTimeout ?? 3600000;
|
|
2198
|
+
this.crossProcessInflight = options.crossProcessInflight ?? false;
|
|
2199
|
+
if (this.minTimeToStale >= this.maxTimeToLive) {
|
|
2200
|
+
throw new Error(`MochiCache: minTimeToStale (${this.minTimeToStale}) must be less than maxTimeToLive (${this.maxTimeToLive}).`);
|
|
2201
|
+
}
|
|
2202
|
+
}
|
|
2203
|
+
async fetch(key, fn) {
|
|
2204
|
+
const result = await this.fetchWithStatus(key, fn);
|
|
2205
|
+
return result.value;
|
|
2206
|
+
}
|
|
2207
|
+
async fetchWithStatus(key, fn) {
|
|
2208
|
+
const entry = await this.read(key);
|
|
2209
|
+
if (entry == null) {
|
|
2210
|
+
const value2 = await this.run(key, fn);
|
|
2211
|
+
return this.emitRead(key, value2, "miss");
|
|
2212
|
+
}
|
|
2213
|
+
const cached = entry.value;
|
|
2214
|
+
const age = this.now() - entry.createdAt;
|
|
2215
|
+
if (age < this.minTimeToStale) {
|
|
2216
|
+
return this.emitRead(key, cached, "fresh");
|
|
2217
|
+
}
|
|
2218
|
+
if (age < this.maxTimeToLive) {
|
|
2219
|
+
if (await this.deferToPeer(key)) {
|
|
2220
|
+
return this.emitRead(key, cached, "stale");
|
|
2221
|
+
}
|
|
2222
|
+
mochiEvents.emit("cache:revalidate", { key });
|
|
2223
|
+
this.run(key, fn).catch((error) => {
|
|
2224
|
+
mochiEvents.emit("cache:revalidate:failed", { key, error });
|
|
2225
|
+
});
|
|
2226
|
+
return this.emitRead(key, cached, "stale");
|
|
2227
|
+
}
|
|
2228
|
+
if (age < this.maxTimeToLive + this.inflightTimeout && await this.deferToPeer(key)) {
|
|
2229
|
+
return this.emitRead(key, cached, "stale");
|
|
2230
|
+
}
|
|
2231
|
+
const value = await this.run(key, fn);
|
|
2232
|
+
return this.emitRead(key, value, "expired");
|
|
2233
|
+
}
|
|
2234
|
+
async delete(key) {
|
|
2235
|
+
this.inflight.delete(key);
|
|
2236
|
+
try {
|
|
2237
|
+
await this.storage.removeItem(key);
|
|
2238
|
+
} catch (error) {
|
|
2239
|
+
mochiEvents.emit("cache:error", { key, operation: "remove", error });
|
|
2240
|
+
throw error;
|
|
2241
|
+
}
|
|
2242
|
+
await this.removeMarker(key);
|
|
2243
|
+
mochiEvents.emit("cache:delete", { key });
|
|
2244
|
+
}
|
|
2245
|
+
async peek(key) {
|
|
2246
|
+
const entry = await this.read(key);
|
|
2247
|
+
if (entry == null) {
|
|
2248
|
+
return null;
|
|
2249
|
+
}
|
|
2250
|
+
const age = this.now() - entry.createdAt;
|
|
2251
|
+
const status = age < this.minTimeToStale ? "fresh" : age < this.maxTimeToLive ? "stale" : "expired";
|
|
2252
|
+
return { value: entry.value, status };
|
|
2253
|
+
}
|
|
2254
|
+
async set(key, value) {
|
|
2255
|
+
this.inflight.delete(key);
|
|
2256
|
+
const entry = this.serialize({ value, createdAt: this.now() });
|
|
2257
|
+
try {
|
|
2258
|
+
await this.storage.setItem(key, entry);
|
|
2259
|
+
} catch (error) {
|
|
2260
|
+
mochiEvents.emit("cache:error", { key, operation: "set", error });
|
|
2261
|
+
throw error;
|
|
2262
|
+
}
|
|
2263
|
+
}
|
|
2264
|
+
async markStale(key) {
|
|
2265
|
+
this.inflight.delete(key);
|
|
2266
|
+
let raw;
|
|
2267
|
+
try {
|
|
2268
|
+
raw = await this.storage.getItem(key);
|
|
2269
|
+
} catch (error) {
|
|
2270
|
+
mochiEvents.emit("cache:error", { key, operation: "get", error });
|
|
2271
|
+
return;
|
|
2272
|
+
}
|
|
2273
|
+
if (raw == null) {
|
|
2274
|
+
return;
|
|
2275
|
+
}
|
|
2276
|
+
const entry = this.deserialize(raw);
|
|
2277
|
+
const staleCreatedAt = this.now() - this.minTimeToStale;
|
|
2278
|
+
if (entry.createdAt <= staleCreatedAt) {
|
|
2279
|
+
return;
|
|
2280
|
+
}
|
|
2281
|
+
const next = this.serialize({ value: entry.value, createdAt: staleCreatedAt });
|
|
2282
|
+
try {
|
|
2283
|
+
await this.storage.setItem(key, next);
|
|
2284
|
+
} catch (error) {
|
|
2285
|
+
mochiEvents.emit("cache:error", { key, operation: "set", error });
|
|
2286
|
+
}
|
|
2287
|
+
}
|
|
2288
|
+
async clearItems() {
|
|
2289
|
+
this.inflight.clear();
|
|
2290
|
+
try {
|
|
2291
|
+
await this.storage.clear();
|
|
2292
|
+
} catch (error) {
|
|
2293
|
+
mochiEvents.emit("cache:error", { key: "*", operation: "clear", error });
|
|
2294
|
+
throw error;
|
|
2295
|
+
}
|
|
2296
|
+
}
|
|
2297
|
+
async read(key) {
|
|
2298
|
+
let raw;
|
|
2299
|
+
try {
|
|
2300
|
+
raw = await this.storage.getItem(key);
|
|
2301
|
+
} catch (error) {
|
|
2302
|
+
mochiEvents.emit("cache:error", { key, operation: "get", error });
|
|
2303
|
+
return null;
|
|
2304
|
+
}
|
|
2305
|
+
return raw == null ? null : this.deserialize(raw);
|
|
2306
|
+
}
|
|
2307
|
+
run(key, fn) {
|
|
2308
|
+
const existing = this.inflight.get(key);
|
|
2309
|
+
if (existing) {
|
|
2310
|
+
return existing;
|
|
2311
|
+
}
|
|
2312
|
+
const ref = { current: null };
|
|
2313
|
+
const runId = randomUUID();
|
|
2314
|
+
const work = (async () => {
|
|
2315
|
+
await this.writeMarker(key, runId);
|
|
2316
|
+
try {
|
|
2317
|
+
const value = await fn();
|
|
2318
|
+
const serialized = this.serialize({ value, createdAt: this.now() });
|
|
2319
|
+
if (this.inflight.get(key) === ref.current) {
|
|
2320
|
+
try {
|
|
2321
|
+
await this.storage.setItem(key, serialized);
|
|
2322
|
+
} catch (error) {
|
|
2323
|
+
mochiEvents.emit("cache:error", { key, operation: "set", error });
|
|
2324
|
+
}
|
|
2325
|
+
}
|
|
2326
|
+
return this.deserialize(serialized).value;
|
|
2327
|
+
} finally {
|
|
2328
|
+
await this.removeMarker(key, runId);
|
|
2329
|
+
}
|
|
2330
|
+
})();
|
|
2331
|
+
const guarded = this.inflightTimeout > 0 && Number.isFinite(this.inflightTimeout) ? withTimeout(work, this.inflightTimeout, key) : work;
|
|
2332
|
+
const promise = guarded.finally(() => {
|
|
2333
|
+
if (this.inflight.get(key) === ref.current) {
|
|
2334
|
+
this.inflight.delete(key);
|
|
2335
|
+
}
|
|
2336
|
+
});
|
|
2337
|
+
ref.current = promise;
|
|
2338
|
+
this.inflight.set(key, promise);
|
|
2339
|
+
return promise;
|
|
2340
|
+
}
|
|
2341
|
+
markerKey(key) {
|
|
2342
|
+
return `mochi:inflight:${key}`;
|
|
2343
|
+
}
|
|
2344
|
+
markerLeaseEnabled() {
|
|
2345
|
+
return this.crossProcessInflight && this.inflightTimeout > 0 && Number.isFinite(this.inflightTimeout);
|
|
2346
|
+
}
|
|
2347
|
+
async deferToPeer(key) {
|
|
2348
|
+
if (!this.markerLeaseEnabled() || this.inflight.has(key)) {
|
|
2349
|
+
return false;
|
|
2350
|
+
}
|
|
2351
|
+
let raw;
|
|
2352
|
+
try {
|
|
2353
|
+
raw = await this.storage.getItem(this.markerKey(key));
|
|
2354
|
+
} catch {
|
|
2355
|
+
return false;
|
|
2356
|
+
}
|
|
2357
|
+
const marker = raw;
|
|
2358
|
+
if (marker == null || typeof marker.startedAt !== "number") {
|
|
2359
|
+
return false;
|
|
2360
|
+
}
|
|
2361
|
+
if (this.now() - marker.startedAt >= this.inflightTimeout) {
|
|
2362
|
+
return false;
|
|
2363
|
+
}
|
|
2364
|
+
mochiEvents.emit("cache:inflight:deferred", { key });
|
|
2365
|
+
return true;
|
|
2366
|
+
}
|
|
2367
|
+
async writeMarker(key, runId) {
|
|
2368
|
+
if (!this.markerLeaseEnabled()) {
|
|
2369
|
+
return;
|
|
2370
|
+
}
|
|
2371
|
+
try {
|
|
2372
|
+
await this.storage.setItem(this.markerKey(key), { startedAt: this.now(), runId });
|
|
2373
|
+
} catch (error) {
|
|
2374
|
+
mochiEvents.emit("cache:error", { key, operation: "set", error });
|
|
2375
|
+
}
|
|
2376
|
+
}
|
|
2377
|
+
async removeMarker(key, runId) {
|
|
2378
|
+
if (!this.markerLeaseEnabled()) {
|
|
2379
|
+
return;
|
|
2380
|
+
}
|
|
2381
|
+
try {
|
|
2382
|
+
if (runId !== undefined) {
|
|
2383
|
+
const raw = await this.storage.getItem(this.markerKey(key));
|
|
2384
|
+
if (raw != null && raw.runId !== undefined && raw.runId !== runId) {
|
|
2385
|
+
return;
|
|
2386
|
+
}
|
|
2387
|
+
}
|
|
2388
|
+
await this.storage.removeItem(this.markerKey(key));
|
|
2389
|
+
} catch (error) {
|
|
2390
|
+
mochiEvents.emit("cache:error", { key, operation: "remove", error });
|
|
2391
|
+
}
|
|
2392
|
+
}
|
|
2393
|
+
emitRead(key, value, status) {
|
|
2394
|
+
mochiEvents.emit("cache:read", { key, status });
|
|
2395
|
+
return { value, status };
|
|
2396
|
+
}
|
|
2397
|
+
now() {
|
|
2398
|
+
return Date.now();
|
|
2399
|
+
}
|
|
2400
|
+
}
|
|
2401
|
+
// node_modules/mochi-framework/src/lifecycle.ts
|
|
2402
|
+
var milestones = pinGlobal("__mochi_startup_milestones__", () => new Set);
|
|
2403
|
+
|
|
2404
|
+
// node_modules/mochi-framework/src/extensions.ts
|
|
2405
|
+
var STARTUP_MILESTONE_HOOKS = new Set(["mochi:init", "mochi:listening", "mochi:queuesMounted", "mochi:ready"]);
|
|
2406
|
+
var FILTER_KINDS = {
|
|
2407
|
+
"csrf:formContentTypes": "sync",
|
|
2408
|
+
"csrf:protectedMethods": "sync",
|
|
2409
|
+
"csrf:trustedOrigins": "sync",
|
|
2410
|
+
"csrf:check": "sync",
|
|
2411
|
+
"trailingSlash:redirect": "sync",
|
|
2412
|
+
"cookie:defaults": "sync",
|
|
2413
|
+
"html:shell": "sync",
|
|
2414
|
+
"serverIsland:secretKey": "async",
|
|
2415
|
+
"payload:compressMinBytes": "sync",
|
|
2416
|
+
"compile:preprocessors": "sync",
|
|
2417
|
+
"publicDir:scan": "async",
|
|
2418
|
+
"consoleLogger:level": "sync",
|
|
2419
|
+
"consoleLogger:line": "sync",
|
|
2420
|
+
"barrel:warn": "sync",
|
|
2421
|
+
"image:maxRedirects": "sync",
|
|
2422
|
+
"image:url": "sync",
|
|
2423
|
+
"image:fileFilter": "sync",
|
|
2424
|
+
"image:localAssetFilename": "sync",
|
|
2425
|
+
"image:localAssetUrl": "sync",
|
|
2426
|
+
"email:message": "async",
|
|
2427
|
+
"captcha:bits": "sync",
|
|
2428
|
+
"captcha:minAgeMs": "sync",
|
|
2429
|
+
"captcha:driftAllowanceMs": "sync",
|
|
2430
|
+
"captcha:solveBudgetMs": "sync",
|
|
2431
|
+
"queue:recoveryStallWarningMs": "sync",
|
|
2432
|
+
"queue:lockDurationMs": "sync"
|
|
2433
|
+
};
|
|
2434
|
+
var registry = pinGlobal("__mochi_extensions_registry__", () => ({ eventHooks: {}, filters: {} }));
|
|
2435
|
+
var SERVER_ONLY_REASON2 = "Hooks and filters are server-only \u2014 the registry only exists in the server process, so this call could never see a registered entry.";
|
|
2436
|
+
function applyFilter(name, value, ctx) {
|
|
2437
|
+
assertServerOnly(`applyFilter('${name}')`, SERVER_ONLY_REASON2);
|
|
2438
|
+
const fn = registry.filters[name];
|
|
2439
|
+
if (FILTER_KINDS[name] === "async") {
|
|
2440
|
+
if (!fn) {
|
|
2441
|
+
return Promise.resolve(value);
|
|
2442
|
+
}
|
|
2443
|
+
return fn(value, ctx);
|
|
2444
|
+
}
|
|
2445
|
+
if (!fn) {
|
|
2446
|
+
return value;
|
|
2447
|
+
}
|
|
2448
|
+
return fn(value, ctx);
|
|
2449
|
+
}
|
|
2450
|
+
|
|
2451
|
+
// node_modules/mochi-framework/src/mochiConfig.ts
|
|
2452
|
+
var GLOBAL_KEY = "__mochi_config__";
|
|
2453
|
+
var SERVER_ONLY_REASON3 = "The Mochi.serve() config singleton \u2014 and the secret key it holds \u2014 only exists in the server process.";
|
|
2454
|
+
function getMochiConfig() {
|
|
2455
|
+
assertServerOnly("getMochiConfig()", SERVER_ONLY_REASON3);
|
|
2456
|
+
const ctx = globalThis[GLOBAL_KEY];
|
|
2457
|
+
if (!ctx) {
|
|
2458
|
+
throw new Error("Mochi.serve() has not been called yet.");
|
|
2459
|
+
}
|
|
2460
|
+
return ctx;
|
|
2461
|
+
}
|
|
2462
|
+
|
|
2463
|
+
// node_modules/mochi-framework/src/runtime/requestCache.ts
|
|
2464
|
+
function isThenable(value) {
|
|
2465
|
+
return typeof value?.then === "function";
|
|
2466
|
+
}
|
|
2467
|
+
var warnedNoContext = false;
|
|
2468
|
+
function warnNoContext(label) {
|
|
2469
|
+
if (warnedNoContext) {
|
|
2470
|
+
return;
|
|
2471
|
+
}
|
|
2472
|
+
let development = true;
|
|
2473
|
+
try {
|
|
2474
|
+
development = getMochiConfig().options.development ?? true;
|
|
2475
|
+
} catch {}
|
|
2476
|
+
if (!development) {
|
|
2477
|
+
return;
|
|
2478
|
+
}
|
|
2479
|
+
warnedNoContext = true;
|
|
2480
|
+
logger.warn(`${label} was called outside of a request; the result is not cached. ` + "Request-cached helpers only memoize inside a Mochi request handler.");
|
|
2481
|
+
}
|
|
2482
|
+
function bumpKey(state2, key, kind) {
|
|
2483
|
+
let tally = state2.perKey.get(key);
|
|
2484
|
+
if (!tally) {
|
|
2485
|
+
tally = { hits: 0, misses: 0 };
|
|
2486
|
+
state2.perKey.set(key, tally);
|
|
2487
|
+
}
|
|
2488
|
+
tally[kind]++;
|
|
2489
|
+
}
|
|
2490
|
+
function getOrSetIn(state2, key, fn) {
|
|
2491
|
+
if (state2.map.has(key)) {
|
|
2492
|
+
state2.hits++;
|
|
2493
|
+
bumpKey(state2, key, "hits");
|
|
2494
|
+
return state2.map.get(key);
|
|
2495
|
+
}
|
|
2496
|
+
state2.misses++;
|
|
2497
|
+
bumpKey(state2, key, "misses");
|
|
2498
|
+
const value = fn();
|
|
2499
|
+
state2.map.set(key, value);
|
|
2500
|
+
if (isThenable(value)) {
|
|
2501
|
+
Promise.resolve(value).then(undefined, () => {
|
|
2502
|
+
if (state2.map.get(key) === value) {
|
|
2503
|
+
state2.map.delete(key);
|
|
2504
|
+
}
|
|
2505
|
+
});
|
|
2506
|
+
}
|
|
2507
|
+
return value;
|
|
2508
|
+
}
|
|
2509
|
+
function currentState() {
|
|
2510
|
+
const ctx = requestContext.getStore();
|
|
2511
|
+
if (!ctx) {
|
|
2512
|
+
return;
|
|
2513
|
+
}
|
|
2514
|
+
return ctx.requestCache ??= { map: new Map, hits: 0, misses: 0, perKey: new Map };
|
|
2515
|
+
}
|
|
2516
|
+
function cacheWith(key, fn, label) {
|
|
2517
|
+
const state2 = currentState();
|
|
2518
|
+
if (!state2) {
|
|
2519
|
+
if (label) {
|
|
2520
|
+
warnNoContext(label);
|
|
2521
|
+
}
|
|
2522
|
+
return fn();
|
|
2523
|
+
}
|
|
2524
|
+
return getOrSetIn(state2, key, fn);
|
|
2525
|
+
}
|
|
2526
|
+
var memoCounter = pinGlobal("__mochi_request_memo_counter__", () => ({ n: 0 }));
|
|
2527
|
+
function requestMemo(fn, options = {}) {
|
|
2528
|
+
const namespace = options.namespace ?? `memo:${++memoCounter.n}`;
|
|
2529
|
+
const keyOf = options.key ?? defaultKey;
|
|
2530
|
+
const label = options.quiet ? undefined : `${fn.name || "A request-memoized function"}()`;
|
|
2531
|
+
return (...args) => cacheWith(`${namespace}:${keyOf(...args)}`, () => fn(...args), label);
|
|
2532
|
+
}
|
|
2533
|
+
function defaultKey(...args) {
|
|
2534
|
+
return args.map(keyPart).join("\x00");
|
|
2535
|
+
}
|
|
2536
|
+
function keyPart(arg) {
|
|
2537
|
+
switch (typeof arg) {
|
|
2538
|
+
case "string":
|
|
2539
|
+
return `s:${arg}`;
|
|
2540
|
+
case "number":
|
|
2541
|
+
return `n:${arg}`;
|
|
2542
|
+
case "boolean":
|
|
2543
|
+
return `b:${arg}`;
|
|
2544
|
+
case "bigint":
|
|
2545
|
+
return `i:${arg}`;
|
|
2546
|
+
case "undefined":
|
|
2547
|
+
return "u";
|
|
2548
|
+
case "object":
|
|
2549
|
+
if (arg === null) {
|
|
2550
|
+
return "null";
|
|
2551
|
+
}
|
|
2552
|
+
try {
|
|
2553
|
+
return `o:${JSON.stringify(arg)}`;
|
|
2554
|
+
} catch {
|
|
2555
|
+
throw new Error("requestMemo() could not serialize an argument for the cache key. Pass a `key` function to build the key yourself.");
|
|
2556
|
+
}
|
|
2557
|
+
default:
|
|
2558
|
+
throw new Error(`requestMemo() cannot key a ${typeof arg} argument. Pass a \`key\` function to build the key yourself.`);
|
|
2559
|
+
}
|
|
2560
|
+
}
|
|
2561
|
+
// node_modules/mochi-framework/src/image/config.ts
|
|
2562
|
+
import { createHash as createHash2 } from "crypto";
|
|
2563
|
+
|
|
2564
|
+
// node_modules/mochi-framework/src/image/imageCache.ts
|
|
2565
|
+
import { createHash } from "crypto";
|
|
2566
|
+
function hash(input) {
|
|
2567
|
+
return createHash("sha256").update(input).digest("base64url").slice(0, 22);
|
|
2568
|
+
}
|
|
2569
|
+
function variantId(src, configHash) {
|
|
2570
|
+
return hash(`variant:${configHash}:${src}`);
|
|
2571
|
+
}
|
|
2572
|
+
function originalId(src) {
|
|
2573
|
+
return hash(`original:${src}`);
|
|
2574
|
+
}
|
|
2575
|
+
var ORIG_PREFIX = "MochiImage:Original:";
|
|
2576
|
+
var VAR_PREFIX = "MochiImage:Variant:";
|
|
2577
|
+
var PH_PREFIX = "MochiImage:Placeholder:";
|
|
2578
|
+
var origKey = (src) => ORIG_PREFIX + src;
|
|
2579
|
+
var varKey = (id) => VAR_PREFIX + id;
|
|
2580
|
+
var phKey = (src) => PH_PREFIX + src;
|
|
2581
|
+
function mapStatus(status) {
|
|
2582
|
+
if (status === "expired" || status === "miss") {
|
|
2583
|
+
return "miss";
|
|
2584
|
+
}
|
|
2585
|
+
return status;
|
|
2586
|
+
}
|
|
2587
|
+
function storedBytesLen(bytes) {
|
|
2588
|
+
return isBlobRef(bytes) ? bytes.bytes : bytes.byteLength;
|
|
2589
|
+
}
|
|
2590
|
+
var cascadeSeq = 0;
|
|
2591
|
+
function pathForKey(storage, key) {
|
|
2592
|
+
const withPath = storage;
|
|
2593
|
+
return typeof withPath.pathForKey === "function" ? withPath.pathForKey(key) : key;
|
|
2594
|
+
}
|
|
2595
|
+
|
|
2596
|
+
class ImageCache {
|
|
2597
|
+
storage;
|
|
2598
|
+
cache;
|
|
2599
|
+
minTimeToStale;
|
|
2600
|
+
maxTimeToLive;
|
|
2601
|
+
sizes;
|
|
2602
|
+
cascadeHandlerName;
|
|
2603
|
+
constructor(options) {
|
|
2604
|
+
this.minTimeToStale = options.minTimeToStale;
|
|
2605
|
+
this.maxTimeToLive = options.maxTimeToLive;
|
|
2606
|
+
this.sizes = options.sizes;
|
|
2607
|
+
this.storage = options.storage ?? new FileStorage({ directory: options.cacheDir, maxAge: options.maxTimeToLive, purgeInterval: 0, offloadBinary: true });
|
|
2608
|
+
this.cache = new MochiCache({
|
|
2609
|
+
minTimeToStale: this.minTimeToStale,
|
|
2610
|
+
maxTimeToLive: this.maxTimeToLive,
|
|
2611
|
+
storage: this.storage,
|
|
2612
|
+
inflightTimeout: 60000,
|
|
2613
|
+
crossProcessInflight: true
|
|
2614
|
+
});
|
|
2615
|
+
this.cascadeHandlerName = `mochi-image:cache-delete:${++cascadeSeq}`;
|
|
2616
|
+
mochiEvents.setHandler(this.cascadeHandlerName, "cache:delete", (event) => {
|
|
2617
|
+
if (event.key.startsWith(ORIG_PREFIX)) {
|
|
2618
|
+
this.cascadeSource(event.key.slice(ORIG_PREFIX.length), "invalidated").catch(() => {});
|
|
2619
|
+
}
|
|
2620
|
+
});
|
|
2621
|
+
}
|
|
2622
|
+
dispose() {
|
|
2623
|
+
mochiEvents.removeHandler(this.cascadeHandlerName);
|
|
2624
|
+
this.storage.dispose?.();
|
|
2625
|
+
}
|
|
2626
|
+
async toBytes(field) {
|
|
2627
|
+
return isBlobRef(field) ? readBlobRef(field) : field;
|
|
2628
|
+
}
|
|
2629
|
+
metaFrom(src, value) {
|
|
2630
|
+
return {
|
|
2631
|
+
version: 1,
|
|
2632
|
+
contentType: value.contentType,
|
|
2633
|
+
etag: value.etag,
|
|
2634
|
+
width: value.width,
|
|
2635
|
+
height: value.height,
|
|
2636
|
+
format: value.format,
|
|
2637
|
+
createdAt: value.createdAt,
|
|
2638
|
+
staleAt: value.createdAt + this.minTimeToStale,
|
|
2639
|
+
evictAt: value.createdAt + this.maxTimeToLive,
|
|
2640
|
+
src,
|
|
2641
|
+
originalCreatedAt: value.originalCreatedAt
|
|
2642
|
+
};
|
|
2643
|
+
}
|
|
2644
|
+
async getVariant(src, id, regenerate) {
|
|
2645
|
+
const key = varKey(id);
|
|
2646
|
+
const orig = await this.cache.peek(origKey(src));
|
|
2647
|
+
if (!orig || orig.status === "expired") {
|
|
2648
|
+
if (await this.cache.peek(key)) {
|
|
2649
|
+
await this.cache.delete(key);
|
|
2650
|
+
}
|
|
2651
|
+
} else {
|
|
2652
|
+
const existing = await this.cache.peek(key);
|
|
2653
|
+
if (existing && existing.status === "fresh" && (orig.status === "stale" || existing.value.originalCreatedAt !== orig.value.createdAt)) {
|
|
2654
|
+
await this.cache.markStale(key);
|
|
2655
|
+
}
|
|
2656
|
+
}
|
|
2657
|
+
const { value, status } = await this.cache.fetchWithStatus(key, async () => {
|
|
2658
|
+
const r = await regenerate();
|
|
2659
|
+
const stored = {
|
|
2660
|
+
createdAt: Date.now(),
|
|
2661
|
+
contentType: r.contentType,
|
|
2662
|
+
etag: id,
|
|
2663
|
+
width: r.width,
|
|
2664
|
+
height: r.height,
|
|
2665
|
+
format: r.format,
|
|
2666
|
+
bytes: r.bytes,
|
|
2667
|
+
originalCreatedAt: r.originalCreatedAt
|
|
2668
|
+
};
|
|
2669
|
+
mochiEvents.emit("image:store", {
|
|
2670
|
+
kind: "variant",
|
|
2671
|
+
src,
|
|
2672
|
+
path: pathForKey(this.storage, key),
|
|
2673
|
+
id,
|
|
2674
|
+
size: r.bytes.byteLength,
|
|
2675
|
+
contentType: r.contentType,
|
|
2676
|
+
width: r.width,
|
|
2677
|
+
height: r.height,
|
|
2678
|
+
format: r.format
|
|
2679
|
+
});
|
|
2680
|
+
return stored;
|
|
2681
|
+
});
|
|
2682
|
+
const bytes = await this.toBytes(value.bytes);
|
|
2683
|
+
return { entry: { bytes, meta: this.metaFrom(src, value) }, status: mapStatus(status) };
|
|
2684
|
+
}
|
|
2685
|
+
async getOriginal(src, fetchFn) {
|
|
2686
|
+
const key = origKey(src);
|
|
2687
|
+
const { value, status } = await this.cache.fetchWithStatus(key, async () => {
|
|
2688
|
+
const fetched = await fetchFn();
|
|
2689
|
+
const contentType = fetched.contentType ?? "application/octet-stream";
|
|
2690
|
+
const stored = {
|
|
2691
|
+
createdAt: Date.now(),
|
|
2692
|
+
contentType,
|
|
2693
|
+
etag: originalId(src),
|
|
2694
|
+
width: 0,
|
|
2695
|
+
height: 0,
|
|
2696
|
+
format: "",
|
|
2697
|
+
bytes: fetched.bytes
|
|
2698
|
+
};
|
|
2699
|
+
mochiEvents.emit("image:store", {
|
|
2700
|
+
kind: "original",
|
|
2701
|
+
src,
|
|
2702
|
+
path: pathForKey(this.storage, key),
|
|
2703
|
+
id: originalId(src),
|
|
2704
|
+
size: fetched.bytes.byteLength,
|
|
2705
|
+
contentType,
|
|
2706
|
+
width: 0,
|
|
2707
|
+
height: 0,
|
|
2708
|
+
format: ""
|
|
2709
|
+
});
|
|
2710
|
+
return stored;
|
|
2711
|
+
});
|
|
2712
|
+
const bytes = await this.toBytes(value.bytes);
|
|
2713
|
+
return { entry: { bytes, meta: this.metaFrom(src, value) }, status: mapStatus(status) };
|
|
2714
|
+
}
|
|
2715
|
+
async invalidateOriginal(src, hard) {
|
|
2716
|
+
const key = origKey(src);
|
|
2717
|
+
if (!hard) {
|
|
2718
|
+
await this.cache.markStale(key);
|
|
2719
|
+
return;
|
|
2720
|
+
}
|
|
2721
|
+
const orig = await this.cache.peek(key);
|
|
2722
|
+
await this.cascadeSource(src, "invalidated");
|
|
2723
|
+
await this.cache.delete(key);
|
|
2724
|
+
if (orig) {
|
|
2725
|
+
mochiEvents.emit("image:delete", {
|
|
2726
|
+
kind: "original",
|
|
2727
|
+
src,
|
|
2728
|
+
path: pathForKey(this.storage, key),
|
|
2729
|
+
id: originalId(src),
|
|
2730
|
+
size: storedBytesLen(orig.value.bytes),
|
|
2731
|
+
reason: "invalidated"
|
|
2732
|
+
});
|
|
2733
|
+
}
|
|
2734
|
+
}
|
|
2735
|
+
async clearAll() {
|
|
2736
|
+
await this.cache.clearItems();
|
|
2737
|
+
}
|
|
2738
|
+
async count() {
|
|
2739
|
+
return await this.storage.count?.() ?? 0;
|
|
2740
|
+
}
|
|
2741
|
+
async keys() {
|
|
2742
|
+
const keys = await this.storage.keys?.() ?? [];
|
|
2743
|
+
return keys.filter((key) => !key.startsWith("mochi:inflight:"));
|
|
2744
|
+
}
|
|
2745
|
+
async inspect(key) {
|
|
2746
|
+
return this.storage.getItem(key);
|
|
2747
|
+
}
|
|
2748
|
+
async cascadeSource(src, reason) {
|
|
2749
|
+
const ph = await this.cache.peek(phKey(src));
|
|
2750
|
+
if (ph) {
|
|
2751
|
+
await this.cache.delete(phKey(src));
|
|
2752
|
+
mochiEvents.emit("image:delete", {
|
|
2753
|
+
kind: "placeholder",
|
|
2754
|
+
src,
|
|
2755
|
+
path: pathForKey(this.storage, phKey(src)),
|
|
2756
|
+
id: originalId(src),
|
|
2757
|
+
size: Buffer.byteLength(ph.value.dataUrl),
|
|
2758
|
+
reason
|
|
2759
|
+
});
|
|
2760
|
+
}
|
|
2761
|
+
for (const size of Object.values(this.sizes)) {
|
|
2762
|
+
const id = variantId(src, size.configHash);
|
|
2763
|
+
const variant = await this.cache.peek(varKey(id));
|
|
2764
|
+
if (variant) {
|
|
2765
|
+
await this.cache.delete(varKey(id));
|
|
2766
|
+
mochiEvents.emit("image:delete", {
|
|
2767
|
+
kind: "variant",
|
|
2768
|
+
src,
|
|
2769
|
+
path: pathForKey(this.storage, varKey(id)),
|
|
2770
|
+
id,
|
|
2771
|
+
size: storedBytesLen(variant.value.bytes),
|
|
2772
|
+
reason
|
|
2773
|
+
});
|
|
2774
|
+
}
|
|
2775
|
+
}
|
|
2776
|
+
}
|
|
2777
|
+
async sweep(now = Date.now()) {
|
|
2778
|
+
const result = await this.storage.sweep?.(now, { reportKeys: true });
|
|
2779
|
+
const removed = result?.removed ?? 0;
|
|
2780
|
+
let removedOriginals = 0;
|
|
2781
|
+
let removedVariants = 0;
|
|
2782
|
+
for (const key of result?.removedKeys ?? []) {
|
|
2783
|
+
if (key.startsWith(ORIG_PREFIX)) {
|
|
2784
|
+
removedOriginals++;
|
|
2785
|
+
} else if (key.startsWith(VAR_PREFIX) || key.startsWith(PH_PREFIX)) {
|
|
2786
|
+
removedVariants++;
|
|
2787
|
+
}
|
|
2788
|
+
}
|
|
2789
|
+
return { removedVariants, removedOriginals, removedOther: removed - removedVariants - removedOriginals };
|
|
2790
|
+
}
|
|
2791
|
+
async getPlaceholder(src) {
|
|
2792
|
+
const cached = await this.cache.peek(phKey(src));
|
|
2793
|
+
if (!cached || cached.status === "expired") {
|
|
2794
|
+
return null;
|
|
2795
|
+
}
|
|
2796
|
+
const orig = await this.cache.peek(origKey(src));
|
|
2797
|
+
if (orig && cached.value.originalCreatedAt !== orig.value.createdAt) {
|
|
2798
|
+
return null;
|
|
2799
|
+
}
|
|
2800
|
+
return cached.value.dataUrl;
|
|
2801
|
+
}
|
|
2802
|
+
async setPlaceholder(src, dataUrl, originalCreatedAt) {
|
|
2803
|
+
const key = phKey(src);
|
|
2804
|
+
await this.cache.set(key, { dataUrl, originalCreatedAt });
|
|
2805
|
+
mochiEvents.emit("image:store", {
|
|
2806
|
+
kind: "placeholder",
|
|
2807
|
+
src,
|
|
2808
|
+
path: pathForKey(this.storage, key),
|
|
2809
|
+
id: originalId(src),
|
|
2810
|
+
size: Buffer.byteLength(dataUrl),
|
|
2811
|
+
contentType: "",
|
|
2812
|
+
width: 0,
|
|
2813
|
+
height: 0,
|
|
2814
|
+
format: ""
|
|
2815
|
+
});
|
|
2816
|
+
}
|
|
2817
|
+
}
|
|
2818
|
+
|
|
2819
|
+
// node_modules/mochi-framework/src/image/config.ts
|
|
2820
|
+
var ALL_FORMATS = ["webp", "jpeg", "png", "avif"];
|
|
2821
|
+
var DEFAULT_INPUT_FORMATS = ["jpeg", "png", "webp", "avif", "gif"];
|
|
2822
|
+
function checkDimension(field, sizeName, value) {
|
|
2823
|
+
if (value === undefined) {
|
|
2824
|
+
return;
|
|
2825
|
+
}
|
|
2826
|
+
if (!Number.isFinite(value) || value < 1) {
|
|
2827
|
+
throw new Error(`Image size "${sizeName}": ${field} must be a positive number, got ${value}`);
|
|
2828
|
+
}
|
|
2829
|
+
return Math.round(value);
|
|
2830
|
+
}
|
|
2831
|
+
function canonicalStringify(value) {
|
|
2832
|
+
return JSON.stringify(value, (_key, v) => {
|
|
2833
|
+
if (v !== null && typeof v === "object" && !Array.isArray(v)) {
|
|
2834
|
+
return Object.fromEntries(Object.entries(v).sort(([a], [b]) => a < b ? -1 : a > b ? 1 : 0));
|
|
2835
|
+
}
|
|
2836
|
+
return v;
|
|
2837
|
+
});
|
|
2838
|
+
}
|
|
2839
|
+
function resolveSize(name, p, defaults) {
|
|
2840
|
+
const format = p.format ?? defaults.format;
|
|
2841
|
+
if (!defaults.outputFormats.includes(format)) {
|
|
2842
|
+
throw new Error(`Image size "${name}": format "${format}" is not in outputFormats`);
|
|
2843
|
+
}
|
|
2844
|
+
const rawQuality = p.quality ?? defaults.quality;
|
|
2845
|
+
if (!Number.isFinite(rawQuality)) {
|
|
2846
|
+
throw new Error(`Image size "${name}": quality must be a finite number, got ${rawQuality}`);
|
|
2847
|
+
}
|
|
2848
|
+
const quality = Math.min(100, Math.max(1, Math.round(rawQuality)));
|
|
2849
|
+
if (p.rotate !== undefined && !Number.isFinite(p.rotate)) {
|
|
2850
|
+
throw new Error(`Image size "${name}": rotate must be a finite number, got ${p.rotate}`);
|
|
2851
|
+
}
|
|
2852
|
+
const resolved = {
|
|
2853
|
+
name,
|
|
2854
|
+
width: checkDimension("width", name, p.width),
|
|
2855
|
+
height: checkDimension("height", name, p.height),
|
|
2856
|
+
fit: p.fit ?? "inside",
|
|
2857
|
+
withoutEnlargement: p.withoutEnlargement ?? false,
|
|
2858
|
+
rotate: p.rotate,
|
|
2859
|
+
flip: p.flip ?? false,
|
|
2860
|
+
flop: p.flop ?? false,
|
|
2861
|
+
modulate: p.modulate,
|
|
2862
|
+
format,
|
|
2863
|
+
quality,
|
|
2864
|
+
autoOrient: p.autoOrient ?? defaults.autoOrient,
|
|
2865
|
+
maxPixels: p.maxPixels ?? defaults.maxPixels,
|
|
2866
|
+
configHash: ""
|
|
2867
|
+
};
|
|
2868
|
+
const { name: _n, configHash: _h, ...bytesAffecting } = resolved;
|
|
2869
|
+
resolved.configHash = createHash2("sha256").update(canonicalStringify(bytesAffecting)).digest("base64url").slice(0, 16);
|
|
2870
|
+
return resolved;
|
|
2871
|
+
}
|
|
2872
|
+
function resolveImageOptions(opts) {
|
|
2873
|
+
const o = opts ?? {};
|
|
2874
|
+
const defaultFormat = o.defaultFormat ?? "webp";
|
|
2875
|
+
const defaultQuality = o.defaultQuality ?? 80;
|
|
2876
|
+
const outputFormats = o.outputFormats ?? ALL_FORMATS;
|
|
2877
|
+
const maxPixels = o.maxPixels ?? 50000000;
|
|
2878
|
+
const autoOrient = o.autoOrient ?? true;
|
|
2879
|
+
const sizes = Object.create(null);
|
|
2880
|
+
for (const [name, p] of Object.entries(o.sizes ?? {})) {
|
|
2881
|
+
sizes[name] = resolveSize(name, p, { format: defaultFormat, quality: defaultQuality, autoOrient, maxPixels, outputFormats });
|
|
2882
|
+
}
|
|
2883
|
+
return {
|
|
2884
|
+
enabled: o.enabled ?? true,
|
|
2885
|
+
sizes,
|
|
2886
|
+
cacheDir: o.cacheDir ?? "./.mochi/image-cache",
|
|
2887
|
+
storage: o.storage,
|
|
2888
|
+
defaultFormat,
|
|
2889
|
+
defaultQuality,
|
|
2890
|
+
outputFormats,
|
|
2891
|
+
inputFormats: o.inputFormats ?? DEFAULT_INPUT_FORMATS,
|
|
2892
|
+
maxPixels,
|
|
2893
|
+
autoOrient,
|
|
2894
|
+
allowedHosts: o.allowedHosts,
|
|
2895
|
+
blockPrivateNetworks: o.blockPrivateNetworks ?? true,
|
|
2896
|
+
fetchTimeoutMs: o.fetchTimeoutMs ?? 1e4,
|
|
2897
|
+
maxResponseBytes: o.maxResponseBytes ?? 20 * 1024 * 1024,
|
|
2898
|
+
timeToStale: o.timeToStale ?? 14400000,
|
|
2899
|
+
timeToEvict: o.timeToEvict ?? 86400000,
|
|
2900
|
+
compressPayload: o.compressPayload ?? true,
|
|
2901
|
+
sweepIntervalMs: o.sweepIntervalMs ?? 3600000
|
|
2902
|
+
};
|
|
2903
|
+
}
|
|
2904
|
+
var GLOBAL_KEY2 = "__mochi_image_runtime__";
|
|
2905
|
+
function getImageRuntime() {
|
|
2906
|
+
const g = globalThis;
|
|
2907
|
+
let runtime = g[GLOBAL_KEY2];
|
|
2908
|
+
if (!runtime) {
|
|
2909
|
+
const { options } = getMochiConfig();
|
|
2910
|
+
const resolved = resolveImageOptions(options.image);
|
|
2911
|
+
runtime = {
|
|
2912
|
+
options: resolved,
|
|
2913
|
+
cache: new ImageCache({
|
|
2914
|
+
cacheDir: resolved.cacheDir,
|
|
2915
|
+
minTimeToStale: resolved.timeToStale,
|
|
2916
|
+
maxTimeToLive: resolved.timeToEvict,
|
|
2917
|
+
sizes: resolved.sizes,
|
|
2918
|
+
storage: resolved.storage
|
|
2919
|
+
})
|
|
2920
|
+
};
|
|
2921
|
+
g[GLOBAL_KEY2] = runtime;
|
|
2922
|
+
}
|
|
2923
|
+
return runtime;
|
|
2924
|
+
}
|
|
2925
|
+
|
|
2926
|
+
// node_modules/mochi-framework/src/utils/assertPublicUrl.ts
|
|
2927
|
+
var import_ipaddr = __toESM(require_ipaddr(), 1);
|
|
2928
|
+
import { isIP } from "net";
|
|
2929
|
+
import { lookup } from "dns/promises";
|
|
2930
|
+
|
|
2931
|
+
class SsrfGuardError extends Error {
|
|
2932
|
+
constructor(message) {
|
|
2933
|
+
super(message);
|
|
2934
|
+
this.name = "SsrfGuardError";
|
|
2935
|
+
}
|
|
2936
|
+
}
|
|
2937
|
+
function hostMatches(hostname, pattern) {
|
|
2938
|
+
const host = hostname.toLowerCase();
|
|
2939
|
+
const pat = pattern.toLowerCase();
|
|
2940
|
+
if (pat.startsWith("*.")) {
|
|
2941
|
+
const suffix = pat.slice(1);
|
|
2942
|
+
return host.endsWith(suffix) && host.length > suffix.length;
|
|
2943
|
+
}
|
|
2944
|
+
return host === pat;
|
|
2945
|
+
}
|
|
2946
|
+
function stripBrackets(hostname) {
|
|
2947
|
+
return hostname.startsWith("[") && hostname.endsWith("]") ? hostname.slice(1, -1) : hostname;
|
|
2948
|
+
}
|
|
2949
|
+
function isBlockedIp(ip) {
|
|
2950
|
+
let addr;
|
|
2951
|
+
try {
|
|
2952
|
+
addr = import_ipaddr.default.process(ip);
|
|
2953
|
+
} catch {
|
|
2954
|
+
return true;
|
|
2955
|
+
}
|
|
2956
|
+
if (addr.kind() === "ipv6") {
|
|
2957
|
+
const g = addr.parts;
|
|
2958
|
+
if (g[0] === 0 && g[1] === 0 && g[2] === 0 && g[3] === 0 && g[4] === 0 && g[5] === 0) {
|
|
2959
|
+
return true;
|
|
2960
|
+
}
|
|
2961
|
+
}
|
|
2962
|
+
return addr.range() !== "unicast";
|
|
2963
|
+
}
|
|
2964
|
+
async function assertPublicUrl(src, opts) {
|
|
2965
|
+
let url;
|
|
2966
|
+
try {
|
|
2967
|
+
url = new URL(src);
|
|
2968
|
+
} catch {
|
|
2969
|
+
throw new SsrfGuardError("Invalid source URL");
|
|
2970
|
+
}
|
|
2971
|
+
if (url.protocol !== "http:" && url.protocol !== "https:") {
|
|
2972
|
+
throw new SsrfGuardError("Source protocol must be http or https");
|
|
2973
|
+
}
|
|
2974
|
+
if (opts.allowedHosts && opts.allowedHosts.length > 0) {
|
|
2975
|
+
if (!opts.allowedHosts.some((p) => hostMatches(url.hostname, p))) {
|
|
2976
|
+
throw new SsrfGuardError("Source host is not in the allowlist");
|
|
2977
|
+
}
|
|
2978
|
+
}
|
|
2979
|
+
if (opts.blockPrivateNetworks) {
|
|
2980
|
+
if (url.hostname.toLowerCase() === "localhost") {
|
|
2981
|
+
throw new SsrfGuardError("Source host resolves to a private address");
|
|
2982
|
+
}
|
|
2983
|
+
const host = stripBrackets(url.hostname);
|
|
2984
|
+
let addresses;
|
|
2985
|
+
if (isIP(host)) {
|
|
2986
|
+
addresses = [host];
|
|
2987
|
+
} else {
|
|
2988
|
+
try {
|
|
2989
|
+
const results = await lookup(host, { all: true });
|
|
2990
|
+
addresses = results.map((r) => r.address);
|
|
2991
|
+
} catch {
|
|
2992
|
+
throw new SsrfGuardError("Could not resolve source host");
|
|
2993
|
+
}
|
|
2994
|
+
}
|
|
2995
|
+
if (addresses.length === 0 || addresses.some(isBlockedIp)) {
|
|
2996
|
+
throw new SsrfGuardError("Source host resolves to a private address");
|
|
2997
|
+
}
|
|
2998
|
+
}
|
|
2999
|
+
return url;
|
|
3000
|
+
}
|
|
3001
|
+
|
|
3002
|
+
// node_modules/mochi-framework/src/image/localAssetRegistry.ts
|
|
3003
|
+
var GLOBAL_KEY3 = "__mochi_local_image_assets__";
|
|
3004
|
+
function registry2() {
|
|
3005
|
+
const g = globalThis;
|
|
3006
|
+
let map = g[GLOBAL_KEY3];
|
|
3007
|
+
if (!map) {
|
|
3008
|
+
map = new Map;
|
|
3009
|
+
g[GLOBAL_KEY3] = map;
|
|
3010
|
+
}
|
|
3011
|
+
return map;
|
|
3012
|
+
}
|
|
3013
|
+
function getLocalImageAsset(url) {
|
|
3014
|
+
return registry2().get(url);
|
|
3015
|
+
}
|
|
3016
|
+
|
|
3017
|
+
// node_modules/mochi-framework/src/image/types.ts
|
|
3018
|
+
class ImageError extends Error {
|
|
3019
|
+
status;
|
|
3020
|
+
constructor(status, message) {
|
|
3021
|
+
super(message);
|
|
3022
|
+
this.status = status;
|
|
3023
|
+
this.name = "ImageError";
|
|
3024
|
+
}
|
|
3025
|
+
}
|
|
3026
|
+
|
|
3027
|
+
// node_modules/mochi-framework/src/image/fetchSource.ts
|
|
3028
|
+
var DEFAULT_MAX_REDIRECTS = 5;
|
|
3029
|
+
async function fetchImageSource(src, opts) {
|
|
3030
|
+
const local = getLocalImageAsset(src);
|
|
3031
|
+
if (local) {
|
|
3032
|
+
return { bytes: await Bun.file(local.diskPath).bytes(), contentType: local.contentType };
|
|
3033
|
+
}
|
|
3034
|
+
const signal = AbortSignal.timeout(opts.fetchTimeoutMs);
|
|
3035
|
+
const maxRedirects = applyFilter("image:maxRedirects", DEFAULT_MAX_REDIRECTS, { src });
|
|
3036
|
+
let target = src;
|
|
3037
|
+
let res;
|
|
3038
|
+
for (let hop = 0;; hop++) {
|
|
3039
|
+
let url;
|
|
3040
|
+
try {
|
|
3041
|
+
url = await assertPublicUrl(target, {
|
|
3042
|
+
allowedHosts: opts.allowedHosts,
|
|
3043
|
+
blockPrivateNetworks: opts.blockPrivateNetworks
|
|
3044
|
+
});
|
|
3045
|
+
} catch (e) {
|
|
3046
|
+
if (e instanceof SsrfGuardError) {
|
|
3047
|
+
throw new ImageError(400, e.message);
|
|
3048
|
+
}
|
|
3049
|
+
throw e;
|
|
3050
|
+
}
|
|
3051
|
+
try {
|
|
3052
|
+
res = await fetch(url, {
|
|
3053
|
+
signal,
|
|
3054
|
+
redirect: "manual",
|
|
3055
|
+
headers: { Accept: "image/*" }
|
|
3056
|
+
});
|
|
3057
|
+
} catch {
|
|
3058
|
+
throw new ImageError(502, "Failed to fetch source image");
|
|
3059
|
+
}
|
|
3060
|
+
const location = res.headers.get("location");
|
|
3061
|
+
if (res.status >= 300 && res.status < 400 && location) {
|
|
3062
|
+
if (hop >= maxRedirects) {
|
|
3063
|
+
throw new ImageError(502, "Too many redirects");
|
|
3064
|
+
}
|
|
3065
|
+
await res.body?.cancel();
|
|
3066
|
+
target = new URL(location, url).href;
|
|
3067
|
+
continue;
|
|
3068
|
+
}
|
|
3069
|
+
break;
|
|
3070
|
+
}
|
|
3071
|
+
if (!res.ok) {
|
|
3072
|
+
throw new ImageError(502, `Source responded with ${res.status}`);
|
|
3073
|
+
}
|
|
3074
|
+
const declaredLength = Number(res.headers.get("content-length"));
|
|
3075
|
+
if (Number.isFinite(declaredLength) && declaredLength > opts.maxResponseBytes) {
|
|
3076
|
+
throw new ImageError(413, "Source image exceeds the maximum size");
|
|
3077
|
+
}
|
|
3078
|
+
const bytes = await readWithMaxSize(res, opts.maxResponseBytes);
|
|
3079
|
+
return { bytes, contentType: res.headers.get("content-type") };
|
|
3080
|
+
}
|
|
3081
|
+
async function readWithMaxSize(res, maxSizeInBytes) {
|
|
3082
|
+
const chunks = [];
|
|
3083
|
+
let total = 0;
|
|
3084
|
+
for await (const chunk of res.body ?? []) {
|
|
3085
|
+
if ((total += chunk.byteLength) > maxSizeInBytes) {
|
|
3086
|
+
throw new ImageError(413, "Source image exceeds the maximum size");
|
|
3087
|
+
}
|
|
3088
|
+
chunks.push(chunk);
|
|
3089
|
+
}
|
|
3090
|
+
return Buffer.concat(chunks);
|
|
3091
|
+
}
|
|
3092
|
+
|
|
3093
|
+
// node_modules/mochi-framework/src/utils/index.ts
|
|
3094
|
+
var import_negotiator = __toESM(require_negotiator(), 1);
|
|
3095
|
+
|
|
3096
|
+
// node_modules/mochi-framework/src/image/imageCodec.ts
|
|
3097
|
+
var ORIGINAL = 1 << 0;
|
|
3098
|
+
var HAS_SIZE = 1 << 1;
|
|
3099
|
+
var HTTPS_PREFIX = 1 << 2;
|
|
3100
|
+
var HTTP_PREFIX = 1 << 3;
|
|
3101
|
+
|
|
3102
|
+
// node_modules/mochi-framework/src/image/resize.ts
|
|
3103
|
+
function imageCtor() {
|
|
3104
|
+
const ctor = Bun.Image;
|
|
3105
|
+
if (!ctor) {
|
|
3106
|
+
throw new ImageError(500, "Bun.Image is unavailable; Bun >= 1.3.14 is required");
|
|
3107
|
+
}
|
|
3108
|
+
return ctor;
|
|
3109
|
+
}
|
|
3110
|
+
async function computePlaceholder(input, opts) {
|
|
3111
|
+
const Image = imageCtor();
|
|
3112
|
+
try {
|
|
3113
|
+
return await new Image(input, { maxPixels: opts.maxPixels }).placeholder();
|
|
3114
|
+
} catch {
|
|
3115
|
+
throw new ImageError(422, "Could not compute placeholder");
|
|
3116
|
+
}
|
|
3117
|
+
}
|
|
3118
|
+
|
|
3119
|
+
// node_modules/mochi-framework/src/image/imageApi.ts
|
|
3120
|
+
var warnedUnknownSize = new Set;
|
|
3121
|
+
var getCachedOriginal = requestMemo(readCachedOriginal, {
|
|
3122
|
+
namespace: "mochi:image:original",
|
|
3123
|
+
key: (src) => src,
|
|
3124
|
+
quiet: true
|
|
3125
|
+
});
|
|
3126
|
+
async function readCachedOriginal(src, resolved, cache) {
|
|
3127
|
+
const { entry, status } = await cache.getOriginal(src, () => fetchImageSource(src, resolved));
|
|
3128
|
+
return { bytes: entry.bytes, contentType: entry.meta.contentType, status, createdAt: entry.meta.createdAt };
|
|
3129
|
+
}
|
|
3130
|
+
var getImagePlaceholder = requestMemo(computeImagePlaceholder, {
|
|
3131
|
+
namespace: "mochi:image:placeholder:blocking",
|
|
3132
|
+
quiet: true
|
|
3133
|
+
});
|
|
3134
|
+
async function computeImagePlaceholder(src) {
|
|
3135
|
+
const { options, cache } = getImageRuntime();
|
|
3136
|
+
const cached = await cache.getPlaceholder(src);
|
|
3137
|
+
if (cached) {
|
|
3138
|
+
return cached;
|
|
3139
|
+
}
|
|
3140
|
+
try {
|
|
3141
|
+
const { bytes, createdAt } = await getCachedOriginal(src, options, cache);
|
|
3142
|
+
const dataUrl = await computePlaceholder(bytes, options);
|
|
3143
|
+
await cache.setPlaceholder(src, dataUrl, createdAt);
|
|
3144
|
+
return dataUrl;
|
|
3145
|
+
} catch (err) {
|
|
3146
|
+
logger.warn(`Could not compute image placeholder for ${src}: ${err instanceof Error ? err.message : String(err)}`);
|
|
3147
|
+
return null;
|
|
3148
|
+
}
|
|
3149
|
+
}
|
|
3150
|
+
var warmingPlaceholders = new Set;
|
|
3151
|
+
function warmImagePlaceholder(src) {
|
|
3152
|
+
if (warmingPlaceholders.has(src)) {
|
|
3153
|
+
return;
|
|
3154
|
+
}
|
|
3155
|
+
warmingPlaceholders.add(src);
|
|
3156
|
+
getImagePlaceholder(src).catch(() => {}).finally(() => warmingPlaceholders.delete(src));
|
|
3157
|
+
}
|
|
3158
|
+
var imagePlaceholder = requestMemo(readPlaceholder, { namespace: "mochi:image:placeholder", quiet: true });
|
|
3159
|
+
async function readPlaceholder(src) {
|
|
3160
|
+
const { cache } = getImageRuntime();
|
|
3161
|
+
const cached = await cache.getPlaceholder(src);
|
|
3162
|
+
if (cached) {
|
|
3163
|
+
return cached;
|
|
3164
|
+
}
|
|
3165
|
+
warmImagePlaceholder(src);
|
|
3166
|
+
return null;
|
|
3167
|
+
}
|
|
3168
|
+
// mochi-env:mochi-framework
|
|
3169
|
+
var isDev = false;
|
|
3170
|
+
function getRequestContext2() {
|
|
3171
|
+
const ctx = globalThis.__mochi_request_context__?.getStore();
|
|
3172
|
+
if (!ctx)
|
|
3173
|
+
throw new Error("getRequestContext() called outside of a request.");
|
|
3174
|
+
return ctx;
|
|
3175
|
+
}
|
|
3176
|
+
function __mochiCtxProxy(key) {
|
|
3177
|
+
return new Proxy({}, {
|
|
3178
|
+
get(_, p) {
|
|
3179
|
+
const v = getRequestContext2()[key];
|
|
3180
|
+
const r = v[p];
|
|
3181
|
+
return typeof r === "function" ? r.bind(v) : r;
|
|
3182
|
+
},
|
|
3183
|
+
has(_, p) {
|
|
3184
|
+
return p in getRequestContext2()[key];
|
|
3185
|
+
},
|
|
3186
|
+
ownKeys() {
|
|
3187
|
+
return Reflect.ownKeys(getRequestContext2()[key]);
|
|
3188
|
+
},
|
|
3189
|
+
getOwnPropertyDescriptor(_, p) {
|
|
3190
|
+
const d = Object.getOwnPropertyDescriptor(getRequestContext2()[key], p);
|
|
3191
|
+
if (d)
|
|
3192
|
+
d.configurable = true;
|
|
3193
|
+
return d;
|
|
3194
|
+
}
|
|
3195
|
+
});
|
|
3196
|
+
}
|
|
3197
|
+
var cookies = __mochiCtxProxy("cookies");
|
|
3198
|
+
var params = __mochiCtxProxy("params");
|
|
3199
|
+
var url = __mochiCtxProxy("url");
|
|
3200
|
+
var locals = __mochiCtxProxy("locals");
|
|
3201
|
+
if (!globalThis.__mochi_events__)
|
|
3202
|
+
globalThis.__mochi_events__ = mitt_default();
|
|
3203
|
+
var mochiEvents2 = globalThis.__mochi_events__;
|
|
3204
|
+
|
|
3205
|
+
// node_modules/mochi-framework/src/islands/HydratableBoundary.svelte
|
|
3206
|
+
import"svelte/internal/flags/async";
|
|
3207
|
+
import * as $ from "svelte/internal/server";
|
|
3208
|
+
import { setContext } from "svelte";
|
|
3209
|
+
function HydratableBoundary($$renderer, $$props) {
|
|
3210
|
+
$$renderer.component(($$renderer2) => {
|
|
3211
|
+
setContext(Symbol.for("mochi:hydratable"), true);
|
|
3212
|
+
let { children } = $$props;
|
|
3213
|
+
children?.($$renderer2);
|
|
3214
|
+
$$renderer2.push(`<!---->`);
|
|
3215
|
+
});
|
|
3216
|
+
}
|
|
3217
|
+
// node_modules/@lucide/svelte/dist/Icon.svelte
|
|
3218
|
+
import"svelte/internal/flags/async";
|
|
3219
|
+
import * as $2 from "svelte/internal/server";
|
|
3220
|
+
|
|
3221
|
+
// node_modules/@lucide/svelte/dist/defaultAttributes.js
|
|
3222
|
+
var defaultAttributes = {
|
|
3223
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
3224
|
+
width: 24,
|
|
3225
|
+
height: 24,
|
|
3226
|
+
viewBox: "0 0 24 24",
|
|
3227
|
+
fill: "none",
|
|
3228
|
+
stroke: "currentColor",
|
|
3229
|
+
"stroke-width": 2,
|
|
3230
|
+
"stroke-linecap": "round",
|
|
3231
|
+
"stroke-linejoin": "round"
|
|
3232
|
+
};
|
|
3233
|
+
var defaultAttributes_default = defaultAttributes;
|
|
3234
|
+
|
|
3235
|
+
// node_modules/@lucide/svelte/dist/utils/hasA11yProp.js
|
|
3236
|
+
var hasA11yProp = (props) => {
|
|
3237
|
+
for (const prop in props) {
|
|
3238
|
+
if (prop.startsWith("aria-") || prop === "role" || prop === "title") {
|
|
3239
|
+
return true;
|
|
3240
|
+
}
|
|
3241
|
+
}
|
|
3242
|
+
return false;
|
|
3243
|
+
};
|
|
3244
|
+
|
|
3245
|
+
// node_modules/@lucide/svelte/dist/context.js
|
|
3246
|
+
import { getContext as getContext2, setContext as setContext2 } from "svelte";
|
|
3247
|
+
var LucideContext = Symbol("lucide-context");
|
|
3248
|
+
var getLucideContext = () => getContext2(LucideContext);
|
|
3249
|
+
|
|
3250
|
+
// node_modules/@lucide/svelte/dist/Icon.svelte
|
|
3251
|
+
function Icon($$renderer, $$props) {
|
|
3252
|
+
$$renderer.component(($$renderer2) => {
|
|
3253
|
+
const globalProps = getLucideContext() ?? {};
|
|
3254
|
+
const {
|
|
3255
|
+
name,
|
|
3256
|
+
color = globalProps.color ?? "currentColor",
|
|
3257
|
+
size = globalProps.size ?? 24,
|
|
3258
|
+
strokeWidth = globalProps.strokeWidth ?? 2,
|
|
3259
|
+
absoluteStrokeWidth = globalProps.absoluteStrokeWidth ?? false,
|
|
3260
|
+
iconNode = [],
|
|
3261
|
+
children,
|
|
3262
|
+
$$slots,
|
|
3263
|
+
$$events,
|
|
3264
|
+
...props
|
|
3265
|
+
} = $$props;
|
|
3266
|
+
const calculatedStrokeWidth = $2.derived(() => absoluteStrokeWidth ? Number(strokeWidth) * 24 / Number(size) : strokeWidth);
|
|
3267
|
+
$$renderer2.push(`<svg${$2.attributes({
|
|
3268
|
+
...defaultAttributes_default,
|
|
3269
|
+
...!children && !hasA11yProp(props) && { "aria-hidden": "true" },
|
|
3270
|
+
...props,
|
|
3271
|
+
width: size,
|
|
3272
|
+
height: size,
|
|
3273
|
+
stroke: color,
|
|
3274
|
+
"stroke-width": calculatedStrokeWidth(),
|
|
3275
|
+
class: $2.clsx([
|
|
3276
|
+
"lucide-icon lucide",
|
|
3277
|
+
globalProps.class,
|
|
3278
|
+
name && `lucide-${name}`,
|
|
3279
|
+
props.class
|
|
3280
|
+
])
|
|
3281
|
+
}, undefined, undefined, undefined, 3)}><!--[-->`);
|
|
3282
|
+
const each_array = $2.ensure_array_like(iconNode);
|
|
3283
|
+
for (let $$index = 0, $$length = each_array.length;$$index < $$length; $$index++) {
|
|
3284
|
+
let [tag, attrs] = each_array[$$index];
|
|
3285
|
+
$2.element($$renderer2, tag, () => {
|
|
3286
|
+
$$renderer2.push(`${$2.attributes({ ...attrs }, undefined, undefined, undefined, 3)}`);
|
|
3287
|
+
});
|
|
3288
|
+
}
|
|
3289
|
+
$$renderer2.push(`<!--]-->`);
|
|
3290
|
+
children?.($$renderer2);
|
|
3291
|
+
$$renderer2.push(`<!----></svg>`);
|
|
3292
|
+
});
|
|
3293
|
+
}
|
|
3294
|
+
|
|
3295
|
+
export { emitIslandProps, isDev, cookies, HydratableBoundary, Icon };
|