如何编写一个TypeScript库

编写模块化的代码是一个非常不错的想法,没有比编写一个库更加模块化了。那要如何编写一个TypeScript库呢?这就是本文的意图,本文的代码可以运行在TypeScript 2.x 3.x和4.x上。 第一步∶设置tsconfig.json 创建一个项目目录,本文目录名称为 typescript-library ,然后在这个目录下面添加配置文件 tsconfig.json 文件内容类似于下面这样: typescript-library/tsconfig.json { "compilerOptions": { "module": "commonjs", "target": "es2015", "declaration": true, "outDir": "./dist" }, "include": [ "src/**/*" ] } 这跟平常配置一个一般的项目差不多,唯一需要强调的一点就是,需要添加 "declaration": true 字段。有了这个配置,编译后的代码会生成以 .d.ts 结尾的文件,这些文件里面会包含代码里面的类型。如果别人在使用你写的代码,他们就会从TypeScript的类型系统中获得自动补全的好处,类型安全的好处。 关于其他选项,让我们快速浏览一下:如果你想让你的代码与大多数当前的node.js应用程序无缝运行,那么"module": "commonjs"模块编译器选项是必需的。如果你正在构建一个面向浏览器的库,那么请将其替换为"module": "esnext"。"target": "es2015"指定你的代码将被转译成哪个版本的JavaScript。这需要与你想要支持的最旧的node.js版本(或最旧的浏览器)保持一致。将编译目标选择为es2015可以使你的库与node.js版本8及以上版本兼容。"outDir": "./dist"将把你编译后的文件写入到dist文件夹中,"include"选项指定你的源代码存放位置。 第二步:实现你的库 就像你不写库代码,同样的方式。创建一个src文件夹,把你的所有库源代码(程序逻辑,数据,资产)都放在这个目录。 为了这个demo,我们将写一个不太实用的hello-world.ts文件,看起来像这样: typescript-library/src/hello-world.ts export function sayHello() { console.log('hi') } export function sayGoodbye() { console.log('goodbye') } 第三步:创建一个 index.ts 文件 在您的src文件夹中添加一个index.ts文件。它的目的是导出您希望供消费者使用的库的所有部分。在我们的例子中,它只是: typescript-library/src/index.ts export {sayHello, sayGoodbye} from './hello-world' 消费者以后可以像这样使用库: someotherproject/src/somefile.ts import {sayHello} from 'hwrld' sayHello(); 你看到我们有一个新的名字叫做“hwrld”,我们还没有在任何地方见过。这是什么名字呢?这是你要发布到npm的库的名字,也叫做包名! 第四步:配置 package.json 包名是消费者以后用来从您的库中导入功能的。 对于此demo,我选择了hwrld,因为它仍然可以在npm上使用。 包名通常位于package.json的顶部。 整个package.json看起来如下: typescript-library/package.json { "name": "hwrld", "version": "1.0.0", "description": "Can log \"hello world\" and \"goodbye world\" to the console!", "main": "dist/index.js", "types": "dist/index.d.ts", "files": [ "/dist" ] } 如果你还没有一个包,你可以使用npm init来创建一个,它会指导你完成整个过程。记住,你选择的包名将被人们用于他们的imports,所以要明智地选择! ...

March 9, 2023

使用MobaXterm做端口转发

SSH端口转发的作用 SSH端口转发是一种网络技术,它允许用户通过SSH连接到远程主机并在两个计算机之间安全地传输数据。SSH端口转发将本地端口绑定到远程主机上的一个端口,从而允许用户在本地主机上运行服务并让远程主机访问该服务。 SSH端口转发可以用于以下几种情况: 安全访问远程服务:在某些情况下,用户需要访问远程主机上的服务,但是这些服务可能不安全或未加密。使用SSH端口转发,用户可以通过SSH隧道连接到远程主机,并将本地端口绑定到远程主机上的服务端口,从而安全地访问远程服务。 绕过防火墙限制:某些网络环境下,防火墙可能会限制对某些端口的访问。使用SSH端口转发,用户可以将本地端口绑定到远程主机上的允许端口,并通过SSH隧道访问被限制的服务。 远程调试应用程序:使用SSH端口转发,开发人员可以在本地主机上运行调试器,并将本地端口绑定到远程主机上的应用程序端口,从而可以在本地主机上调试远程应用程序。 SSH端口转发是一种强大的网络技术,可以帮助用户安全地访问远程服务,绕过防火墙限制以及进行远程调试应用程序等操作。 SSH端口转发的应用场景 SSH端口转发可以用于以下场景: 访问本地服务:在某些情况下,用户需要访问本地主机上的服务,但是该主机无法公开访问。使用SSH端口转发,用户可以将本地服务端口绑定到远程主机上的端口,从而在远程主机上访问本地服务。 跳板机访问内网服务:在企业内部网络中,某些服务可能只能在内网中访问。使用SSH端口转发,用户可以通过跳板机访问内网服务,而无需直接暴露内网服务。 安全文件传输:使用SSH端口转发,用户可以在两台主机之间安全地传输文件,而无需将文件暴露在公共网络中。 SSH端口转发是一种非常有用的网络技术,可以帮助用户在各种场景下安全地访问服务和传输数据。 MobaXterm软件 MobaXterm是一款功能强大的终端软件,不仅支持SSH连接,还支持端口转发功能。在MobaXterm中进行端口转发非常简单,只需要在SSH会话中配置端口转发规则即可。用户可以通过MobaXterm实现安全访问远程服务、绕过防火墙限制、访问本地服务、跳板机访问内网服务以及安全文件传输等操作。 配置MobaXterm端口转发访问服务器内网的数据库案例 假设用户需要从本地主机访问远程服务器内网中的数据库,可以使用MobaXterm进行端口转发。首先,在MobaXterm中创建一个SSH会话到远程服务器,然后在“端口转发”选项卡中添加一个新的端口转发规则。用户需要将本地主机上任意一个端口绑定到远程服务器上的数据库端口(通常是3306),并选择“本地端口绑定到远程端口”选项。然后,用户可以在本地主机上使用数据库客户端连接到绑定的本地端口,从而访问远程服务器内网中的数据库。 首先找到工具栏上的 Tunneling 按钮,如图1 图1 在弹出的 MobaSSHTunnel 窗口的左下角点击 New SSH tunnel 按钮,如图2 图2 在弹出的配置窗口,填写本地监听的端口 Forwarded port , SSH server SSH login SSH port ,然后是目标服务器的IP地址和端口 Remote server Remote port 图3 SSH login 指得是登录跳板机的用户名 可以把登录的服务器当中跳板机,把本地的端口转发到内网的其他机器 当然,还有更简单的一行命令就可以搞定的方式 😁 ssh -L local_port:remote_server:remote_port ssh_login@ssh_host_or_ip 名称 解释 local_port 本地监听端口 remote_server 目标服务器内网IP remote_port 目标服务器端口 ssh_login 跳板机使用用户名 ssh_host_or_ip 跳板机的host或者ip Socks协议 偷偷的告诉你,还可以使用这种方式来进行socks协议的转发,这个办法可以用来科学上网哟 😀上 ...

February 24, 2023

是什么造就了高级工程师?编写软件还是构建系统

是什么造就了高级工程师?编写软件还是构建系统? 初级工程师关心编写软件,他们以代码质量、采用最佳实践,采用前沿技术为价值。他们投入大量时间学习新技术。对他们来说,最终目标是创建优雅、高性能、可维护的软件。 高级工程师关心的是构建系统。 对他们来说,创建软件只是其中一个步骤。 首先,他们会质疑是否需要构建软件。他们会问将要解决什么问题,为什么解决这些问题很重要。他们询问谁将使用该软件以及使用的规模。他们考虑软件将在哪里运行,以及他们将如何监控它是否正常工作。 他们还决定如何衡量软件是否真正解决了它应该解决的问题。 构建系统比构建软件要难得多。 甚至可能会使人不自在。作为一名工程师,呆在原地,并专注于完善这段漂亮的代码是非常诱人的。人们很容易认为确定需求是产品经理的工作,而部署软件应该由运营团队负责。但是,通过参与构建系统的这些方面,您会带来很多价值。您是最了解您的软件的人,也是您最了解如何运行它、如何监控它、扩展它有多容易等等。更重要的是,您的分析思维和解决问题的能力,使您有洞察力关于产品要求非常有价值。 技术专长当然非常重要。优雅、高性能、可维护的软件更易于运行,中断次数更少,更易于扩展和推理。然而,它可能解决了一个错误的商业问题。或者客户不喜欢它是因为性能问题,而您甚至不知道,因为您没有监控它。 让我们更深入地了解构建系统的一部分事项(非详尽)列表: 定义需求-与产品经理合作,了解他们想要解决的问题;也许您会有更好的办法,更少的投入; 定义NFR(non-functional requirements)-与PM讨论非功能需求-系统应处理多少用户,性能、吞吐量和延迟的要求是什么?是否有任何安全或法规遵从性考虑?我们需要审计吗?期望的可用性是什么? 规划迭代-与您的团队一起提出实施计划;确保您定义了小的、可演示的里程碑,以便您能够尽快开始交付价值;与PM(Product Manager 产品经理)就里程碑达成一致。 确定依赖关系-确保您确定了团队之外的所有依赖关系,并与EM(Engagement Manager 项目经理)或团队直接合作,为他们获取一些ETA(预计到达时间)。相应地调整里程碑。 测试-根据公司的运营方式,与团队或QE(Quality Engineer 质量工程师)团队一起决定测试策略。同意推出所需的质量阈值(例如,没有未解决的主要错误或测试覆盖率超过X%)。 部署-与您的团队一起决定如何部署系统。您需要一些新的基础设施吗?还是可以重用现有的基础设施?如果您需要很多,费用是多少? 可观察性-决定如何监控系统的运行状况,并建立解决生产问题的流程(例如随叫随到的团队)。使用第三方解决方案设置监控器和仪表板。 推广沟通-一旦您与团队和项目经理商定了推广日期,请确保所有利益相关者都知道。检查是否需要任何文档更改。 衡量成功-决定衡量项目是否成功的指标。有人在使用新系统吗?用户是否能够完成他们的任务? 我见过很多工程师,他们坚信,提升职业生涯的唯一途径是投资于他们的技术技能。虽然这很重要,但对公司来说唯一重要的是你对业务的影响有多大。将重点从软件转移到系统将使您在增加软件方面处于更好的位置。

December 10, 2022

快速上手!如何使用MySQL导入CSV格式数据

在大数据时代,我们每天面临着大量的数据需要处理。表格型数据是最常见的一种,特别是财务从业者。如何快速的把CSV类型的数据导入到数据库进行快速处理呢?今天我们就来介绍其中一种。 LOAD DATA语句定义 我们先来看看MySQL的 LOAD DATA 语句的定义 LOAD DATA [LOW_PRIORITY | CONCURRENT] [LOCAL] INFILE 'file_name' [REPLACE | IGNORE] INTO TABLE tbl_name [PARTITION (partition_name [, partition_name] ...)] [CHARACTER SET charset_name] [{FIELDS | COLUMNS} [TERMINATED BY 'string'] [[OPTIONALLY] ENCLOSED BY 'char'] [ESCAPED BY 'char'] ] [LINES [STARTING BY 'string'] [TERMINATED BY 'string'] ] [IGNORE number {LINES | ROWS}] [(col_name_or_user_var [, col_name_or_user_var] ...)] [SET col_name={expr | DEFAULT} [, col_name={expr | DEFAULT}] ...] LOAD DATA 语句以非常高的速度将文本文件中的行读入表中。 该文件可以从服务器主机或客户端主机读取,具体取决于是否给出了 LOCAL 修饰符。 LOCAL 还会影响数据解释和错误处理。 ...

December 1, 2022

Docker删除镜像的另外一种姿势

Docker删除镜像的另外一种姿势 我们来看一下官方 docker image rm 的文档 是的,你没有看错,就是这么简单,没有非常详细的解释。当你碰到下面的情况的时候,很有可能就不知道所措了。 <none> <none> 当你使用使用 docker images 查看镜像列表的时候,很有可能你会看到下面这样的一些镜像列表 还有可能多个tag对象到同一个镜像,像下面这样 这时候直接通过 IMAGE ID 删除镜像,会得到如下的提示内容: $ docker image rm 3635ffe4971c Error response from daemon: conflict: unable to delete 3635ffe4971c (must be forced) - image is referenced in multiple repositories 提示不能删除这个镜像,因为有多个 repositories 使用了这个镜像 上面第一种情况比较好处理,直接使用命令 docker image rm IMAGE_ID 即可删除,可是第二种情况就不行了。 使用@符号 这时我们使用另外一种方式,使用 @ 符号把 REPOSITORY 和 sha256 连接起来进行删除。 首先得找到 sha256 ...

December 1, 2022

保持SSH会话在线

保持SSH会话在线 1. 概览 有多少次,我们想要保持SSH会话一直处于连接状态,以保持应用程序运行,或者只是避免在返回我们使用的SSH窗口时感到沮丧。 在本教程中,你将获得如何通过防止SSH会话超时,直到你关闭终端窗口。 2. 为什么SSH会关闭连接? 我们为了使用SSH登录到服务器上,目的服务器上的守护进程(sshd)一定是保持运行状态。如果SSH客户端一段时间没有发送到目的服务器,服务器会在超过一段时间后关闭连接。 为了防止关闭SSH连接,我们可以在客户端或者服务端进行配置。 3. 设置配置文件 有几个配置文件可以修改,以保持SSH会话的连接,避免超时。要看是从客户端配置还是服务端配置。 3.1 客户端配置 客户端文件位置 $HOME/.ssh/config 如果我们使用使用 cat $HOME/.ssh/config ,可能会得到一个错误信息 “no file found”。 $ cat $HOME/.ssh/config cat: /.ssh/config: No such file or directory 如果我们看到这个错误消息,意味着我们需要手动创建这个配置文件。如果 .ssh 目录不存在,首先创建 .ssh 目录,使用命令 mkdir $HOME/.ssh 来创建目录,如果提示目录已经存在,我们将会看到一个消息 “File exists”,请忽略即可;如果目录创建成功,我们不会看到任何输出信息。 $ mkdir $HOME/.ssh 然后创建配置文件 touch $HOME/.ssh/config。 $ touch $HOME/.ssh/config 一旦我们创建好配置文件,我们还需要使用 chmod 修改配置文件的权限,不能让所有人都可以编辑这个配置文件。 $ chmod 600 $HOME/.ssh/config 现在我们可以任何编辑器来编辑这个配置文件了,比如 nano 或者 vim ,在终端使用 vim $HOME/.ssh/config 打开配置文件。 现在让我们来添加一些配置信息到配置文件里面。在 vim 按 i 进入编辑模式,然后输入下面的内容: ...

November 29, 2022

Python变量可变性

Python变量的可变与不可变 Mutable and Immutable 可变是一种奇特的说法,即对象的内部状态已更改/突变。 所以,最简单的定义是:内部状态可以改变的对象是可变的。 另一方面,不可变对象一旦创建就不允许对其进行任何更改。这两种状态都是 Python 数据结构的组成部分。 可变定义 可变是指某些东西是可变的或有能力改变的。 在 Python 中“可变”是对象改变其值的能力。这些通常是存储数据集合的对象。 不可变定义 不可变是指随着时间的推移不可能发生变化。 在 Python 中,如果一个对象的值不能随时间改变,那么它就是不可变的。一旦创建,这些对象的值是永久固定的,直到被回收。 可变和不可变对象列表 内置可变类型: 列表(List) 集合(Set) 字典(Dictionarie) 自定义类(User-Defined Classes 取决于用户的定义) 内置不可变类型: 数字 (Integer, Rational, Float, Decimal, Complex & Booleans) 字符串(String) 元组(Tuple) 冻结的集合(Frozen Set) 自定义类(User-Defined Classes 取决于用户的定义) 对象可变性是使 Python 成为动态类型语言的特征之一。尽管 Python 中的 Mutable 和 Immutable 是一个非常基本的概念,但由于不变性的不传递性,它有时会让人有些困惑。 Python 中的对象 在 Python 中,一切都被视为对象。 每个对象都具有以下三个属性: Identity — 这是指对象在计算机内存中引用的地址,使用id函数可以得到唯一标识。 Type — 这是指创建的对象的类型。 例如:整数、列表、字符串等。 Value — 这是指对象存储的值。 例如:List=[1,2,3] 将保存数字 1,2 和 3 虽然 ID 和 Type 一经创建就无法更改,但 Mutable 对象的值可以更改。 ...

November 13, 2022

Docker修改时区

修改各Linux发行版本时区为上海 Debian系统 在系统命令行使用 echo "Asia/Shanghai" > /etc/timezone cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 在Dockerfile使用 RUN echo "Asia/Shanghai" > /etc/timezone && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 在Docker compose的配置文件里面进行配置,添加一个环境变量 TZ=Asia/Shanghai Ubuntu 20.04 在Dockerfile使用 ENV DEBIAN_FRONTEND=noninteractive TZ="Asia/Shanghai" RUN apt-get update && apt-get install -y tzdata 这里需要注意两点: 需要设置DEBIAN_FRONTEND=noninteractive,否则在安装tzdata的时候会有交互的选择,会阻止后面的命令运行 设置环境变量TZ Apline RUN apk --update add tzdata && \ cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && \ echo "Asia/Shanghai" > /etc/timezone && \ apk del tzdata && \ rm -rf /var/cache/apk/* CentOS 在系统命令行使用 echo "Asia/Shanghai" > /etc/timezone cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 在Dockerfile使用 RUN echo "Asia/Shanghai" > /etc/timezone && cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime 其实跟Debian系统的配置一样的 ...

July 8, 2022

Java的Exception体系

众所周知,Java异常分为两大类:检查弄(checked)异常和非检查型(unchecked)异常。 Java异常层级 先来看看Java异常层级图: 所有异常都是由Throwable继承而来,但在在下一层立即分解为两个分支:Error和Exception。 Error类层级结构描述了Java运行时系统的内部错误和资源耗尽错误,例如OutOfMemoryError。你的应用不应该抛出这种类型的对象。如果出现了这样的内部错误,除了通知用户,并尽力妥善终止程序之外,你几乎做了不什么处理。这各情况也非常少出现。 在设计Java程序时,着重关注Exception以及基子类。Exception又分解为两个分支:一个是派生于RuntimeException;另外一个包含其他异常。一般的使用规则是:由编程错误导致的异常属于RuntimeException;如果程序本身没有问题,但由于像I/O错误这类问题导致的异常属于其他异常。 派生于RuntimeException的异常通常包括如下问题: 错误的强制类型转换 数组访问越界 访问null指针 不派生于RuntimeException的异常包括: 访问一个不存在的文件 超载文件末尾继续读取数据 根据给定的字符串查找Class对象,而这个字符串表示的类并不存在 使用检查型和非检查型异常的基本准则 如果可以合理的期望客户端(调用端)从异常中恢复,则使用检查型异常 如果客户端(启用端)无法从异常中恢复,则使用非检查型异常 举个例子,在打开一个文件之前,我们需要先验证文件名。如果用户输入的文件名是非法的,我们可以抛出一个自定义的检查型异常。 if (!isCorrectFileName(fileName)) { throw new InvalidFilenameCheckedException("非法的文件名"); } 这样的话,客户端(调用端)在得到异常之后,可以要求用户输入另外一个合法的文件名。 然而,如果客户端(调用端)传入了一个null或者空的字符串,意味着在代码当中出现了某些错误,这各情况可以抛出一个非检查型异常。 if (fileName == null || fileName.isEmpty()) { throw new FilenameUncheckedException("未知错误"); } Spring Boot当中是使用RuntimeException还是其他的Exception 这个问题在我刚开始使用Spring Boot的时候困扰了我很久,现在我有了一个统一的答案,那就是上面的原则。但是再加一条,那就是优先考虑使用检查型(checked)异常,尽可能把问题都暴露出来,这样的话在别人调用代码的时候就知道什么异常可能会发生,然后做出必要的处理。而不是等到了上线之后发现一堆的runtime exception,这样对用户体验是非常差的。

March 21, 2022 · Kevin Jiang

本地虚拟机搭建Kubernetes

以下内容都是在Ubuntu20.04.3系统上完成。 安装Docker-ce # step 1: 安装必要的一些系统工具 sudo apt-get update sudo apt-get -y install apt-transport-https ca-certificates curl software-properties-common # step 2: 安装GPG证书 curl -fsSL https://mirrors.aliyun.com/docker-ce/linux/ubuntu/gpg | sudo apt-key add - # Step 3: 写入软件源信息 sudo add-apt-repository "deb [arch=amd64] https://mirrors.aliyun.com/docker-ce/linux/ubuntu $(lsb_release -cs) stable" sudo apt -y install docker-ce docker-ce-cli containerd.io 修改 Docker 的 Cgroup Driver,编辑/etc/docker/daemon.json(没有该文件就新建一个),添加如下参数 { "exec-opts": ["native.cgroupdriver=systemd"], "registry-mirrors":[ "http://docker.mirrors.ustc.edu.cn", "http://registry.docker-cn.com", "http://hub-mirror.c.163.com" ], "insecure-registries":[ "docker.mirrors.ustc.edu.cn", "registry.docker-cn.com", "hub-mirror.c.163.com" ] } 如果当前用户为非root用户,把当前用户加入到docker用户组。 ...

December 2, 2021