first commit
This commit is contained in:
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
node_modules
|
||||
|
||||
19
app/App.tsx
Normal file
19
app/App.tsx
Normal file
@@ -0,0 +1,19 @@
|
||||
import { defineComponent, computed, ref } from "vue";
|
||||
import Test from '@/test.tsx';
|
||||
|
||||
export default defineComponent({
|
||||
name: "app-root",
|
||||
setup() {
|
||||
const count = ref(0);
|
||||
const countDouble = computed(() => count.value * 2);
|
||||
count.value++;
|
||||
return () => (
|
||||
<div class="app-main">
|
||||
<button class="test" onClick={() => count.value++}>Click me!</button>
|
||||
<div>Count: {count.value}</div>
|
||||
<div>Count Double: {countDouble.value}</div>
|
||||
<Test />
|
||||
</div>
|
||||
);
|
||||
},
|
||||
});
|
||||
1
app/test.tsx
Normal file
1
app/test.tsx
Normal file
@@ -0,0 +1 @@
|
||||
export default () => <div class="test">Test</div>;
|
||||
23
deno.json
Normal file
23
deno.json
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"tasks": {
|
||||
"start": "deno --allow-read --allow-net --allow-env --allow-write --allow-run main.ts",
|
||||
"watch": "deno --watch --allow-read --allow-net --allow-env --allow-write --allow-run main.ts"
|
||||
},
|
||||
"fmt": {
|
||||
"lineWidth": 120,
|
||||
"indentWidth": 4
|
||||
},
|
||||
"imports": {
|
||||
"@stock3/koala": "npm:@stock3/koala@^15.3.8-esm.0",
|
||||
"vue": "npm:vue@^3.5.12",
|
||||
"vue/jsx-runtime": "npm:vue/jsx-runtime",
|
||||
"@/": "./app/"
|
||||
},
|
||||
"nodeModulesDir": "auto",
|
||||
"compilerOptions": {
|
||||
"jsx": "react-jsx",
|
||||
"jsxFactory": "h",
|
||||
"jsxFragmentFactory": "Fragment",
|
||||
"jsxImportSource": "vue"
|
||||
}
|
||||
}
|
||||
331
deno.lock
generated
Normal file
331
deno.lock
generated
Normal file
@@ -0,0 +1,331 @@
|
||||
{
|
||||
"version": "4",
|
||||
"specifiers": {
|
||||
"jsr:@deno/cache-dir@0.13.2": "0.13.2",
|
||||
"jsr:@deno/emit@*": "0.46.0",
|
||||
"jsr:@deno/graph@~0.73.1": "0.73.1",
|
||||
"jsr:@luca/esbuild-deno-loader@0.11": "0.11.0",
|
||||
"jsr:@std/assert@0.223": "0.223.0",
|
||||
"jsr:@std/bytes@0.223": "0.223.0",
|
||||
"jsr:@std/bytes@^1.0.2": "1.0.2",
|
||||
"jsr:@std/cli@^1.0.6": "1.0.6",
|
||||
"jsr:@std/encoding@^1.0.5": "1.0.5",
|
||||
"jsr:@std/fmt@0.223": "0.223.0",
|
||||
"jsr:@std/fmt@^1.0.3": "1.0.3",
|
||||
"jsr:@std/fs@*": "1.0.5",
|
||||
"jsr:@std/fs@0.223": "0.223.0",
|
||||
"jsr:@std/http@*": "1.0.9",
|
||||
"jsr:@std/io@0.223": "0.223.0",
|
||||
"jsr:@std/media-types@*": "1.0.3",
|
||||
"jsr:@std/media-types@^1.0.3": "1.0.3",
|
||||
"jsr:@std/net@^1.0.4": "1.0.4",
|
||||
"jsr:@std/path@0.223": "0.223.0",
|
||||
"jsr:@std/path@^1.0.6": "1.0.7",
|
||||
"jsr:@std/path@^1.0.7": "1.0.7",
|
||||
"jsr:@std/streams@^1.0.7": "1.0.7",
|
||||
"npm:@stock3/koala@^15.3.8-esm.0": "15.3.8-esm.0_@stock3+auth-js@4.2.3_bg-auth-legacy@2.5.0_bg-status-js@2.4.3_flora-client-js@0.5.3_m-gate@2.12.8_vue@3.5.12_vue-router@4.4.5__vue@3.5.12",
|
||||
"npm:@types/node@*": "22.5.4",
|
||||
"npm:vue@*": "3.5.12",
|
||||
"npm:vue@3.5.12": "3.5.12",
|
||||
"npm:vue@^3.5.12": "3.5.12"
|
||||
},
|
||||
"jsr": {
|
||||
"@deno/cache-dir@0.13.2": {
|
||||
"integrity": "c22419dfe27ab85f345bee487aaaadba498b005cce3644e9d2528db035c5454d",
|
||||
"dependencies": [
|
||||
"jsr:@deno/graph",
|
||||
"jsr:@std/fmt@0.223",
|
||||
"jsr:@std/fs@0.223",
|
||||
"jsr:@std/io",
|
||||
"jsr:@std/path@0.223"
|
||||
]
|
||||
},
|
||||
"@deno/emit@0.46.0": {
|
||||
"integrity": "e276be2c77bac1b93caf775762e2a49a54cb00da2d48ca2b01ed8d7cba9d082c",
|
||||
"dependencies": [
|
||||
"jsr:@deno/cache-dir",
|
||||
"jsr:@std/path@0.223"
|
||||
]
|
||||
},
|
||||
"@deno/graph@0.73.1": {
|
||||
"integrity": "cd69639d2709d479037d5ce191a422eabe8d71bb68b0098344f6b07411c84d41"
|
||||
},
|
||||
"@luca/esbuild-deno-loader@0.11.0": {
|
||||
"integrity": "c05a989aa7c4ee6992a27be5f15cfc5be12834cab7ff84cabb47313737c51a2c",
|
||||
"dependencies": [
|
||||
"jsr:@std/bytes@^1.0.2",
|
||||
"jsr:@std/encoding",
|
||||
"jsr:@std/path@^1.0.6"
|
||||
]
|
||||
},
|
||||
"@std/assert@0.223.0": {
|
||||
"integrity": "eb8d6d879d76e1cc431205bd346ed4d88dc051c6366365b1af47034b0670be24"
|
||||
},
|
||||
"@std/bytes@0.223.0": {
|
||||
"integrity": "84b75052cd8680942c397c2631318772b295019098f40aac5c36cead4cba51a8"
|
||||
},
|
||||
"@std/bytes@1.0.2": {
|
||||
"integrity": "fbdee322bbd8c599a6af186a1603b3355e59a5fb1baa139f8f4c3c9a1b3e3d57"
|
||||
},
|
||||
"@std/cli@1.0.6": {
|
||||
"integrity": "d22d8b38c66c666d7ad1f2a66c5b122da1704f985d3c47f01129f05abb6c5d3d"
|
||||
},
|
||||
"@std/encoding@1.0.5": {
|
||||
"integrity": "ecf363d4fc25bd85bd915ff6733a7e79b67e0e7806334af15f4645c569fefc04"
|
||||
},
|
||||
"@std/fmt@0.223.0": {
|
||||
"integrity": "6deb37794127dfc7d7bded2586b9fc6f5d50e62a8134846608baf71ffc1a5208"
|
||||
},
|
||||
"@std/fmt@1.0.3": {
|
||||
"integrity": "97765c16aa32245ff4e2204ecf7d8562496a3cb8592340a80e7e554e0bb9149f"
|
||||
},
|
||||
"@std/fs@0.223.0": {
|
||||
"integrity": "3b4b0550b2c524cbaaa5a9170c90e96cbb7354e837ad1bdaf15fc9df1ae9c31c"
|
||||
},
|
||||
"@std/fs@1.0.5": {
|
||||
"integrity": "41806ad6823d0b5f275f9849a2640d87e4ef67c51ee1b8fb02426f55e02fd44e",
|
||||
"dependencies": [
|
||||
"jsr:@std/path@^1.0.7"
|
||||
]
|
||||
},
|
||||
"@std/http@1.0.9": {
|
||||
"integrity": "d409fc319a5e8d4a154e576c758752e9700282d74f31357a12fec6420f9ecb6c",
|
||||
"dependencies": [
|
||||
"jsr:@std/cli",
|
||||
"jsr:@std/encoding",
|
||||
"jsr:@std/fmt@^1.0.3",
|
||||
"jsr:@std/media-types@^1.0.3",
|
||||
"jsr:@std/net",
|
||||
"jsr:@std/path@^1.0.7",
|
||||
"jsr:@std/streams"
|
||||
]
|
||||
},
|
||||
"@std/io@0.223.0": {
|
||||
"integrity": "2d8c3c2ab3a515619b90da2c6ff5ea7b75a94383259ef4d02116b228393f84f1",
|
||||
"dependencies": [
|
||||
"jsr:@std/assert",
|
||||
"jsr:@std/bytes@0.223"
|
||||
]
|
||||
},
|
||||
"@std/media-types@1.0.3": {
|
||||
"integrity": "b12d30a7852f7578f4d210622df713bbfd1cbdd9b4ec2eaf5c1845ab70bab159"
|
||||
},
|
||||
"@std/net@1.0.4": {
|
||||
"integrity": "2f403b455ebbccf83d8a027d29c5a9e3a2452fea39bb2da7f2c04af09c8bc852"
|
||||
},
|
||||
"@std/path@0.223.0": {
|
||||
"integrity": "593963402d7e6597f5a6e620931661053572c982fc014000459edc1f93cc3989",
|
||||
"dependencies": [
|
||||
"jsr:@std/assert"
|
||||
]
|
||||
},
|
||||
"@std/path@1.0.7": {
|
||||
"integrity": "76a689e07f0e15dcc6002ec39d0866797e7156629212b28f27179b8a5c3b33a1"
|
||||
},
|
||||
"@std/streams@1.0.7": {
|
||||
"integrity": "1a93917ca0c58c01b2bfb93647189229b1702677f169b6fb61ad6241cd2e499b"
|
||||
}
|
||||
},
|
||||
"npm": {
|
||||
"@babel/helper-string-parser@7.25.9": {
|
||||
"integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA=="
|
||||
},
|
||||
"@babel/helper-validator-identifier@7.25.9": {
|
||||
"integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ=="
|
||||
},
|
||||
"@babel/parser@7.26.1": {
|
||||
"integrity": "sha512-reoQYNiAJreZNsJzyrDNzFQ+IQ5JFiIzAHJg9bn94S3l+4++J7RsIhNMoB+lgP/9tpmiAQqspv+xfdxTSzREOw==",
|
||||
"dependencies": [
|
||||
"@babel/types"
|
||||
]
|
||||
},
|
||||
"@babel/types@7.26.0": {
|
||||
"integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==",
|
||||
"dependencies": [
|
||||
"@babel/helper-string-parser",
|
||||
"@babel/helper-validator-identifier"
|
||||
]
|
||||
},
|
||||
"@jridgewell/sourcemap-codec@1.5.0": {
|
||||
"integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
|
||||
},
|
||||
"@stock3/auth-js@4.2.3": {
|
||||
"integrity": "sha512-zGtenGSxx/PVfbd9oIPPyPA9K2kOWYZ382lSNFZ2JzdB8SBVZinMP5c5s406cnxgMujTpim9lpaY/o7nUUCF1w==",
|
||||
"dependencies": [
|
||||
"bg-api-authorization"
|
||||
]
|
||||
},
|
||||
"@stock3/koala@15.3.8-esm.0_@stock3+auth-js@4.2.3_bg-auth-legacy@2.5.0_bg-status-js@2.4.3_flora-client-js@0.5.3_m-gate@2.12.8_vue@3.5.12_vue-router@4.4.5__vue@3.5.12": {
|
||||
"integrity": "sha512-7VUztN6HIRYVgUjhouR3uBlZmLcQrvt7Z2ZVidb5DvSPRFtpYxGq65fqpovR+8O8k3d8BWs338Vc9sdPBYEV4A==",
|
||||
"dependencies": [
|
||||
"@stock3/auth-js",
|
||||
"bg-auth-legacy",
|
||||
"bg-status-js",
|
||||
"flora-client-js",
|
||||
"m-gate",
|
||||
"vue",
|
||||
"vue-router"
|
||||
]
|
||||
},
|
||||
"@types/node@22.5.4": {
|
||||
"integrity": "sha512-FDuKUJQm/ju9fT/SeX/6+gBzoPzlVCzfzmGkwKvRHQVxi4BntVbyIwf6a4Xn62mrvndLiml6z/UBXIdEVjQLXg==",
|
||||
"dependencies": [
|
||||
"undici-types"
|
||||
]
|
||||
},
|
||||
"@vue/compiler-core@3.5.12": {
|
||||
"integrity": "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==",
|
||||
"dependencies": [
|
||||
"@babel/parser",
|
||||
"@vue/shared",
|
||||
"entities",
|
||||
"estree-walker",
|
||||
"source-map-js"
|
||||
]
|
||||
},
|
||||
"@vue/compiler-dom@3.5.12": {
|
||||
"integrity": "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==",
|
||||
"dependencies": [
|
||||
"@vue/compiler-core",
|
||||
"@vue/shared"
|
||||
]
|
||||
},
|
||||
"@vue/compiler-sfc@3.5.12": {
|
||||
"integrity": "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw==",
|
||||
"dependencies": [
|
||||
"@babel/parser",
|
||||
"@vue/compiler-core",
|
||||
"@vue/compiler-dom",
|
||||
"@vue/compiler-ssr",
|
||||
"@vue/shared",
|
||||
"estree-walker",
|
||||
"magic-string",
|
||||
"postcss",
|
||||
"source-map-js"
|
||||
]
|
||||
},
|
||||
"@vue/compiler-ssr@3.5.12": {
|
||||
"integrity": "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA==",
|
||||
"dependencies": [
|
||||
"@vue/compiler-dom",
|
||||
"@vue/shared"
|
||||
]
|
||||
},
|
||||
"@vue/devtools-api@6.6.4": {
|
||||
"integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g=="
|
||||
},
|
||||
"@vue/reactivity@3.5.12": {
|
||||
"integrity": "sha512-UzaN3Da7xnJXdz4Okb/BGbAaomRHc3RdoWqTzlvd9+WBR5m3J39J1fGcHes7U3za0ruYn/iYy/a1euhMEHvTAg==",
|
||||
"dependencies": [
|
||||
"@vue/shared"
|
||||
]
|
||||
},
|
||||
"@vue/runtime-core@3.5.12": {
|
||||
"integrity": "sha512-hrMUYV6tpocr3TL3Ad8DqxOdpDe4zuQY4HPY3X/VRh+L2myQO8MFXPAMarIOSGNu0bFAjh1yBkMPXZBqCk62Uw==",
|
||||
"dependencies": [
|
||||
"@vue/reactivity",
|
||||
"@vue/shared"
|
||||
]
|
||||
},
|
||||
"@vue/runtime-dom@3.5.12": {
|
||||
"integrity": "sha512-q8VFxR9A2MRfBr6/55Q3umyoN7ya836FzRXajPB6/Vvuv0zOPL+qltd9rIMzG/DbRLAIlREmnLsplEF/kotXKA==",
|
||||
"dependencies": [
|
||||
"@vue/reactivity",
|
||||
"@vue/runtime-core",
|
||||
"@vue/shared",
|
||||
"csstype"
|
||||
]
|
||||
},
|
||||
"@vue/server-renderer@3.5.12_vue@3.5.12": {
|
||||
"integrity": "sha512-I3QoeDDeEPZm8yR28JtY+rk880Oqmj43hreIBVTicisFTx/Dl7JpG72g/X7YF8hnQD3IFhkky5i2bPonwrTVPg==",
|
||||
"dependencies": [
|
||||
"@vue/compiler-ssr",
|
||||
"@vue/shared",
|
||||
"vue"
|
||||
]
|
||||
},
|
||||
"@vue/shared@3.5.12": {
|
||||
"integrity": "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg=="
|
||||
},
|
||||
"bg-api-authorization@2.0.0": {
|
||||
"integrity": "sha512-eo4lPdyktT3S2i6Ef+1drJuHku3NyvhLzM3JNkRsS70v+0J7C2jrsGQAXTVLnaJ5V+tC51g8C6BoanwQxi//8Q=="
|
||||
},
|
||||
"bg-auth-legacy@2.5.0": {
|
||||
"integrity": "sha512-+V1vVpUDrMJB1s8CcOak4yXBXbz3oejQ16GqKyuRrqy9e43VLozaHl/Xmsj1TCm2TrB7Ha2rExnk7VLbcjFU6w=="
|
||||
},
|
||||
"bg-status-js@2.4.3": {
|
||||
"integrity": "sha512-Ys0rGJGDZuPAfnYhTqwndRtZYxhmGopDZ2t42OGgJXnYxaZT1dDaKV56tXf75tMO9+y0PIOewP6kEgkkSccN1g=="
|
||||
},
|
||||
"csstype@3.1.3": {
|
||||
"integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
|
||||
},
|
||||
"entities@4.5.0": {
|
||||
"integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw=="
|
||||
},
|
||||
"estree-walker@2.0.2": {
|
||||
"integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
|
||||
},
|
||||
"flora-client-js@0.5.3": {
|
||||
"integrity": "sha512-00CHCjfIDxo+/ROQkHGqS+9mzhGVmdEMErmwBg7roYD4gIKNjDgFJgYoDB8V1VmTeK4LFaPm2B1du1iMxgY8sQ==",
|
||||
"dependencies": [
|
||||
"has"
|
||||
]
|
||||
},
|
||||
"has@1.0.4": {
|
||||
"integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ=="
|
||||
},
|
||||
"m-gate@2.12.8": {
|
||||
"integrity": "sha512-QAyDRBBYFx6k+WoVMpGwWFf2Z554LMNfF6yVmqW92FgP5hx9qUQypWZPl9P2XEw3Htlv/rBVQ9q9n+uBcx6yEg=="
|
||||
},
|
||||
"magic-string@0.30.12": {
|
||||
"integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==",
|
||||
"dependencies": [
|
||||
"@jridgewell/sourcemap-codec"
|
||||
]
|
||||
},
|
||||
"nanoid@3.3.7": {
|
||||
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g=="
|
||||
},
|
||||
"picocolors@1.1.1": {
|
||||
"integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
|
||||
},
|
||||
"postcss@8.4.47": {
|
||||
"integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
|
||||
"dependencies": [
|
||||
"nanoid",
|
||||
"picocolors",
|
||||
"source-map-js"
|
||||
]
|
||||
},
|
||||
"source-map-js@1.2.1": {
|
||||
"integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA=="
|
||||
},
|
||||
"undici-types@6.19.8": {
|
||||
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw=="
|
||||
},
|
||||
"vue-router@4.4.5_vue@3.5.12": {
|
||||
"integrity": "sha512-4fKZygS8cH1yCyuabAXGUAsyi1b2/o/OKgu/RUb+znIYOxPRxdkytJEx+0wGcpBE1pX6vUgh5jwWOKRGvuA/7Q==",
|
||||
"dependencies": [
|
||||
"@vue/devtools-api",
|
||||
"vue"
|
||||
]
|
||||
},
|
||||
"vue@3.5.12": {
|
||||
"integrity": "sha512-CLVZtXtn2ItBIi/zHZ0Sg1Xkb7+PU32bJJ8Bmy7ts3jxXTcbfsEfBivFYYWz1Hur+lalqGAh65Coin0r+HRUfg==",
|
||||
"dependencies": [
|
||||
"@vue/compiler-dom",
|
||||
"@vue/compiler-sfc",
|
||||
"@vue/runtime-dom",
|
||||
"@vue/server-renderer",
|
||||
"@vue/shared"
|
||||
]
|
||||
}
|
||||
},
|
||||
"workspace": {
|
||||
"dependencies": [
|
||||
"npm:@stock3/koala@^15.3.8-esm.0",
|
||||
"npm:vue@*",
|
||||
"npm:vue@^3.5.12"
|
||||
]
|
||||
}
|
||||
}
|
||||
5
deps.ts
Normal file
5
deps.ts
Normal file
@@ -0,0 +1,5 @@
|
||||
import "jsr:@deno/emit";
|
||||
import "jsr:@std/media-types";
|
||||
import "jsr:@std/http";
|
||||
import "vue";
|
||||
import "@stock3/koala";
|
||||
42
main.ts
Normal file
42
main.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
import { serveFile } from "jsr:@std/http/file-server";
|
||||
import { createSSRApp } from "vue";
|
||||
import { renderToString } from "vue/server-renderer";
|
||||
import App from "@/App.tsx";
|
||||
import transpileResponse from './transpileTs.ts';
|
||||
|
||||
const utf8Decoder = new TextDecoder("utf-8");
|
||||
|
||||
Deno.serve({
|
||||
port: 8080,
|
||||
hostname: "0.0.0.0",
|
||||
onListen({ port, hostname }) {
|
||||
console.log(`Listening on port http://${hostname}:${port}/`);
|
||||
},
|
||||
}, async (req, _conn) => {
|
||||
if (req.method === "GET") {
|
||||
const pathname = URL.parse(req.url)?.pathname ?? "/";
|
||||
if (pathname === "/") {
|
||||
const rendered = await renderToString(createSSRApp(App));
|
||||
const content = utf8Decoder.decode(await Deno.readFile("./playground/index.html"))
|
||||
.replace(`<!-- SSR OUTLET -->`, rendered)
|
||||
.replace(`<!-- SSR HEAD OUTLET -->`, '');
|
||||
return new Response(content, { headers: { "Content-Type": "text/html" } });
|
||||
} else if (pathname === "/health") {
|
||||
return new Response("OK");
|
||||
} else if (pathname.startsWith('/app') && (pathname.endsWith('.ts') || pathname.endsWith('.tsx'))) {
|
||||
const response = await serveFile(req, './' + pathname);
|
||||
return await transpileResponse(response, req.url, pathname);
|
||||
} else if (pathname.startsWith('/deps')) {
|
||||
return serveFile(req, `node_modules/${pathname.split('/deps')[1]}`);
|
||||
} else {
|
||||
return serveFile(req, `playground${pathname}`);
|
||||
}
|
||||
} else {
|
||||
return new Response("Only GET allowed.", { status: 500 });
|
||||
}
|
||||
});
|
||||
|
||||
Deno.addSignalListener("SIGINT", () => {
|
||||
console.info("Shutting down (received SIGINT)");
|
||||
Deno.exit();
|
||||
});
|
||||
4
public/app.js
Normal file
4
public/app.js
Normal file
@@ -0,0 +1,4 @@
|
||||
import { createSSRApp } from "vue";
|
||||
import App from "@/App.tsx";
|
||||
|
||||
createSSRApp(App).mount('#app-root');
|
||||
BIN
public/icon.webp
Normal file
BIN
public/icon.webp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 23 KiB |
BIN
public/image.jpeg
Normal file
BIN
public/image.jpeg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 9.7 KiB |
27
public/index.html
Normal file
27
public/index.html
Normal file
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<title>G'day</title>
|
||||
<link rel="icon" href="icon.webp" />
|
||||
<link rel="stylesheet" href="styles.css" />
|
||||
<script type="importmap">
|
||||
{
|
||||
"imports": {
|
||||
"vue": "/deps/vue/dist/vue.esm-browser.js",
|
||||
"vue/jsx-runtime": "/deps/vue/jsx-runtime/index.mjs",
|
||||
"@/": "/app/"
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<script type="module" src="app.js"></script>
|
||||
<!-- SSR HEAD OUTLET -->
|
||||
</head>
|
||||
<body>
|
||||
<main class="container">
|
||||
<h1>G'day, mate!</h1>
|
||||
<h2>Willkommen auf Daniels Spielwiese</h2>
|
||||
<img src="image.jpeg" alt="KANGAROO" />
|
||||
<div id="app-root"><!-- SSR OUTLET --></div>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
22
public/styles.css
Normal file
22
public/styles.css
Normal file
@@ -0,0 +1,22 @@
|
||||
.container {
|
||||
margin: auto;
|
||||
text-align: center;
|
||||
width: 100%;
|
||||
background-color: #fffafa;
|
||||
box-shadow: #000000;
|
||||
padding-top: 10px;
|
||||
min-height: calc(100vh - 10px);
|
||||
box-shadow: 0px 0px 12px rgba(0, 0, 0, 0.2);
|
||||
|
||||
@media (min-width: 992px) {
|
||||
width: 900px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
|
||||
body {
|
||||
margin: 0;
|
||||
}
|
||||
80
transpileTs.ts
Normal file
80
transpileTs.ts
Normal file
@@ -0,0 +1,80 @@
|
||||
import { contentType } from "jsr:@std/media-types";
|
||||
import { transpile } from "jsr:@deno/emit";
|
||||
import config from "./deno.json" with { type: "json" };
|
||||
|
||||
const jsContentType = contentType(".js");
|
||||
|
||||
export enum MediaType {
|
||||
TypeScript,
|
||||
JSX,
|
||||
TSX,
|
||||
};
|
||||
|
||||
// https://github.com/denoland/deno_ast/blob/ea1ccec37e1aa8e5e1e70f983a7ed1472d0e132a/src/media_type.rs#L117
|
||||
const customContentType = {
|
||||
[MediaType.TypeScript]: "text/typescript; charset=utf-8",
|
||||
[MediaType.JSX]: "text/jsx; charset=utf-8",
|
||||
[MediaType.TSX]: "text/tsx; charset=utf-8",
|
||||
};
|
||||
|
||||
async function rewriteTsResponse(response: Response, url: URL, mediaType: MediaType) {
|
||||
const tsCode = await response.text();
|
||||
const targetUrlStr = url.toString();
|
||||
try {
|
||||
const result = await transpile(url, {
|
||||
importMap: config,
|
||||
compilerOptions: config.compilerOptions,
|
||||
load(specifier) {
|
||||
if (specifier !== targetUrlStr) {
|
||||
return Promise.resolve({
|
||||
kind: "module",
|
||||
specifier,
|
||||
content: "",
|
||||
headers: { "content-type": "application/javascript; charset=utf-8" },
|
||||
});
|
||||
} else {
|
||||
return Promise.resolve({
|
||||
kind: "module",
|
||||
specifier,
|
||||
content: tsCode,
|
||||
headers: {
|
||||
"content-type": customContentType[mediaType],
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
});
|
||||
const jsCode = result.get(targetUrlStr);
|
||||
const { headers } = response;
|
||||
headers.set("content-type", jsContentType);
|
||||
headers.delete("content-length");
|
||||
|
||||
return new Response(jsCode, {
|
||||
status: response.status,
|
||||
statusText: response.statusText,
|
||||
headers,
|
||||
});
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
return new Response(`${e}`, {
|
||||
status: 500,
|
||||
statusText: `${e}`,
|
||||
headers: response.headers,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
export default async function transpileResponse(response: Response, requestUrl: string, filepath?: string): Promise<Response> {
|
||||
const url = new URL(`ts-serve:///${ requestUrl }`);
|
||||
if (response.status !== 200) {
|
||||
return response;
|
||||
}
|
||||
const pathname = filepath !== undefined ? filepath : url.pathname;
|
||||
const extension = pathname.split('.').at(-1) ?? null;
|
||||
switch (extension) {
|
||||
case 'ts': return await rewriteTsResponse(response, url, MediaType.TypeScript);
|
||||
case 'tsx': return await rewriteTsResponse(response, url, MediaType.TSX);
|
||||
case 'jsx': return await rewriteTsResponse(response, url, MediaType.JSX);
|
||||
default: return response;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user