vercel-deno-dev
Advanced tools
Comparing version 0.1.0-f70846502a35418f076600ad35051939bbbc228e to 0.1.0-f772020eecce5d6d1cd3cbd89debaa9a427c9c33
@@ -1,5 +0,5 @@ | ||
# vercel-deno | ||
# vercel-deno-runtime | ||
> This runtime is currently on development and might be broken on some specific cases specified in the Known Limitation section. | ||
Run Deno runtime on `vercel`. 🦕 + ▲ = ❤️ | ||
Deno runtime for `vercel`. | ||
@@ -13,3 +13,3 @@ ## Usage | ||
"api/**/*.{ts,tsx}": { | ||
"runtime": "vercel-deno" | ||
"runtime": "vercel-deno-runtime" | ||
} | ||
@@ -20,4 +20,3 @@ }, | ||
"DENO_VERSION":"1.0.5 OR latest", | ||
"DENO_TSCONFIG":"tsconfig.json", | ||
"DENO_FLAGS":"--allow-read", | ||
"DENO_CONFIG":"tsconfig.json", | ||
"DENO_UNSTABLE":true | ||
@@ -30,29 +29,14 @@ } | ||
```ts | ||
// hello.ts | ||
import { | ||
APIGatewayProxyEvent, | ||
APIGatewayProxyResult, | ||
Context | ||
} from "https://deno.land/x/lambda/mod.ts"; | ||
export async function handler( | ||
event: APIGatewayProxyEvent, | ||
context: Context | ||
): Promise<APIGatewayProxyResult> { | ||
return { | ||
body: `Welcome to deno ${Deno.version.deno} 🦕`, | ||
headers: { "content-type": "text/html;charset=utf8" }, | ||
statusCode: 200 | ||
}; | ||
// /api/hello.ts | ||
import { NowRequest, NowResponse } from "https://deno.land/x/npm:vercel-deno-runtime/dist/boot/nowHandler.ts"; | ||
export default async function handler(req:NowRequest,res:NowResponse) { | ||
res.statuscode(200).send(`Welcome to deno ${Deno.version.deno} 🦕`); | ||
} | ||
``` | ||
## Available config ( with default value ) | ||
``` | ||
DENO_VERSION : "latest" | ||
DENO_TSCONFIG : "" | ||
DENO_FLAGS : "--allow-all" | ||
DENO_UNSTABLE : false | ||
``` | ||
## Default configs | ||
- `DENO_VERSION` : "latest" | ||
- `DENO_CONFIG` : "" | ||
- `DENO_UNSTABLE` : false | ||
@@ -62,14 +46,13 @@ Note: `vercel` v17.x or above are required to use the above configuration. | ||
## Known limitation | ||
- Limited to AWS Lambda gateway | ||
- Unable to send response with binary files | ||
- only works on linux, for now. | ||
## TODO | ||
- [ ] Suport Now Launcher | ||
- [ ] Support base64 conversion for binary files response | ||
- [ ] implement caching | ||
- [x] Suport Now Launcher | ||
- [x] Support base64 conversion for binary files response | ||
- [ ] implement caching for downloading deno | ||
- [ ] add support for windows and macos | ||
## Credits | ||
## References | ||
- [deno-lambda](https://github.com/hayd/deno-lambda) by [Andy Hayden](https://github.com/hayd) | ||
- [vercel-deno](https://github.com/TooTallNate/vercel-deno) by [TooTallNate](https://github.com/TooTallNate) | ||
- [now-deno](https://github.com/lucacasonato/now-deno) by [lucacasonato](https://github.com/lucacasonato) |
@@ -52,2 +52,3 @@ import * as base64 from 'https://deno.land/x/base64/mod.ts'; | ||
const output = new Deno.Buffer(); | ||
output.grow(33554432); // 2^25 ~~ 33.5 MB | ||
const req:NowRequest = new ServerRequest(); | ||
@@ -59,5 +60,5 @@ req.r = new BufReader(input); | ||
req.url = data.path; | ||
req.proto = 'HTTP/1.1'; | ||
req.protoMinor = 1; | ||
req.protoMajor = 1; | ||
req.proto = 'HTTP/2.0'; | ||
req.protoMinor = 0; | ||
req.protoMajor = 2; | ||
@@ -94,3 +95,3 @@ for (const [name, value] of Object.entries(data.headers)) { | ||
const bufr = new BufReader(output); | ||
const bufr = new BufReader(output,output.capacity); | ||
const tp = new TextProtoReader(bufr); | ||
@@ -106,4 +107,14 @@ | ||
const body = await bufr.readFull(new Uint8Array(bufr.buffered())); | ||
let buff = new Uint8Array(output.capacity); | ||
const size = await bufr.read(buff)||output.capacity; | ||
const body = buff.slice(0,size); | ||
if (!body) throw new Deno.errors.UnexpectedEof(); | ||
console.log(res.body); | ||
console.log(body); | ||
console.log({ | ||
bufrlen:buff.byteLength, | ||
outlen:output.capacity - output.length, | ||
size:size | ||
}) | ||
@@ -113,3 +124,3 @@ await req.finalize(); | ||
result = { | ||
statuscode: statuscode, | ||
statusCode: statuscode, | ||
headers: headersObj, | ||
@@ -116,0 +127,0 @@ encoding: 'base64', |
@@ -8,5 +8,3 @@ "use strict"; | ||
const fs_extra_1 = __importDefault(require("fs-extra")); | ||
const path_1 = __importDefault(require("path")); | ||
const util_1 = require("./util"); | ||
const getDenoFiles_1 = __importDefault(require("./getDenoFiles")); | ||
async function build(opts) { | ||
@@ -16,8 +14,8 @@ const { files, entrypoint, workPath, meta = {} } = opts; | ||
console.log("downloading source files"); | ||
const downloadedFiles = await build_utils_1.download(files, path_1.default.join(workPath, "src"), meta); | ||
const downloadedFiles = await build_utils_1.download(files, workPath, meta); | ||
// configure environment variable | ||
const denoFiles = await getDenoFiles_1.default(workPath); | ||
const bootFiles = await util_1.getbootFiles(); | ||
const genFiles = await util_1.getgenFiles(opts, downloadedFiles, bootFiles, denoFiles); | ||
console.log({ downloadedFiles, denoFiles, bootFiles, genFiles }); | ||
const denoFiles = await util_1.getdenoFiles(workPath, meta.isDev || false); | ||
const bootFiles = await util_1.getbootFiles(workPath); | ||
const cacheFiles = await util_1.CacheEntryPoint(opts, downloadedFiles, denoFiles, bootFiles); | ||
// console.log({downloadedFiles, denoFiles,bootFiles,genFiles}) | ||
// Files directory: | ||
@@ -27,4 +25,4 @@ // - .deno | ||
// - /gen | ||
// - /bin/deno | ||
// - src | ||
// - /bin/deno | ||
// - *.d.ts | ||
// - bootstrap | ||
@@ -37,5 +35,5 @@ // - runtime.ts | ||
...downloadedFiles, | ||
...denoFiles, | ||
...cacheFiles, | ||
...bootFiles, | ||
...genFiles, | ||
...denoFiles | ||
}, | ||
@@ -42,0 +40,0 @@ environment: { |
@@ -6,8 +6,7 @@ "use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
exports.getbootFiles = exports.getgenFiles = exports.parseDenoVersion = exports.DENO_VERSION = exports.DENO_LATEST = void 0; | ||
const child_process_1 = require("child_process"); | ||
const path_1 = __importDefault(require("path")); | ||
exports.CacheEntryPoint = exports.getbootFiles = exports.getdenoFiles = exports.parseDenoVersion = void 0; | ||
const dist_1 = require("@vercel/build-utils/dist"); | ||
exports.DENO_LATEST = "latest"; | ||
exports.DENO_VERSION = process.env.DENO_VERSION || exports.DENO_LATEST; | ||
const fs_extra_1 = require("fs-extra"); | ||
const path_1 = require("path"); | ||
const execa_1 = __importDefault(require("execa")); | ||
function parseDenoVersion(version) { | ||
@@ -25,11 +24,73 @@ if (version === "latest") | ||
exports.parseDenoVersion = parseDenoVersion; | ||
async function getdenoFiles(workPath, isDev) { | ||
console.log("get deno binary files"); | ||
const DENO_LATEST = "latest"; | ||
const DENO_VERSION = process.env.DENO_VERSION || DENO_LATEST; | ||
const DOWNLOAD_URL = DENO_VERSION === DENO_LATEST | ||
? `https://github.com/denoland/deno/releases/latest/download/deno-x86_64-unknown-linux-gnu.zip` | ||
: `https://github.com/denoland/deno/releases/download/v${DENO_VERSION}/deno-x86_64-unknown-linux-gnu.zip`; | ||
const denobinDir = path_1.join(workPath, '.deno/bin/'); | ||
const denozipPath = path_1.join(denobinDir, 'deno.zip'); | ||
let denoPath = ''; | ||
// check if local deno binary exists | ||
if (isDev) { | ||
try { | ||
const checklocalDeno = await execa_1.default('which', ['deno'], { stderr: 'ignore' }); | ||
denoPath = checklocalDeno.stdout; | ||
} | ||
catch (e) { } | ||
; | ||
} | ||
if (!denoPath) { | ||
try { | ||
console.log(`downloading deno ${DENO_VERSION}`); | ||
await execa_1.default("curl", ['--location', '--create-dirs', '--output', denozipPath, DOWNLOAD_URL], { stdio: 'pipe' }); | ||
console.log(`Extract deno.zip`); | ||
await execa_1.default("unzip", [denozipPath, '-d', denobinDir], { stdio: 'pipe' }); | ||
// const {stdout} = await execa(`ls`,[ join(workPath,'.deno/bin/')],{ stdio: 'pipe' }); | ||
// console.log(stdout); | ||
// await execa('chmod',['+x',denoPath]); | ||
console.log(`remove deno.zip`); | ||
await execa_1.default("rm", [denozipPath], { stdio: 'pipe' }); | ||
denoPath = path_1.join(denobinDir, 'deno'); | ||
} | ||
catch (err) { | ||
console.log(err); | ||
throw new Error(err); | ||
} | ||
} | ||
else | ||
console.log('using local deno binary'); | ||
return { | ||
".deno/bin/deno": new dist_1.FileFsRef({ | ||
mode: 0o755, | ||
fsPath: denoPath, | ||
}) | ||
}; | ||
} | ||
exports.getdenoFiles = getdenoFiles; | ||
async function getbootFiles(workPath) { | ||
console.log('get bootstrap'); | ||
const bootstrapPath = path_1.join(__dirname, "../boot/bootstrap"); | ||
const runtimeGlobs = await dist_1.glob("boot/*.ts", { cwd: path_1.join(__dirname, "../") }); | ||
const runtimeFiles = await dist_1.download(runtimeGlobs, workPath); | ||
return { | ||
...runtimeFiles, | ||
bootstrap: new dist_1.FileFsRef({ | ||
mode: 0o755, | ||
fsPath: bootstrapPath, | ||
}) | ||
}; | ||
} | ||
exports.getbootFiles = getbootFiles; | ||
/** | ||
* returns .deno files | ||
*/ | ||
async function getgenFiles(opts, downloadedFiles, bootFiles, denoFiles) { | ||
async function CacheEntryPoint(opts, downloadedFiles, denoFiles, bootFiles) { | ||
console.log(`Caching imports for ${opts.entrypoint}`); | ||
console.log({ downloadedFiles, bootFiles, denoFiles }); | ||
// TODO: create separate function to parse user ENV values | ||
const tsconfig = process.env.DENO_CONFIG ? [`-c`, `${downloadedFiles[process.env.DENO_CONFIG].fsPath}`] : []; | ||
const { workPath, entrypoint } = opts; | ||
const denobinPath = '.deno/bin/deno'; | ||
const runtimePath = 'boot/runtime.ts'; | ||
const denobinPath = '.deno/bin/deno'; | ||
const denobin = denoFiles[denobinPath].fsPath; | ||
@@ -39,24 +100,47 @@ const runtime = bootFiles[runtimePath].fsPath; | ||
if (denobin && runtime) { | ||
child_process_1.spawn(denobin, ['cache', entry, runtime], { | ||
env: { DENO_DIR: path_1.default.join(workPath, '.deno/') }, | ||
stdio: 'inherit', | ||
await execa_1.default(denobin, ['cache', ...tsconfig, runtime, entry], { | ||
env: { DENO_DIR: path_1.join(workPath, '.deno/') }, | ||
stdio: 'ignore', | ||
}); | ||
} | ||
const cwd = path_1.default.join(workPath, '.deno', 'gen', 'file', workPath); | ||
const aws_task = path_1.default.join(workPath, '.deno', 'gen', 'file', 'var', 'task'); | ||
return await dist_1.glob("**/*", { cwd: cwd }, aws_task); | ||
// patch .graph files to use file paths beginning with /var/task | ||
// reference : https://github.com/TooTallNate/vercel-deno/blob/5a236aab30eeb4a6e68216a80f637e687bc59d2b/src/index.ts#L98-L118 | ||
const workPathUri = `file://${workPath}`; | ||
for await (const file of getGraphFiles(path_1.join(workPath, '.deno/gen/file'))) { | ||
let needsWrite = false; | ||
const graph = JSON.parse(await fs_extra_1.readFile(file, 'utf8')); | ||
for (let i = 0; i < graph.deps.length; i++) { | ||
const dep = graph.deps[i]; | ||
if (dep.startsWith(workPathUri)) { | ||
const updated = `file:///var/task/${dep.substring(workPathUri.length)}`; | ||
graph.deps[i] = updated; | ||
needsWrite = true; | ||
} | ||
} | ||
if (needsWrite) { | ||
console.log('Patched %j', file); | ||
await fs_extra_1.writeFile(file, JSON.stringify(graph)); | ||
} | ||
} | ||
// move generated files to AWS path /var/task | ||
const cwd = path_1.join(workPath, '.deno', 'gen', 'file', workPath); | ||
const aws_task = path_1.join(workPath, '.deno', 'gen', 'file', 'var', 'task'); | ||
await fs_extra_1.move(cwd, aws_task, { overwrite: true }); | ||
return await dist_1.glob(".deno/**", workPath); | ||
} | ||
exports.getgenFiles = getgenFiles; | ||
async function getbootFiles() { | ||
console.log('get bootstrap'); | ||
const bootstrapPath = path_1.default.join(__dirname, "../boot/bootstrap"); | ||
let runtimefiles = await dist_1.glob("**/*.ts", { cwd: path_1.default.join(__dirname, '../boot') }, "boot"); | ||
return { | ||
...runtimefiles, | ||
bootstrap: new dist_1.FileFsRef({ | ||
mode: 0o755, | ||
fsPath: bootstrapPath, | ||
}) | ||
}; | ||
exports.CacheEntryPoint = CacheEntryPoint; | ||
async function* getGraphFiles(dir) { | ||
const files = await fs_extra_1.readdir(dir); | ||
for (const file of files) { | ||
const absolutePath = path_1.join(dir, file); | ||
if (file.endsWith('.graph')) { | ||
yield absolutePath; | ||
} | ||
else { | ||
const s = await fs_extra_1.stat(absolutePath); | ||
if (s.isDirectory()) { | ||
yield* getGraphFiles(absolutePath); | ||
} | ||
} | ||
} | ||
} | ||
exports.getbootFiles = getbootFiles; |
"use strict"; | ||
Object.defineProperty(exports, "__esModule", { value: true }); | ||
//import { spawn } from 'child_process'; | ||
/// unused. | ||
function prepareCache({ files, entrypoint }) { | ||
@@ -13,11 +13,3 @@ console.log("Execute caching for deno"); | ||
console.log({ deno, entry, env }); | ||
// if (deno && entry) { | ||
// const ls = spawn(deno,['cache',entry], | ||
// { | ||
// env | ||
// }) | ||
// } | ||
// execute caching | ||
// TODO: add cache here | ||
} | ||
exports.default = prepareCache; |
{ | ||
"name": "vercel-deno-dev", | ||
"version": "0.1.0-f70846502a35418f076600ad35051939bbbc228e", | ||
"version": "0.1.0-f772020eecce5d6d1cd3cbd89debaa9a427c9c33", | ||
"description": "run deno on vercel", | ||
@@ -5,0 +5,0 @@ "main": "./dist/index", |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Shell access
Supply chain riskThis module accesses the system shell. Accessing the system shell increases the risk of executing arbitrary code.
Found 1 instance in 1 package
22911
513
0
13
54
7