@absolutejs/absolute 0.19.0-beta.783 → 0.19.0-beta.784
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/angular/browser.js +57 -9801
- package/dist/angular/browser.js.map +4 -246
- package/dist/angular/index.js +61 -14967
- package/dist/angular/index.js.map +4 -282
- package/dist/angular/server.js +45 -5699
- package/dist/angular/server.js.map +3 -52
- package/dist/build.js +45 -18021
- package/dist/build.js.map +3 -100
- package/dist/chunk-102fp7xe.js +63 -0
- package/dist/chunk-102fp7xe.js.map +10 -0
- package/dist/chunk-11zpfqz6.js +19 -0
- package/dist/chunk-11zpfqz6.js.map +10 -0
- package/dist/chunk-1e9vsfyh.js +100 -0
- package/dist/chunk-1e9vsfyh.js.map +10 -0
- package/dist/chunk-25v9t56f.js +29 -0
- package/dist/chunk-25v9t56f.js.map +11 -0
- package/dist/chunk-2f21eenc.js +21 -0
- package/dist/chunk-2f21eenc.js.map +10 -0
- package/dist/chunk-2ga2znex.js +13 -0
- package/dist/chunk-2ga2znex.js.map +9 -0
- package/dist/chunk-30yrw0f6.js +33 -0
- package/dist/chunk-30yrw0f6.js.map +10 -0
- package/dist/chunk-3c7mpj3m.js +784 -0
- package/dist/chunk-3c7mpj3m.js.map +10 -0
- package/dist/chunk-3g91wb4f.js +358 -0
- package/dist/chunk-3g91wb4f.js.map +10 -0
- package/dist/chunk-3yjzpcne.js +34 -0
- package/dist/chunk-3yjzpcne.js.map +10 -0
- package/dist/chunk-4bq79t8v.js +136 -0
- package/dist/chunk-4bq79t8v.js.map +10 -0
- package/dist/chunk-4d39r92n.js +81 -0
- package/dist/chunk-4d39r92n.js.map +10 -0
- package/dist/chunk-4m75s5xf.js +184 -0
- package/dist/chunk-4m75s5xf.js.map +11 -0
- package/dist/chunk-5003emhv.js +17 -0
- package/dist/chunk-5003emhv.js.map +10 -0
- package/dist/chunk-5fhp1jap.js +9169 -0
- package/dist/chunk-5fhp1jap.js.map +236 -0
- package/dist/chunk-6fkgm9s5.js +569 -0
- package/dist/chunk-6fkgm9s5.js.map +10 -0
- package/dist/chunk-6pdj08z3.js +73 -0
- package/dist/chunk-6pdj08z3.js.map +12 -0
- package/dist/chunk-6qjbrt0k.js +13 -0
- package/dist/chunk-6qjbrt0k.js.map +9 -0
- package/dist/chunk-6sccb4jr.js +14 -0
- package/dist/chunk-6sccb4jr.js.map +9 -0
- package/dist/chunk-73brtyw5.js +16 -0
- package/dist/chunk-73brtyw5.js.map +9 -0
- package/dist/chunk-77cqkarb.js +25 -0
- package/dist/chunk-77cqkarb.js.map +9 -0
- package/dist/chunk-798spvzv.js +50 -0
- package/dist/chunk-798spvzv.js.map +10 -0
- package/dist/chunk-7fw6x3js.js +131 -0
- package/dist/chunk-7fw6x3js.js.map +11 -0
- package/dist/chunk-7kjj42xm.js +11 -0
- package/dist/chunk-7kjj42xm.js.map +10 -0
- package/dist/chunk-851whwc7.js +17 -0
- package/dist/chunk-851whwc7.js.map +10 -0
- package/dist/chunk-85n68sy6.js +103 -0
- package/dist/chunk-85n68sy6.js.map +10 -0
- package/dist/chunk-8feq2qek.js +17 -0
- package/dist/chunk-8feq2qek.js.map +9 -0
- package/dist/chunk-8kcfffry.js +35 -0
- package/dist/chunk-8kcfffry.js.map +10 -0
- package/dist/chunk-93sqk7be.js +139 -0
- package/dist/chunk-93sqk7be.js.map +12 -0
- package/dist/chunk-97572s32.js +262 -0
- package/dist/chunk-97572s32.js.map +12 -0
- package/dist/chunk-9a307ca6.js +1742 -0
- package/dist/chunk-9a307ca6.js.map +11 -0
- package/dist/chunk-9c5tj4k3.js +130 -0
- package/dist/chunk-9c5tj4k3.js.map +10 -0
- package/dist/chunk-9xrsjeem.js +12 -0
- package/dist/chunk-9xrsjeem.js.map +9 -0
- package/dist/chunk-a9mvyp04.js +87 -0
- package/dist/chunk-a9mvyp04.js.map +10 -0
- package/dist/chunk-b3gbnrwe.js +21 -0
- package/dist/chunk-b3gbnrwe.js.map +10 -0
- package/dist/chunk-bmgqm774.js +65 -0
- package/dist/chunk-bmgqm774.js.map +9 -0
- package/dist/chunk-bxfghpma.js +69 -0
- package/dist/chunk-bxfghpma.js.map +10 -0
- package/dist/chunk-c1jfjnka.js +74 -0
- package/dist/chunk-c1jfjnka.js.map +10 -0
- package/dist/chunk-cbkrwmvh.js +80 -0
- package/dist/chunk-cbkrwmvh.js.map +10 -0
- package/dist/chunk-cdxd7sy2.js +71 -0
- package/dist/chunk-cdxd7sy2.js.map +10 -0
- package/dist/chunk-cg95827x.js +21 -0
- package/dist/chunk-cg95827x.js.map +10 -0
- package/dist/chunk-d9c0am65.js +12 -0
- package/dist/chunk-d9c0am65.js.map +10 -0
- package/dist/chunk-daqghmg8.js +12 -0
- package/dist/chunk-daqghmg8.js.map +9 -0
- package/dist/chunk-dr9yqsdb.js +203 -0
- package/dist/chunk-dr9yqsdb.js.map +10 -0
- package/dist/chunk-e8eecyrq.js +244 -0
- package/dist/chunk-e8eecyrq.js.map +10 -0
- package/dist/chunk-ex2hxe0v.js +160 -0
- package/dist/chunk-ex2hxe0v.js.map +11 -0
- package/dist/chunk-ey5hs6x6.js +253 -0
- package/dist/chunk-ey5hs6x6.js.map +11 -0
- package/dist/chunk-fak944et.js +91 -0
- package/dist/chunk-fak944et.js.map +10 -0
- package/dist/chunk-fygx2ymm.js +118 -0
- package/dist/chunk-fygx2ymm.js.map +12 -0
- package/dist/chunk-g15qj669.js +271 -0
- package/dist/chunk-g15qj669.js.map +11 -0
- package/dist/chunk-g3j22qf6.js +51 -0
- package/dist/chunk-g3j22qf6.js.map +9 -0
- package/dist/chunk-gd6wmknh.js +121 -0
- package/dist/chunk-gd6wmknh.js.map +11 -0
- package/dist/chunk-gf0ygptk.js +85 -0
- package/dist/chunk-gf0ygptk.js.map +11 -0
- package/dist/chunk-gq0zxpm0.js +90 -0
- package/dist/chunk-gq0zxpm0.js.map +10 -0
- package/dist/chunk-gytkmthr.js +220 -0
- package/dist/chunk-gytkmthr.js.map +10 -0
- package/dist/chunk-h5bbfn3n.js +28 -0
- package/dist/chunk-h5bbfn3n.js.map +11 -0
- package/dist/chunk-h6mye9r3.js +93 -0
- package/dist/chunk-h6mye9r3.js.map +10 -0
- package/dist/chunk-hcsmxw1v.js +85 -0
- package/dist/chunk-hcsmxw1v.js.map +10 -0
- package/dist/chunk-hep68ja7.js +4444 -0
- package/dist/chunk-hep68ja7.js.map +29 -0
- package/dist/chunk-hhqh49fz.js +149 -0
- package/dist/chunk-hhqh49fz.js.map +10 -0
- package/dist/chunk-hyjs4bqs.js +8 -0
- package/dist/chunk-hyjs4bqs.js.map +10 -0
- package/dist/chunk-hza0n8qm.js +20 -0
- package/dist/chunk-hza0n8qm.js.map +9 -0
- package/dist/chunk-jn91vzkh.js +66 -0
- package/dist/chunk-jn91vzkh.js.map +10 -0
- package/dist/chunk-jwxt8gnp.js +13 -0
- package/dist/chunk-jwxt8gnp.js.map +9 -0
- package/dist/chunk-kk8w9rh5.js +195 -0
- package/dist/chunk-kk8w9rh5.js.map +10 -0
- package/dist/chunk-kndkjsya.js +261 -0
- package/dist/chunk-kndkjsya.js.map +10 -0
- package/dist/chunk-kvq01j35.js +36 -0
- package/dist/chunk-kvq01j35.js.map +10 -0
- package/dist/chunk-mbazhahf.js +60 -0
- package/dist/chunk-mbazhahf.js.map +10 -0
- package/dist/chunk-mgfwq18r.js +15 -0
- package/dist/chunk-mgfwq18r.js.map +9 -0
- package/dist/chunk-mtgf69xn.js +88 -0
- package/dist/chunk-mtgf69xn.js.map +10 -0
- package/dist/chunk-nehhtthw.js +225 -0
- package/dist/chunk-nehhtthw.js.map +10 -0
- package/dist/chunk-nhzf4az4.js +149 -0
- package/dist/chunk-nhzf4az4.js.map +10 -0
- package/dist/chunk-p5504p14.js +16 -0
- package/dist/chunk-p5504p14.js.map +10 -0
- package/dist/chunk-pnscgw95.js +90 -0
- package/dist/chunk-pnscgw95.js.map +10 -0
- package/dist/chunk-pvpp4pvs.js +17 -0
- package/dist/chunk-pvpp4pvs.js.map +10 -0
- package/dist/chunk-qh75agse.js +95 -0
- package/dist/chunk-qh75agse.js.map +10 -0
- package/dist/chunk-qk8kd3hr.js +526 -0
- package/dist/chunk-qk8kd3hr.js.map +12 -0
- package/dist/chunk-qxq2zcty.js +52 -0
- package/dist/chunk-qxq2zcty.js.map +10 -0
- package/dist/chunk-r7jmgqnw.js +114 -0
- package/dist/chunk-r7jmgqnw.js.map +10 -0
- package/dist/chunk-s6defjk2.js +116 -0
- package/dist/chunk-s6defjk2.js.map +10 -0
- package/dist/chunk-sd39p726.js +619 -0
- package/dist/chunk-sd39p726.js.map +10 -0
- package/dist/chunk-smgj0epn.js +18 -0
- package/dist/chunk-smgj0epn.js.map +9 -0
- package/dist/chunk-swrnzs4c.js +63 -0
- package/dist/chunk-swrnzs4c.js.map +10 -0
- package/dist/chunk-t81a331y.js +27 -0
- package/dist/chunk-t81a331y.js.map +10 -0
- package/dist/chunk-tfe3sb44.js +33 -0
- package/dist/chunk-tfe3sb44.js.map +10 -0
- package/dist/chunk-tx9edm1x.js +34 -0
- package/dist/chunk-tx9edm1x.js.map +10 -0
- package/dist/chunk-vkrpm7kc.js +247 -0
- package/dist/chunk-vkrpm7kc.js.map +12 -0
- package/dist/chunk-vvz7dcvq.js +434 -0
- package/dist/chunk-vvz7dcvq.js.map +13 -0
- package/dist/chunk-w3m4m5we.js +4925 -0
- package/dist/chunk-w3m4m5we.js.map +12 -0
- package/dist/chunk-wrxtn9ve.js +18 -0
- package/dist/chunk-wrxtn9ve.js.map +10 -0
- package/dist/chunk-xpkjbmd3.js +428 -0
- package/dist/chunk-xpkjbmd3.js.map +14 -0
- package/dist/chunk-xrmjy8kk.js +454 -0
- package/dist/chunk-xrmjy8kk.js.map +10 -0
- package/dist/chunk-xw0tx842.js +13 -0
- package/dist/chunk-xw0tx842.js.map +9 -0
- package/dist/chunk-xx5b6b9m.js +69 -0
- package/dist/chunk-xx5b6b9m.js.map +10 -0
- package/dist/chunk-xz1kdswj.js +21 -0
- package/dist/chunk-xz1kdswj.js.map +9 -0
- package/dist/chunk-xzvy9hr4.js +377 -0
- package/dist/chunk-xzvy9hr4.js.map +10 -0
- package/dist/chunk-yfqhr31t.js +39 -0
- package/dist/chunk-yfqhr31t.js.map +9 -0
- package/dist/chunk-ygzd5s4z.js +184 -0
- package/dist/chunk-ygzd5s4z.js.map +10 -0
- package/dist/chunk-ywjn0rad.js +14 -0
- package/dist/chunk-ywjn0rad.js.map +9 -0
- package/dist/chunk-z9nvhm6r.js +13 -0
- package/dist/chunk-z9nvhm6r.js.map +9 -0
- package/dist/chunk-zhmvdpk6.js +15 -0
- package/dist/chunk-zhmvdpk6.js.map +9 -0
- package/dist/client/index.js +32 -1112
- package/dist/client/index.js.map +4 -22
- package/dist/core/streamingSlotRegistrar.js +11 -108
- package/dist/core/streamingSlotRegistrar.js.map +3 -4
- package/dist/core/streamingSlotRegistry.js +7 -169
- package/dist/core/streamingSlotRegistry.js.map +3 -5
- package/dist/index.js +536 -19835
- package/dist/index.js.map +3 -117
- package/dist/islands/browser.js +9 -228
- package/dist/islands/browser.js.map +4 -9
- package/dist/islands/index.js +17 -1986
- package/dist/islands/index.js.map +3 -28
- package/dist/react/browser.js +12 -328
- package/dist/react/browser.js.map +4 -12
- package/dist/react/components/index.js +16 -167
- package/dist/react/components/index.js.map +3 -6
- package/dist/react/hooks/index.js +8 -183
- package/dist/react/hooks/index.js.map +3 -7
- package/dist/react/index.js +36 -3705
- package/dist/react/index.js.map +4 -46
- package/dist/react/jsxDevRuntimeCompat.js +2 -61
- package/dist/react/jsxDevRuntimeCompat.js.map +2 -2
- package/dist/react/server.js +18 -1789
- package/dist/react/server.js.map +3 -21
- package/dist/src/core/index.d.ts +0 -2
- package/dist/svelte/browser.js +12 -247
- package/dist/svelte/browser.js.map +3 -10
- package/dist/svelte/index.js +37 -3810
- package/dist/svelte/index.js.map +4 -48
- package/dist/svelte/server.js +21 -2787
- package/dist/svelte/server.js.map +3 -27
- package/dist/vue/browser.js +12 -348
- package/dist/vue/browser.js.map +4 -12
- package/dist/vue/components/Image.js +7 -240
- package/dist/vue/components/Image.js.map +3 -6
- package/dist/vue/components/index.js +11 -544
- package/dist/vue/components/index.js.map +3 -9
- package/dist/vue/index.js +52 -4290
- package/dist/vue/index.js.map +4 -51
- package/dist/vue/server.js +18 -1849
- package/dist/vue/server.js.map +3 -21
- package/package.json +7 -7
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
lowerSvelteAwaitSlotSyntax,
|
|
4
|
+
lowerSvelteIslandSyntax
|
|
5
|
+
} from "./chunk-7fw6x3js.js";
|
|
6
|
+
import {
|
|
7
|
+
resolvePackageImport
|
|
8
|
+
} from "./chunk-mbazhahf.js";
|
|
9
|
+
import {
|
|
10
|
+
createSvelteStylePreprocessor
|
|
11
|
+
} from "./chunk-6fkgm9s5.js";
|
|
12
|
+
import {
|
|
13
|
+
__require
|
|
14
|
+
} from "./chunk-bmgqm774.js";
|
|
15
|
+
|
|
16
|
+
// src/core/svelteServerModule.ts
|
|
17
|
+
import { mkdir, readdir } from "fs/promises";
|
|
18
|
+
import { basename, dirname, extname, join, relative, resolve } from "path";
|
|
19
|
+
var serverCacheRoot = join(process.cwd(), ".absolutejs", "islands", "svelte");
|
|
20
|
+
var compiledModuleCache = new Map;
|
|
21
|
+
var originalSourcePathCache = new Map;
|
|
22
|
+
var transpiler = new Bun.Transpiler({
|
|
23
|
+
loader: "ts",
|
|
24
|
+
target: "browser"
|
|
25
|
+
});
|
|
26
|
+
var ensureRelativeImportPath = (from, target) => {
|
|
27
|
+
const importPath = relative(dirname(from), target).replace(/\\/g, "/");
|
|
28
|
+
return importPath.startsWith(".") ? importPath : `./${importPath}`;
|
|
29
|
+
};
|
|
30
|
+
var processDirectoryEntries = (entries, dir, targetFileName, stack) => {
|
|
31
|
+
for (const entry of entries) {
|
|
32
|
+
const entryPath = join(dir, entry.name);
|
|
33
|
+
if (entry.isDirectory())
|
|
34
|
+
stack.push(entryPath);
|
|
35
|
+
if (entry.isFile() && entry.name === targetFileName) {
|
|
36
|
+
return entryPath;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return null;
|
|
40
|
+
};
|
|
41
|
+
var searchDirectoryLevel = async (dirs, targetFileName) => {
|
|
42
|
+
if (dirs.length === 0)
|
|
43
|
+
return null;
|
|
44
|
+
const nextStack = [];
|
|
45
|
+
const dirEntries = await Promise.all(dirs.map(async (dir) => ({
|
|
46
|
+
dir,
|
|
47
|
+
entries: await readdir(dir, {
|
|
48
|
+
encoding: "utf-8",
|
|
49
|
+
withFileTypes: true
|
|
50
|
+
})
|
|
51
|
+
})));
|
|
52
|
+
for (const { dir, entries } of dirEntries) {
|
|
53
|
+
const found = processDirectoryEntries(entries, dir, targetFileName, nextStack);
|
|
54
|
+
if (found)
|
|
55
|
+
return found;
|
|
56
|
+
}
|
|
57
|
+
return searchDirectoryLevel(nextStack, targetFileName);
|
|
58
|
+
};
|
|
59
|
+
var findSourceFileByBasename = async (searchRoot, targetFileName) => searchDirectoryLevel([searchRoot], targetFileName);
|
|
60
|
+
var normalizeBuiltSvelteFileName = (sourcePath) => basename(sourcePath).replace(/-[a-z0-9]{6,}(?=\.svelte$)/i, "");
|
|
61
|
+
var resolveOriginalSourcePath = async (sourcePath) => {
|
|
62
|
+
const cachedPath = originalSourcePathCache.get(sourcePath);
|
|
63
|
+
if (cachedPath !== undefined) {
|
|
64
|
+
return cachedPath;
|
|
65
|
+
}
|
|
66
|
+
if (!sourcePath.includes(`${join(process.cwd(), "build")}${process.platform === "win32" ? "" : "/"}`) && !sourcePath.includes("/build/")) {
|
|
67
|
+
originalSourcePathCache.set(sourcePath, sourcePath);
|
|
68
|
+
return sourcePath;
|
|
69
|
+
}
|
|
70
|
+
const resolvedSourcePath = await findSourceFileByBasename(join(process.cwd(), "src"), normalizeBuiltSvelteFileName(sourcePath));
|
|
71
|
+
const nextPath = resolvedSourcePath ?? sourcePath;
|
|
72
|
+
originalSourcePathCache.set(sourcePath, nextPath);
|
|
73
|
+
return nextPath;
|
|
74
|
+
};
|
|
75
|
+
var resolveRelativeModule = async (spec, from) => {
|
|
76
|
+
if (!spec.startsWith(".")) {
|
|
77
|
+
return null;
|
|
78
|
+
}
|
|
79
|
+
const basePath = resolve(dirname(from), spec);
|
|
80
|
+
const candidates = [
|
|
81
|
+
basePath,
|
|
82
|
+
`${basePath}.ts`,
|
|
83
|
+
`${basePath}.js`,
|
|
84
|
+
`${basePath}.mjs`,
|
|
85
|
+
`${basePath}.cjs`,
|
|
86
|
+
`${basePath}.json`,
|
|
87
|
+
join(basePath, "index.ts"),
|
|
88
|
+
join(basePath, "index.js"),
|
|
89
|
+
join(basePath, "index.mjs"),
|
|
90
|
+
join(basePath, "index.cjs"),
|
|
91
|
+
join(basePath, "index.json")
|
|
92
|
+
];
|
|
93
|
+
const existResults = await Promise.all(candidates.map((candidate) => Bun.file(candidate).exists()));
|
|
94
|
+
const foundIndex = existResults.indexOf(true);
|
|
95
|
+
return foundIndex >= 0 ? candidates[foundIndex] ?? null : null;
|
|
96
|
+
};
|
|
97
|
+
var getCachedModulePath = (sourcePath) => {
|
|
98
|
+
const relativeSourcePath = relative(process.cwd(), sourcePath).replace(/\\/g, "/");
|
|
99
|
+
const normalizedSourcePath = relativeSourcePath.startsWith("..") ? sourcePath.replace(/[:\\/]/g, "_") : relativeSourcePath;
|
|
100
|
+
return join(serverCacheRoot, `${normalizedSourcePath}.server.js`);
|
|
101
|
+
};
|
|
102
|
+
var resolveSvelteImport = async (spec, from) => {
|
|
103
|
+
if (!spec.startsWith(".") && !spec.startsWith("/")) {
|
|
104
|
+
const resolved = resolvePackageImport(spec);
|
|
105
|
+
return resolved && resolved.endsWith(".svelte") ? resolved : null;
|
|
106
|
+
}
|
|
107
|
+
if (spec.startsWith("/")) {
|
|
108
|
+
return spec;
|
|
109
|
+
}
|
|
110
|
+
if (!spec.startsWith(".")) {
|
|
111
|
+
return null;
|
|
112
|
+
}
|
|
113
|
+
const explicitPath = resolve(dirname(from), spec);
|
|
114
|
+
if (extname(explicitPath) === ".svelte") {
|
|
115
|
+
return explicitPath;
|
|
116
|
+
}
|
|
117
|
+
const candidate = `${explicitPath}.svelte`;
|
|
118
|
+
if (await Bun.file(candidate).exists() === true) {
|
|
119
|
+
return candidate;
|
|
120
|
+
}
|
|
121
|
+
return null;
|
|
122
|
+
};
|
|
123
|
+
var writeIfChanged = async (path, content) => {
|
|
124
|
+
const targetFile = Bun.file(path);
|
|
125
|
+
const exists = await targetFile.exists();
|
|
126
|
+
if (exists) {
|
|
127
|
+
const currentContent = await targetFile.text();
|
|
128
|
+
if (currentContent === content) {
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
await Bun.write(path, content);
|
|
133
|
+
};
|
|
134
|
+
var compileSvelteServerModule = async (sourcePath) => {
|
|
135
|
+
const cachedModulePath = compiledModuleCache.get(sourcePath);
|
|
136
|
+
if (cachedModulePath) {
|
|
137
|
+
return cachedModulePath;
|
|
138
|
+
}
|
|
139
|
+
const resolutionSourcePath = await resolveOriginalSourcePath(sourcePath);
|
|
140
|
+
const source = await Bun.file(sourcePath).text();
|
|
141
|
+
const { compile, preprocess } = await import("svelte/compiler");
|
|
142
|
+
const loweredAwaitSource = lowerSvelteAwaitSlotSyntax(source);
|
|
143
|
+
const loweredSource = lowerSvelteIslandSyntax(loweredAwaitSource.code, "server");
|
|
144
|
+
const preprocessed = await preprocess(loweredSource.code, createSvelteStylePreprocessor());
|
|
145
|
+
let transpiled = sourcePath.endsWith(".ts") || sourcePath.endsWith(".svelte.ts") ? transpiler.transformSync(preprocessed.code) : preprocessed.code;
|
|
146
|
+
const childImportSpecs = Array.from(transpiled.matchAll(/from\s+['"]([^'"]+)['"]/g)).map((match) => match[1]).filter((value) => value !== undefined);
|
|
147
|
+
const resolvedChildModules = await Promise.all(childImportSpecs.map((spec) => resolveSvelteImport(spec, resolutionSourcePath)));
|
|
148
|
+
const resolvedModuleImports = await Promise.all(childImportSpecs.map((spec) => resolveRelativeModule(spec, resolutionSourcePath)));
|
|
149
|
+
const childModulePaths = new Map;
|
|
150
|
+
const rewrittenModulePaths = new Map;
|
|
151
|
+
const compiledChildren = await Promise.all(childImportSpecs.map(async (spec, index) => {
|
|
152
|
+
const resolvedChild = resolvedChildModules[index];
|
|
153
|
+
if (!spec || !resolvedChild)
|
|
154
|
+
return null;
|
|
155
|
+
return {
|
|
156
|
+
compiledPath: await compileSvelteServerModule(resolvedChild),
|
|
157
|
+
resolvedChild,
|
|
158
|
+
spec
|
|
159
|
+
};
|
|
160
|
+
}));
|
|
161
|
+
for (const result of compiledChildren) {
|
|
162
|
+
if (!result)
|
|
163
|
+
continue;
|
|
164
|
+
childModulePaths.set(result.spec, result.compiledPath);
|
|
165
|
+
childModulePaths.set(result.resolvedChild, result.compiledPath);
|
|
166
|
+
}
|
|
167
|
+
for (let index = 0;index < childImportSpecs.length; index += 1) {
|
|
168
|
+
const spec = childImportSpecs[index];
|
|
169
|
+
const resolvedModuleImport = resolvedModuleImports[index];
|
|
170
|
+
if (!spec || !resolvedModuleImport)
|
|
171
|
+
continue;
|
|
172
|
+
if (resolvedChildModules[index])
|
|
173
|
+
continue;
|
|
174
|
+
rewrittenModulePaths.set(spec, ensureRelativeImportPath(getCachedModulePath(sourcePath), resolvedModuleImport));
|
|
175
|
+
}
|
|
176
|
+
for (const [spec, resolvedModuleImport] of rewrittenModulePaths) {
|
|
177
|
+
transpiled = transpiled.replaceAll(spec, resolvedModuleImport);
|
|
178
|
+
}
|
|
179
|
+
let compiledCode = compile(transpiled, {
|
|
180
|
+
css: "injected",
|
|
181
|
+
experimental: {
|
|
182
|
+
async: loweredAwaitSource.transformed || loweredSource.transformed
|
|
183
|
+
},
|
|
184
|
+
filename: resolutionSourcePath,
|
|
185
|
+
generate: "server"
|
|
186
|
+
}).js.code;
|
|
187
|
+
for (const [spec, compiledChildPath] of childModulePaths) {
|
|
188
|
+
compiledCode = compiledCode.replaceAll(spec, ensureRelativeImportPath(getCachedModulePath(sourcePath), compiledChildPath));
|
|
189
|
+
}
|
|
190
|
+
for (const [spec, resolvedModuleImport] of rewrittenModulePaths) {
|
|
191
|
+
compiledCode = compiledCode.replaceAll(spec, resolvedModuleImport);
|
|
192
|
+
}
|
|
193
|
+
const compiledModulePath = getCachedModulePath(sourcePath);
|
|
194
|
+
await mkdir(dirname(compiledModulePath), { recursive: true });
|
|
195
|
+
await writeIfChanged(compiledModulePath, compiledCode);
|
|
196
|
+
compiledModuleCache.set(sourcePath, compiledModulePath);
|
|
197
|
+
return compiledModulePath;
|
|
198
|
+
};
|
|
199
|
+
|
|
200
|
+
export { compileSvelteServerModule };
|
|
201
|
+
|
|
202
|
+
//# debugId=7E4C5416175915DB64756E2164756E21
|
|
203
|
+
//# sourceMappingURL=chunk-dr9yqsdb.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/core/svelteServerModule.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import type { Dirent } from 'node:fs';\nimport { mkdir, readdir } from 'node:fs/promises';\nimport { basename, dirname, extname, join, relative, resolve } from 'node:path';\nimport { resolvePackageImport } from '../build/resolvePackageImport';\nimport { lowerSvelteIslandSyntax } from '../svelte/lowerIslandSyntax';\nimport { lowerSvelteAwaitSlotSyntax } from '../svelte/lowerAwaitSlotSyntax';\nimport { createSvelteStylePreprocessor } from '../build/stylePreprocessor';\n\nconst serverCacheRoot = join(process.cwd(), '.absolutejs', 'islands', 'svelte');\n\nconst compiledModuleCache = new Map<string, string>();\nconst originalSourcePathCache = new Map<string, string>();\n\nconst transpiler = new Bun.Transpiler({\n\tloader: 'ts',\n\ttarget: 'browser'\n});\n\nconst ensureRelativeImportPath = (from: string, target: string) => {\n\tconst importPath = relative(dirname(from), target).replace(/\\\\/g, '/');\n\n\treturn importPath.startsWith('.') ? importPath : `./${importPath}`;\n};\n\nconst processDirectoryEntries = (\n\tentries: Dirent<string>[],\n\tdir: string,\n\ttargetFileName: string,\n\tstack: string[]\n) => {\n\tfor (const entry of entries) {\n\t\tconst entryPath = join(dir, entry.name);\n\t\tif (entry.isDirectory()) stack.push(entryPath);\n\n\t\tif (entry.isFile() && entry.name === targetFileName) {\n\t\t\treturn entryPath;\n\t\t}\n\t}\n\n\treturn null;\n};\n\nconst searchDirectoryLevel = async (dirs: string[], targetFileName: string) => {\n\tif (dirs.length === 0) return null;\n\n\tconst nextStack: string[] = [];\n\tconst dirEntries = await Promise.all(\n\t\tdirs.map(async (dir) => ({\n\t\t\tdir,\n\t\t\tentries: await readdir(dir, {\n\t\t\t\tencoding: 'utf-8',\n\t\t\t\twithFileTypes: true\n\t\t\t})\n\t\t}))\n\t);\n\n\tfor (const { dir, entries } of dirEntries) {\n\t\tconst found = processDirectoryEntries(\n\t\t\tentries,\n\t\t\tdir,\n\t\t\ttargetFileName,\n\t\t\tnextStack\n\t\t);\n\t\tif (found) return found;\n\t}\n\n\treturn searchDirectoryLevel(nextStack, targetFileName);\n};\n\nconst findSourceFileByBasename = async (\n\tsearchRoot: string,\n\ttargetFileName: string\n) => searchDirectoryLevel([searchRoot], targetFileName);\n\nconst normalizeBuiltSvelteFileName = (sourcePath: string) =>\n\tbasename(sourcePath).replace(/-[a-z0-9]{6,}(?=\\.svelte$)/i, '');\n\nconst resolveOriginalSourcePath = async (sourcePath: string) => {\n\tconst cachedPath = originalSourcePathCache.get(sourcePath);\n\tif (cachedPath !== undefined) {\n\t\treturn cachedPath;\n\t}\n\n\tif (\n\t\t!sourcePath.includes(\n\t\t\t`${join(process.cwd(), 'build')}${process.platform === 'win32' ? '' : '/'}`\n\t\t) &&\n\t\t!sourcePath.includes('/build/')\n\t) {\n\t\toriginalSourcePathCache.set(sourcePath, sourcePath);\n\n\t\treturn sourcePath;\n\t}\n\n\tconst resolvedSourcePath = await findSourceFileByBasename(\n\t\tjoin(process.cwd(), 'src'),\n\t\tnormalizeBuiltSvelteFileName(sourcePath)\n\t);\n\tconst nextPath = resolvedSourcePath ?? sourcePath;\n\toriginalSourcePathCache.set(sourcePath, nextPath);\n\n\treturn nextPath;\n};\n\nconst resolveRelativeModule = async (spec: string, from: string) => {\n\tif (!spec.startsWith('.')) {\n\t\treturn null;\n\t}\n\n\tconst basePath = resolve(dirname(from), spec);\n\tconst candidates = [\n\t\tbasePath,\n\t\t`${basePath}.ts`,\n\t\t`${basePath}.js`,\n\t\t`${basePath}.mjs`,\n\t\t`${basePath}.cjs`,\n\t\t`${basePath}.json`,\n\t\tjoin(basePath, 'index.ts'),\n\t\tjoin(basePath, 'index.js'),\n\t\tjoin(basePath, 'index.mjs'),\n\t\tjoin(basePath, 'index.cjs'),\n\t\tjoin(basePath, 'index.json')\n\t];\n\n\tconst existResults = await Promise.all(\n\t\tcandidates.map((candidate) => Bun.file(candidate).exists())\n\t);\n\tconst foundIndex = existResults.indexOf(true);\n\n\treturn foundIndex >= 0 ? (candidates[foundIndex] ?? null) : null;\n};\n\nconst getCachedModulePath = (sourcePath: string) => {\n\tconst relativeSourcePath = relative(process.cwd(), sourcePath).replace(\n\t\t/\\\\/g,\n\t\t'/'\n\t);\n\tconst normalizedSourcePath = relativeSourcePath.startsWith('..')\n\t\t? sourcePath.replace(/[:\\\\/]/g, '_')\n\t\t: relativeSourcePath;\n\n\treturn join(serverCacheRoot, `${normalizedSourcePath}.server.js`);\n};\n\nconst resolveSvelteImport = async (spec: string, from: string) => {\n\tif (!spec.startsWith('.') && !spec.startsWith('/')) {\n\t\tconst resolved = resolvePackageImport(spec);\n\n\t\treturn resolved && resolved.endsWith('.svelte') ? resolved : null;\n\t}\n\n\tif (spec.startsWith('/')) {\n\t\treturn spec;\n\t}\n\n\tif (!spec.startsWith('.')) {\n\t\treturn null;\n\t}\n\n\tconst explicitPath = resolve(dirname(from), spec);\n\tif (extname(explicitPath) === '.svelte') {\n\t\treturn explicitPath;\n\t}\n\n\tconst candidate = `${explicitPath}.svelte`;\n\tif ((await Bun.file(candidate).exists()) === true) {\n\t\treturn candidate;\n\t}\n\n\treturn null;\n};\n\nconst writeIfChanged = async (path: string, content: string) => {\n\tconst targetFile = Bun.file(path);\n\tconst exists = await targetFile.exists();\n\tif (exists) {\n\t\tconst currentContent = await targetFile.text();\n\t\tif (currentContent === content) {\n\t\t\treturn;\n\t\t}\n\t}\n\n\tawait Bun.write(path, content);\n};\n\nexport const compileSvelteServerModule = async (sourcePath: string) => {\n\tconst cachedModulePath = compiledModuleCache.get(sourcePath);\n\tif (cachedModulePath) {\n\t\treturn cachedModulePath;\n\t}\n\n\tconst resolutionSourcePath = await resolveOriginalSourcePath(sourcePath);\n\tconst source = await Bun.file(sourcePath).text();\n\tconst { compile, preprocess } = await import('svelte/compiler');\n\tconst loweredAwaitSource = lowerSvelteAwaitSlotSyntax(source);\n\tconst loweredSource = lowerSvelteIslandSyntax(\n\t\tloweredAwaitSource.code,\n\t\t'server'\n\t);\n\tconst preprocessed = await preprocess(\n\t\tloweredSource.code,\n\t\tcreateSvelteStylePreprocessor()\n\t);\n\tlet transpiled =\n\t\tsourcePath.endsWith('.ts') || sourcePath.endsWith('.svelte.ts')\n\t\t\t? transpiler.transformSync(preprocessed.code)\n\t\t\t: preprocessed.code;\n\tconst childImportSpecs = Array.from(\n\t\ttranspiled.matchAll(/from\\s+['\"]([^'\"]+)['\"]/g)\n\t)\n\t\t.map((match) => match[1])\n\t\t.filter((value): value is string => value !== undefined);\n\tconst resolvedChildModules = await Promise.all(\n\t\tchildImportSpecs.map((spec) =>\n\t\t\tresolveSvelteImport(spec, resolutionSourcePath)\n\t\t)\n\t);\n\tconst resolvedModuleImports = await Promise.all(\n\t\tchildImportSpecs.map((spec) =>\n\t\t\tresolveRelativeModule(spec, resolutionSourcePath)\n\t\t)\n\t);\n\tconst childModulePaths = new Map<string, string>();\n\tconst rewrittenModulePaths = new Map<string, string>();\n\n\tconst compiledChildren = await Promise.all(\n\t\tchildImportSpecs.map(async (spec, index) => {\n\t\t\tconst resolvedChild = resolvedChildModules[index];\n\t\t\tif (!spec || !resolvedChild) return null;\n\n\t\t\treturn {\n\t\t\t\tcompiledPath: await compileSvelteServerModule(resolvedChild),\n\t\t\t\tresolvedChild,\n\t\t\t\tspec\n\t\t\t};\n\t\t})\n\t);\n\n\tfor (const result of compiledChildren) {\n\t\tif (!result) continue;\n\t\tchildModulePaths.set(result.spec, result.compiledPath);\n\t\tchildModulePaths.set(result.resolvedChild, result.compiledPath);\n\t}\n\n\tfor (let index = 0; index < childImportSpecs.length; index += 1) {\n\t\tconst spec = childImportSpecs[index];\n\t\tconst resolvedModuleImport = resolvedModuleImports[index];\n\t\tif (!spec || !resolvedModuleImport) continue;\n\t\tif (resolvedChildModules[index]) continue;\n\n\t\trewrittenModulePaths.set(\n\t\t\tspec,\n\t\t\tensureRelativeImportPath(\n\t\t\t\tgetCachedModulePath(sourcePath),\n\t\t\t\tresolvedModuleImport\n\t\t\t)\n\t\t);\n\t}\n\n\tfor (const [spec, resolvedModuleImport] of rewrittenModulePaths) {\n\t\ttranspiled = transpiled.replaceAll(spec, resolvedModuleImport);\n\t}\n\n\tlet compiledCode = compile(transpiled, {\n\t\tcss: 'injected',\n\t\texperimental: {\n\t\t\tasync: loweredAwaitSource.transformed || loweredSource.transformed\n\t\t},\n\t\tfilename: resolutionSourcePath,\n\t\tgenerate: 'server'\n\t}).js.code;\n\n\tfor (const [spec, compiledChildPath] of childModulePaths) {\n\t\tcompiledCode = compiledCode.replaceAll(\n\t\t\tspec,\n\t\t\tensureRelativeImportPath(\n\t\t\t\tgetCachedModulePath(sourcePath),\n\t\t\t\tcompiledChildPath\n\t\t\t)\n\t\t);\n\t}\n\n\tfor (const [spec, resolvedModuleImport] of rewrittenModulePaths) {\n\t\tcompiledCode = compiledCode.replaceAll(spec, resolvedModuleImport);\n\t}\n\n\tconst compiledModulePath = getCachedModulePath(sourcePath);\n\tawait mkdir(dirname(compiledModulePath), { recursive: true });\n\tawait writeIfChanged(compiledModulePath, compiledCode);\n\tcompiledModuleCache.set(sourcePath, compiledModulePath);\n\n\treturn compiledModulePath;\n};\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "7E4C5416175915DB64756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
// @bun
|
|
2
|
+
import {
|
|
3
|
+
validateSafePath
|
|
4
|
+
} from "./chunk-cg95827x.js";
|
|
5
|
+
import"./chunk-hyjs4bqs.js";
|
|
6
|
+
import {
|
|
7
|
+
DEFAULT_DEVICE_SIZES,
|
|
8
|
+
DEFAULT_IMAGE_SIZES,
|
|
9
|
+
DEFAULT_QUALITY,
|
|
10
|
+
OPTIMIZATION_ENDPOINT,
|
|
11
|
+
formatToMime,
|
|
12
|
+
getCacheDir,
|
|
13
|
+
getCacheKey,
|
|
14
|
+
isCacheStale,
|
|
15
|
+
matchRemotePattern,
|
|
16
|
+
negotiateFormat,
|
|
17
|
+
optimizeImage,
|
|
18
|
+
readFromCache,
|
|
19
|
+
writeToCache
|
|
20
|
+
} from "./chunk-kk8w9rh5.js";
|
|
21
|
+
import"./chunk-qh75agse.js";
|
|
22
|
+
import"./chunk-bmgqm774.js";
|
|
23
|
+
|
|
24
|
+
// src/plugins/imageOptimizer.ts
|
|
25
|
+
import { existsSync } from "fs";
|
|
26
|
+
import { resolve } from "path";
|
|
27
|
+
import { Elysia } from "elysia";
|
|
28
|
+
var DEFAULT_CACHE_TTL_SECONDS = 60;
|
|
29
|
+
var MS_PER_SECOND = 1000;
|
|
30
|
+
var MAX_QUALITY = 100;
|
|
31
|
+
var avifInProgress = new Set;
|
|
32
|
+
var safeResolve = (path, baseDir) => {
|
|
33
|
+
try {
|
|
34
|
+
const resolved = validateSafePath(path, baseDir);
|
|
35
|
+
if (existsSync(resolved))
|
|
36
|
+
return resolved;
|
|
37
|
+
return null;
|
|
38
|
+
} catch {
|
|
39
|
+
return null;
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
var resolveLocalImage = (url, buildDir) => {
|
|
43
|
+
const cleanPath = url.startsWith("/") ? url.slice(1) : url;
|
|
44
|
+
return safeResolve(cleanPath, buildDir) ?? safeResolve(cleanPath, resolve(process.cwd()));
|
|
45
|
+
};
|
|
46
|
+
var parseQueryParams = (query, allowedSizes, defaultQuality) => {
|
|
47
|
+
const url = typeof query["url"] === "string" ? query["url"] : undefined;
|
|
48
|
+
const wParam = typeof query["w"] === "string" ? query["w"] : undefined;
|
|
49
|
+
const qParam = typeof query["q"] === "string" ? query["q"] : undefined;
|
|
50
|
+
if (!url || !wParam) {
|
|
51
|
+
return {
|
|
52
|
+
error: new Response("Missing required params: url, w", {
|
|
53
|
+
status: 400
|
|
54
|
+
})
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
const width = parseInt(wParam, 10);
|
|
58
|
+
if (isNaN(width) || !allowedSizes.has(width)) {
|
|
59
|
+
return {
|
|
60
|
+
error: new Response(`Invalid width: ${wParam}. Must be one of: ${[...allowedSizes].sort((left, right) => left - right).join(", ")}`, { status: 400 })
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
const quality = qParam ? parseInt(qParam, 10) : defaultQuality;
|
|
64
|
+
if (isNaN(quality) || quality < 1 || quality > MAX_QUALITY) {
|
|
65
|
+
return {
|
|
66
|
+
error: new Response("Invalid quality: must be 1-100", {
|
|
67
|
+
status: 400
|
|
68
|
+
})
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
return { params: { quality, url, width } };
|
|
72
|
+
};
|
|
73
|
+
var validateImageSecurity = (url, remotePatterns, buildDir) => {
|
|
74
|
+
const isRemote = url.startsWith("http://") || url.startsWith("https://");
|
|
75
|
+
if (isRemote) {
|
|
76
|
+
if (remotePatterns.length === 0 || !matchRemotePattern(url, remotePatterns)) {
|
|
77
|
+
return {
|
|
78
|
+
error: new Response("Remote image not allowed. Configure remotePatterns in images config.", { status: 400 }),
|
|
79
|
+
isRemote
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
return { isRemote, resolvedPath: null };
|
|
83
|
+
}
|
|
84
|
+
const resolvedPath = resolveLocalImage(url, buildDir);
|
|
85
|
+
if (!resolvedPath) {
|
|
86
|
+
return {
|
|
87
|
+
error: new Response(`Image not found: ${url}`, { status: 404 }),
|
|
88
|
+
isRemote
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
return { isRemote, resolvedPath };
|
|
92
|
+
};
|
|
93
|
+
var fetchSourceImage = async (url, isRemote, resolvedPath) => {
|
|
94
|
+
if (isRemote) {
|
|
95
|
+
const response = await fetch(url);
|
|
96
|
+
if (!response.ok) {
|
|
97
|
+
return {
|
|
98
|
+
error: new Response(`Failed to fetch remote image: ${response.status}`, { status: 502 })
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
return {
|
|
102
|
+
buffer: Buffer.from(await response.arrayBuffer()),
|
|
103
|
+
upstreamEtag: response.headers.get("ETag") ?? undefined
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
if (!resolvedPath) {
|
|
107
|
+
return {
|
|
108
|
+
error: new Response(`Image not found: ${url}`, { status: 404 })
|
|
109
|
+
};
|
|
110
|
+
}
|
|
111
|
+
const file = Bun.file(resolvedPath);
|
|
112
|
+
if (!await file.exists()) {
|
|
113
|
+
return {
|
|
114
|
+
error: new Response(`Image not found: ${url}`, { status: 404 })
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
return {
|
|
118
|
+
buffer: Buffer.from(await file.arrayBuffer()),
|
|
119
|
+
upstreamEtag: undefined
|
|
120
|
+
};
|
|
121
|
+
};
|
|
122
|
+
var scheduleAvifPregen = (url, width, quality, sourceBuffer, configuredFormats, format, cacheDir, minimumCacheTTL, upstreamEtag) => {
|
|
123
|
+
if (!configuredFormats.includes("avif") || format === "avif") {
|
|
124
|
+
return;
|
|
125
|
+
}
|
|
126
|
+
const avifKey = `${url}|${width}|${quality}`;
|
|
127
|
+
if (avifInProgress.has(avifKey))
|
|
128
|
+
return;
|
|
129
|
+
const avifCacheKey = getCacheKey(url, width, quality, "avif");
|
|
130
|
+
const avifCached = readFromCache(cacheDir, avifCacheKey);
|
|
131
|
+
if (avifCached && !isCacheStale(avifCached.meta))
|
|
132
|
+
return;
|
|
133
|
+
avifInProgress.add(avifKey);
|
|
134
|
+
queueMicrotask(async () => {
|
|
135
|
+
try {
|
|
136
|
+
const avifBuffer = await optimizeImage(sourceBuffer, width, quality, "avif");
|
|
137
|
+
const avifMeta = {
|
|
138
|
+
contentType: "image/avif",
|
|
139
|
+
etag: `"${avifCacheKey}"`,
|
|
140
|
+
expireAt: Date.now() + minimumCacheTTL,
|
|
141
|
+
upstreamEtag
|
|
142
|
+
};
|
|
143
|
+
writeToCache(cacheDir, avifCacheKey, avifBuffer, avifMeta);
|
|
144
|
+
} catch {} finally {
|
|
145
|
+
avifInProgress.delete(avifKey);
|
|
146
|
+
}
|
|
147
|
+
});
|
|
148
|
+
};
|
|
149
|
+
var imageOptimizer = (config, buildDir) => {
|
|
150
|
+
const plugin = new Elysia({ name: "image-optimizer" });
|
|
151
|
+
if (!config && config !== undefined)
|
|
152
|
+
return plugin;
|
|
153
|
+
if (config?.unoptimized)
|
|
154
|
+
return plugin;
|
|
155
|
+
const endpointPath = config?.path ?? OPTIMIZATION_ENDPOINT;
|
|
156
|
+
const allowedSizes = new Set([
|
|
157
|
+
...config?.deviceSizes ?? DEFAULT_DEVICE_SIZES,
|
|
158
|
+
...config?.imageSizes ?? DEFAULT_IMAGE_SIZES
|
|
159
|
+
]);
|
|
160
|
+
const defaultQuality = config?.quality ?? DEFAULT_QUALITY;
|
|
161
|
+
const minimumCacheTTL = (config?.minimumCacheTTL ?? DEFAULT_CACHE_TTL_SECONDS) * MS_PER_SECOND;
|
|
162
|
+
const cacheControlHeader = `public, max-age=${Math.ceil(minimumCacheTTL / MS_PER_SECOND)}, must-revalidate`;
|
|
163
|
+
const configuredFormats = config?.formats ?? ["webp"];
|
|
164
|
+
const remotePatterns = config?.remotePatterns ?? [];
|
|
165
|
+
const cacheDir = getCacheDir(buildDir);
|
|
166
|
+
return plugin.get(endpointPath, async ({ query, request }) => {
|
|
167
|
+
const parsed = parseQueryParams(query, allowedSizes, defaultQuality);
|
|
168
|
+
if ("error" in parsed)
|
|
169
|
+
return parsed.error;
|
|
170
|
+
const { quality, url, width } = parsed.params;
|
|
171
|
+
const security = validateImageSecurity(url, remotePatterns, buildDir);
|
|
172
|
+
if ("error" in security)
|
|
173
|
+
return security.error;
|
|
174
|
+
const { isRemote, resolvedPath } = security;
|
|
175
|
+
const acceptHeader = request.headers.get("Accept") ?? "";
|
|
176
|
+
const format = negotiateFormat(acceptHeader, configuredFormats);
|
|
177
|
+
const mime = formatToMime(format);
|
|
178
|
+
const cacheKey = getCacheKey(url, width, quality, format);
|
|
179
|
+
const cached = readFromCache(cacheDir, cacheKey);
|
|
180
|
+
if (cached && !isCacheStale(cached.meta)) {
|
|
181
|
+
const ifNoneMatch = request.headers.get("If-None-Match");
|
|
182
|
+
if (ifNoneMatch && ifNoneMatch === cached.meta.etag) {
|
|
183
|
+
return new Response(null, {
|
|
184
|
+
headers: {
|
|
185
|
+
"Cache-Control": cacheControlHeader,
|
|
186
|
+
ETag: cached.meta.etag,
|
|
187
|
+
Vary: "Accept"
|
|
188
|
+
},
|
|
189
|
+
status: 304
|
|
190
|
+
});
|
|
191
|
+
}
|
|
192
|
+
return new Response(new Uint8Array(cached.buffer), {
|
|
193
|
+
headers: {
|
|
194
|
+
"Cache-Control": cacheControlHeader,
|
|
195
|
+
"Content-Type": cached.meta.contentType,
|
|
196
|
+
ETag: cached.meta.etag,
|
|
197
|
+
Vary: "Accept"
|
|
198
|
+
}
|
|
199
|
+
});
|
|
200
|
+
}
|
|
201
|
+
let sourceBuffer;
|
|
202
|
+
let upstreamEtag;
|
|
203
|
+
try {
|
|
204
|
+
const source = await fetchSourceImage(url, isRemote, resolvedPath ?? null);
|
|
205
|
+
if ("error" in source)
|
|
206
|
+
return source.error;
|
|
207
|
+
sourceBuffer = source.buffer;
|
|
208
|
+
({ upstreamEtag } = source);
|
|
209
|
+
} catch (err) {
|
|
210
|
+
return new Response(`Failed to load image: ${err instanceof Error ? err.message : "unknown error"}`, { status: 500 });
|
|
211
|
+
}
|
|
212
|
+
let optimizedBuffer;
|
|
213
|
+
try {
|
|
214
|
+
optimizedBuffer = await optimizeImage(sourceBuffer, width, quality, format);
|
|
215
|
+
} catch {
|
|
216
|
+
optimizedBuffer = sourceBuffer;
|
|
217
|
+
}
|
|
218
|
+
const etag = `"${cacheKey}"`;
|
|
219
|
+
const meta = {
|
|
220
|
+
contentType: mime,
|
|
221
|
+
etag,
|
|
222
|
+
expireAt: Date.now() + minimumCacheTTL,
|
|
223
|
+
upstreamEtag
|
|
224
|
+
};
|
|
225
|
+
try {
|
|
226
|
+
writeToCache(cacheDir, cacheKey, optimizedBuffer, meta);
|
|
227
|
+
} catch {}
|
|
228
|
+
scheduleAvifPregen(url, width, quality, sourceBuffer, configuredFormats, format, cacheDir, minimumCacheTTL, upstreamEtag);
|
|
229
|
+
return new Response(new Uint8Array(optimizedBuffer), {
|
|
230
|
+
headers: {
|
|
231
|
+
"Cache-Control": cacheControlHeader,
|
|
232
|
+
"Content-Type": mime,
|
|
233
|
+
ETag: etag,
|
|
234
|
+
Vary: "Accept"
|
|
235
|
+
}
|
|
236
|
+
});
|
|
237
|
+
});
|
|
238
|
+
};
|
|
239
|
+
export {
|
|
240
|
+
imageOptimizer
|
|
241
|
+
};
|
|
242
|
+
|
|
243
|
+
//# debugId=6A88C49F9E6C16C364756E2164756E21
|
|
244
|
+
//# sourceMappingURL=chunk-e8eecyrq.js.map
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
{
|
|
2
|
+
"version": 3,
|
|
3
|
+
"sources": ["../src/plugins/imageOptimizer.ts"],
|
|
4
|
+
"sourcesContent": [
|
|
5
|
+
"import { existsSync } from 'node:fs';\nimport { resolve } from 'node:path';\nimport { Elysia } from 'elysia';\nimport type { ImageConfig, ImageFormat } from '../../types/image';\nimport {\n\ttype CacheMeta,\n\tDEFAULT_DEVICE_SIZES,\n\tDEFAULT_IMAGE_SIZES,\n\tDEFAULT_QUALITY,\n\tOPTIMIZATION_ENDPOINT,\n\tformatToMime,\n\tgetCacheDir,\n\tgetCacheKey,\n\tisCacheStale,\n\tmatchRemotePattern,\n\tnegotiateFormat,\n\toptimizeImage,\n\treadFromCache,\n\twriteToCache\n} from '../utils/imageProcessing';\nimport { validateSafePath } from '../utils/validateSafePath';\n\n/** Default cache TTL in seconds */\nconst DEFAULT_CACHE_TTL_SECONDS = 60;\n\n/** Milliseconds per second */\nconst MS_PER_SECOND = 1000;\n\n/** Maximum image quality value */\nconst MAX_QUALITY = 100;\n\n/** Set of AVIF cache keys currently being generated to avoid duplicate work */\nconst avifInProgress = new Set<string>();\n\n/** Try to resolve a path safely against a base directory, returning null if the file doesn't exist */\nconst safeResolve = (path: string, baseDir: string) => {\n\ttry {\n\t\tconst resolved = validateSafePath(path, baseDir);\n\n\t\tif (existsSync(resolved)) return resolved;\n\n\t\treturn null;\n\t} catch {\n\t\treturn null;\n\t}\n};\n\n/** Resolve a local image path against build dir and project root */\nconst resolveLocalImage = (url: string, buildDir: string) => {\n\tconst cleanPath = url.startsWith('/') ? url.slice(1) : url;\n\n\treturn (\n\t\tsafeResolve(cleanPath, buildDir) ??\n\t\tsafeResolve(cleanPath, resolve(process.cwd()))\n\t);\n};\n\n/** Parse and validate query parameters, returning an error Response or valid params */\nconst parseQueryParams = (\n\tquery: Record<string, string | undefined>,\n\tallowedSizes: Set<number>,\n\tdefaultQuality: number\n) => {\n\tconst url = typeof query['url'] === 'string' ? query['url'] : undefined;\n\tconst wParam = typeof query['w'] === 'string' ? query['w'] : undefined;\n\tconst qParam = typeof query['q'] === 'string' ? query['q'] : undefined;\n\n\tif (!url || !wParam) {\n\t\treturn {\n\t\t\terror: new Response('Missing required params: url, w', {\n\t\t\t\tstatus: 400\n\t\t\t})\n\t\t};\n\t}\n\n\tconst width = parseInt(wParam, 10);\n\tif (isNaN(width) || !allowedSizes.has(width)) {\n\t\treturn {\n\t\t\terror: new Response(\n\t\t\t\t`Invalid width: ${wParam}. Must be one of: ${[...allowedSizes].sort((left, right) => left - right).join(', ')}`,\n\t\t\t\t{ status: 400 }\n\t\t\t)\n\t\t};\n\t}\n\n\tconst quality = qParam ? parseInt(qParam, 10) : defaultQuality;\n\tif (isNaN(quality) || quality < 1 || quality > MAX_QUALITY) {\n\t\treturn {\n\t\t\terror: new Response('Invalid quality: must be 1-100', {\n\t\t\t\tstatus: 400\n\t\t\t})\n\t\t};\n\t}\n\n\treturn { params: { quality, url, width } };\n};\n\n/** Validate security for the given image URL */\nconst validateImageSecurity = (\n\turl: string,\n\tremotePatterns: ImageConfig['remotePatterns'] & object,\n\tbuildDir: string\n) => {\n\tconst isRemote = url.startsWith('http://') || url.startsWith('https://');\n\n\tif (isRemote) {\n\t\tif (\n\t\t\tremotePatterns.length === 0 ||\n\t\t\t!matchRemotePattern(url, remotePatterns)\n\t\t) {\n\t\t\treturn {\n\t\t\t\terror: new Response(\n\t\t\t\t\t'Remote image not allowed. Configure remotePatterns in images config.',\n\t\t\t\t\t{ status: 400 }\n\t\t\t\t),\n\t\t\t\tisRemote\n\t\t\t};\n\t\t}\n\n\t\treturn { isRemote, resolvedPath: null };\n\t}\n\n\tconst resolvedPath = resolveLocalImage(url, buildDir);\n\tif (!resolvedPath) {\n\t\treturn {\n\t\t\terror: new Response(`Image not found: ${url}`, { status: 404 }),\n\t\t\tisRemote\n\t\t};\n\t}\n\n\treturn { isRemote, resolvedPath };\n};\n\n/** Fetch the source image buffer from remote URL or local file */\nconst fetchSourceImage = async (\n\turl: string,\n\tisRemote: boolean,\n\tresolvedPath: string | null\n) => {\n\tif (isRemote) {\n\t\tconst response = await fetch(url);\n\t\tif (!response.ok) {\n\t\t\treturn {\n\t\t\t\terror: new Response(\n\t\t\t\t\t`Failed to fetch remote image: ${response.status}`,\n\t\t\t\t\t{ status: 502 }\n\t\t\t\t)\n\t\t\t};\n\t\t}\n\n\t\treturn {\n\t\t\tbuffer: Buffer.from(await response.arrayBuffer()),\n\t\t\tupstreamEtag: response.headers.get('ETag') ?? undefined\n\t\t};\n\t}\n\n\tif (!resolvedPath) {\n\t\treturn {\n\t\t\terror: new Response(`Image not found: ${url}`, { status: 404 })\n\t\t};\n\t}\n\n\tconst file = Bun.file(resolvedPath);\n\tif (!(await file.exists())) {\n\t\treturn {\n\t\t\terror: new Response(`Image not found: ${url}`, { status: 404 })\n\t\t};\n\t}\n\n\treturn {\n\t\tbuffer: Buffer.from(await file.arrayBuffer()),\n\t\tupstreamEtag: undefined\n\t};\n};\n\n/** Schedule AVIF pre-generation in the background */\nconst scheduleAvifPregen = (\n\turl: string,\n\twidth: number,\n\tquality: number,\n\tsourceBuffer: Buffer,\n\tconfiguredFormats: ImageFormat[],\n\tformat: ImageFormat,\n\tcacheDir: string,\n\tminimumCacheTTL: number,\n\tupstreamEtag: string | undefined\n) => {\n\tif (!configuredFormats.includes('avif') || format === 'avif') {\n\t\treturn;\n\t}\n\n\tconst avifKey = `${url}|${width}|${quality}`;\n\tif (avifInProgress.has(avifKey)) return;\n\n\tconst avifCacheKey = getCacheKey(url, width, quality, 'avif');\n\tconst avifCached = readFromCache(cacheDir, avifCacheKey);\n\tif (avifCached && !isCacheStale(avifCached.meta)) return;\n\n\tavifInProgress.add(avifKey);\n\tqueueMicrotask(async () => {\n\t\ttry {\n\t\t\tconst avifBuffer = await optimizeImage(\n\t\t\t\tsourceBuffer,\n\t\t\t\twidth,\n\t\t\t\tquality,\n\t\t\t\t'avif'\n\t\t\t);\n\t\t\tconst avifMeta: CacheMeta = {\n\t\t\t\tcontentType: 'image/avif',\n\t\t\t\tetag: `\"${avifCacheKey}\"`,\n\t\t\t\texpireAt: Date.now() + minimumCacheTTL,\n\t\t\t\tupstreamEtag\n\t\t\t};\n\t\t\twriteToCache(cacheDir, avifCacheKey, avifBuffer, avifMeta);\n\t\t} catch {\n\t\t\t// AVIF generation failure is non-fatal\n\t\t} finally {\n\t\t\tavifInProgress.delete(avifKey);\n\t\t}\n\t});\n};\n\nexport const imageOptimizer = (\n\tconfig: ImageConfig | undefined,\n\tbuildDir: string\n) => {\n\tconst plugin = new Elysia({ name: 'image-optimizer' });\n\n\t// No-op if disabled or no config\n\tif (!config && config !== undefined) return plugin;\n\tif (config?.unoptimized) return plugin;\n\n\tconst endpointPath = config?.path ?? OPTIMIZATION_ENDPOINT;\n\tconst allowedSizes = new Set([\n\t\t...(config?.deviceSizes ?? DEFAULT_DEVICE_SIZES),\n\t\t...(config?.imageSizes ?? DEFAULT_IMAGE_SIZES)\n\t]);\n\tconst defaultQuality = config?.quality ?? DEFAULT_QUALITY;\n\tconst minimumCacheTTL =\n\t\t(config?.minimumCacheTTL ?? DEFAULT_CACHE_TTL_SECONDS) * MS_PER_SECOND;\n\tconst cacheControlHeader = `public, max-age=${Math.ceil(minimumCacheTTL / MS_PER_SECOND)}, must-revalidate`;\n\tconst configuredFormats: ImageFormat[] = config?.formats ?? ['webp'];\n\tconst remotePatterns = config?.remotePatterns ?? [];\n\tconst cacheDir = getCacheDir(buildDir);\n\n\treturn plugin.get(endpointPath, async ({ query, request }) => {\n\t\t// ── Parse & Validate ────────────────────────────────\n\t\tconst parsed = parseQueryParams(query, allowedSizes, defaultQuality);\n\t\tif ('error' in parsed) return parsed.error;\n\t\tconst { quality, url, width } = parsed.params;\n\n\t\t// ── Security ────────────────────────────────────────\n\t\tconst security = validateImageSecurity(url, remotePatterns, buildDir);\n\t\tif ('error' in security) return security.error;\n\t\tconst { isRemote, resolvedPath } = security;\n\n\t\t// ── Content Negotiation ─────────────────────────────\n\t\tconst acceptHeader = request.headers.get('Accept') ?? '';\n\t\tconst format = negotiateFormat(acceptHeader, configuredFormats);\n\t\tconst mime = formatToMime(format);\n\n\t\t// ── Cache Lookup ────────────────────────────────────\n\t\tconst cacheKey = getCacheKey(url, width, quality, format);\n\t\tconst cached = readFromCache(cacheDir, cacheKey);\n\n\t\tif (cached && !isCacheStale(cached.meta)) {\n\t\t\tconst ifNoneMatch = request.headers.get('If-None-Match');\n\t\t\tif (ifNoneMatch && ifNoneMatch === cached.meta.etag) {\n\t\t\t\treturn new Response(null, {\n\t\t\t\t\theaders: {\n\t\t\t\t\t\t'Cache-Control': cacheControlHeader,\n\t\t\t\t\t\tETag: cached.meta.etag,\n\t\t\t\t\t\tVary: 'Accept'\n\t\t\t\t\t},\n\t\t\t\t\tstatus: 304\n\t\t\t\t});\n\t\t\t}\n\n\t\t\treturn new Response(new Uint8Array(cached.buffer), {\n\t\t\t\theaders: {\n\t\t\t\t\t'Cache-Control': cacheControlHeader,\n\t\t\t\t\t'Content-Type': cached.meta.contentType,\n\t\t\t\t\tETag: cached.meta.etag,\n\t\t\t\t\tVary: 'Accept'\n\t\t\t\t}\n\t\t\t});\n\t\t}\n\n\t\t// ── Fetch Source ────────────────────────────────────\n\t\tlet sourceBuffer: Buffer;\n\t\tlet upstreamEtag: string | undefined;\n\n\t\ttry {\n\t\t\tconst source = await fetchSourceImage(\n\t\t\t\turl,\n\t\t\t\tisRemote,\n\t\t\t\tresolvedPath ?? null\n\t\t\t);\n\t\t\tif ('error' in source) return source.error;\n\t\t\tsourceBuffer = source.buffer;\n\t\t\t({ upstreamEtag } = source);\n\t\t} catch (err) {\n\t\t\treturn new Response(\n\t\t\t\t`Failed to load image: ${err instanceof Error ? err.message : 'unknown error'}`,\n\t\t\t\t{ status: 500 }\n\t\t\t);\n\t\t}\n\n\t\t// ── Optimize ────────────────────────────────────────\n\t\tlet optimizedBuffer: Buffer;\n\t\ttry {\n\t\t\toptimizedBuffer = await optimizeImage(\n\t\t\t\tsourceBuffer,\n\t\t\t\twidth,\n\t\t\t\tquality,\n\t\t\t\tformat\n\t\t\t);\n\t\t} catch {\n\t\t\t// Graceful degradation: serve original\n\t\t\toptimizedBuffer = sourceBuffer;\n\t\t}\n\n\t\t// ── Cache Write ─────────────────────────────────────\n\t\tconst etag = `\"${cacheKey}\"`;\n\t\tconst meta: CacheMeta = {\n\t\t\tcontentType: mime,\n\t\t\tetag,\n\t\t\texpireAt: Date.now() + minimumCacheTTL,\n\t\t\tupstreamEtag\n\t\t};\n\n\t\ttry {\n\t\t\twriteToCache(cacheDir, cacheKey, optimizedBuffer, meta);\n\t\t} catch {\n\t\t\t// Cache write failure is non-fatal\n\t\t}\n\n\t\t// ── AVIF Async Pre-generation ───────────────────────\n\t\tscheduleAvifPregen(\n\t\t\turl,\n\t\t\twidth,\n\t\t\tquality,\n\t\t\tsourceBuffer,\n\t\t\tconfiguredFormats,\n\t\t\tformat,\n\t\t\tcacheDir,\n\t\t\tminimumCacheTTL,\n\t\t\tupstreamEtag\n\t\t);\n\n\t\t// ── Response ────────────────────────────────────────\n\t\treturn new Response(new Uint8Array(optimizedBuffer), {\n\t\t\theaders: {\n\t\t\t\t'Cache-Control': cacheControlHeader,\n\t\t\t\t'Content-Type': mime,\n\t\t\t\tETag: etag,\n\t\t\t\tVary: 'Accept'\n\t\t\t}\n\t\t});\n\t});\n};\n"
|
|
6
|
+
],
|
|
7
|
+
"mappings": "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",
|
|
8
|
+
"debugId": "6A88C49F9E6C16C364756E2164756E21",
|
|
9
|
+
"names": []
|
|
10
|
+
}
|