# 系统

# 导入

通过如下方式导入系统api

import sys from "svr-api/sys";

# 方法

/**
 * 系统相关API,包括产品的、jvm的和操作系统的
 */


/**
 * 根据访问本系统的URL,获取第三方系统在本系统所在的局域网中的访问地址或者代理地址。
 *
 * 比如访问本系统的地址为 `http://192.168.10.179:8080/login`,系统设置记录内容为:
 * ```
 * {
 *     "http://192.168.10.179:8080": {
 *       "https://api.amap.com": "http://192.168.23.43:8081"
 *     }
 * }
 * ```
 *
 * 那么`getIntranetUrlMapping("http://192.168.10.179:8080", "https://api.amap.com/api1")`返回
 * `http://192.168.23.43:8081/api1`。
 *
 * 使用场景:
 *
 * 1. oauth2单点登录,本系统作为子系统跳转到主系统授权登录页面。
 * 2. gis地图,在内网中配置代理高德地图等API访问地址。
 * 3. 门户页面上跳转到第三方系统的link。
 * 4. 用户在子系统注销,带动主系统注销。
 *
 * @param extranet 将要被访问到的第三方外网地址。
 * @param url 可选,访问本系统的URL,若不设置使用系统默认的。
 * @return 如果没有找到访问本系统URL的映射记录 或者 在本系统URL映射关系中没有找到第三方系统代理地址
 * 配置,将直接返回 参数extranet对应值。
 */
export function getIntranetUrlMapping(extranet: string, url?: string): string;

/**
 * 获取系统的系统设置(`/sysdata/settings/settings.json`)中的配置信息。
 */
export function getSysSetting(propertyName: string): any;

/**
 * 修改系统设置中的某个属性。
 *
 * 如:
 * `
 *  sys.setSysSetting("sys.basic.name", "test");
 * `
 * 调用之后setting.json变成:
 * `
 * {
 *     "sys.basic.name":"test"
 * }
 * `
 *
 * @param propertyName 属性名。
 * @param propertyValue 属性值,支持字符串、数字或布尔值,json,数组。
 */
export function setSysSetting(propertyName: string, propertyValue: any): void;

/**判断当前服务器是否为集群 */
export function isCluster(): boolean;

/**判断当前服务器是否为集群主节点,如果当前系统不是集群配置,那么总是返回true */
export function isMasterClusterNode(): boolean;

/**返回当前集群节点的名称 */
export function getClusterNodeName(): string;

// /**
//  * 发送一个或一批消息队列消息
//  * 
//  * @param serverName 消息队列的服务器名称
//  * @param message 消息体,一个或一个消息的数组
//  */
// export function sendMQMessage(serverName: string, message: MQMessage | MQMessage[]): void;

/**发送消息,如邮件、企业微信消息、邮件, 由于设计需要,这个方法不能用来发送短信消息,发送短信请调用 {sendSMS()} */
export function sendMessage(message: {
	/** 表明消息类型, wework-企业微信消息,pm-私信,email-邮件 */
	type: string;
	/** 谁发起订阅操作,订阅者USER_NAME */
	sender?: string;
	/** 消息主题 */
	subject?: string;
	/** 消息主体内容,支持html */
	message: string;
	/** 消息接收者,
	 * 
	 * 说明:
	 * 	- 对于发送消息的方式为邮件时,支持传入邮箱地址,
	 * 	- 其余方式仅支持传入用户id 
	 */
	receivers: Array<string>;
	/** 分享或订阅推送出去的消息所关联元数据文件链接 */
	url?: string;
	/** 对分享或订阅的链接的说明文本 */
	urlDesc?: string;
	/** 查看链接内容所需要的密码 */
	urlPassword?: string;
	/** 分享获取订阅推送出去的消息中的图片的id,仅支持一张图片 */
	pictureId?: string;
	/** 需要分享的dashboard名 ,如dashboard对应的文件名为'总览.dash',则取picName为'总览' */
	picName?: string;
	/** 消息投递最大次数,超过该次数则将消息移除队列,  0代表没有次数限制 */
	maxFailTimes?: number;
	/** 消息有效截止时间 ,超过有效期将被移除消息队列,0代表没有有效期限制 */
	validEndTime?: number;
}): void;

/**
 * 发送邮件
 * @param args
 */
export function sendEmail(args: {
	/**
	 * 主题
	 */
	subject: string;
	/**
	 * 发件人,如果设置了将会将发件邮箱的名称设置为这个用户的昵称
	 *
	 * 不填,则默认为 no-reply
	 */
	sender?: string;
	/**
	 * 收件人
	 * 
	 * 可以填入用户id,也可以填入邮箱好
	 */
	receivers: Array<string>;
	/**
	 * 抄送人
	 *
	 * 可以填入用户id,也可以填入邮箱好
	 */
	cc?: Array<string>;
	/**
	 * 邮件主体内容
	 *
	 * 可以支持html,样式写到html标签上
	 */
	body: string;

	/**
	 * 附件
	 */
	attachments?: Array<{
		// 附件在操作系统中的文件路径,如果对应的文件不存在,则会忽略掉这个附件的发送
		path: string;
		// 附件的名称, 如果不指定,则直接取文件的名称
		name?: string;
	}>
}): void;

/**
 * 发送短信消息,不同于验证码消息(见security模块`sendVerificationCode`函数),`sendSMS`只是一个通知消息。
 * 
 * @param messageInfo : 有些短信服务商要求用仅能使用模板的形式发送消息(比如阿里云短信服务), 这里的json
 * 	- 系统支持的阿里云短信服务,需要调用者指定如下参数才能正常发送消息:
 * 		{
 * 			signName: string; // 签名名称, 如果不传,则将使用系统中配置的默认签名,如果没有配置默认也没有传,则默认发送失败,并打印控制台日志(error日志)
 * 			templateCode: string; // 模板ID,如果不传,将使用系统设置中配置的默认模板,如果没有配置默认也没有传,则默认发送失败,并打印控制台日志(error日志)
 * 			[p: string]: any; // 其他参数将作为模板中的变量传递给阿里云平台
 * 		}
 * 		比如阿里云的模板:`证码为:{1},您正在登录,若非本人操作,请勿泄露。`
 * 		调用发送短信: `sys.sendSMS(["13111111111"], messageInfo: {"1": "99999"})`
 *  - 系统支持的腾讯云短信服务,需要调用者指定如下参数才能正常发送消息:
 * 		{
 * 			signName: string; // 签名名称, 如果不传,则将使用系统中配置的默认签名,如果没有配置默认也没有传,则默认发送失败,并打印控制台日志(error日志)
 * 			templateCode: string; // 模板ID,如果不传,将使用系统设置中配置的默认模板,如果没有配置默认也没有传,则默认发送失败,并打印控制台日志(error日志)
 * 			params: string[]; // 传递个腾讯云的参数列表
 * 		}
 * 		比如腾讯云模板 :`证码为:{1},您正在登录,若非本人操作,请勿泄露。`
 *   	调用发送短信: `sys.sendSMS(["13111111111"], messageInfo: {params: ["99999"]})`
 * @param phones 接收短信的手机号,支持传递多个号码
 */
export function sendSMS(phones: string[], messageInfo: string | JSONObject): void;

/**
 * 发送站内信
 */
export function sendStationMessage(args: {
	/**
	 * 消息发送者,如果不传,则使用当前登录的用户ID
	 */
	sender?: string;
	/** 消息接收者 */
	receivers: string[];
	/**
	 * 类型:
		1. `announcement-公告`: 系统公告,由管理员发出,通常发向每个用户。
		2. `notice-通知`: 针对业务变化而变化,比如审批未通过,通知提交审批的用户。
		3. `urge-催办`
		4. `todo-待办`
		5. `pm-私信`
		6. `warning-警告`:比如系统警告:服务器磁盘快满了,通知管理员处理。
	 */
	type: SMessageType
	/** 标题 */
	subject?: string;
	/** 内容主体 */
	content?: string;
	/** 导航地址链接 */
	link?: string;
	/** 业务标签 */
	labels?: string[];
}): void;

/**设置一个脚本定时执行 */
export function schedule(args: {
	/**
	 * 执行的脚本有两种情况,一种是持久化了的脚本文件,另一种是一段字符串形式的脚本
	 * 持久化的脚本文件执行外部脚本支持相对于当前脚本的相对路径
	 * 而字符串形式的脚本没有路径可言,执行外部脚本只支持传入绝对路径
	 */
	path?: string;
	/**执行脚本中的哪个函数,不传递时执行`main` */
	method?: string;
	/**传递给脚本函数的参数,不传递表示无参数,以调用`main`为例:
	 * 1. 传递`1`,则执行:`main(1)`
	 * 1. 传递`[1,2]`,则执行:`main(1,2)`
	 * 1. 传递`[[1,2]`,则执行:`main([1,2])`
	 **/
	args?: any;
	/**传递此参数表示等多少毫秒之后执行脚本 */
	delay?: number;
	/**传递此参数表示在date指定的日期和时间执行脚本,可传递日期对象或时间戳毫秒 */
	date?: Date | number;
	/**传递此参数表示循环执行脚本,每次间隔period毫秒,如果没有传递period,那么只执行一次脚本 */
	period?: number;
}): void;



/**执行一个脚本函数,并返回它的结果 */
export function exeScript(args: {
	/**
	 * 执行的脚本有两种情况,一种是持久化了的脚本文件,另一种是一段字符串形式的脚本
	 * 持久化的脚本文件执行外部脚本支持相对于当前脚本的相对路径
	 * 而字符串形式的脚本没有路径可言,执行外部脚本只支持传入绝对路径
	 */
	path?: string;
	/**执行脚本中的哪个函数,不传递时执行`main` */
	method?: string;
	/**传递给脚本函数的参数,不传递表示无参数,以调用`main`为例:
	 * 1. 传递`1`,则执行:`main(1)`
	 * 1. 传递`[1,2]`,则执行:`main(1,2)`
	 * 1. 传递`[[1,2]`,则执行:`main([1,2])`
	 **/
	args?: any;
}): any;

/**
 * 记录服务器端事件日志。
 *
 * 说明:
 * 
 * 1. 当event为字符串时:
 *     1. 事件名,由`模块标记`+`事件简称`构成,如`fapp.submitData`表示提交表单数据,必须符合规范,见
 *        《事件和日志规范.md》。
 *     2. 通过事件名系统会自动设置事件的描述、安全级别、和日志记录级别。
 *
 * @param event 传递一个事件名称字符串,或者是事件的详细信息。
 * @param log 当第一个参数传递的是字符串时,可传递此函数表示一条事件中的日志信息。
 */
export function fireEvent(event: string | ServerEvent, log?: string): void;


/**
 * 返回系统工作目录路径,不带最后的`/`或`\`。如:
 * 
 * 1. getWorkDir() 返回 `/path/to/workdir`
 * 2. getWorkDir('abc/def') 返回 `/path/to/workdir/abc/def`
 * 
 * @param subPath 传递`subPath`时将返回 相对于工作目录的 `subPath`的绝对路径
 */
export function getWorkDir(subPath?: string): string;

/**返回用于存放临时文件的目录,不带最后的`/`或`\` */
export function getTempDir(): string;

/**返回用于存放缓存文件的目录,不带最后的`/`或`\` */
export function getCacheDir(): string;

/**返回在集群上每个节点都可以访问的一个跨集群共享的目录,不带最后的`/`或`\` */
export function getClusterShareDir(): string;

/**获取系统环境变量JAVA_HOME的值 */
export function getJavaHome(): string;

/**获取用户文件夹的路径,即Java环境变量user.home的值 */
export function getUserHome(): string;

/**获取tomcat的web根目录,以/结尾,如`/Users/xxxxx/workspace5.0/bi/com.succez.bi/web/` */
export function getWebRootDir(): string;

/**获取Java虚拟机的版本号 */
export function getJavaVersion(): string;

/**返回jvm的空闲内存,单位字节*/
export function getJvmFreeMemeory(): number;
/**返回jvm已分配的内存,单位字节 */
export function getJvmTotalMemeory(): number;
/**返回jvm最大可用内存,单位字节 */
export function getJvmMaxMemeory(): number;
/**返回jvm的进程id */
export function getJvmProcessID(): number;

/**返回逻辑cpu数目,多核的每核算一个cpu  */
export function getAvailableProcessors(): number;

/**
 * 对应System.currentTimeMills()方法
 */
export function getTimeMills(): number;

/**
 * 返回操作系统的名称,如:
 * 1. Linux
 * 1. Mac OS
 * 1. Mac OS X
 * 1. Windows 2000
 * 1. Windows XP
 * 1. Windows 2003
 * 1. Windows CE
 * 1. OS/2
 * 1. Solaris
 * 1. SunOS
 * 1. MPE/iX
 * 1. HP-UX
 * 1. AIX
 * 1. OS/390
 * 1. FreeBSD
 * 1. Irix
 * 1. Digital Unix
 * 1. NetWare 4.11
 * 1. OSF1
 * 1. OpenVMS
 * 
 * 更多信息参考:<http://lopica.sourceforge.net/os.html>
 */
export function getOSName(): string;

/**
 * 返回操作系统的版本号,如:
 * 1. 10.2.6
 * 1. 6.3
 */
export function getOSVersion(): string;

/**
 * 返回操作系统的架构信息,如:
 * 1. x86_64
 * 1. x86
 * 1. Power
 * 1. ppc
 */
export function getOSArch(): string;

/**返回所有当前进程的所有OS环境变量 */
export function getOSEnvironments(): { [envName: string]: string };

/**
 * 执行指定的外部程序,并等待其执行完毕后返回标准输出信息、错误信息等
 * @param file 外部程序的绝对路径,如果是`\`分隔符,需要写成`'\\'`
 * @param args 可选,传递给外部程序的执行参数数组
 */
export function exe(file: string, args?: Array<string>): { stdout: string, stderr: string; errorcode: number };

/**
 * 异步执行指定的外部程序,不等待其执行完毕
 * @param file 外部程序的绝对路径,如果是`\`分隔符,需要写成`'\\'`
 * @param args 可选,传递给外部程序的执行参数数组
 */
export function exea(file: string, args?: Array<string>): void;

/**
 * 查找满足条件的进程信息。
 *
 * @param assign windows系统是进程名关键字,其他系统是进程命令行的关键字。
 */
export function findProcess(assign: string): Array<{
	/**进程id */
	pid: number;
	/**父进程id */
	ppid?: number;
	/**文件名 */
	name: string;
	/**命令行内容 */
	cmd: string;
}>;


/**
 * 对应Thread.sleep()方法
 * @param sleepTime 
 */
export function sleep(sleepTime: number): void;


/**
 * 判断一个应用是否有权限访问某一项API。
 *
 * @param appId 若为null或不正确,或enabled为false,或type不为oauth,code,auto此三种类型,则返回类
 *     似如下错误信息:{"result": false,"errorCode": "appNotFound","message": "授信应用{appId}不存在
 *     "}。
 * @param appSecret 若为null或不正确,则返回类似如下错误信息:{"result": false,"errorCode":
 *     "secretMismatch","message": "授信应用{appId}秘钥不正确"}。
 * @param apiPath api路径,如api/oauth2/verifyUser。若api不在当前app的白名单中,则返回类似如下错误信
 *     息:{"result": false,"errorCode": "permissionDenied","message": "授信应用没有权限"}。
 */
export function checkAppPermission(appId: string, appSecret: string, apiPath: string): { result: boolean, errorCode?: string, message?: string };

/**
 * 根据appId获取app的信息,不存在返回null或抛出异常。
 * @param appId 
 * @param throwException 不存在对应appId的信息是否抛出异常,默认为false。
 */
export function getAppInfo(appId: string, throwException?: boolean): TrustedAppInfo;

/**
 * 获取当前脚本所在线程绑定的进度条对象。
 * 
 * 常用于脚本输出自己的相关上下文日志,并最终返回给用户查看,如:
 * 1. 数据加工中的脚本节点输出自己的日志,日志会最终和加工本身的日志在一起输出给用户。
 * 2. 脚本中通过${@link ScriptThreadPoolImpl#submit(Map)}启用的多线程脚本可以通过此对象输出相关日志。
 * 
 * 注意:这里输出的日志和通过`print`函数输出的不同,print函数常用于开发者自己调试脚本使用,而使用`ProgressMonitor`输出的日志
 * 是给具体终端用户查看日志用的。
 * 
 * @return 若当前线程没有绑定的进度条对象,则会创建一个新的返回并设置给当前线程。
 */
export function getThreadProcessMonitor(): ProgressMonitor;

/**
 * 获得一个线程池,不存在则创建
 * @param options 
 * @returns 返回一个线程池对象,用于提交线程任务
 */
export function getThreadPool(options: {
	/**线程池名称 */
	name: string,

	/**核心线程数,默认大小为3 */
	corePoolSize?: number,

	/**线程池最大线程数,默认大小为5 */
	maximumPoolSize?: number,

	/**线程空闲时间,当线程空闲时间达到keepAliveTime,线程会退出 ,默认大小为30000*/
	keepAliveTime?: number

}): ThreadPool;

/**
 * 尝试获取一个锁,并等待获取成功或超时,如果获取失败或超时会触发异常。获取成功后必须在特定时间内释放锁,否则将自动释放锁。
 *
 * @param key 必须传递一个合法的key,长度小于256,调用者自己确保key之间的冲突问题。
 * @param timeout 等待超时时间,单位毫秒。
 * @param maxKeepTime 持有锁超过这个时间将自动释放锁,通常用于防止应用系统宕机导致的死锁。
 * @return 返回的对象被关闭后锁就释放了,如果获取失败或超时会触发异常。
 */
export function distLock(key: string, timeout?: number, maxKeepTime?: number): Closeable;

/**
 * 释放锁。
 * 
 * 通过上面的{@link distLock()}函数获取锁后可以通过close其返回的锁来释放,也可以调用此函数来释放。
 *
 * @param key 必须传递一个合法的key,长度小于256,调用者自己确保key之间的冲突问题。
 */
export function distUnlock(key: string): void;


/**
 * 扩展对象。
 */
export interface SysExtension {
	/**
	 * 扩展的名字,如`succ-portalTemplate-darkblue`。
	 */
	getName(): string;

	/**
	 * 获得package.json的内容。
	 */
	getPackageJSON(): JSONObject;

	/**
	 * 获取扩展内的自带的java对象。
	 * 
	 * 关于扩展自带第三方java类库,见<https://docs.succbi.com/v5/dev/extension/faq/051be50>。
	 * 
	 * @param clazz 类路径,如`com.xxx.yyy.Class1`
	 * @param errorIfNotExists 不存在时是否抛出异常,默认false
	 */
	getJavaType(clazz: string, errorIfNotExists?: boolean): any;

	/**
	 * 返回扩展内的文件。
	 * 
	 * @param file 要获取的文件的路径,不以/开头
	 * @param errorIfNotExists 不存在时是否抛出异常,默认false
	 */
	getFile(file: string): import("./fs").File;
}

/**
 * 获取系统扩展对象。
 * 
 * 扩展是一种插件,安装一个扩展可以提供SuccBI默认不具备的功能,可以改变产品的默认功能和行为。
 * 
 * @param extensionName 扩展名称,如`succ-portalTemplate-darkblue`。
 * @param errorIfNotExists 不存在时是否抛出异常,默认false
 */
export function getExtension(extensionName: string, errorIfNotExists?: boolean): SysExtension;

/**
 * 文件存储器中文件信息
 */
interface FileInfo {
	/** 文件名 */
	name: string,
	/** 文件大小 */
	size: number,
	/** 文件最后修改时间 */
	lastModifyTime: number
}

interface FileStorage {
	/**
	 * 往文件存储器中存储文件。
	 * 
	 * @param file 文件对象或者文件路径
	 * @param info 文件信息,不传递时使用传入磁盘文件文件信息
	 * @param 返回文件id
	 */
	saveFile(file: string | import("./fs").File, info?: FileInfo): string;

	/**
	 * 通过文件id删除文件存储器中的内容
	 * 
	 * 注意:
	 * 
	 * 此操作是不可逆请谨慎使用。
	 * 
	 * @param fileId 文件id
	 */
	delete(fileId: string): void;

	/**
	 * 通过文件id获取文件存储器中存储的文件信息。
	 * 
	 * 若需要获取文件内容,使用{@link getFile(string, boolean)}
	 * 
	 * @param fileId 文件id
	 * @param errorIfNotExists 不存在时是否抛出异常,默认false
	 * @returns 文件信息
	 */
	getFileInfo(fileId: string, errorIfNotExists?: boolean): FileInfo;

	/**
	 * 通过文件id获取文件存储器中存储的文件
	 * 
	 * 若需要获取文件信息,使用{@link getFileInfo(string, boolean)}
	 * 
	 * @param fileId 文件id
	 * @param errorIfNotExists 不存在时是否抛出异常,默认false
	 * @returns 文件对象
	 */
	getFile(fileId: string, errorIfNotExists?: boolean): import("./fs").File;
}

/**
 * 获取文件存储器。
 *
 * 文件存储器负责存储系统中存储在文件系统上的附件,可以通过物理表中存储的文件系统id从文件存储器中获
 * 取文件、文件信息、删除文件等操作
 *
 * @param type 文件存储器类型,若不传递默认为default
 * @returns 不存在类型对应文件存储器时返回null
 */
export function getFileStorage(type?: "default" | "workdir" | "unique" | string): FileStorage;

/**
 * 编译、加载java代码返回对应的class对象。
 *
 * 用于在脚本中动态构建java二进制代码。
 *
 * ```ts
 * let source =
 *    `package a.b.c;
 *    import java.util.function.Supplier;
 *    public class Test1 implements Supplier<Object>{
 *        public Object get(){
 *            return 2;
 *        }
 *    }
 *    `;
 * let Test1 = sys.compileInlineClass(source, null);
 * let instance = new Test1();
 * ```
 *
 * @param srouce java代码的文件,包括`package ... import ... public class ...` 等部分。
 * @param extraClasspath 编译时可能会引用到的一些类所在的classpath,此函数会自动将当前jvm运行时的
 *        classpath加上,如果脚本所在的扩展有javalib,那么也会自动加上,所以这里只需要指定额外的
 *        classpath即可,没有时可传递null。
 */
export function compileInlineClass<T = any>(srouce: string, extraClasspath?: string): T;

# 对象

/**定义系统核心的类型 */

/**
 * 表示一个需要关闭的对象。
 * 
 * 同`java.io.Closeable`
 */
declare interface Closeable {

	/**
	 * 关闭流并释放使用的系统资源,如果流已经关闭了重复调用并不会有其他影响。
	 */
	close(): void;
}

declare interface OutputStream extends Closeable {

	/** 写出字节码 */
	write(bytes: number[]): void;

	/**
	 * 写出字节码
	 * @param bytes 
	 * @param off  开始写出的起始位置the start offset in the data.
	 * @param len  写出字节长度长度
	 */
	write(bytes: number[], off: number, len: number): void;

	/** 写出一个字节 */
	write(byte: number): void

	/**
	 * 刷新输出流,强制将所有缓存区的数据写出
	 */
	flush(): void;

}

declare interface InputStream extends Closeable {
	/** 
	 * 读取一个字节
	 * @returns 如果流已经读取结束,则返回-1
	 */
	read(): number;

	/**
	 * 从流中特定长度的字节数存入bytes 数组中,流中的数据不够bytes数组长度时,也不会补足数据
	 * @param bytes 
	 * @returns 从流中读取出来的字节数,如果已经读取完成,返回-1
	 */
	read(bytes: number[]): number;

	/**
	 * 从流中特定长度的字节数存入bytes 数组中,流中的数据不够bytes数组长度时,也不会补足数据
	 * @param bytes 
	 * @param off bytes数组中的第一个被写入字节的偏移位置
	 * @param len 最大读取长度
	 * @returns 从流中读取出来的字节数,如果已经读取完成,返回-1
	 */
	read(bytes: number[], off: number, len: number): number;

}

declare interface Writer extends Closeable {

	/** write a string or number */
	write(c: string): Writer;

	/** Appends the specified string to this writer. */
	append(c: string): Writer;

	/** 
	 * Flushes the stream.  If the stream has saved any characters from the
	 * various write() methods in a buffer, write them immediately to their
	 * intended destination.  Then, if that destination is another character or
	 * byte stream, flush it.  Thus one flush() invocation will flush all the
	 * buffers in a chain of Writers and OutputStreams. 
	 */
	flush(): void;

}

/**
 * 对应的是{@link java.io.BufferedReader}
 */
declare interface Reader extends InputStream {
	/**
	 *  从输入流中读取一行作为字符串
	 * @param ignoreLF 默认false, 是否忽略下一个 `\n` 
	 */
	readLine(ignoreLF?: boolean): string;
}

/**
 * 一个高性能的CSV文件的读取工具类。
 * 
 * 支持标准的CSV规范,支持双引号引起来的字段,双引号内部的所有字符都认为是字段的值。
 */
declare interface CSVReader extends Closeable {

	/**
	 * 读取一行。
	 * 
	 * 调用此函数并返回true之后才能继续调用{@link #getColumnCount()}判断此行有多少列,调用
	 * {@link CsvReader.getObject}获取指定列的值。
	 */
	next(): boolean;

	/**
	 * 返回当前行有多少列。
	 *
	 * 只有当调用{@link CsvReader.next}且返回true后才能调用此函数。
	 */
	getColumnCount(): number;

	/**
	 * 获取当前行的所有值。
	 * 
	 * 1. 只有当调用{@link CsvReader.next()}且返回true后才能调用此函数,否则可能出现空指针异常。
	 * 2. 返回的数组是内部复用的,调用者不要长期持有或修改这个数组,在下次调用{@link CsvReader.next()}时数组
	 *    对象中的内容会被修改。
	 * 3. 返回的数组的长度就是当前行实际的有效列数的。
	 */
	getRowValues(): any[];

	/**
	 * 将当前行的所有值,复制到指定的数组。
	 * 
	 * @param values 
	 * @param offset 
	 * @param len 
	 */
	getRowValues(values: any[], offset: number, len: number): void;

	/**
	 * 获取当前行的指定列的值。
	 * 
	 * 只有当调用{@link CsvReader.next}且返回true后才能调用此函数。
	 * 
	 * @param i 第i列,从0开始。
	 * @returns i大于总列数时返回null。
	 */
	getObject(i: number): any;
}

/**
 * 一个高性能CSV写入器。
 */
declare interface CSVWriter extends Writer {

	/**
	 * 输出一行数据并自动换行。
	 * 
	 * @param values 
	 */
	writeRow(values: any[]): void;

}

/**
 * 让后端的数组对象好用点,js原生的比较晦涩。
 * 
 * Copy from global.d.ts 
 */
interface Array<T> {
	/**
	 * 将`arr`中的元素挨个push到自己内部。
	 * 
	 * @returns 返回自己
	 */
	pushAll(arr: T[]): T[];

	/**
	 * 添加其不存在的条目
	 * @param arr 准备加入的数组
	 * @returns 返回自己
	 */
	distinctPushAll(arr: T[]): T[];

	/**
	 * 添加其不存在的元素
	 * @param obj 准备加入的元素
	 * @returns 返回自己
	 */
	distinctPush(obj: T): T[];

	/**
	 * 比较本数组和另外一个数组arr是否内容相同
	 */
	equals(arr: T[]): boolean;

	/**
	 * 返回去掉重复项的一个新数组
	 */
	distinct(): T[];

	/**
	 * 从数组中删除一个元素
	 */
	remove(obj: number | T): T;

	/**
	 * 从数组中删除多个元素
	 */
	removeAll(objs: number[] | T[]): T;
}

/**
 * 消息队列的消息结构
 */
declare interface MQMessage {
	/**消息的主题,用于订阅消息的时候区分消息 */
	topic: string,
	/**消息的标签,用于订阅消息的时候区分消息*/
	tag: string,
	/**消息体,可以是一个数组 */
	message: any
}

/**
 * 输出一个日志信息。
 *
 * 1. 日志可以输出到控制台,见<https://docs.succbi.com/dev/script-debug/#debug-with-log>
 * 2. 日志也可以输出到进度对话框中,这一点与{@link console.log()}不同。
 *
 * @param log 可以是字符串、Error、Json或其他对象,如果是字符串,内部可以包含参数占位符,会依次取
 * {@link args}中的参数替换,如:
 *  1. `%s` 替换为字符串
 *  2. `%d`或`%i` 替换为整形数字
 *  3. `%f` 替换为浮点数字
 *  4. `%o` 替换为对象
 * @param args 附加参数,可选,args中的参数会依次替换并输出到第一个参数中的动态占位符中,剩下的参数
 * 将自动输出到日志后面,最后一个参数如果是Error对象,那么将输出堆栈信息。
 */
declare function print(log: any, ...args: any[]): void

/**
 * `Java.type("java.util.Locale")` 等价于 `java.util.Locale`
 * @see https://docs.oracle.com/javase/8/docs/technotes/guides/scripting/nashorn/api.html
 */
declare const Java: {
	/**
	 * 返回一个java的class对象。
	 *
	 * 关于扩展自带第三方java类库,见<https://docs.succbi.com/v5/dev/extension/faq/051be50>。
	 *
	 * @param fullClassName 类名,如`java.util.ArrayList`
	 * @throws 找不到类时会抛出异常
	 */
	type(fullClassName: string): any;

	/**
	 * 构造一个java的ArrayList对象并返回。
	 * 
	 * @param initialCapacity 初始化长度,不传递时,将使用java默认的构造长度。
	 */
	newArrayList(initialCapacity?: number): Array<any> | any;

	/**
	 * 构造一个java的HashMap对象并返回。
	 * 
	 * @param initialCapacity 初始化长度,不传递时,将使用java默认的构造长度。
	 */
	newHashMap(initialCapacity?: number): JSONObject;

	/**
	 * 构造一个java的ConcurrentHashMap对象(支持多线程操作)并返回。
	 *
	 * 在action脚本模块中初始化一个ConcurrentHashMap对象,后续的action函数调用可以并发的(多线程)读
	 * 取和设置这个map中的信息。
	 *
	 * @param initialCapacity 初始化长度,不传递时,将使用java默认的构造长度。
	 */
	newConcurrentHashMap(initialCapacity?: number): JSONObject;
};

/** 通过java可以引用java开头的类,如`java.util.Locale`  */
declare const java: any;
/** 通过com可以引用com开头的类,如`com.succsoft.bi.Xxxxx` */
declare const com: any;
/**
 * 通过`new JavaAdapter(...)`语法,动态生成字节码的方式创建一个满足java接口的java匿名类,并实例化这个匿名类的对象。
 * 
 * @see https://web.archive.org/web/20200704031304/https://developer.mozilla.org/en-US/docs/Mozilla/Projects/Rhino/Scripting_Java The JavaAdapter Constructor
 */
declare const JavaAdapter: any;

/**
 * getThreadPool()创建的线程池对象
 */
declare interface ThreadPool {

	/**
	 * 提交一个任务到线程池执行,该任务是某段脚本的export的方法
	 * @param args 
	 */
	submit(args: {
		/**指定任务的uuid,可以根据id轮训任务,在浏览器上显示等待信息 */
		uuid?: string;
		/**任务的一段描述文字,方便在线程管理界面理解这个线程 */
		desc?: string;
		/**
		 * 要执行的脚本的路径。
		 * 可以是绝对路径或者相对路径,不传递默认为当前文件路径
		 */
		path?: string,

		/**执行的脚本的方法 */
		method: string,

		/**方法执行的参数 */
		params?: Array<any>,

		/**
		 * 给线程设置进度条对象,可以使线程池中线程共享一个进度条对象这个方法一般是通过主线程创建
		 * createSubProgress,
		 */
		progress?: ProgressMonitor
	}): ThreadPoolTask;

	/**
	 * 等待制定的任务完成
	 * @param tasks 待完成的任务,可以是一个Task,可以是一个Task数组
	 * @param waitTime 等待完成时间,单位为ms
	 * @param throwErrorIfTimeout 超过最大等待时间是否抛出异常,默认为true
	 */
	waitTasks(tasks: ThreadPoolTask | ThreadPoolTask[], waitTime: number, throwErrorIfTimeout?: boolean): boolean;

	/**获取线程池中正在执行的任务数量 */
	getActiveCount(): number;

	/**获取线程池中执行过的任务数量 */
	getTaskCount(): number;

	/**
	 * 关闭线程池。
	 * 
	 * @param waitTime 默认等待关闭的时间为10秒,超过该时间会强行终止正在执行的线程
	 */
	shutDown(waitTime?: number): void;
}

declare interface ThreadPoolTask {
	/**等待执行完成并获取任务执行的结果 */
	get(): any;
}

/**
 * 线程的进度对象
 */
declare interface ProgressMonitor {
	/**设置进度的最小值,不设置默认为0 */
	setMinimum(value: number): void,

	/**设置进度条的最大值,一般情况需要进行设置 */
	setMaximum(value: number): void,

	/**设置进度条的位置 */
	setProgress(value: number): void,

	/**获取进度条的位置 */
	getProgress(): number,

	/**
	 * 进度条增加value的值
	 * @param value 不传递默认加1
	 */
	step(value?: number): void,

	/**
	 * 创建子进度对象,可以将主进度的一部分切分给子对象。
	 * 
	 * 一个复杂的业务流程(以系统的启动初始化过程为例)往往内部会执行很多子业务逻辑(如创建系统表、还原demo数据……),父业务流程需要有一个完整的进度信息呈现给用户,
	 * 父业务流程调用内部的子业务逻辑时也需要传递一个`ProgressMonitor`给它(比如系统初始化业务逻辑调用创建系统表的子业务逻辑),此时子业务逻辑只能走总的进度条的
	 * 一部分,为了让子业务逻辑好开发,就还是给它一个完整的进度条信息,让他可以“以为”它能走到100%,这样好开发些。
	 * 
	 * @param totalProgress 子进度条站总的任务条的多少进度
	 * @param acceptSubMessage 子进度条的{@link #setMessage(String)}是否反应给父进度条
	 * @param acceptSubLogs 子进度条的{@link #addLog(String)}是否反应给父进度条
	 * @return
	 */
	createSubProgress(totalProgress: number, acceptSubMessage: boolean, acceptSubLogs: boolean): ProgressMonitor

	/**
	 * 添加一条普通的表示详细信息的log
	 * @param log 
	 */
	addLog(log: string): void;

	/**
	 * 前台界面显示sql日志的规则:如果是SQL的日志,该日志应该以<sql>xxx</sql>包裹起来的,需要对SQL日志进行格式化并高亮显示。
	 * 后台在生成sql日志时,需要满足以上规则。本方法用于当日志为sql语句时,为该语句提供格式化包装,然后再添加到日志中。
	 * 例如sql描述信息为"开始查询:",sql语句为select * from ajxx,则sql日志为    开始查询:<sql>select * from ajxx</sql>
	 * @param sqlInfo sql描述信息
	 * @param sql sql语句
	 */
	addSql(sqlInfo: string, sql: string): void;

	/**
	 * 修改最后一条添加的日志,如果没有一条日志,那么添加一条<br />
	 * 此方法一个比较常见的应用场景就是,一行日志中显示百分比,可以看到数字不停地闪动,而不是数字变化一次就生成新的日志行
	 */
	setLastLog(log: string): void;

	/**
	 * 获取包含所有日志的字符串,通常用于刷新日志显示界面
	 */
	getLogs(): string;

	/**
	 * 获取日志的json结构,便于解析日志。
	 */
	getJsonLogs(): string;

	/**
	 * 获取已经存在的日志条数
	 */
	getLogCount(): number;
	/**
	 * 判断进程是否已经取消了
	 *
	 * @return
	 */
	isCanceled(): boolean;

	/**
	 * 设置是否要取消进度条,并给出取消的原因
	 *
	 * @param cancel 是否取消进度
	 * @param msg 取消进度的原因
	 */
	setCancel(cancel: boolean, msg: string): void;

	/**
	 * 检查是否已经取消了,如果取消了则触发异常CancelException
	 *
	 * @return
	 */
	checkCancel(): void;
}

/**
 * 脚本所在的文件的元数据路径。
 *
 * 通常以.action结尾(会自动去掉.ts后缀),如`/sysdata/public/test.action`。当使用require函数引入另
 * 一个脚本时,如在`/path/to/a.action`中引入了`/path/to/b.action`,此时此属性表示所在文件的名称,即
 * 如果在a.action中访问__filename,得到的是`/path/to/a.action`,在b.action中访问__filename,得到的是
 * `/path/to/b.action`。
 */
declare const __filename: string;

/**
 * 最初启动时的脚本。
 *
 * 在脚本互相引用时,此属性可以表示最初启动脚本运行环境时的那个脚本文件,如在`/path/to/a.action`中引
 * 入了`/path/to/b.action`,此时此属性总是表示`/path/to/a.action`,即便在b.action中访问__filename,
 * 得到的依然是`/path/to/a.action`。
 */
declare const __filename_root: string;

/**
 * 脚本所在文件夹元数据路径,如`/sysdata/public`。
 * 
 * 和{@link __filename}类似,当脚本文件require另一个脚本文件时,此属性代表所在脚本文件的所在目录。
 */
declare const __dirname: string;

/**
 * 脚本执行器对象。
 */
declare const _script_runner: any;

declare namespace Dom4j {

	/**
	 * 定义XML文档。
	 */
	interface Document extends Branch {

		/**
		 * 获取根元素。
		 *
		 * @return 
		 */
		getRootElement(): Element;
	}

	/**
	 * 定义能包含子节点的节点。
	 */
	interface Branch extends Node {

		/**
		 * 返回指定索引位置的节点。
		 *
		 * @param index 
		 * @return 索引超出范围抛异常IndexOutOfBoundsException。
		 */
		node(index: number): Node;

		/**
		 * 返回此分支包含的节点实例数。
		 *
		 * @return 
		 */
		nodeCount(): number;
	}

	/**
	 * 节点定义dom4j树中所有XML节点的行为。
	 */
	interface Node {

		/**
		 * 返回此节点的名称。
		 * 
		 * @return 对于CDATA和Text nodes返回null。
		 */
		getName(): string;

		/**
		 * 返回此节点的文本。如果内容为空则返回一个空字符串而不是null。
		 * 
		 * @return 
		 */
		getText(): string;

		/**
		 * 返回此节点的XML文本字符串。
		 * 
		 * @return 
		 */
		asXML(): string;

		/**
		 * 获取多个节点。
		 *
		 * @param xpathExpression 传入符合[XPath](https://www.w3school.com.cn/xpath/index.asp)的节点路径。
		 * 
		 * 以如下xml为例:
		 *```xml
		 *<?xml version="1.0" encoding="ISO-8859-1"?>
		 *<bookstore>
		 *<book category="COOKING">
		 *  <title lang="en">Everyday Italian</title>
		 *  <author>Giada De Laurentiis</author>
		 *  <year>2005</year>
		 *  <price>30.00</price>
		 *</book>
		 *
		 *<book category="CHILDREN">
		 *  <title lang=" en">Harry Potter</title>
		 *  <author>J K. Rowling</author>
		 *  <year>2005</year>
		 *  <price>29.99</price>
		 *</book>
		 *</bookstore>
		 *```
		 * 
		 * 参考示例:
		 * 1. selectNodes("/bookstore/book/title") ----->> 选取路径在/bookstore/book所有title节点
		 * 2. selectNodes("//book/title")----->>选择所有父元素是book的title元素
		 * 3. selectNodes("/bookstore/book/*")----->>选择所有路径依附于/bookstore/book的元素
		 * 4. selectNodes("/bookstore/book[1]/title")----->>选取bookstore 元素下面的第一个 book 节点的 title
		 * 5. selectNodes("/bookstore/book/title[@lang]")----->>选择有lang属性的title元素
		 * 6. selectNodes("/bookstore/book/title[normalize-space(@lang)='en']")----->>选择含有属性lang且其值(在用normalize-space函数去掉前后空格后)为'en'的title元素
		 * 7. selectNodes("//title|//price")----->>选择所有title和price元素
		 * @return 
		 */
		selectNodes(xpathExpression: string): Array<Node>;

		/**
		 * 查找满足XPath表达式的第一个子节点。
		 *
		 * @param xpathExpression 传入符合[XPath](https://www.w3school.com.cn/xpath/index.asp)语法的节点路径,具体规则说明详见{@link selectNodes(xpathExpression: string)}。
		 * @return 
		 */
		selectSingleNode(xpathExpression: string): Node;

		/**
		 * 查找满足XPath表达式的第一个子节点的文本内容。
		 * 
		 * @param xpathExpression 传入符合[XPath](https://www.w3school.com.cn/xpath/index.asp)语法的节点路径。具体规则说明详见{@link selectNodes(xpathExpression: string)}。
		 * @return 
		 */
		valueOf(xpathExpression: string): string;

	}

	/**
	 * 定义XML元素。
	 */
	interface Element extends Branch {

		/**
		 * 返回所含有的text内容,其中连续的空格被转化为单个空格,该方法不会返回null。
		 *
		 * @return 
		 */
		getTextTrim(): string;

		/**
		 * 返回属性列表。
		 *
		 * @return 
		 */
		attributes(): Array<Attribute>;

		/**
		 * 返回一个属性。
		 *
		 * @param indexOrName 指定索引或者给定name。
		 * @return 
		 * 1. 指定索引处的属性,若索引超出范围则抛IndexOutOfBoundsException异常。
		 * 2. 如果有多个符合的name的属性,则返回第一个。
		 * 3. 若没有符合name的属性,则返回null。
		 */
		attribute(indexOrName: number | string): Attribute;

		/**
		 * 返回具有给定name的属性的属性值。
		 *
		 * @param name 
		 * @return 如果没有此类属性,则返回null,如果属性值为空,则返回空字符串。
		 */
		attributeValue(name: string): string;

		/**
		 * 返回具有给定name的属性的属性值,如果没有此类属性值,则返回默认值。
		 *
		 * @param name 
		 * @param defaultValue 
		 * @return 
		 */
		attributeValue(name: string, defaultValue: string): string;

		/**
		 * 返回元素具有指定name的第一个子元素。若没有找到对应的元素,则返回null。
		 *
		 * @param name 
		 * @return 
		 */
		element(name: string): Element;

		/**
		 * 返回该元素中具有指定name的子元素数组,如果没有找到对应的元素,则返回空数组。
		 *
		 * @param name 
		 * @return 
		 */
		elements(name?: string): Array<Element>;

	}

	/**
	 * 定义XML的属性。
	 */
	interface Attribute extends Node {

		/**
		 * 返回属性值。
		 *
		 * @return 
		 */
		getValue(): string;
	}
}

/**
 * 服务器事件对象。对应服务器端的`com.succez.metadata.service.event.Event`接口。
 */
declare interface ServerEvent {
	/**
	 * 事件名称。
	 */
	name: string,

	/**
	 * 事件级别,默认是INFO,当需要VERB级别的日志时,需要将使用sys.setSysSetting('log.level','VERB'),
	 * 表示可记录从OFF-VERB之间的所有类型的日志,需要ALL级别的日志时同理。
	 *
	 * @example
	 * OFF  服务器断开产生的日志,这个是最严重的错误,直接导致服务器宕机的日志
	 * FATAL 灾难性的日志,例如系统设置错误后导致系统无法正常运行的灾难性的日志
	 * ERROR 错误类型的日志,例如报表计算错误,表单提交错误等,对系统的运行不产生影响的错误日志
	 * IMPT 比较重要的操作,例如登录,备份恢复等
	 * INFO 详细日志,重要性相对important相对要小一级别,但又不是可有可无的日志
	 * VERB 冗余的不重要的日志,可以忽略不计的日志
	 * ALL 所有级别:所有的日志都会记录
	 */
	logLevel?: string,

	/**
	 * 元数据文件信息,应该是一个绝对路径,/开头的包含项目名的。
	 */
	resPath?: string,

	/**
	 * 操作结果,默认是成功的,如果是成功的操作,可以不用设置。
	 *
	 * 说明:
	 *
	 * 1. `exception`不为空时会自动设置为`EventOperationState#EXCPT`。
	 */
	operationState?: EventOperationState,

	/**
	 * 操作开始时间,如果不指定则为调用时的时间。
	 */
	startTime?: number,

	/*
	 * 操作结束时间,如果不指定则默认为该方法结束的时间。
	 */
	endTime?: number,

	/**
	 * 异常。如果有异常,那么`operationState`会自动设置为`EventOperationState#EXCPT`。
	 */
	exception?: Error,

	/**
	 * 日志的详细信息,例如报表计算的计算参数等,是一个json对象,会直接当作json序列化到系统日志表的
	 * clob字段中。
	 */
	detailInfo?: JSONObject,

	/**
	 * 一系列的进度日志条目。系统中有些操作是会产生一些进度日志的,比如用到了{@link ProgressMonitor},
	 * 如果需要记录进度日志可以指定本参数。
	 */
	logs?: Array<any>,

	/**
	 * 提供2个VARCHAR类型的附加字段,用于记录日志的一些个性化信息。
	 */
	option1?: string,
	option2?: string,

	/**
	 * 触发事件的用户ID。
	 */
	userId?: string,

	/**
	 * 用户登录的sessionId。
	 */
	sessionId?: string

	/**
	 * 数据完整性验证。
	 *
	 * 允许传入一个hash值,用于查询时判断数据是否篡改。
	 *
	 * 提供给`server.action.ts`中的`onPersistEvents`拓展点使用,默认为null,设置值后产品会自动写入模型对应的
	 * 数据完整性校验字段上。
	 */
	consistencyInfo?: string;
}

/**
 * 事件的状态:0成功,1失败,2异常,3错误。
 */
declare const enum EventOperationState {
	/**
	 * "成功完成"状态,如计划任务成功执行完毕,用户登录成功等。
	 */
	OK = 0,

	/**
	 * "失败状态"状态,如用户登录失败等。
	 */
	FAIL = 1,

	/**
	 * "异常状态"状态,如执行计算时表不存在。
	 */
	EXCPT = 2,

	/**
	 * "错误状态"状态,服务器级别的比较严重的错误结果,这个很少遇到,但是遇到后会对服务器运行产生影响。
	 */
	ERROR = 3
}
是否有帮助?
0条评论
评论