Deno开发REST API实战

Deno
说明:Deno正处于快速发展阶段,版本发布较为频繁,标准库尚不稳定,本文会不定期更新以保证其可用性。完整源码已上传到GitHub https://github.com/sunjc/heroes-deno

Deno简介

Deno与Node.js

2009年11月8日,在JavaScript社区欧洲 JSConf 大会上,Node.js之父Ryan Dahl首度发布了Node。Node把浏览器端的 JavaScript 技术带入了服务端应用领域。

2012年Ryan Dahl开始淡出 Node.js 社区,进入 Go、Rust社区,重回他擅长的数学应用领域。后来,Ryan Dahl使用Node.js设计一款类似 IPython 的互动式数据科学分析命令行工具时,发现Node现在太难用了。Ryan Dahl认为自从他把项目移交出去后,Node的走向越来越背离他的初衷,存在很多无法解决的问题,因此他决定重新开发一个新项目Deno,目标是Destroy-node,单词Deno的英文意思则为恐龙。

2018年6月,在Node.js迈入第 10 年之前,JSConf 欧洲大会再次邀请 Ryan Dahl进行开场演讲。在这次引发全球开发社区热烈讨论的演讲中,Ryan Dahl分享了“我在 Node.js 最悔恨的10件事”,并介绍了开发中的Deno。

Node.js十大恨

  1. 没采用 JavaScript 异步处理的 Promise 对象
  2. 低估了安全的重要性
  3. 采用 gyp 设计Build系统
  4. 没有听从社区建议改用 FFI 而继续用 gyp
  5. 过度依赖 npm(内建package.json支持是个错误)
  6. 太容易造成 require(“任意模块”)
  7. package.json容易造成错误的模块概念
  8. 臃肿复杂的 node_module 设计和下载黑洞
  9. require(“module”) 没有强制要求添加.js 扩展名
  10. 无用的 index.js 设计

Deno特性

Deno是一个简单、现代、安全的JavaScript和TypeScript运行时,采用了Chrome V8引擎(与Node.js相同),基于RustTokio构建。由于Rust原生支持WebAssembly,所以Deno也能直接运行WebAssembly。
architecture

  • 基于最新的 JavaScript 语言,现代化的Javascript ES 模块,支持async/await语法。
  • 原生支持TypeScript,无需额外配置,无需任何手动编译。
  • 去中心化的模块系统,Deno不使用npm,不使用package.json,不需要一个集中的存储库。
  • 默认情况下是安全的。除非显式启用,否则无法访问文件、网络或环境变量。
  • 单一可执行文件(deno),其中包含功能完整的Runtime API,没有外部依赖,可以部署到各种环境中。
  • 内置实用工具,如依赖检查器(deno info)、代码格式化工具(deno fmt)。
  • 脚本可以打包到单个 JavaScript 文件中。
  • 拥有一套经过审核、功能广泛的标准库:deno.land/std
  • 可以从网络上的任何位置导入模块,比如GitHub、CDN、个人服务器。Deno官方提供代码托管服务deno.land/x,现已托管千余个第三方模块。

依赖管理

Deno没有包管理器的概念,可以通过URL网址将外部模块直接导入本地模块,可以有选择地加载所需部件:

import {
    oakCors } from "https://deno.land/x/cors/mod.ts";

在URL中可以指定版本号,若未指定,则使用最近的版本:

import {
    oakCors } from "https://deno.land/x/cors@v1.2.0/mod.ts";

第一次访问外部模块时,Deno会自动下载并缓存到本地,再次使用时就不需要下载了。如要重新下载,只需在命令中添加–reload选项即可。而本地运行Node.js时,必须先从 NPM 安装所有依赖项,不同的项目需要重新下载。

deps.ts
在具有许多依赖项的大项目中,如果每个模块都单独导入,更新这些模块将变得非常繁琐和耗时。为解决这个问题,可以创建名为deps.ts的文件来集中管理外部模块:

export {
   serve} from "https://deno.land/std@0.70.0/http/server.ts";
export * as bcrypt from "https://deno.land/x/bcrypt@v0.2.4/mod.ts";
export {
   oakCors} from "https://deno.land/x/cors@v1.2.0/mod.ts";

本地模块引用deps.ts:

import {
   Application, createConnection, oakCors} from "./deps.ts";

import maps
import maps是管理模块的另一种方案,目前尚不稳定。

首先创建import_map.json文件:

{
   
   "imports": {
   
      "fmt/": "https://deno.land/std@0.70.0/fmt/"
   }
}

使用import_map.json中映射的名称导入模块:

import {
    red } from "fmt/colors.ts";

console.log(red("hello world"));

在运行时指定–importmap选项:

$ deno run --importmap=import_map.json --unstable color.ts

安装与配置

安装Deno

Deno可以运行在macOS、Linux和Windows系统,仅一个可执行文件,没有外部依赖。

安装
Using Shell (macOS and Linux):

curl -fsSL https://deno.land/x/install/install.sh | sh

Using PowerShell (Windows):

iwr https://deno.land/x/install/install.ps1 -useb | iex

测试安装
查看deno版本:

$ deno --version

运行第一个程序:

$ deno run https://deno.land/std/examples/welcome.ts
...
Welcome to Deno 🦕

升级
升级到最新版:

deno upgrade

安装指定版本:

deno upgrade --version 1.2.1

配置环境变量

  • DENO_DIR 设置cache目录,默认值为$HOME/.cache/deno
  • DENO_INSTALL_ROOT 设置Deno的安装目录,默认值为$HOME/.deno/bin
  • NO_COLOR 关闭彩色输出

运行deno info命令可以查看cache信息,Windows系统如下:

deno info
DENO_DIR location: "C:\\Users\\jason\\AppData\\Local\\deno"
Remote modules cache: "C:\\Users\\jason\\AppData\\Local\\deno\\deps"
TypeScript compiler cache: "C:\\Users\\jason\\AppData\\Local\\deno\\gen"

IDE插件

以IntelliJ IDEA为例,访问Deno插件页面,点击Install to IDE,按提示操作即可完成安装。重启IDE后,进入Preferences > Languages & Frameworks > Deno,启用Enable Deno support for this project。

Denon

Denon 类似于Node.js的nodemon自动重启工具,用来在开发环境中监视文件的变更,发现更改后会自动重新启动。它显著提升了开发体验,开发人员无需再手动停止和重启服务。

Denon还支持配置脚本功能,其灵感源于velociraptor(迅猛龙)。Deno没有包管理器,缺少一些npm功能,尤其是不方便运行脚本。Deno CLI命令可能会非常长,如果没有地方存储,不容易共享脚本,也不方便在外部工具中调用。

安装Denon

deno install --allow-read --allow-run --allow-write --allow-net -f -q --unstable https://deno.land/x/denon@2.4.0/denon.ts

用法
可以直接使用denon命令运行程序,可以传递deno命令支持的所有参数:

$ denon run --allow-env app.ts --arg-for-my-app

更常用来运行script:

$ denon [script name]

配置
支持json和yaml两种格式的配置文件。

运行如下命令创建denon.json文件:

$ denon --init

生成的文件内容如下:

{
   
  // optional but highly recommended
  "$schema": "https://deno.land/x/denon/schema.json",
  "scripts": {
   
    "start": {
   
      "cmd": "deno run app.ts",
      "desc": "run my app.ts file"
    }
  }
}

也可以使用denon.yml文件:

scripts:
  start:
    cmd: "deno run app.ts"
    desc: "run my app.ts file"

Script选项
简单的scripts:

{
   
  "scripts": {
   
    // they all resolve to `deno run app.ts` when you run `denon start`
    "start": "app.ts",
    // OR
    "start": "run app.ts",
    // OR
    "start": "deno run app.ts"
  }
}

也可以定义复杂的script对象。denon script支持环境变量、权限、tsconfig、imap、log等选项,可以配置是否监视文件,详细信息请查阅官方文档,一些选项的含义可以查看下节Deno CLI。

{
   
  // globally applied to all scripts
  // now denon will essentialy be a script runner
  "watch": false

  // globally applied to all scripts
  "env": {
   
    "TOKEN": "SUPER SECRET TOKEN",
  },

  // globally applied to all scripts
  // as object ...
  "allow": {
   
    "read": "/etc,/tmp", // --allow-read=/etc,/tmp
    "env": true     // --allow-env
  },
  // ... or as array
  "allow": [
    "run", // --allow-run
    "net" // --allow-net
  ]

  "scripts": {
   
    "start": {
   
      "cmd": "deno run app.ts",
      "desc": "Run the main server.",
      "importmap": "importmap.json",
      "tsconfig": "tsconfig.json",
      "log": "debug", // or "info"
      "unstable": true,
      // you can still enable watch on a script-by-script basis
      "watch": true,

      "inspect": "127.0.0.1:9229",
      // OR
      "inspectBrk": "127.0.0.1:9229"

      "env": {
   
        "PORT": 3000
      },

      // specific for a single script
      // as object ...
      "allow": {
   
        "read": "/etc,/tmp", // --allow-read=/etc,/tmp
        "env": true     // --allow-env
      },
      // ... or as array
      "allow": [
        "run", // --allow-run
        "net" // --allow-net
      ]
    }
  }
}

Nest.land

Nest.land是Deno去中心化的模块registry和CDN。您可以访问nest.land/gallery查找所需模块:
Nest.land Gallery
比如,我们也可以从Nest.land安装denon:

$ deno install --allow-read --allow-run --allow-write --allow-net -f -q --unstable https://x.nest.land/denon@2.4.0/denon.ts

相对于将模块托管在Github、deno.land/x或你自己的Web服务器,使用Nest.land有以下优点:

  • 永不可变,Nest.land将Deno模块存储在Arweave Permaweb,永远不会被删除或修改。
  • 安全、开源
  • 无需Git,可以使用任何版本管理工具,只需将模块相关代码上传

Eggs CLI
Eggs CLI是Nest.land管理和发布模块的工具。
安装Eggs CLI

$ deno install -A -f --unstable -n eggs https://x.nest.land/eggs@0.2.1/mod.ts
or
$ deno run -A --unstable https://x.nest.land/eggs@0.2.1/mod.ts install -A -f --unstable -n eggs https://x.nest.land/eggs@0.2.1/mod.ts

Eggs CLI支持的命令

help         - Show this help or the help of a sub-command.
completions  - Generate shell completions for zsh and bash.
link         - Links your nest.land API key to the CLI
init         - Initiates a new module for the nest.land registry.
publish      - Publishes the current directory to the nest.land registry.
update       - Update your dependencies
install      - A simple wrapper around the deno install command to handle global script updates.
upgrade      - Upgrade the current nest.land CLI.

有关发布模块的流程请查看官方文档。对于普通用户,update是非常有用的命令,会自动更新deps.ts的依赖版本。官方文档声明当前支持以下的Registry:

  • x.nest.land
  • deno.land/x
  • deno.land/std
  • raw.githubusercontent.com
  • denopkg.com

本人测试x.nest.land能更新成功,deno.land/x、deno.land/std更新失败。

Deno CLI

帮助

查看帮助

# Using the subcommand.
deno help

# Using the short flag
deno -h

# Using the long flag
deno --help

查看子命令的帮助

deno help bundle
deno bundle -h
deno bundle --help

支持的子命令

bundle         Bundle module and dependencies into single file
cache          Cache the dependencies
completions    Generate shell completions
doc            Show documentation for a module
eval           Eval script
fmt            Format source files
help           Prints this message or the help of the given subcommand(s)
info           Show info about cache or info related to source file
install        Install script as an executable
lint           Lint source files
repl           Read Eval Print Loop
run            Run a program given a filename or url to the module. Use '-' as a filename to read from stdin.
test           Run tests
types          Print runtime TypeScript declarations
upgrade        Upgrade deno executable to given version

deno run

deno run可以从本地文件、url、stdin获取脚本:

deno run main.ts
deno run https://mydomain.com/main.ts
cat main.ts | deno run -

如果在无服务器服务上部署了 Deno,指定一个网址就能运行这个服务,而不用上传代码到无服务器服务平台。

运行流程
在安装deno时曾运行过welcome示例:

$ deno run https://deno.land/std/examples/welcome.ts
Download https://deno.land/std/examples/welcome.ts
Warning Implicitly using latest version (0.70.0) for https://deno.land/std/examples/welcome.ts
Download https://deno.land/std@0.70.0/examples/welcome.ts
Check https://deno.land/std@0.70.0/examples/welcome.ts
Welcome to Deno 🦕

首次运行时先下载welcome.ts文件,然后编译为JavaScript,最后通过 V8 引擎运行编译后的js文件。再次运行时则直接执行缓存中已生成的文件:

deno run https://deno.land/std/examples/welcome.ts
Welcome to Deno 🦕

刷新缓存
要重新下载和编译文件,使用–reload选项:

deno run --reload https://deno.land/std/examples/welcome.ts
Download https://deno.land/std/examples/welcome.ts
Warning Implicitly using latest version (0.70.0) for https://deno.land/std/examples/welcome.ts
Download https://deno.land/std@0.70.0/examples/welcome.ts
Check https://deno.land/std@0.70.0/examples/welcome.ts
Welcome to Deno 🦕

TypeScript类型检查
默认启用所有的strict检查,任何不合格的TypeScript代码都会得到提示。下面是当前的默认配置:

{
   
  "compilerOptions": {
   
    "allowJs": false,
    "allowUmdGlobalAccess": false,
    "allowUnreachableCode": false,
    "allowUnusedLabels": false,
    "alwaysStrict": true,
    "assumeChangesOnlyAffectDirectDependencies": false,
    "checkJs": false,
    "disableSizeLimit": false,
    "generateCpuProfile": "profile.cpuprofile",
    "jsx": "react",
    "jsxFactory": "React.createElement",
    "lib": [],
    "noFallthroughCasesInSwitch": false,
    "noImplicitAny": true,
    "noImplicitReturns": true,
    "noImplicitThis": true,
    "noImplicitUseStrict": false,
    "noStrictGenericChecks": false,
    "noUnusedLocals": false,
    "noUnusedParameters": false,
    "preserveConstEnums": false,
    "removeComments": false,
    "resolveJsonModule": true,
    "strict": true,
    "strictBindCallApply": true,
    "strictFunctionTypes": true,
    "strictNullChecks": true,
    "strictPropertyInitialization": true,
    "suppressExcessPropertyErrors": false,
    "suppressImplicitAnyIndexErrors": false,
    "useDefineForClassFields": false
  }
}

可以自定义tsconfig.json文件覆盖默认配置:

deno run -c tsconfig.json [your-script.ts]

为减少程序启动时间,在执行过TypeScript类型检查后,可以使用–no-check选项将之关闭。
安全权限
启用环境变量、网络、文件访问权限:

deno run --allow-env --allow-net --allow-read --allow-write <SCRIPT_ARG>

其中–allow-net、 --allow-read、 --allow-write可以进一步指定具体参数:

deno run --allow-net=github.com,deno.land fetch.ts
deno run --allow-read=/etc https://deno.land/std@0.70.0/examples/cat.ts /etc/passwd

启用调试

--inspect=<HOST:PORT>
    activate inspector on host:port (default: 127.0.0.1:9229)

--inspect-brk=<HOST:PORT>
    activate inspector on host:port and break at start of user script

为激活调试功能,使用–inspect 或 --inspect-brk选项运行deno。–inspect允许在任何时间点连接调试器,–inspect-brk将等待调试器连接,第一行代码即暂停执行。在IntelliJ IDEA点击调试按钮会自动启用–inspect-brk。

$ deno run --inspect-brk --allow-read --allow-net https://deno.land/std@0.70.0/http/file_server.ts
Debugger listening on ws://127.0.0.1:9229/ws/e43c9cae-c270-47a9-b0ac-99718cd9d6b7
Download https://deno.land/std@0.70.0/http/file_server.ts
Download https://deno.land/std@0.70.0/flags/mod.ts
Check https://deno.land/std@0.70.0/http/file_server.ts

启用调试后,我们使用 Chrome DevTools来调试程序,打开chrome://inspect,然后点击inspect:
DevTools
说明:若未显示target,点击Port forwarding和Configure配置主机和端口。

稍等一会儿,待所有模块加载完毕即可进入Chrome Devtools调试程序了:
调试Deno

deno cache

下载、编译模块及其所有静态依赖项,并保存到本地缓存中。如:

deno cache https://deno.land/std/http/file_server.ts

重新加载全部/部分模块:

deno cache --reload my_module.ts
deno cache --reload=https://deno.land/std@0.70.0/fs/copy.ts,https://deno.land/std@0.70.0/fmt/colors.ts my_module.ts

deno install

deno install用来安装和分发可执行代码,简单来说就是生成一个shell或cmd可执行文件,默认会安装在deno的bin目录下。前面安装denon时曾使用过此命令:

deno install --allow-read --allow-run --allow-write --allow-net -f -q --unstable https://deno.land/x/denon@2.4.0/denon.ts

也可以指定安装目录:

deno install --allow-net --allow-read -n file_server --root /usr/local https://deno.land/std@0.70.0/http/file_server.ts

注意,必须指定运行脚本时要使用的权限。

在windows下生成的cmd文件内容如下:
file_server.cmd

% generated by deno install %
@deno.exe "run" "--allow-read" "--allow-net" "https://deno.land/std@0.70.0/http/file_server.ts" %*

deno bundle

deno bundle将所有的依赖打包为一个JavaScript文件,例如:

deno bundle https://deno.land/std@0.70.0/examples/colors.ts colors.bundle.js
Bundle https://deno.land/std@0.70.0/examples/colors.ts
Download https://deno.land/std@0.70.0/examples/colors.ts
Emit "colors.bundle.js" (9.83 KB)

运行打包后的文件:

deno run colors.bundle.js

deno info

前文我们使用deno info查看cache信息,还可以使用deno info查看模块和其所有依赖:

deno info https://deno.land/std@0.70.0/http/file_server.ts
local: C:\Users\jason\AppData\Local\deno\deps\https\deno.land\93365353fdab1ce0009ac74c0900e9ad4ea0676c3cbb14fcc1c3d45b40d511d7
type: TypeScript
compiled: C:\Users\jason\AppData\Local\deno\gen\https\deno.land\93365353fdab1ce0009ac74c0900e9ad4ea0676c3cbb14fcc1c3d45b40d511d7.js
deps:
https://deno.land/std@0.70.0/http/file_server.ts
  ├─┬ https://deno.land/std@0.70.0/path/mod.ts
  │ ├── https://deno.land/std@0.70.0/path/_constants.ts
  │ ├─┬ https://deno.land/std@0.70.0/path/win32.ts
  │ │ ├── https://deno.land/std@0.70.0/path/_constants.ts
  │ │ ├─┬ https://deno.land/std@0.70.0/path/_util.ts
  │ │ │ └── https://deno.land/std@0.70.0/path/_constants.ts
...

deno fmt

格式化TypeScript和JavaScript代码。

# format all JS/TS files in the current directory and subdirectories
deno fmt
# format specific files
deno fmt myfile1.ts myfile2.ts
# check if all the JS/TS files in the current directory and subdirectories are formatted
deno fmt --check
# format stdin and write to stdout
cat file.ts | deno fmt -

Rest API实战

本部分将使用Deno重构本人博客Angular 9集成Spring Boot 2详解中的Spring Boot项目,演示Deno开发Rest API的过程与Deno框架(或模块)的用法。

技术框架

应用的技术框架或模块:

dep.ts

export {
   
  green,
  cyan,
  bold,
  yellow,
} from "https://deno.land/std@0.70.0/fmt/colors.ts";
export * as bcrypt from "https://deno.land/x/bcrypt@v0.2.4/mod.ts";
export {
    oakCors } from "https://deno.land/x/cors@v1.2.0/mod.ts";
export {
   
  makeJwt,
  setExpiration,
  Jose,
  Payload,
} from "https://deno.land/x/djwt@v1.4/create.ts";
export {
    validateJwt } from "https://deno.land/x/djwt@v1.4/validate.ts";
export {
    config } from "https://deno.land/x/dotenv@v0.5.0/mod.ts";
export {
   
  Application,
  Context,
  helpers as oakHelpers,
  HttpError,
  httpErrors,
  HTTPMethods,
  isHttpError,
  Request,
  Response,
  Router,
  RouterContext,
  RouteParams,
  Status,
} from "https://deno.land/x/oak@v6.2.0/mod.ts";
export {
   
  Column,
  ConnectionOptions,
  ConnectionOptionsReader,
  createConnection,
  CreateDateColumn,
  DeleteResult,
  Entity,
  EntityRepository,
  getConnection,
  getCustomRepository,
  getRepository,
  JoinTable,
  ManyToMany,
  MigrationInterface,
  PrimaryGeneratedColumn,
  Repository,
  QueryRunner,
  UpdateDateColumn,
} from "https://raw.githubusercontent.com/denolib/typeorm/master/mod.ts";
export {
    Snelm } from "https://deno.land/x/snelm@1.3.0/mod.ts";
export {
   
  firstMessages,
  InputData,
  isEmail,
  lengthBetween,
  match,
  required,
  validate,
  ValidationErrors,
  ValidationRules,
} from "https://deno.land/x/validasaur@v0.15.0/mod.ts";

export {
   
  assert,
  assertEquals,
  assertThrows,
  assertThrowsAsync,
} from "https://deno.land/std@0.70.0/testing/asserts.ts";
export {
    superoak } from "https://deno.land/x/superoak@2.3.1/mod.ts";

说明:

  1. 下载Deno模块时若出现不能访问https://raw.githubusercontent.com的情况,请到https://www.ipaddress.com/查询其IP,然后添加到hosts文件中。
  2. 目前typeorm master支持最新版本的deno,但尚未release,因此直接使用了github raw。

创建TypeORM项目

Deno fork of TypeORM
TypeORM是Node.js中常用的ORM框架,我们使用其Deno fork版。TypeORM支持mysql、mariadb、postgres、cockroachdb、sqlite、mssql、oracle、mongodb、cordova、react-native、expo、nativescript等数据库。

TypeORM CLI
安装TypeORM CLI:

deno install --allow-read --allow-write --allow-net --allow-env -f -n typeorm https://raw.githubusercontent.com/denolib/typeorm/master/cli.ts

支持的命令:

schema:sync [...args]         Synchronizes your entities with database schema. It runs schema update queries on all connections you have. 
schema:log [...args]          Shows sql to be executed by schema:sync command. It shows sql log only for your default connection. 
schema:drop [...args]         Drops all tables in the database on your default connection. 
query [...args]               Executes given SQL query on a default connection. Specify connection name to run query on a specific connection.
entity:create [...args]       Generates a new entity.
subscriber:create [...args]   Generates a new subscriber.
migration:create [...args]    Creates a new migration file.
migration:generate [...args]  Generates a new migration file with sql needs to be executed to update schema.
migration:run [...args]       Runs all pending migrations.
migration:show [...args]      Show all migrations and whether they have been run or not
migration:revert [...args]    Reverts last executed migration.
version [...args]             Prints TypeORM version this project uses.
cache:clear [...args]         Clears all data stored in query runner cache.
init [...args]                Generates initial TypeORM project structure. 

创建项目
TypeORM提供CLI命令来快速创建项目,我们使用sqlite数据库来创建heroes-deno项目:

typeorm init --name heroes-deno --database sqlite

创建的项目包含User Entity、mod.ts、ormconfig.json、tsconfig.json等文件,习惯上mod.ts一般用于导出模块的公用组件,我们将之重命名为app.ts。

目前,创建的项目存在问题是不能成功运行的,需做以下修改:

  1. 修改User Entity导入Column注解
  2. 修改tsconfig.json,如下:
{
   
   "compilerOptions": {
   
      "experimentalDecorators": true,
      "importsNotUsedAsValues": "remove",
      "isolatedModules": false,
      "strictPropertyInitialization": false
   }
}

修改后,执行下面命令测试运行app.ts:

deno run -c tsconfig.json app.ts

还是会报错:

NotImplementedError: `PlatformTools.load("app-root-path")` is not supported
    at Function.load (PlatformTools.ts:75:23)
    at ConnectionOptionsReader.get baseDirectory (ConnectionOptionsReader.ts:212:29)
    at ConnectionOptionsReader.get baseFilePath (ConnectionOptionsReader.ts:203:21)
    at ConnectionOptionsReader.load (ConnectionOptionsReader.ts:87:40)
    at ConnectionOptionsReader.all (ConnectionOptionsReader.ts:40:36)
    at ConnectionOptionsReader.get (ConnectionOptionsReader.ts:52:39)
    at getConnectionOptions (index.ts:194:42)
    at createConnection (index.ts:229:77)
    at app.ts:5:1

我们来看一下app.ts:

import {
   createConnection} from "https://denolib.com/denolib/typeorm@v0.2.23-rc8/mod.ts";
import {
   User} from "./entity/User.ts";

createConnection().then(async connection => {
   

    console.log("Inserting a new user into the database...");
    const user = new User();
    user.firstName = "Timber";
    user.lastName = "Saw";
    user.age = 25;
    await connection.manager.save(user);
    console.log("Saved a new user with id: " + user.id);

    console.log("Loading users from the database...");
    const users = await connection.manager.find(User);
    console.log("Loaded users: ", users);

    console.log("Here you can setup and run express/koa/any other framework.");

}).catch(error => console.log(error));

代码中调用了createConnection()函数来创建数据库连接,这会通过ConnectionOptionsReader从项目根目录的ormconfig或env文件(.env或ormconfig.env)读取连接选项,查找根目录时调用了Node.js的方法,因此报错。我们稍做修改,添加getConnectionOptions()函数,调用ConnectionOptionsReader时传入root参数:

import {
   
    ConnectionOptions,
    ConnectionOptionsReader,
    createConnection
} from "https://denolib.com/denolib/typeorm@v0.2.23-rc8/mod.ts";
import {
   User} from "./entity/User.ts";

/**
 * Reads connection options stored in ormconfig configuration file.
 */
async function getConnectionOptions(connectionName: string = "default"): Promise<ConnectionOptions> {
   
    return new ConnectionOptionsReader({
   root: "."}).get(connectionName);
}

const connectionOptions: ConnectionOptions = await getConnectionOptions();

createConnection(connectionOptions).then(async connection => {
   
   ...
}).catch(error => console.log(error));

再次运行程序会成功输出如下结果:

deno run -c tsconfig.json --allow-env --allow-net --allow-read --allow-write  app.ts
Inserting a new user into the database...
Saved a new user with id: 1
Loading users from the database...
Loaded users:  [ User { id: 1, firstName: "Timber", lastName: "Saw", age: 25 } ]
Here you can setup and run express/koa/any other framework.

环境变量

dotenv能自动从项目根目录下的.env 文件读取环境变量。TypeORM也使用了dotenv,可使用环境变量配置连接选项,如:

TYPEORM_CONNECTION = sqlite
TYPEORM_DATABASE = heroes.sqlite
TYPEORM_SYNCHRONIZE = true
TYPEORM_LOGGING = true
TYPEORM_MIGRATIONS_RUN = true
TYPEORM_ENTITIES = entity/**/*.ts
TYPEORM_MIGRATIONS = migration/**/*.ts
TYPEORM_ENTITIES_DIR = entity
TYPEORM_MIGRATIONS_DIR = migration

在项目根目录下创建.env和.env.example两个文件,分别添加如下内容供后面程序使用:
.env

# .env
APP_HOST = localhost
APP_PORT = 8080

IGNORE_PATHS = /api/auth

JWT_SECRET = mySecret
JWT_ACCESS_TOKEN_EXP = 1800
JWT_REFRESH_TOKEN_EXP = 7200
JWT_ISSUER = iTRunner

CORS_ORIGIN = *
CORS_METHODS = GET,POST,DELETE,PUT,OPTIONS
CORS_ALLOWED_HEADERS = Accept,Accept-Encoding,Accept-Language,Authorization,Connection,Content-Type,Host,Origin,Referer,User-Agent,X-Requested-With

.env.example

# .env.example
APP_HOST =
APP_PORT =

IGNORE_PATHS =

JWT_SECRET =
JWT_ACCESS_TOKEN_EXP =
JWT_REFRESH_TOKEN_EXP =
JWT_ISSUER =

CORS_ORIGIN =
CORS_METHODS =
CORS_ALLOWED_HEADERS =

.env.example文件的作用是确保.env文件配置了所有环境变量,防止生产程序中出现运行时错误。当启用安全模式加载时,若.env中有未配置的项,在启动程序时就会报错:

error: Uncaught MissingEnvVarsError: The following variables were defined in the example file but are not present in the environment:
  APP_HOST

Make sure to add them to your env file.

启用安全模式加载环境变量:
config/config.ts

import {
    config as loadConfig } 
  • 5
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
该资源内项目源码是个人的课程设计、毕业设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。 该资源内项目源码是个人的课程设计,代码都测试ok,都是运行成功后才上传资源,答辩评审平均分达到96分,放心下载使用! ## 项目备注 1、该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的,请放心下载使用! 2、本项目适合计算机相关专业(如计科、人工智能、通信工程、自动化、电子信息等)的在校学生、老师或者企业员工下载学习,也适合小白学习进阶,当然也可作为毕设项目、课程设计、作业、项目初期立项演示等。 3、如果基础还行,也可在此代码基础上进行修改,以实现其他功能,也可用于毕设、课设、作业等。 下载后请首先打开README.md文件(如有),仅供学习参考, 切勿用于商业用途。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值