通过typescript 开发jint js 插件
以前简单讲过开发机制以及设计,以下是集成typescript 方便进行开发的似乎以及简单示例代码
项目依赖的包
为了方便处理使用了tsup进行构建,同时基于ts 类型定义提供types 支持
代码简单说明
包含了对于公共部分的type 定义,以及插件部分代码引用
- 代码结构
├── loginplugin
│ ├── app.json
│ ├── myconfig.ts
│ └── userlogin.ts
├── package.json
├── tsconfig.json
├── tsup.config.ts
├── types
│ ├── global.d.ts
│ └── platform.d.ts
└── yarn.lock
- package.json
{
"name": "modules",
"version": "1.0.0",
"license": "MIT",
"devDependencies": {
"tsup": "^8.5.0",
"typescript": "^5.8.3"
},
"type": "module",
"main": "dist/userlogin.js",
"module": "dist/userlogin.js",
"types": "dist/userlogin.d.ts",
"files": [
"dist",
"README.md",
"LICENSE",
"types/platform.d.ts",
"types/global.d.ts"
],
"exports": {
".": "./dist/userlogin.js",
"./package.json": "./package.json"
},
"scripts": {
"build": "tsup",
"pack": "npm pack"
}
}
- tsconfig.json
{
"compilerOptions": {
"types": [
"./types/platform.d.ts",
"./types/global.d.ts"
],
"resolveJsonModule": true,
"target": "es2017",
"module": "commonjs",
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"strict": true,
"skipLibCheck": true
}
}
- tsup.config.ts
import { defineConfig } from 'tsup'
export default defineConfig({
entry: ['loginplugin/userlogin.ts'],
splitting: false,
sourcemap: true,
minify: false,
format:"esm",
dts: true,
external:["@scope/platform-common"], // @scope/platform-common 作为外部
clean: true,
})
- common 定义
包含了模块以及require 以及importNamespace
global.d.ts 属于公共定义,方便支持强类型定义,主要是类型定义
export {}
class Shortid {
static Generate(): string
}
type ShortIdModule = {
ShortId: typeof Shortid
}
interface ModuleMap {
shortid: ShortIdModule;
}
interface Platform {
funcs: {
queryDb: (name: string) => Promise<string>;
add: (name: string) => Promise<string>;
init: () => Promise<void>;
};
name: string;
version: string;
description: string;
}
type PlatformModule = {
"@scope/platform-common": {
platform: Platform
}
}
type PlatformTypes = "@scope/platform-common" | "platform-login"
type ModuleTypes = "shortid"
// 包装的global, 方便require 以及importNamespace 使用强类型,注意改写了node 的require(兼容jint),importNamespace 是jint 提供的
declare global {
function require<K extends PlatformTypes>(name: K): PlatformModule[K]
function importNamespace<K extends ModuleTypes>(name: K): ModuleMap[K]
}
- platform.d.ts 模块定义
declare module "@scope/platform-common" {
export interface Platform {
funcs: {
queryDb: (name: string) => Promise<string>;
add: (name: string) => Promise<string>;
init: () => Promise<void>;
};
name: string;
version: string;
description: string;
}
export const platform: Platform;
}
declare module "shortid" {
export class ShortId {
static Generate(): string;
}
}
namespace System {
namespace IO {
export class StreamWriter {
constructor(fileName: string);
WriteLine(line: string): void;
Dispose(): void;
}
}
}
- loginplugin/userlogin.ts
简单插件定义,会使用common 以及通过系统clr 暴露的三方库
import {platform} from "@scope/platform-common"
import conf from "./myconfig";
import appJson from "./app.json";
async function getNames(name:string):Promise<string> {
console.log("getNames "+name)
return await platform.funcs.queryDb(name);
}
function po(ob:string):string {
console.log(JSON.stringify(ob))
let ob_new = JSON.parse(ob);
ob_new.Login = (name:string)=> name;
ob_new.Name = "dddddddddddd" + Math.random()*100;
let token = ob_new.Login(ob_new.Name);
console.log("token"+token);
return JSON.stringify(ob_new);
}
function fs_op() {
let file = new System.IO.StreamWriter(`log-${Math.random()*100}.txt`);
file.WriteLine("Hello World");
file.Dispose();
}
function my_id():void {
console.log("my_conf"+ JSON.stringify(conf));
let platform = require("@scope/platform-common");
console.log("appJson"+JSON.stringify(appJson));
console.log(platform.platform.description);
let shortid = importNamespace("shortid");
let id = shortid.ShortId.Generate();
console.log("myid: "+id);
}
const queryUser = {
name: "dalong demo",
qv2: platform.funcs.queryDb,
add: platform.funcs.add,
init: platform.funcs.init,
getNames: getNames,
po: po,
fs_op: fs_op,
id:my_id,
qv2Async:platform.funcs.queryDb
}
export default queryUser
- c# 代码使用
实际上就是通过engine 引用模块,调用模块里边的方法
var ns = _engine.Modules.Import("./dist/userlogin.js").Get("default").AsObject();
var fn = ns.Get("id").AsFunctionInstance();
n.Call().UnwrapIfPromise();
- 打包
对于打包我们实际上可以直接复用npm 的,对于使用方基于npm 周边生态的玩法就可以了,平台部分提供调用npm api 的下载,解压,解析等
说明
以上是一个简单示例,比较粗糙,实际上对于common 部分的types 使用通用的包,对于插件部分使用更加明确的生命周期方法开发就会清晰不少,对于开发者也就比较友好了,后边抽象一个通用的模型
参考资料
https://github.com/egoist/tsup
https://tsup.egoist.dev/#typescript--javascript