diff --git a/.dockerignore b/.dockerignore index 62d0536e..6c9d86bd 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,5 +1,6 @@ * +!/lib/** !/src/** !/.npmrc !/deno.json @@ -8,3 +9,4 @@ !/mise.toml !/package.json !/rolldown.config.ts +!/tsconfig.json \ No newline at end of file diff --git a/.gitignore b/.gitignore index 8abd6b55..e1a4075e 100644 --- a/.gitignore +++ b/.gitignore @@ -5,6 +5,8 @@ !/.github/workflows/*.yml !/.zed/ !/.zed/settings.json +!/lib/ +!/lib/** !/src/ !/src/** !/.dockerignore @@ -23,3 +25,4 @@ !/package.json !/README.md !/rolldown.config.ts +!/tsconfig.json \ No newline at end of file diff --git a/.npmrc b/.npmrc deleted file mode 100644 index 41583e36..00000000 --- a/.npmrc +++ /dev/null @@ -1 +0,0 @@ -@jsr:registry=https://npm.jsr.io diff --git a/deno.json b/deno.json index 5e1ae0f3..0687cade 100644 --- a/deno.json +++ b/deno.json @@ -4,43 +4,38 @@ "lock": true, "nodeModulesDir": "manual", "unstable": ["cron", "temporal", "raw-imports"], - "compilerOptions": { - "lib": ["deno.window", "deno.unstable"], - "types": ["node"], - "module": "esnext", - "moduleResolution": "bundler", - - "checkJs": false, - "skipLibCheck": true, - - "strict": true, - "allowUnreachableCode": false, - "allowUnusedLabels": false, - "exactOptionalPropertyTypes": false, - "isolatedDeclarations": false, - "noErrorTruncation": false, - "noFallthroughCasesInSwitch": true, - "noImplicitAny": true, - "noImplicitOverride": true, - "noImplicitReturns": true, - "noImplicitThis": true, - "noPropertyAccessFromIndexSignature": false, - "noUncheckedIndexedAccess": true, - "noUnusedLocals": true, - "noUnusedParameters": true, - "useUnknownInCatchVariables": true, - "verbatimModuleSyntax": true, - - "baseUrl": ".", - "paths": { - "#/*": ["./src/*"], - "#db/*": ["./src/database/*"], - "#document/*": ["./src/document/*"], - "#endpoint/*": ["./src/endpoints/*"], - "#http/*": ["./src/http/*"], - "#task/*": ["./src/tasks/*"], - "#util/*": ["./src/utils/*"] - } + "allowScripts": [], + "imports": { + "#/": "./src/", + "#db/": "./src/database/", + "#document/": "./src/document/", + "#endpoint/": "./src/endpoints/", + "#http/": "./src/http/", + "#task/": "./src/tasks/", + "#util/": "./src/utils/", + "@deno/loader": "jsr:@deno/loader@~0.3.11", + "@hono/hono": "jsr:@hono/hono@^4.11.4", + "@hono/openapi": "npm:hono-openapi@^1.1.2", + "@hono/standard-validator": "jsr:@hono/standard-validator@~0.2.2", + "@std/assert": "jsr:@std/assert@^1.0.16", + "@std/async": "jsr:@std/async@^1.0.16", + "@std/cache": "jsr:@std/cache@~0.2.1", + "@std/collections": "jsr:@std/collections@^1.1.3", + "@std/dotenv": "jsr:@std/dotenv@~0.225.6", + "@std/encoding": "jsr:@std/encoding@^1.0.10", + "@std/fmt": "jsr:@std/fmt@^1.0.8", + "@std/fs": "jsr:@std/fs@^1.0.21", + "@std/path": "jsr:@std/path@^1.1.4", + "@std/streams": "jsr:@std/streams@^1.0.16", + "@std/ulid": "jsr:@std/ulid@^1.0.0", + "@types/node": "npm:@types/node@^25.0.8", + "arkenv": "npm:arkenv@~0.8.3", + "arktype": "npm:arktype@^2.1.29", + "biome": "npm:@biomejs/biome@2.3.11", + "hash-wasm": "npm:hash-wasm@^4.12.0", + "nanoid": "jsr:@sitnik/nanoid@^5.1.5", + "rolldown": "npm:rolldown@1.0.0-beta.60", + "vite-bundle-analyzer": "npm:vite-bundle-analyzer@^1.3.2" }, "fmt": { "exclude": ["**"] @@ -48,6 +43,5 @@ "lint": { "exclude": ["**"] }, - "exclude": ["./dist/", "./node_modules/", "./storage/"], - "allowScripts": [] + "exclude": ["./dist/", "./node_modules/", "./storage/"] } diff --git a/deno.lock b/deno.lock index 8761d376..dc73d2ab 100644 --- a/deno.lock +++ b/deno.lock @@ -1,28 +1,107 @@ { "version": "5", "specifiers": { + "jsr:@deno/loader@~0.3.11": "0.3.11", + "jsr:@hono/hono@^4.11.4": "4.11.4", + "jsr:@hono/hono@^4.8.3": "4.11.4", + "jsr:@hono/standard-validator@~0.2.2": "0.2.2", + "jsr:@sitnik/nanoid@^5.1.5": "5.1.5", + "jsr:@standard-schema/spec@1": "1.1.0", + "jsr:@std/assert@^1.0.16": "1.0.16", + "jsr:@std/async@^1.0.16": "1.0.16", + "jsr:@std/bytes@^1.0.6": "1.0.6", + "jsr:@std/cache@~0.2.1": "0.2.1", + "jsr:@std/collections@^1.1.3": "1.1.3", + "jsr:@std/dotenv@~0.225.6": "0.225.6", + "jsr:@std/encoding@^1.0.10": "1.0.10", + "jsr:@std/fmt@^1.0.8": "1.0.8", + "jsr:@std/fs@^1.0.21": "1.0.21", + "jsr:@std/internal@^1.0.12": "1.0.12", + "jsr:@std/path@^1.1.4": "1.1.4", + "jsr:@std/streams@^1.0.16": "1.0.16", + "jsr:@std/ulid@1": "1.0.0", "npm:@biomejs/biome@2.3.11": "2.3.11", - "npm:@jsr/hono__hono@^4.11.4": "4.11.4", - "npm:@jsr/hono__standard-validator@~0.2.2": "0.2.2", - "npm:@jsr/std__assert@^1.0.16": "1.0.16", - "npm:@jsr/std__async@^1.0.16": "1.0.16", - "npm:@jsr/std__cache@~0.2.1": "0.2.1", - "npm:@jsr/std__collections@^1.1.3": "1.1.3", - "npm:@jsr/std__dotenv@~0.225.6": "0.225.6", - "npm:@jsr/std__encoding@^1.0.10": "1.0.10", - "npm:@jsr/std__fmt@^1.0.8": "1.0.8", - "npm:@jsr/std__fs@^1.0.21": "1.0.21", - "npm:@jsr/std__streams@^1.0.16": "1.0.16", - "npm:@jsr/std__ulid@1": "1.0.0", "npm:@types/node@^25.0.8": "25.0.8", "npm:arkenv@~0.8.3": "0.8.3_arktype@2.1.29", "npm:arktype@^2.1.29": "2.1.29", "npm:hash-wasm@^4.12.0": "4.12.0", "npm:hono-openapi@^1.1.2": "1.1.2_@standard-community+standard-json@0.3.5__@standard-schema+spec@1.1.0__@types+json-schema@7.0.15__arktype@2.1.29__quansync@0.2.11_@standard-community+standard-openapi@0.2.9__@standard-community+standard-json@0.3.5___@standard-schema+spec@1.1.0___@types+json-schema@7.0.15___arktype@2.1.29___quansync@0.2.11__@standard-schema+spec@1.1.0__arktype@2.1.29__openapi-types@12.1.3__@types+json-schema@7.0.15_@types+json-schema@7.0.15_openapi-types@12.1.3_arktype@2.1.29", - "npm:nanoid@^5.1.6": "5.1.6", "npm:rolldown@1.0.0-beta.60": "1.0.0-beta.60", "npm:vite-bundle-analyzer@^1.3.2": "1.3.2" }, + "jsr": { + "@deno/loader@0.3.11": { + "integrity": "7c62f4f09cdfc34e66ba25b5a775a1830cbb5266b3e39f67b0f620c75484df8d" + }, + "@hono/hono@4.11.4": { + "integrity": "aaf7b9d5a6b2422b0778c091b712ee1f018bc7e82138067d21eb27d7c2e1f5be" + }, + "@hono/standard-validator@0.2.2": { + "integrity": "bc94e1ab41d677a571cb6dd5012823f1162b9856ca24dfd60233734824bb0b0c", + "dependencies": [ + "jsr:@hono/hono@^4.8.3", + "jsr:@standard-schema/spec" + ] + }, + "@sitnik/nanoid@5.1.5": { + "integrity": "55bd5f57087d67b1dcb7c1f4a07efdfe77a3ac57ca0af90f162c1f676ebf8f4b" + }, + "@standard-schema/spec@1.1.0": { + "integrity": "2ccd54513cd9c960bd155ab569b1a901bc99c6f9ad29559d3f38a28c91c1822d" + }, + "@std/assert@1.0.16": { + "integrity": "6a7272ed1eaa77defe76e5ff63ca705d9c495077e2d5fd0126d2b53fc5bd6532", + "dependencies": [ + "jsr:@std/internal" + ] + }, + "@std/async@1.0.16": { + "integrity": "6c9e43035313b67b5de43e2b3ee3eadb39a488a0a0a3143097f112e025d3ee9a" + }, + "@std/bytes@1.0.6": { + "integrity": "f6ac6adbd8ccd99314045f5703e23af0a68d7f7e58364b47d2c7f408aeb5820a" + }, + "@std/cache@0.2.1": { + "integrity": "b6f1abfd118d35b1c4ca90f2b3f4c709a2014ae368f244bdc7533bf1c169d759" + }, + "@std/collections@1.1.3": { + "integrity": "bf8b0818886df6a32b64c7d3b037a425111f28278d69fd0995aeb62777c986b0" + }, + "@std/dotenv@0.225.6": { + "integrity": "1d6f9db72f565bd26790fa034c26e45ecb260b5245417be76c2279e5734c421b" + }, + "@std/encoding@1.0.10": { + "integrity": "8783c6384a2d13abd5e9e87a7ae0520a30e9f56aeeaa3bdf910a3eaaf5c811a1" + }, + "@std/fmt@1.0.8": { + "integrity": "71e1fc498787e4434d213647a6e43e794af4fd393ef8f52062246e06f7e372b7" + }, + "@std/fs@1.0.21": { + "integrity": "d720fe1056d78d43065a4d6e0eeb2b19f34adb8a0bc7caf3a4dbf1d4178252cd", + "dependencies": [ + "jsr:@std/internal", + "jsr:@std/path" + ] + }, + "@std/internal@1.0.12": { + "integrity": "972a634fd5bc34b242024402972cd5143eac68d8dffaca5eaa4dba30ce17b027" + }, + "@std/path@1.1.4": { + "integrity": "1d2d43f39efb1b42f0b1882a25486647cb851481862dc7313390b2bb044314b5", + "dependencies": [ + "jsr:@std/internal" + ] + }, + "@std/streams@1.0.16": { + "integrity": "85030627befb1767c60d4f65cb30fa2f94af1d6ee6e5b2515b76157a542e89c4", + "dependencies": [ + "jsr:@std/bytes" + ] + }, + "@std/ulid@1.0.0": { + "integrity": "d41c3d27a907714413649fee864b7cde8d42ee68437d22b79d5de4f81d808780" + } + }, "npm": { "@ark/schema@0.56.0": { "integrity": "sha512-ECg3hox/6Z/nLajxXqNhgPtNdHWC9zNsDyskwO28WinoFEnWow4IsERNz9AnXRhTZJnYIlAJ4uGn3nlLk65vZA==", @@ -106,87 +185,6 @@ "tslib" ] }, - "@jsr/hono__hono@4.11.4": { - "integrity": "sha512-GdHrXgX+q2Q9LCse3RVXo5vmg8wJDlQoavZVXW3eXN9bczlzdkWBiy712FELfRdLZ0ij16BDQM5nkcc86O/fwg==", - "tarball": "https://npm.jsr.io/~/11/@jsr/hono__hono/4.11.4.tgz" - }, - "@jsr/hono__standard-validator@0.2.2": { - "integrity": "sha512-BXapiKtKoY63PuQlxs/dYmCcqWkwpOUi7yKfwZyHdBhuW9WtII/C5QDx6kimzXShG/e/Jk7U5aAtnlUeDpgUmA==", - "dependencies": [ - "@jsr/hono__hono", - "@jsr/standard-schema__spec" - ], - "tarball": "https://npm.jsr.io/~/11/@jsr/hono__standard-validator/0.2.2.tgz" - }, - "@jsr/standard-schema__spec@1.1.0": { - "integrity": "sha512-mWncLgOE1ZVd/xXG+SPmmDmYPQ9Q3OcIbkCn/3oPpp4WOw3RpbHWdxk/jiG8m4Bd9utE2b1yyfynSStpuhdXew==", - "tarball": "https://npm.jsr.io/~/11/@jsr/standard-schema__spec/1.1.0.tgz" - }, - "@jsr/std__assert@1.0.16": { - "integrity": "sha512-bX9ih0nR1kQ12/cnQRCQU0ppTCV7MFkP0qjyWxJRoDI8RC5cpTAmLFH/KcFgxmdN4flKkRbub8VtLuyKq+4OxA==", - "dependencies": [ - "@jsr/std__internal" - ], - "tarball": "https://npm.jsr.io/~/11/@jsr/std__assert/1.0.16.tgz" - }, - "@jsr/std__async@1.0.16": { - "integrity": "sha512-WoYmNEPSh+Bs09HvVceERknVX813wQjSb2D9Z0KdxGTMYl5Pm13e5xqa3mYu9QBRlxIxpTivGhIQYaslEezrhw==", - "tarball": "https://npm.jsr.io/~/11/@jsr/std__async/1.0.16.tgz" - }, - "@jsr/std__bytes@1.0.6": { - "integrity": "sha512-St6yKggjFGhxS52IFLJWvkchRFbAKg2Xh8UxA4S1EGz7GJ2Ui+ssDDldj/w2c8vCxvl6qgR0HaYbKeFJNqujmA==", - "tarball": "https://npm.jsr.io/~/11/@jsr/std__bytes/1.0.6.tgz" - }, - "@jsr/std__cache@0.2.1": { - "integrity": "sha512-K4qXWEOWiwo04zyJNxBogPdoXHcmmKjX+O8aKFEbVAd22/AiD9JFK25ZQ85/jCRZu+tDq99mSUz4x8NKqLsISQ==", - "tarball": "https://npm.jsr.io/~/11/@jsr/std__cache/0.2.1.tgz" - }, - "@jsr/std__collections@1.1.3": { - "integrity": "sha512-jGG6mv3IjOyxm6PyT1YVbLyAlZL+Gow6LOpBw+84qb1nkdJY0+t6bi7ICEqAwUz87cNjBS0P+yZQ5HHclJhsfw==", - "tarball": "https://npm.jsr.io/~/11/@jsr/std__collections/1.1.3.tgz" - }, - "@jsr/std__dotenv@0.225.6": { - "integrity": "sha512-rqh5RrHccbyzmP4v1/vqUyYy4dqopjTRgW8bJqk2ZXTKBbvpmMjPxJ+xy+YAk6XnEvtPCPAgqbFhHWcomjnX+w==", - "tarball": "https://npm.jsr.io/~/11/@jsr/std__dotenv/0.225.6.tgz" - }, - "@jsr/std__encoding@1.0.10": { - "integrity": "sha512-WK2njnDTyKefroRNk2Ooq7GStp6Y0ccAvr4To+Z/zecRAGe7+OSvH9DbiaHpAKwEi2KQbmpWMOYsdNt+TsdmSw==", - "tarball": "https://npm.jsr.io/~/11/@jsr/std__encoding/1.0.10.tgz" - }, - "@jsr/std__fmt@1.0.8": { - "integrity": "sha512-miZHzj9OgjuajrcMKzpqNVwFb9O71UHZzV/FHVq0E0Uwmv/1JqXgmXAoBNPrn+MP0fHT3mMgaZ6XvQO7dam67Q==", - "tarball": "https://npm.jsr.io/~/11/@jsr/std__fmt/1.0.8.tgz" - }, - "@jsr/std__fs@1.0.21": { - "integrity": "sha512-k/agrcKGm6KD89ci3AEyRmu3wRWf9JZNliOF4ZUxagTHiySmxjiKU3Lk+d2ksRtwEi7oWlLGS0AVM9Lciwc/xg==", - "dependencies": [ - "@jsr/std__internal", - "@jsr/std__path" - ], - "tarball": "https://npm.jsr.io/~/11/@jsr/std__fs/1.0.21.tgz" - }, - "@jsr/std__internal@1.0.12": { - "integrity": "sha512-6xReMW9p+paJgqoFRpOE2nogJFvzPfaLHLIlyADYjKMUcwDyjKZxryIbgcU+gxiTygn8yCjld1HoI0ET4/iZeA==", - "tarball": "https://npm.jsr.io/~/11/@jsr/std__internal/1.0.12.tgz" - }, - "@jsr/std__path@1.1.4": { - "integrity": "sha512-SK4u9H6NVTfolhPdlvdYXfNFefy1W04AEHWJydryYbk+xqzNiVmr5o7TLJLJFqwHXuwMRhwrn+mcYeUfS0YFaA==", - "dependencies": [ - "@jsr/std__internal" - ], - "tarball": "https://npm.jsr.io/~/11/@jsr/std__path/1.1.4.tgz" - }, - "@jsr/std__streams@1.0.16": { - "integrity": "sha512-8vQHEDIpAr5m9upZEcF1UO2ylZCJsOs5mlsXaJNehQmSm8Iiz/XaKtb73Fh6fj8Ybc2jNw2zyi9CLfqd3Ph6mA==", - "dependencies": [ - "@jsr/std__bytes" - ], - "tarball": "https://npm.jsr.io/~/11/@jsr/std__streams/1.0.16.tgz" - }, - "@jsr/std__ulid@1.0.0": { - "integrity": "sha512-RvVolUwRoFtoSuYZROBmhCYEIuI4xsxeHjGGbJQZVDCBnDBJwfm16vOJyE1Va9+BnTl1iW7o1nCloBI+EQAWVg==", - "tarball": "https://npm.jsr.io/~/11/@jsr/std__ulid/1.0.0.tgz" - }, "@napi-rs/wasm-runtime@1.1.1": { "integrity": "sha512-p64ah1M1ld8xjWv3qbvFwHiFVWrq1yFvV4f7w+mzaqiR4IlSgkqhcRdHwsGgomwzBH51sRY4NEowLxnaBjcW/A==", "dependencies": [ @@ -342,10 +340,6 @@ "openapi-types" ] }, - "nanoid@5.1.6": { - "integrity": "sha512-c7+7RQ+dMB5dPwwCp4ee1/iV/q2P6aK1mTZcfr1BTuVlyW9hJYiMPybJCcnBlQtuSmTIWNeazm/zqNoZSSElBg==", - "bin": true - }, "openapi-types@12.1.3": { "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==" }, @@ -387,30 +381,30 @@ } }, "workspace": { - "packageJson": { - "dependencies": [ - "npm:@biomejs/biome@2.3.11", - "npm:@jsr/hono__hono@^4.11.4", - "npm:@jsr/hono__standard-validator@~0.2.2", - "npm:@jsr/std__assert@^1.0.16", - "npm:@jsr/std__async@^1.0.16", - "npm:@jsr/std__cache@~0.2.1", - "npm:@jsr/std__collections@^1.1.3", - "npm:@jsr/std__dotenv@~0.225.6", - "npm:@jsr/std__encoding@^1.0.10", - "npm:@jsr/std__fmt@^1.0.8", - "npm:@jsr/std__fs@^1.0.21", - "npm:@jsr/std__streams@^1.0.16", - "npm:@jsr/std__ulid@1", - "npm:@types/node@^25.0.8", - "npm:arkenv@~0.8.3", - "npm:arktype@^2.1.29", - "npm:hash-wasm@^4.12.0", - "npm:hono-openapi@^1.1.2", - "npm:nanoid@^5.1.6", - "npm:rolldown@1.0.0-beta.60", - "npm:vite-bundle-analyzer@^1.3.2" - ] - } + "dependencies": [ + "jsr:@deno/loader@~0.3.11", + "jsr:@hono/hono@^4.11.4", + "jsr:@hono/standard-validator@~0.2.2", + "jsr:@sitnik/nanoid@^5.1.5", + "jsr:@std/assert@^1.0.16", + "jsr:@std/async@^1.0.16", + "jsr:@std/cache@~0.2.1", + "jsr:@std/collections@^1.1.3", + "jsr:@std/dotenv@~0.225.6", + "jsr:@std/encoding@^1.0.10", + "jsr:@std/fmt@^1.0.8", + "jsr:@std/fs@^1.0.21", + "jsr:@std/path@^1.1.4", + "jsr:@std/streams@^1.0.16", + "jsr:@std/ulid@1", + "npm:@biomejs/biome@2.3.11", + "npm:@types/node@^25.0.8", + "npm:arkenv@~0.8.3", + "npm:arktype@^2.1.29", + "npm:hash-wasm@^4.12.0", + "npm:hono-openapi@^1.1.2", + "npm:rolldown@1.0.0-beta.60", + "npm:vite-bundle-analyzer@^1.3.2" + ] } } diff --git a/lib/deno-rolldown/LICENSE b/lib/deno-rolldown/LICENSE new file mode 100644 index 00000000..24295035 --- /dev/null +++ b/lib/deno-rolldown/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2018-2025 the Deno authors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/lib/deno-rolldown/mod.ts b/lib/deno-rolldown/mod.ts new file mode 100644 index 00000000..abd0256f --- /dev/null +++ b/lib/deno-rolldown/mod.ts @@ -0,0 +1,240 @@ +// biome-ignore-all lint: vibecode +// based on: https://github.com/denoland/deno-rolldown-plugin + +import { + type Loader, + type LoadResponse, + MediaType, + RequestedModuleType, + ResolutionMode, + Workspace, + type WorkspaceOptions +} from "@deno/loader"; +import { fromFileUrl } from "@std/path"; + +const MARegex = /.*/; + +type Module = { + specifier: string; + code: string; +}; + +/** Options for creating the Deno plugin. */ +export interface DenoPluginOptions extends WorkspaceOptions { + /** Entry points for the build (optional, can be provided in buildStart) */ + entrypoints?: string[]; + /** + * Patterns to treat as external when Deno loader can't resolve them. + * Useful for npm packages that should remain external. + */ + externalPatterns?: (string | RegExp)[]; +} + +export type BuildStartOptions = { + input?: string | string[] | Record; +}; + +export type ResolveIdOptions = { + kind: "import-statement" | "dynamic-import" | "require-call"; +}; + +export interface DenoPlugin extends Disposable { + name: string; + buildStart(options?: BuildStartOptions): Promise; + resolveId: { + filter: { id: RegExp }; + handler( + source: string, + importer: string | undefined, + options: ResolveIdOptions + ): Promise; + }; + load: { + filter: { id: RegExp }; + handler(id: string): string | undefined; + }; +} + +/** + * Creates a deno plugin for use with rolldown. + * @returns The plugin. + */ +export default function denoPlugin(pluginOptions: DenoPluginOptions = {}): DenoPlugin { + let loader: Loader | undefined; + const loads = new Map>(); + const modules = new Map(); + + return { + name: "deno-plugin", + + [Symbol.dispose]: () => { + if (loader && typeof loader[Symbol.dispose] === "function") { + loader[Symbol.dispose](); + } + }, + + buildStart: async (options) => { + let inputs: string[] = []; + + if (options?.input != null) { + const { input } = options; + if (Array.isArray(input)) { + inputs = input; + } else if (typeof input === "object") { + inputs = Object.values(input); + } else if (typeof input === "string") { + inputs = [input]; + } + } else if (pluginOptions.entrypoints?.length) { + inputs = pluginOptions.entrypoints; + } + + if (inputs.length === 0) return; + + const workspace = new Workspace({ ...pluginOptions }); + loader = await workspace.createLoader(); + await loader.addEntrypoints(inputs); + }, + + resolveId: { + filter: { id: MARegex }, + + handler: async (source, importer, options) => { + if (!loader) { + throw new Error("Deno loader not initialized. Make sure buildStart was called."); + } + + const resolutionMode = resolveKindToResolutionMode(options.kind); + const normalizedImporter = importer != null ? (modules.get(importer)?.specifier ?? importer) : undefined; + + let resolvedSpecifier: string; + try { + resolvedSpecifier = await loader.resolve(source, normalizedImporter, resolutionMode); + } catch (error: unknown) { + if ((error as { code?: string })?.code === "ERR_MODULE_NOT_FOUND") { + if (pluginOptions.externalPatterns) { + for (const pattern of pluginOptions.externalPatterns) { + if (typeof pattern === "string") { + if (source === pattern || source.startsWith(`${pattern}/`)) { + return { id: source, external: true }; + } + } else if (pattern.test(source)) { + return { id: source, external: true }; + } + } + } + + if ( + !( + source.startsWith(".") || + source.startsWith("/") || + source.startsWith("file:") || + source.startsWith("http") + ) + ) { + return { id: source, external: true }; + } + + return; + } + throw error; + } + + let loadPromise = loads.get(resolvedSpecifier); + if (!loadPromise) { + loadPromise = loader.load(resolvedSpecifier, RequestedModuleType.Default); + loads.set(resolvedSpecifier, loadPromise); + } + + const result = await loadPromise; + + if (!result) { + modules.set(resolvedSpecifier, undefined); + return resolvedSpecifier; + } + + if (result.kind === "external") { + return { id: result.specifier, external: true }; + } + + const ext = mediaTypeToExtension(result.mediaType); + let { specifier } = result; + + if (!specifier.endsWith(ext)) { + specifier += `.rolldown${ext}`; + } + + if (specifier.startsWith("file:///")) { + specifier = fromFileUrl(specifier); + } + + modules.set(specifier, { + specifier: result.specifier, + code: new TextDecoder().decode(result.code) + }); + + return specifier; + } + }, + + load: { + filter: { id: MARegex }, + + handler: (id) => { + return modules.get(id)?.code; + } + } + }; +} + +function mediaTypeToExtension(mediaType: MediaType): string { + switch (mediaType) { + case MediaType.JavaScript: + return ".js"; + case MediaType.Mjs: + return ".mjs"; + case MediaType.Cjs: + return ".cjs"; + case MediaType.Jsx: + return ".jsx"; + case MediaType.TypeScript: + case MediaType.Mts: + return ".ts"; + case MediaType.Cts: + return ".cts"; + case MediaType.Dts: + return ".d.ts"; + case MediaType.Dmts: + return ".d.mts"; + case MediaType.Dcts: + return ".d.cts"; + case MediaType.Tsx: + return ".tsx"; + case MediaType.Css: + return ".css"; + case MediaType.Json: + return ".json"; + case MediaType.Html: + return ".html"; + case MediaType.Sql: + return ".sql"; + case MediaType.Wasm: + return ".wasm"; + case MediaType.SourceMap: + return ".map"; + default: + return ""; + } +} + +function resolveKindToResolutionMode(kind: string): ResolutionMode { + switch (kind) { + case "import-statement": + case "dynamic-import": + return ResolutionMode.Import; + case "require-call": + return ResolutionMode.Require; + default: + throw new Error(`not implemented: ${kind}`); + } +} diff --git a/package.json b/package.json index f92477c0..e018ade4 100644 --- a/package.json +++ b/package.json @@ -1,51 +1,4 @@ { - "$schema": "https://www.schemastore.org/package.json", "license": "EUPL-1.2", - "type": "module", - "dependencies": { - "@hono/hono": "npm:@jsr/hono__hono@^4.11.4", - "@hono/openapi": "npm:hono-openapi@^1.1.2", - "@hono/standard-validator": "npm:@jsr/hono__standard-validator@~0.2.2", - "@std/assert": "npm:@jsr/std__assert@^1.0.16", - "@std/async": "npm:@jsr/std__async@^1.0.16", - "@std/cache": "npm:@jsr/std__cache@~0.2.1", - "@std/collections": "npm:@jsr/std__collections@^1.1.3", - "@std/dotenv": "npm:@jsr/std__dotenv@~0.225.6", - "@std/encoding": "npm:@jsr/std__encoding@^1.0.10", - "@std/fmt": "npm:@jsr/std__fmt@^1.0.8", - "@std/fs": "npm:@jsr/std__fs@^1.0.21", - "@std/streams": "npm:@jsr/std__streams@^1.0.16", - "@std/ulid": "npm:@jsr/std__ulid@^1.0.0", - "@types/node": "npm:@types/node@^25.0.8", - "arkenv": "npm:arkenv@~0.8.3", - "arktype": "npm:arktype@^2.1.29", - "biome": "npm:@biomejs/biome@2.3.11", - "hash-wasm": "npm:hash-wasm@^4.12.0", - "nanoid": "npm:nanoid@^5.1.6", - "rolldown": "npm:rolldown@1.0.0-beta.60", - "vite-bundle-analyzer": "npm:vite-bundle-analyzer@^1.3.2" - }, - "imports": { - "#/*": [ - "./src/*" - ], - "#db/*": [ - "./src/database/*" - ], - "#document/*": [ - "./src/document/*" - ], - "#endpoint/*": [ - "./src/endpoints/*" - ], - "#http/*": [ - "./src/http/*" - ], - "#task/*": [ - "./src/tasks/*" - ], - "#util/*": [ - "./src/utils/*" - ] - } + "type": "module" } diff --git a/rolldown.config.ts b/rolldown.config.ts index d1c696cd..3578f3b3 100644 --- a/rolldown.config.ts +++ b/rolldown.config.ts @@ -1,5 +1,6 @@ import type { RolldownOptions } from "rolldown"; import { analyzer, unstableRolldownAdapter } from "vite-bundle-analyzer"; +import deno from "./lib/deno-rolldown/mod.ts"; const analyze = false; @@ -25,13 +26,8 @@ export default { optimization: { inlineConst: true }, - transform: { - // deno.json compilerOptions - typescript: { - onlyRemoveTypeImports: true - } - }, plugins: [ + deno(), unstableRolldownAdapter( analyzer({ enabled: analyze, diff --git a/tsconfig.json b/tsconfig.json new file mode 100644 index 00000000..52a5cb2c --- /dev/null +++ b/tsconfig.json @@ -0,0 +1,42 @@ +{ + "$schema": "https://www.schemastore.org/tsconfig.json", + "compilerOptions": { + "lib": ["ESNext", "deno.window", "deno.unstable"], + "types": ["node"], + "module": "esnext", + "moduleResolution": "bundler", + + "checkJs": false, + "skipLibCheck": true, + + "strict": true, + "allowUnreachableCode": false, + "allowUnusedLabels": false, + "exactOptionalPropertyTypes": false, + "isolatedDeclarations": false, + "noErrorTruncation": false, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": true, + "noImplicitOverride": true, + "noImplicitReturns": true, + "noImplicitThis": true, + "noPropertyAccessFromIndexSignature": false, + "noUncheckedIndexedAccess": true, + "noUnusedLocals": true, + "noUnusedParameters": true, + "useUnknownInCatchVariables": true, + "verbatimModuleSyntax": true, + + "baseUrl": ".", + "paths": { + "#/*": ["./src/*"], + "#db/*": ["./src/database/*"], + "#document/*": ["./src/document/*"], + "#endpoint/*": ["./src/endpoints/*"], + "#http/*": ["./src/http/*"], + "#task/*": ["./src/tasks/*"], + "#util/*": ["./src/utils/*"] + } + }, + "exclude": ["./dist/", "./node_modules/", "./storage/"] +}