chore: 更新版本号至 0.2.2,修改路由相关属性为 rid,重构认证中间件,添加 README 文档
This commit is contained in:
2
.npmrc
2
.npmrc
@@ -1,2 +1,2 @@
|
|||||||
//npm.xiongxiao.me/:_authToken=${ME_NPM_TOKEN}
|
/npm.cnb.cool/kevisual/registry/-/packages/:_authToken=${CNB_API_KEY}
|
||||||
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
|
//registry.npmjs.org/:_authToken=${NPM_TOKEN}
|
||||||
@@ -55,7 +55,7 @@ app
|
|||||||
|
|
||||||
| 方法 | 参数 | 说明 |
|
| 方法 | 参数 | 说明 |
|
||||||
| ----------------------------------- | ----------------------------------------- | -------------------------------------------- |
|
| ----------------------------------- | ----------------------------------------- | -------------------------------------------- |
|
||||||
| `ctx.call(msg, ctx?)` | `{ path, key?, payload?, ... } \| { id }` | 调用其他路由,返回完整 context |
|
| `ctx.call(msg, ctx?)` | `{ path, key?, payload?, ... } \| { rid }` | 调用其他路由,返回完整 context |
|
||||||
| `ctx.run(msg, ctx?)` | `{ path, key?, payload? }` | 调用其他路由,返回 `{ code, data, message }` |
|
| `ctx.run(msg, ctx?)` | `{ path, key?, payload? }` | 调用其他路由,返回 `{ code, data, message }` |
|
||||||
| `ctx.forward(res)` | `{ code, data?, message? }` | 设置响应结果 |
|
| `ctx.forward(res)` | `{ code, data?, message? }` | 设置响应结果 |
|
||||||
| `ctx.throw(code?, message?, tips?)` | - | 抛出自定义错误 |
|
| `ctx.throw(code?, message?, tips?)` | - | 抛出自定义错误 |
|
||||||
@@ -64,13 +64,13 @@ app
|
|||||||
|
|
||||||
```ts
|
```ts
|
||||||
import { App } from '@kevisual/router';
|
import { App } from '@kevisual/router';
|
||||||
import z from 'zod';
|
import { z } from 'zod';
|
||||||
const app = new App();
|
const app = new App();
|
||||||
app.listen(4002);
|
app.listen(4002);
|
||||||
|
|
||||||
// 基本路由
|
// 基本路由
|
||||||
app
|
app
|
||||||
.route({ path: 'user', key: 'info', id: 'user-info' })
|
.route({ path: 'user', key: 'info', rid: 'user-info' })
|
||||||
.define(async (ctx) => {
|
.define(async (ctx) => {
|
||||||
// ctx.query 包含请求参数
|
// ctx.query 包含请求参数
|
||||||
const { id } = ctx.query;
|
const { id } = ctx.query;
|
||||||
@@ -129,7 +129,7 @@ const app = new App();
|
|||||||
// 定义中间件
|
// 定义中间件
|
||||||
app
|
app
|
||||||
.route({
|
.route({
|
||||||
id: 'auth-example',
|
rid: 'auth-example',
|
||||||
description: '权限校验中间件',
|
description: '权限校验中间件',
|
||||||
})
|
})
|
||||||
.define(async (ctx) => {
|
.define(async (ctx) => {
|
||||||
@@ -142,7 +142,7 @@ app
|
|||||||
})
|
})
|
||||||
.addTo(app);
|
.addTo(app);
|
||||||
|
|
||||||
// 使用中间件(通过 id 引用)
|
// 使用中间件(通过 rid 引用)
|
||||||
app
|
app
|
||||||
.route({ path: 'admin', key: 'panel', middleware: ['auth-example'] })
|
.route({ path: 'admin', key: 'panel', middleware: ['auth-example'] })
|
||||||
.define(async (ctx) => {
|
.define(async (ctx) => {
|
||||||
@@ -164,17 +164,17 @@ app
|
|||||||
path: 'dog',
|
path: 'dog',
|
||||||
key: 'info',
|
key: 'info',
|
||||||
description: '获取狗的信息',
|
description: '获取狗的信息',
|
||||||
metedata: {
|
metadata: {
|
||||||
args: {
|
args: {
|
||||||
owner: z.string().describe('狗主人姓名'),
|
name: z.string().describe('狗的姓名'),
|
||||||
age: z.number().describe('狗的年龄'),
|
age: z.number().describe('狗的年龄'),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
.define(async (ctx) => {
|
.define(async (ctx) => {
|
||||||
const { owner, age } = ctx.query;
|
const { name, age } = ctx.query;
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
content: `这是一只${age}岁的狗,主人是${owner}`,
|
content: `这是一只${age}岁的狗,名字是${name}`,
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
.addTo(app);
|
.addTo(app);
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"$schema": "https://json.schemastore.org/package",
|
"$schema": "https://json.schemastore.org/package",
|
||||||
"name": "@kevisual/router",
|
"name": "@kevisual/router",
|
||||||
"version": "0.1.7",
|
"version": "0.2.2",
|
||||||
"description": "",
|
"description": "",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"main": "./dist/router.js",
|
"main": "./dist/router.js",
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
"@kevisual/query": "^0.0.55",
|
"@kevisual/query": "^0.0.55",
|
||||||
"@kevisual/remote-app": "^0.0.7",
|
"@kevisual/remote-app": "^0.0.7",
|
||||||
"@kevisual/use-config": "^1.0.30",
|
"@kevisual/use-config": "^1.0.30",
|
||||||
"@opencode-ai/plugin": "^1.2.27",
|
"@opencode-ai/plugin": "^1.3.0",
|
||||||
"@types/bun": "^1.3.11",
|
"@types/bun": "^1.3.11",
|
||||||
"@types/crypto-js": "^4.2.2",
|
"@types/crypto-js": "^4.2.2",
|
||||||
"@types/node": "^25.5.0",
|
"@types/node": "^25.5.0",
|
||||||
|
|||||||
@@ -60,11 +60,11 @@ export const createRouterAgentPluginFn = (opts?: {
|
|||||||
addCallFn(router as App)
|
addCallFn(router as App)
|
||||||
}
|
}
|
||||||
if (router) {
|
if (router) {
|
||||||
(router as any).route({ path: 'auth', key: '', id: 'auth', description: '认证' }).define(async (ctx) => { }).addTo(router as App, {
|
(router as any).route({ path: 'auth', key: '', rid: 'auth', description: '认证' }).define(async (ctx) => { }).addTo(router as App, {
|
||||||
overwrite: false
|
overwrite: false
|
||||||
});
|
});
|
||||||
|
|
||||||
(router as any).route({ path: 'auth-admin', key: '', id: 'auth-admin', description: '认证' }).define(async (ctx) => { }).addTo(router as App, {
|
(router as any).route({ path: 'auth-admin', key: '', rid: 'auth-admin', description: '认证' }).define(async (ctx) => { }).addTo(router as App, {
|
||||||
overwrite: false
|
overwrite: false
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
68
src/route.ts
68
src/route.ts
@@ -78,18 +78,18 @@ export type RouteContext<T = { code?: number }, U extends SimpleObject = {}, S =
|
|||||||
export type SimpleObject = Record<string, any>;
|
export type SimpleObject = Record<string, any>;
|
||||||
export type Run<T extends SimpleObject = {}> = (ctx: Required<RouteContext<T>>) => Promise<typeof ctx | null | void>;
|
export type Run<T extends SimpleObject = {}> = (ctx: Required<RouteContext<T>>) => Promise<typeof ctx | null | void>;
|
||||||
export type RunMessage = { path?: string; key?: string; id?: string; payload?: any; };
|
export type RunMessage = { path?: string; key?: string; id?: string; payload?: any; };
|
||||||
export type NextRoute = Pick<Route, 'id' | 'path' | 'key'>;
|
export type NextRoute = Pick<Route, 'rid' | 'path' | 'key'>;
|
||||||
export type RouteMiddleware =
|
export type RouteMiddleware =
|
||||||
| {
|
| {
|
||||||
path?: string;
|
path?: string;
|
||||||
key?: string;
|
key?: string;
|
||||||
id?: string;
|
rid?: string;
|
||||||
}
|
}
|
||||||
| string;
|
| string;
|
||||||
export type RouteOpts<U = {}, T = SimpleObject> = {
|
export type RouteOpts<U = {}, T = SimpleObject> = {
|
||||||
path?: string;
|
path?: string;
|
||||||
key?: string;
|
key?: string;
|
||||||
id?: string;
|
rid?: string;
|
||||||
run?: Run<U>;
|
run?: Run<U>;
|
||||||
nextRoute?: NextRoute; // route to run after this route
|
nextRoute?: NextRoute; // route to run after this route
|
||||||
description?: string;
|
description?: string;
|
||||||
@@ -99,7 +99,7 @@ export type RouteOpts<U = {}, T = SimpleObject> = {
|
|||||||
isDebug?: boolean;
|
isDebug?: boolean;
|
||||||
};
|
};
|
||||||
export type DefineRouteOpts = Omit<RouteOpts, 'idUsePath' | 'nextRoute'>;
|
export type DefineRouteOpts = Omit<RouteOpts, 'idUsePath' | 'nextRoute'>;
|
||||||
const pickValue = ['path', 'key', 'id', 'description', 'type', 'middleware', 'metadata'] as const;
|
const pickValue = ['path', 'key', 'rid', 'description', 'type', 'middleware', 'metadata'] as const;
|
||||||
|
|
||||||
|
|
||||||
export type Skill<T = SimpleObject> = {
|
export type Skill<T = SimpleObject> = {
|
||||||
@@ -143,7 +143,7 @@ export class Route<M extends SimpleObject = SimpleObject, U extends SimpleObject
|
|||||||
* 二级路径
|
* 二级路径
|
||||||
*/
|
*/
|
||||||
key?: string;
|
key?: string;
|
||||||
id?: string;
|
rid?: string;
|
||||||
run?: Run<BuildRouteContext<M, U>>;
|
run?: Run<BuildRouteContext<M, U>>;
|
||||||
nextRoute?: NextRoute; // route to run after this route
|
nextRoute?: NextRoute; // route to run after this route
|
||||||
description?: string;
|
description?: string;
|
||||||
@@ -164,7 +164,7 @@ export class Route<M extends SimpleObject = SimpleObject, U extends SimpleObject
|
|||||||
this.key = key;
|
this.key = key;
|
||||||
const pathKey = `${path}$$${key}`;
|
const pathKey = `${path}$$${key}`;
|
||||||
if (opts) {
|
if (opts) {
|
||||||
this.id = opts.id || hashIdMd5Sync(pathKey);
|
this.rid = opts.rid || hashIdMd5Sync(pathKey);
|
||||||
this.run = opts.run as Run<BuildRouteContext<M, U>>;
|
this.run = opts.run as Run<BuildRouteContext<M, U>>;
|
||||||
this.nextRoute = opts.nextRoute;
|
this.nextRoute = opts.nextRoute;
|
||||||
this.description = opts.description;
|
this.description = opts.description;
|
||||||
@@ -176,8 +176,8 @@ export class Route<M extends SimpleObject = SimpleObject, U extends SimpleObject
|
|||||||
} else {
|
} else {
|
||||||
this.middleware = [];
|
this.middleware = [];
|
||||||
}
|
}
|
||||||
if (!this.id) {
|
if (!this.rid) {
|
||||||
this.id = hashIdMd5Sync(pathKey);
|
this.rid = hashIdMd5Sync(pathKey);
|
||||||
}
|
}
|
||||||
this.isDebug = opts?.isDebug ?? false;
|
this.isDebug = opts?.isDebug ?? false;
|
||||||
}
|
}
|
||||||
@@ -313,7 +313,7 @@ export class QueryRouter<T extends SimpleObject = SimpleObject> implements throw
|
|||||||
* @param uniqueId
|
* @param uniqueId
|
||||||
*/
|
*/
|
||||||
removeById(uniqueId: string) {
|
removeById(uniqueId: string) {
|
||||||
this.routes = this.routes.filter((r) => r.id !== uniqueId);
|
this.routes = this.routes.filter((r) => r.rid !== uniqueId);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 执行route
|
* 执行route
|
||||||
@@ -327,7 +327,7 @@ export class QueryRouter<T extends SimpleObject = SimpleObject> implements throw
|
|||||||
const maxNextRoute = this.maxNextRoute;
|
const maxNextRoute = this.maxNextRoute;
|
||||||
ctx = (ctx || {}) as RouteContext<T>;
|
ctx = (ctx || {}) as RouteContext<T>;
|
||||||
ctx.currentPath = path;
|
ctx.currentPath = path;
|
||||||
ctx.currentId = route?.id;
|
ctx.currentId = route?.rid;
|
||||||
ctx.currentKey = key;
|
ctx.currentKey = key;
|
||||||
ctx.currentRoute = route;
|
ctx.currentRoute = route;
|
||||||
ctx.index = (ctx.index || 0) + 1;
|
ctx.index = (ctx.index || 0) + 1;
|
||||||
@@ -354,11 +354,11 @@ export class QueryRouter<T extends SimpleObject = SimpleObject> implements throw
|
|||||||
let route: Route | undefined;
|
let route: Route | undefined;
|
||||||
const isString = typeof item === 'string';
|
const isString = typeof item === 'string';
|
||||||
if (isString) {
|
if (isString) {
|
||||||
route = this.routes.find((r) => r.id === item);
|
route = this.routes.find((r) => r.rid === item);
|
||||||
} else {
|
} else {
|
||||||
route = this.routes.find((r) => {
|
route = this.routes.find((r) => {
|
||||||
if (item.id) {
|
if (item.rid) {
|
||||||
return r.id === item.id;
|
return r.rid === item.rid;
|
||||||
} else {
|
} else {
|
||||||
// key 可以是空,所以可以不严格验证
|
// key 可以是空,所以可以不严格验证
|
||||||
return r.path === item.path && r.key == item.key;
|
return r.path === item.path && r.key == item.key;
|
||||||
@@ -408,8 +408,8 @@ export class QueryRouter<T extends SimpleObject = SimpleObject> implements throw
|
|||||||
ctx.message = e.message;
|
ctx.message = e.message;
|
||||||
ctx.body = null;
|
ctx.body = null;
|
||||||
} else {
|
} else {
|
||||||
console.error(`[router error] fn:${route.path}-${route.key}:${route.id}`);
|
console.error(`[router error] fn:${route.path}-${route.key}:${route.rid}`);
|
||||||
console.error(`[router error] middleware:${middleware.path}-${middleware.key}:${middleware.id}`);
|
console.error(`[router error] middleware:${middleware.path}-${middleware.key}:${middleware.rid}`);
|
||||||
console.error(e)
|
console.error(e)
|
||||||
ctx.code = 500;
|
ctx.code = 500;
|
||||||
ctx.message = 'Internal Server Error';
|
ctx.message = 'Internal Server Error';
|
||||||
@@ -438,7 +438,7 @@ export class QueryRouter<T extends SimpleObject = SimpleObject> implements throw
|
|||||||
ctx.code = e.code;
|
ctx.code = e.code;
|
||||||
ctx.message = e.message;
|
ctx.message = e.message;
|
||||||
} else {
|
} else {
|
||||||
console.error(`[router error] fn:${route.path}-${route.key}:${route.id}`);
|
console.error(`[router error] fn:${route.path}-${route.key}:${route.rid}`);
|
||||||
console.error(`[router error] error`, e);
|
console.error(`[router error] error`, e);
|
||||||
ctx.code = 500;
|
ctx.code = 500;
|
||||||
ctx.message = 'Internal Server Error';
|
ctx.message = 'Internal Server Error';
|
||||||
@@ -455,8 +455,8 @@ export class QueryRouter<T extends SimpleObject = SimpleObject> implements throw
|
|||||||
if (route.nextRoute.path || route.nextRoute.key) {
|
if (route.nextRoute.path || route.nextRoute.key) {
|
||||||
path = route.nextRoute.path;
|
path = route.nextRoute.path;
|
||||||
key = route.nextRoute.key;
|
key = route.nextRoute.key;
|
||||||
} else if (route.nextRoute.id) {
|
} else if (route.nextRoute.rid) {
|
||||||
const nextRoute = this.routes.find((r) => r.id === route.nextRoute.id);
|
const nextRoute = this.routes.find((r) => r.rid === route.nextRoute.rid);
|
||||||
if (nextRoute) {
|
if (nextRoute) {
|
||||||
path = nextRoute.path;
|
path = nextRoute.path;
|
||||||
key = nextRoute.key;
|
key = nextRoute.key;
|
||||||
@@ -529,14 +529,14 @@ export class QueryRouter<T extends SimpleObject = SimpleObject> implements throw
|
|||||||
* @param ctx
|
* @param ctx
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
async call(message: { id?: string; path?: string; key?: string; payload?: any }, ctx?: RouteContext<T> & { [key: string]: any }) {
|
async call(message: { rid?: string; path?: string; key?: string; payload?: any }, ctx?: RouteContext<T> & { [key: string]: any }) {
|
||||||
let path = message.path;
|
let path = message.path;
|
||||||
let key = message.key;
|
let key = message.key;
|
||||||
// 优先 path + key
|
// 优先 path + key
|
||||||
if (path) {
|
if (path) {
|
||||||
return await this.parse({ ...message, path, key }, { ...this.context, ...ctx });
|
return await this.parse({ ...message, path, key }, { ...this.context, ...ctx });
|
||||||
} else if (message.id) {
|
} else if (message.rid) {
|
||||||
const route = this.routes.find((r) => r.id === message.id);
|
const route = this.routes.find((r) => r.rid === message.rid);
|
||||||
if (route) {
|
if (route) {
|
||||||
path = route.path;
|
path = route.path;
|
||||||
key = route.key;
|
key = route.key;
|
||||||
@@ -630,11 +630,11 @@ export class QueryRouter<T extends SimpleObject = SimpleObject> implements throw
|
|||||||
hasRoute(path: string, key: string = '') {
|
hasRoute(path: string, key: string = '') {
|
||||||
return this.routes.find((r) => r.path === path && r.key === key);
|
return this.routes.find((r) => r.path === path && r.key === key);
|
||||||
}
|
}
|
||||||
findRoute(opts?: { path?: string; key?: string; id?: string }) {
|
findRoute(opts?: { path?: string; key?: string; rid?: string }) {
|
||||||
const { path, key, id } = opts || {};
|
const { path, key, rid } = opts || {};
|
||||||
return this.routes.find((r) => {
|
return this.routes.find((r) => {
|
||||||
if (id) {
|
if (rid) {
|
||||||
return r.id === id;
|
return r.rid === rid;
|
||||||
}
|
}
|
||||||
if (path) {
|
if (path) {
|
||||||
if (key !== undefined) {
|
if (key !== undefined) {
|
||||||
@@ -655,14 +655,14 @@ export class QueryRouter<T extends SimpleObject = SimpleObject> implements throw
|
|||||||
const tokenUser = ctx.state as unknown as { tokenUser?: any };
|
const tokenUser = ctx.state as unknown as { tokenUser?: any };
|
||||||
let isUser = !!tokenUser;
|
let isUser = !!tokenUser;
|
||||||
const list = this.getList(opts?.filter).filter((item) => {
|
const list = this.getList(opts?.filter).filter((item) => {
|
||||||
if (item.id === 'auth' || item.id === 'auth-can' || item.id === 'check-auth-admin' || item.id === 'auth-admin') {
|
if (item.rid === 'auth' || item.rid === 'auth-can' || item.rid === 'check-auth-admin' || item.rid === 'auth-admin') {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
ctx.body = {
|
ctx.body = {
|
||||||
list: list.map((item) => {
|
list: list.map((item) => {
|
||||||
const route = pick(item, ['id', 'path', 'key', 'description', 'middleware', 'metadata'] as const);
|
const route = pick(item, ['rid', 'path', 'key', 'description', 'middleware', 'metadata'] as const);
|
||||||
return toJSONSchemaRoute(route);
|
return toJSONSchemaRoute(route);
|
||||||
}),
|
}),
|
||||||
isUser
|
isUser
|
||||||
@@ -766,7 +766,7 @@ export class QueryRouterServer<C extends SimpleObject = SimpleObject> extends Qu
|
|||||||
* @param param0
|
* @param param0
|
||||||
* @returns
|
* @returns
|
||||||
*/
|
*/
|
||||||
async run(msg: { id?: string; path?: string; key?: string; payload?: any, token?: string, data?: any }, ctx?: Partial<RouteContext<C>>) {
|
async run(msg: { rid?: string; path?: string; key?: string; payload?: any, token?: string, data?: any }, ctx?: Partial<RouteContext<C>>) {
|
||||||
const handle = this.handle;
|
const handle = this.handle;
|
||||||
if (handle) {
|
if (handle) {
|
||||||
return handle(msg, ctx);
|
return handle(msg, ctx);
|
||||||
@@ -774,13 +774,13 @@ export class QueryRouterServer<C extends SimpleObject = SimpleObject> extends Qu
|
|||||||
return super.run(msg, ctx as RouteContext<C>);
|
return super.run(msg, ctx as RouteContext<C>);
|
||||||
}
|
}
|
||||||
|
|
||||||
async runAction<T extends { id?: string; path?: string; key?: string; metadata?: { args?: any } } = {}>(
|
async runAction<T extends { rid?: string; path?: string; key?: string; metadata?: { args?: any } } = {}>(
|
||||||
api: T,
|
api: T,
|
||||||
payload: RunActionPayload<T>,
|
payload: RunActionPayload<T>,
|
||||||
ctx?: RouteContext<C>
|
ctx?: RouteContext<C>
|
||||||
) {
|
) {
|
||||||
const { path, key, id } = api as any;
|
const { path, key, rid } = api as any;
|
||||||
return this.run({ path, key, id, payload }, ctx);
|
return this.run({ path, key, rid, payload }, ctx);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 创建认证相关的中间件,默认是 auth, auth-admin, auth-can 三个中间件
|
* 创建认证相关的中间件,默认是 auth, auth-admin, auth-can 三个中间件
|
||||||
@@ -790,7 +790,7 @@ export class QueryRouterServer<C extends SimpleObject = SimpleObject> extends Qu
|
|||||||
this.route({
|
this.route({
|
||||||
path: 'auth',
|
path: 'auth',
|
||||||
key: 'auth',
|
key: 'auth',
|
||||||
id: 'auth',
|
rid: 'auth',
|
||||||
description: 'token验证',
|
description: 'token验证',
|
||||||
}).define(async (ctx) => {
|
}).define(async (ctx) => {
|
||||||
if (fun) {
|
if (fun) {
|
||||||
@@ -801,7 +801,7 @@ export class QueryRouterServer<C extends SimpleObject = SimpleObject> extends Qu
|
|||||||
this.route({
|
this.route({
|
||||||
path: 'auth-admin',
|
path: 'auth-admin',
|
||||||
key: 'auth-admin',
|
key: 'auth-admin',
|
||||||
id: 'auth-admin',
|
rid: 'auth-admin',
|
||||||
description: 'admin token验证',
|
description: 'admin token验证',
|
||||||
middleware: ['auth']
|
middleware: ['auth']
|
||||||
}).define(async (ctx) => {
|
}).define(async (ctx) => {
|
||||||
@@ -813,7 +813,7 @@ export class QueryRouterServer<C extends SimpleObject = SimpleObject> extends Qu
|
|||||||
this.route({
|
this.route({
|
||||||
path: 'auth-can',
|
path: 'auth-can',
|
||||||
key: 'auth-can',
|
key: 'auth-can',
|
||||||
id: 'auth-can',
|
rid: 'auth-can',
|
||||||
description: '权限验证'
|
description: '权限验证'
|
||||||
}).define(async (ctx) => {
|
}).define(async (ctx) => {
|
||||||
if (fun) {
|
if (fun) {
|
||||||
|
|||||||
@@ -53,8 +53,8 @@ class Chain {
|
|||||||
this.object.key = key;
|
this.object.key = key;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
setId(key: string) {
|
setRid(key: string) {
|
||||||
this.object.id = key;
|
this.object.rid = key;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
setRun<U extends SimpleObject = {}>(run: Run<U>) {
|
setRun<U extends SimpleObject = {}>(run: Run<U>) {
|
||||||
|
|||||||
Reference in New Issue
Block a user