UNPKG

@code-recycle/cli

Version:

高级语法查询替换工具;Advanced syntax query replacement tool

1,379 lines (1,251 loc) 55.3 kB
/// <reference types="node" /> import { default as __2 } from 'lodash'; import { basename } from '@angular-devkit/core'; import { dirname } from '@angular-devkit/core'; import { firstValueFrom } from 'rxjs'; import { getSystemPath } from '@angular-devkit/core'; import { InjectionToken } from 'static-injector'; import { Injector } from 'static-injector'; import { isAbsolute } from '@angular-devkit/core'; import { join } from '@angular-devkit/core'; import { normalize } from '@angular-devkit/core'; import { Observable } from 'rxjs'; import { Path } from '@angular-devkit/core'; import { Pattern } from 'fast-glob'; import { relative } from '@angular-devkit/core'; import { resolve } from '@angular-devkit/core'; import { split } from '@angular-devkit/core'; import { virtualFs } from '@angular-devkit/core'; export declare function arrayBufferToText(buffer: ArrayBuffer, path?: string): string; declare class ASTViewNode<NODE> implements CommonNode<NODE> { #private; index: number; /** 节点类型 */ type: ASTViewNodeType; /** 内容 */ value: string; /** 位置 */ range: NodeRange; /** 额外数据 */ private extraFn; context: { map: Map<string, (origin?: boolean) => any>; node: NODE; }; /** 标签 */ tag?: string; private options?; infer: InferData<NODE>; parent?: ASTViewNode<NODE>; clone(): ASTViewNode<NODE>; /** 只在上下文存在,没有上下文正常 */ toJSON?: () => {}; get contentRange(): NodeRange; constructor(index: number, /** 节点类型 */ type: ASTViewNodeType, /** 内容 */ value: string, /** 位置 */ range: NodeRange, /** @internal */ childrenFn: () => ASTViewNode<NODE>[], /** 额外数据 */ extraFn: () => Record<string, ExtraDataItem>, context: { map: Map<string, (origin?: boolean) => any>; node: NODE; }, /** 标签 */ tag?: string, options?: TreeOptions); /** 子元素 */ get children(): ASTViewNode<NODE>[]; get extra(): Record<string, ExtraDataItem>; } /** node是普通类型 token是最后的元素 */ declare type ASTViewNodeType = 'node' | 'token'; export declare type AutoDATA<INPUT extends any[], RETURN = string> = ((...contextArgs: INPUT) => Promise<RETURN>) | ((...contextArgs: INPUT) => RETURN) | RETURN | Promise<RETURN>; export declare function autoDataRunner<INPUT extends any[], RETURN>(data: AutoDATA<INPUT, RETURN>, input: INPUT): Promise<RETURN>; declare interface BaseOptions { toJsonWithChildren?: boolean; toJsonWithExtra?: boolean; } export declare function bufferEqual(a: ArrayBuffer, b: ArrayBuffer): boolean; declare type CallBackReturn = (Partial<ContentResolveItem> | CUSTOM_CHANGE | undefined)[] | undefined | Promise<(Partial<ContentResolveItem> | CUSTOM_CHANGE | undefined)[]> | void | Partial<ContentResolveItem> | CUSTOM_CHANGE; export declare function codeRecycleByNode(path: string, root?: string, options?: Partial<CoreOptions>): Promise<(<T>(Instance: ScriptFunction<T>) => Promise<T>)>; /** 外部暴露这个,但是允许手动变更成其他的 */ declare interface CommonNode<NODE_TYPE, VALUE = string> { type: string; value: VALUE; range: NodeRange; infer: InferData<NODE_TYPE>; children: CommonNode<NODE_TYPE, VALUE>[]; } export declare function completePromise(input: Observable<void>): Promise<unknown>; declare class ComposedNode<T> implements CommonNode<T> { item: LikeMatchItem<T>; range: NodeRange; value: string; infer: InferData<T>; static create<T>(item: LikeMatchItem<T>, fileContent: string): ComposedNode<T>; readonly type = "composed"; children: CommonNode<T, string>[]; constructor(item: LikeMatchItem<T>, range: NodeRange, value: string, infer: InferData<T>); } export declare function condition(value: any | Statement, trueInput: Statement | string, falseInput: Statement | string): (context: QueryContext) => string; /** * @group 配置 */ export declare interface Config { debug?: boolean | Record<keyof typeof DEBUG_OPTION, boolean>; /** 演练模式,修改内容输出到控制台 */ dryRun?: boolean; /** git clone 的远程仓库放到哪里.默认为系统临时文件夹 */ gitCloneTmpDir?: string; /** 执行撤销模板时,相同文件是否需要确认(编辑器) */ revokeSameConfirm?: boolean; get?: (name: string) => Promise<any>; /** antlr4 解析器位置,使用 download/dir 需要指定;使用编辑器时默认下载到拓展文件夹内 */ antlrParserDir?: string; /** tree-sitter 解析器位置,使用 download/dir 需要指定;使用编辑器时默认下载到拓展文件夹内 */ treeSitterParserDir?: string; /** 使用不同的包管理工具,默认为 npm */ packageManager?: PackageManager; /** 解析器下载方式, cli默认为 package(npm),编辑器为 download */ parserDownload?: 'package' | 'download' | 'dir'; /** 下载额外依赖时指定的 npm 仓库镜像位置 */ registryList?: string[]; /** @ignore */ disableDebugDate?: boolean; /** 指定拓展名对应解析器; `code-recycle parserList` 查看解析器; `code-recycle extnameList` 查看默认拓展名对应解析器*/ parserMap?: Record<string, { use: string; language: string; }>; /** 一些默认行为修改 */ default?: { /** 节点查询 */ nodeQueryOption: DefaultNodeQueryOption; /** 模板策略 */ templateStrategy: ConflictStrategy; /** 文件查询 */ fileQueryLayer: Pick<FileCopyLayer, 'ignoreList' | 'excludeList'>; }; } /** 一些配置 */ export declare const ConfigToken: InjectionToken<Config>; /** @group 配置 */ export declare interface ConflictStrategy { /** * 存在文件冲突时的操作 * * error: 抛出异常 * * default: 不改变 * * override: 覆盖当前文件 * * editor: 编辑器处理(需要编辑器支持) * */ conflict?: 'error' | 'default' | 'override' | 'editor' | (string & {}); /** {@inheritDoc ConflictStrategy.conflict} */ binaryConflict?: 'error' | 'default' | 'override' | (string & {}); /** * 撤销时产生冲突时的操作(当前文件与撤销文件不同时) * * delete: 直接删除 * * retain: 保留文件 * * editor: 编辑器处理(需要编辑器支持) * */ revokeConflict?: 'delete' | 'retain' | 'editor' | (string & {}); /** {@inheritDoc ConflictStrategy.revokeConflict} */ binaryRevokeConflict?: 'delete' | 'retain' | (string & {}); } export declare interface ContentResolveItem extends ResolveItemBase { /** 文件内容 */ content: string; /** 文件路径 */ path?: string; /** 查询到的文件节点 */ node?: CommonNode<any>; readonly originNode?: CommonNode<any>; readonly id: string; readonly languageConfig: LanguageOption; } declare class ContentResolveUpdate implements ContentResolveItem { #private; content: string; private parserService; languageConfig: LanguageOption; path?: string | undefined; resolve$$: Observable<CssSelectorBase<any>>; private resolveCache$$; node?: CommonNode<any>; readonly id: string; constructor(content: string, parserService: ParserService, languageConfig: LanguageOption, path?: string | undefined); refresh(content: string): void; cloneNode(node: CommonNode<any>): this; get originNode(): CommonNode<any, string> | undefined; toJSON(): { node: CommonNode<any, string> | undefined; content: string; path: string | undefined; resolve$$: string; position: { line: number; column: number; }[] | undefined; }; } export declare type CopyFormItem = string | { url: string; match?: string[] | string; output?: string; type?: 'branch' | 'tag' | 'commit'; commit?: string; }; export declare interface CoreOptions { path: string; /** 默认cwd */ workspacePath?: string; vfs: virtualFs.Host; hint: Hint; documentContext?: DocumentContext; globalContext?: GlobalContext; config: Partial<Config>; platform?: Platform; scriptCwd: string; } /** 核心 */ export declare const CoreOptionsToken: InjectionToken<ResolvedCoreOptions>; /** * 通用节点模式,所有节点的数据结构相同 * 保护类型为语言需要实现的,astTree调用 */ declare abstract class CssSelectorBase<NODE extends object> { #private; private baseOptions?; abstract readonly rootNodeList: NODE[]; /** 可选 */ protected abstract content: string; constructor(baseOptions?: BaseOptions); protected abstract getNodePosition(node: NODE): NodeRange; protected abstract findTagName(node: NODE): string | undefined; /** 用于通用节点的使用 */ protected abstract getChildren(node: NODE): NODE[]; get nodeList(): ASTViewNode<NODE>[]; queryAll(node: ASTViewNode<NODE>, selector: SelectorType, options?: QueryOptions<NODE>): ASTViewNode<NODE>[]; queryAll(selector: SelectorType, options?: QueryOptions<NODE>): ASTViewNode<NODE>[]; queryOne(node: ASTViewNode<NODE>, selector: SelectorType, options?: QueryOptions<NODE>): ASTViewNode<NODE>; queryOne(selector: SelectorType, options?: QueryOptions<NODE>): ASTViewNode<NODE>; match(node: ASTViewNode<NODE>, content: string, options?: LikeMatchOptions): ComposedNode<NODE>[]; match(content: string, options?: LikeMatchOptions): ComposedNode<NODE>[]; locate(position: NodeRange): { node: ASTViewNode<NODE>; pathList: number[]; }[]; protected getNodeExtraData(node: NODE, callPath: string, registryMap: Map<string, () => any>, filterList?: string[]): Record<string, ExtraDataItem>; getAstTree(nodeList?: NODE[], hasChildren?: boolean | number, options?: TreeOptions): { children: ASTViewNode<NODE>[]; callbackMap: Map<string, () => any>; }; protected registryMethod(root: string, name: string, fn: () => any, map: Map<string, () => void>): ExtraDataCallItem; /** 引用数据 */ protected registryRefData(root: string, name: string, fn: (origin?: boolean) => any, map: Map<string, (origin?: boolean) => void>): ExtraDataRefItem; } /** 当前调用处于哪个文件夹 */ export declare const CurrentDirToken: InjectionToken<Path>; export declare const CurrentPathToken: InjectionToken<Path>; declare type CUSTOM_CHANGE = { value: string; range: NumberTuple2; }; export declare function data(str: string): (context: QueryContext) => string; /** @group 配置 */ declare const DEBUG_OPTION: { parser: string; installParser: string; }; /** @group 配置 */ export declare type DefaultNodeQueryOption = Pick<NodeQueryOption, 'delete' | 'multi' | 'nullable' | 'optional' | 'mode' | 'insertBefore' | 'insertAfter'>; export declare function deleteImport(name: string): NodeQueryOption; /** 从编辑器中传入的值 */ export declare interface DocumentContext { /** 编辑器选中/代码片段调用 */ insertRange?: { value: string; range: NumberTuple2; }[]; /** 代码片段调用 */ selectRange?: { value: string; range: NumberTuple2; }[]; path: Path; dir: Path; workspacePath: Path; /** 代码片段 */ snippetParameters?: Record<string, any>; /** 代码片段 */ trigger?: string; } /** 文档,可选 */ export declare const DocumentContextToken: InjectionToken<DocumentContext>; declare type EachFunction<T> = (node: ASTViewNode<T>, infer: InferData<T>) => boolean | undefined | void | ASTViewNode<T>[] | ASTViewNode<T>; declare class ExtraDataCallItem { value: string; readonly type = "Call"; constructor(value: string); } declare type ExtraDataItem = ExtraDataLiteralItem | ExtraDataCallItem | ExtraDataRefItem; declare class ExtraDataLiteralItem { value: string | number | boolean | Record<string, any> | undefined; readonly type = "Literal"; constructor(value: string | number | boolean | Record<string, any> | undefined); } /** 可能是节点 */ declare class ExtraDataRefItem { value: string; readonly type = "Node"; constructor(value: string); } export declare function fileBufferToString(fileBuffer: ArrayBuffer): string; export declare function fileContent(str: string): (context: QueryContext) => string; /** * @group 文件查询 */ export declare type FileCopyLayer = { type: 'copy'; /** 默认为本地文件,允许使用git拉取远程仓库 */ source?: 'local' | 'git'; /** 文件夹或路径(列表);使用git时可以配置拉取文件,排除文件,分支 */ from: AutoDATA<[context: QueryContext], CopyFormItem | undefined> | AutoDATA<[context: QueryContext], CopyFormItem | undefined>[]; /** 排除路径 */ excludeList?: string[]; /** 忽略文件 * * 比如.gitignore */ ignoreList?: string[]; /** 文件夹或路径 */ to: AutoDATA<[context: QueryContext], string>; disable?: AutoDATA<[context: QueryContext], boolean>; } & TemplateOption & { strategy?: ConflictStrategy; }; /** * @group 文件查询 */ export declare interface FileCreateLayer { type: 'create'; /** 文件名 */ path: AutoDATA<[context: QueryContext], string | undefined>; /** 内容 */ content: AutoDATA<[context: QueryContext], string>; /** 禁用此层 */ disable?: AutoDATA<[context: QueryContext], boolean>; } /** * @group 文件查询 * */ export declare interface FileQueryCommon { path?: AutoDATA<[context: QueryContext], string>; /** 以内容创建解析器 */ content?: AutoDATA<[context: QueryContext], string>; /** 默认为ts解析器 */ parser?: { use: string; language: string; }; glob?: boolean; /** 创建新文件时查询节点内容作为解析内容 */ query?: string; disable?: AutoDATA<[context: QueryContext], boolean>; } /** * @group 文件查询 */ export declare interface FileQueryLayer extends FileQueryCommon { /** 不指定类型时默认为 query */ type?: 'query'; /** 文件路径;与 content 互斥 */ path?: AutoDATA<[context: QueryContext], string>; /** 以内容创建解析器;与 path 互斥 */ content?: AutoDATA<[context: QueryContext], string>; /** 链式查询节点 */ list: NodeQueryFlowList; /** 根据后缀自动判断解析器类型,允许显式指定 */ parser?: { use: string; language: string; }; /** 开启后 path 为 pattern;[帮助](https://github.com/micromatch/picomatch?tab=readme-ov-file#basic-globbing) */ glob?: boolean; /** 创建新文件时查询节点内容作为解析内容 */ query?: string; /** * ? 不确定此设计是否合理 * 将查询/替换结果直接更新,使用 query(如果存在)查询到的内容写入到此文件中 */ newPath?: string; /** 命名之后,可以使用`root.xx`访问该层上下文,如果该层有多个文件,那么获得的是一个主上下文,使用xx[index]访问真实文件上下文 */ name?: string; /** 是否将替换结果直接更新到文件中 */ update?: boolean; /** 禁用此层 */ disable?: AutoDATA<[context: QueryContext], boolean>; } /** * @group 文件查询 * */ export declare type FileQueryList = (FileQueryLayer | FileCreateLayer | FileCopyLayer)[]; /** 函数上下文,可选 */ export declare const FunctionParametersToken: InjectionToken<Record<string, (arg: any) => Promise<any>>>; /** 如果是原始值,那么就是原始值,否则会调用上下文 */ export declare function getData<T = string>(data: Statement<T> | T, context: QueryContext): T; export declare function getStatementValue<T = string>(input: AutoDATA<[context: QueryContext], T>, context: QueryContext): Promise<T>; export declare function gitCloneRepoName(options: { url: string; commit: string | undefined; type: string | undefined; match: string | string[] | undefined; }): string; export declare interface GlobalContext { setBoolean: (list: InputInfo[]) => Promise<Record<string, boolean>>; setInput: (list: InputInfo[]) => Promise<Record<string, string>>; } export declare const GlobalInputToken: InjectionToken<GlobalContext>; export declare type GridList = GridType[] | GridType[][]; export declare interface GridType { fixed?: boolean; cols?: number; config: Record<string, any>; } export declare interface Hint { dialogInfo(message: string, options: any): Promise<void>; outputLog(...list: any[]): Promise<any>; outputWarn(...list: any[]): Promise<any>; outputError(...list: any[]): Promise<any>; debug(...list: any[]): void; } /** 提示 */ export declare const HintToken: InjectionToken<Hint>; export declare type ImportInfo = { type?: boolean; path: string; importList: string[]; default?: boolean; }; export declare function ImportNode(node: ContentResolveItem, importList: string | ImportInfo[], prefix?: 'import' | 'export'): ContentResolveItem; export declare type ImportOrExportInfo2 = { type?: boolean; path?: string; newPath?: string; importList?: (string | { name: string; as?: string; newName?: string; newAs?: string; })[]; default?: boolean; delete?: boolean; }; export declare function importText(importList: ImportInfo[], prefix?: 'import' | 'export'): string; export declare function includeValue(list: string[], map?: (item: string) => string): () => string; export declare function incrementalChange(oldChange: string, newChange: string, start: number): ({ readonly start: number; readonly content: string; readonly type: 1; readonly length?: undefined; } | { readonly start: number; readonly length: number; readonly type: -1; readonly content?: undefined; })[]; declare type InferData<T> = Record<string, ASTViewNode<T> | ASTViewNode<T>[]>; export { Injector } export declare interface InputInfo { name: string; message?: string; force?: boolean; } export declare function isInWorkspace(root: Path, filePath: Path): boolean; export declare function isObject(obj: unknown): obj is Object; export declare function isPlainText(buffer: Uint8Array | ArrayBuffer): Promise<boolean>; export declare interface LanguageOption { use: string; language: string; extraOptions?: any; } declare type LikeMatchItem<T> = { pathList: ASTViewNode<T>[]; matchedCountList: number[]; infer: InferData<T>; last: ASTViewNode<T>; next?: ASTViewNode<T>; }; declare type LikeMatchLevel = 'all' | 'top' | 'bottom'; declare interface LikeMatchOptions { count?: number; matchLevel?: LikeMatchLevel; } export declare const mayBeVar = ":is(VariableDeclaration>Identifier,BindingElement>ColonToken+*,PropertyAccessExpression::children(0),CallExpression>SyntaxList>Identifier,BinaryExpression>Identifier,ConditionalExpression>Identifier,PropertyAssignment>ColonToken+Identifier,CallExpression>Identifier,ParenthesizedExpression>OpenParenToken+Identifier)"; export declare function methodRename(name: string, replace: string, options?: Partial<NodeQueryOption>): NodeQueryOption; export declare const nextPromise: typeof firstValueFrom; /** * @group 文件查询 * */ export declare type NodeQueryFlowList = (NodeQueryItem | NodeQueryItem[])[]; /** * @group 文件查询 * * */ export declare type NodeQueryItem = NodeQueryOption | { /** 全部有查询结果 */ allOf: NodeQueryItem[]; } | { /** 有且只有一个有查询结果 */ oneOf: NodeQueryItem[]; } | { /** 任意一个有查询结果,不会再查询后面的兄弟选项 */ anyOf: NodeQueryItem[]; } | { /** 不能有查询结果 */ not: NodeQueryItem; }; /** * @group 文件查询 * */ export declare interface NodeQueryOption { disable?: AutoDATA<[context: QueryContext], boolean>; /** * 用于上下文匹配 * 当使用 multi 时,需要指定 name[x] 匹配到指定选项, */ name?: string; /** 根据查询模式不同使用不同语法 */ query?: AutoDATA<[context: QueryContext], string>; /** 查询模式. selector: css选择器 like: 相似模式 */ mode?: QueryMode; /** 模式的一些选项,目前用于like */ modeOptions?: { matchLevel?: 'all' | 'top' | 'bottom'; }; /** true:返回多个结果列表,false:只有一个结果 */ multi?: boolean; /** 使用当前查询结果作为父节点进行下一步查询 */ children?: NodeQueryFlowList; /** 直接替换时,表示替换当前匹配节点,使用对象替换时表示替换查询中匹配到的变量 */ replace?: AutoDATA<[context: QueryContext], string> | Record<string, AutoDATA<[context: QueryContext, node: CommonNode<any>], string | { value: string; range?: NumberTuple2; }>>; /** 删除节点 */ delete?: boolean; /** 插入到节点前面 */ insertBefore?: boolean; /** 插入到节点后面 */ insertAfter?: boolean; /** 可选,当查询不到时不会报错;使用 oneOf/anyOf/not 时强制为 true */ optional?: boolean; /** * * 替换节点时处理节点范围 */ offset?: AutoDATA<[context: QueryContext], [number, number]>; /** 返回一个范围,替换query */ range?: AutoDATA<[context: QueryContext, range?: [number, number]], [number, number] | undefined>; /** 查询到节点时使用 */ callback?: (context: QueryContext, index: number) => CallBackReturn; /** multi:true 时,列表回调 */ listCallback?: (contextList: QueryContext[], self: QueryContext) => CallBackReturn; /** * 查询时使用其他节点作为父节点,仅上下文中查询父节点变化 */ parentMap?: AutoDATA<[context: QueryContext], ParentMap>; /** 返回一个列表,替换当前节点循环进行查询 */ loop?: (context: QueryContext, index: number) => ContentResolveItem[] | boolean; /** 用于异常提示 */ description?: string; /** * 未查询到数据时是否可以继续 * 子级节点应该使用 parentMap 获得新的父节点进行查询 */ nullable?: boolean; } declare type NodeRange = [number, number]; /** * ! 仅限 selector 使用 * @param str 路径 * @param contentRange 内容 * @returns */ export declare function nodeValue(str: string, contentRange?: boolean): (context: QueryContext) => string; export declare function not(input: Statement): (context: QueryContext) => string; /** 范围 */ export declare type NumberTuple2 = [number, number]; export declare function or(...args: (string | Statement)[]): (context: QueryContext) => string; /** @group 配置 */ export declare type PackageManager = 'npm' | 'cnpm' | 'yarn' | 'pnpm' | (string & {}); export declare type ParentMap = string | QueryContext | ContentResolveItem | FileQueryCommon; declare class ParserService { #private; constructor(); get parserMap$(): Map<string, RawLanguageItem>; getParserInstance(filePath: string, content: string, options: BaseOptions, option: LanguageOption): Promise<CssSelectorBase<any>>; getDefaultExtLanguageOptions(filePath: Path): { use: string; language: string; }[] | undefined; get parserList(): LanguageOption[]; } export declare function parseYaml(content: string): any; export { Path } export declare type PathTemplateFn = (input: string, path: Path) => any; declare type PipeObject = Record<string, (input: any, ...args: any[]) => any>; /** @ignore */ export declare interface Platform { applyFile?: (filePath: Path, templateBuffer: ArrayBuffer, originBuffer: ArrayBuffer, mergeStrategy: string, option: { host: ReadScopedHost; }) => Promise<boolean>; revokeFile?: (filePath: Path, templateBuffer: ArrayBuffer, originBuffer: ArrayBuffer, mergeStrategy: string, option: { host: ReadScopedHost; }) => Promise<boolean>; } /** 平台,可选 */ export declare const PlatformToken: InjectionToken<Platform>; export declare function proxyClone<T extends Record<string, any>>(obj: T, type?: Object): T; export declare function queryCall(name: string): string; /** * @group 文件查询 * **/ export declare class QueryContext { #private; parent?: QueryContext | undefined; name?: string | number | undefined; /** 子查询 */ children: QueryContext[]; data?: any; /** 解析节点,带文件来源的 */ node?: ContentResolveItem; /** 根上下文,可以查询到所有信息 */ root: QueryContext; /** 当前查询文件项的文件上下文,节点查询选项中使用 parentMap 不会修改 file 属性 */ file: QueryContext; /** 如果没有查询到内容会写入原因 */ unFindMessage?: string; constructor(util: Util, node?: ContentResolveItem, parent?: QueryContext | undefined, name?: string | number | undefined); create(node?: ContentResolveItem, name?: string | number): QueryContext; get index(): number; /** * 用于上下文中手动调用管道 * 管道就是函数在模板上的应用 */ get pipe(): Record<string, any>; /** * root 获得根上下文 * item 获得当前项上下文 * parent[1-?] 返回父级上下文 */ getContext<OPT extends boolean = false>(path?: string | string[], optional?: OPT): OPT extends false ? QueryContext : QueryContext | undefined; getNode<OPT extends boolean = false>(path?: string | string[], optional?: OPT): OPT extends false ? ContentResolveItem : ContentResolveItem | undefined; getNodeValue<OPT extends boolean = false>(path?: string, optional?: OPT): OPT extends false ? string : string | undefined; mark(message: string): void; } /** 变更导入 */ export declare function queryDeclaration(name: string, type: 'FunctionDeclaration' | 'TypeAliasDeclaration' | 'InterfaceDeclaration'): string; export declare function queryImport(name: string): string; export declare function queryImportInclude(name: string, list?: string[]): string; export declare type QueryMode = 'selector' | 'like'; declare interface QueryOptions<T> { eachFunction?: Record<string, EachFunction<T>>; matchLevel?: LikeMatchLevel; } /** pipe对象 */ export declare type QueryPipe = PipeObject | Record<string, PipeObject>; declare function queryStatement(str: string): (data?: Record<string, any>) => any; /** * ! 仅限 selector */ export declare function range(str: string, contentRange: boolean): (context: QueryContext) => [number, number]; export declare function raw(str: string | Statement): (context: QueryContext) => string; declare interface RawLanguageItem { use: string; language: string; parser: (fileName: string, content: string, baseOption: BaseOptions, extraOptions?: any) => Promise<CssSelectorBase<any>>; extraOptions?: any; } declare class ReadCordHost extends virtualFs.CordHost { private delegate; hint?: Hint | undefined; constructor(delegate: virtualFs.Host, hint?: Hint | undefined); clear(): void; writeToVFS(dryRun?: boolean): Promise<void>; restore(filePath: Path): void; } export declare class ReadScopedHost extends virtualFs.ResolverHost<{}> { #private; private delegate; path?: Path | undefined; protected _resolve(path: Path): Path; workspacePath?: Path; constructor(delegate: ReadCordHost | virtualFs.Host, path?: Path | undefined); listAll(searchDir: Path, options?: { ignoreList?: string[]; excludeList?: string[]; }): Path[] | Promise<Path[]>; /** * todo 解码,目前默认是utf-8 */ readContent(path: Path, options?: { encoding: string; }): Promise<string | undefined>; /** 绝对路径 0 当前 -1 向里 1 向外,*/ queryFile(dir: Path, item: { filePattern?: string; queryMode: 0 | 1 | -1; ignore?: Pattern[]; }, filter: (filePath: Path) => Promise<boolean>): Promise<Path[] | undefined>; clear(): void; writeToFs(dryRun?: boolean): Promise<void>; restore(filePath: Path): void; records(): virtualFs.CordHostRecord[]; /** 返回改路径对应的文件夹(如果是文件夹就直接返回) */ pathDir(path: Path): Promise<Path>; } export declare function renameImport(oldName: string, newName: string): NodeQueryOption; /** @ignore */ export declare interface ResolvedCoreOptions extends CoreOptions { /** 指定文件夹,相对位置 */ dir: Path; /** 指定文件(文件夹) */ path: Path; /** 根位置 */ workspacePath: Path; /** 脚本位置/运行位置 */ scriptCwd: Path; } declare interface ResolveItemBase { resolve$$: Observable<CssSelectorBase<any>>; refresh: (content: string) => void; cloneNode: (item: any) => ContentResolveItem; } export declare type RuleMap = RuleRunner['runnerCall']; declare class RuleRunner { #private; injector: Injector; /** 文件夹 */ host: ReadScopedHost; extraRule: Record<string, Record<string, (...args: any) => any>>; constructor(); runnerCall: { call: { /** 调用其他脚本,可以与源脚本格式不同 */ script: (filePath: string) => Promise<any>; }; read: { /** 通过 glob 匹配符合条件的文件创建解析器 */ fileResolveByPattern: <T extends boolean = false>(filePattern?: string, selector?: string, options?: { ignore?: string[] | undefined; queryMode?: 0 | 1 | -1 | undefined; all: T; languageOption?: LanguageOption | undefined; }) => Promise<(T extends true ? ContentResolveItem[] : ContentResolveItem) | undefined>; /** 根据文件路径/文件路径列表创建文件解析器 */ fileResolve: <T_1 extends string | string[]>(filePath: T_1, languageOption?: LanguageOption) => Promise<T_1 extends string[] ? ContentResolveItem[] : ContentResolveItem>; /** 根据文本创建解析器 */ contentResolve: (content: string, languageOption?: LanguageOption) => Promise<ContentResolveUpdate>; /** 读取文件编辑器上的相关参数(限编辑器支持) */ editorInput: (type: 'insertRange' | 'selectRange' | 'path' | 'workspacePath' | 'snippetParameters' | 'trigger' | 'dir') => Promise<string | Record<string, any> | Path | { value: string; range: NumberTuple2; }[] | { value: string; range: NumberTuple2; }[] | undefined>; /** 将文件解析为:对象(json/yaml)/buffer/plaintxt */ parseToObject: (filePath: string, type: 'json' | 'plain' | 'buffer' | 'yaml') => Promise<any>; /** 读取一些设置;需要平台传入 */ setting: (value: string) => Promise<any>; }; query: { /** * 选择器查询模式 * * 使用[CSS选择器查询](https://developer.mozilla.org/en-US/docs/Web/CSS/CSS_selectors) * @param contentResolve * @param selector * @param all * @returns */ selector: <ALL extends boolean = false>(contentResolve: ContentResolveItem, selector: string, all?: ALL, options?: QueryOptions<any>) => Promise<ALL extends true ? ContentResolveItem[] : ContentResolveItem | undefined>; /** * like 查询模式 * 与普通查询的语法几乎一样,但是更遵循语言的语法 * @param contentResolve * @param selector * @param count * @returns */ like: <Count extends number>(contentResolve: ContentResolveItem, selector: string, count: Count, options?: LikeMatchOptions) => Promise<Count extends 1 ? ContentResolveItem | undefined : ContentResolveItem[]>; }; resolve: { queryStatement: typeof queryStatement; }; operator: { /** * 替换文件的指定范围 * @param list * @param fileMap 返回需要修改的文件 * @param rangeMap 返回需要修改的范围 * @param contentMap 返回需要修改的内容 * @returns */ replaceNode: <T_2>(list: T_2[], fileMap: (item: T_2) => ContentResolveItem | Promise<ContentResolveItem>, rangeMap: (item: T_2) => NumberTuple2 | Promise<NumberTuple2>, contentMap: (item: T_2) => string | Promise<string>) => Promise<void>; /** * 删除指定文件 * @param filePath */ deleteFile: (filePath: string) => Promise<void>; /** 创建新文件 */ newFile: (fileName: string, content: string | Buffer) => Promise<void>; /** 重命名文件 */ renameFile: (oldName: string, newName: string) => Promise<void>; /** 插入代码片段;需要编辑器支持 */ insertSnippet: (input: string, position: NumberTuple2 | NumberTuple2[]) => Promise<never>; template: (fromList: CopyFormItem[], to: string, source: "local" | "git" | undefined, excludeList?: string[] | undefined, ignoreList?: string[] | undefined, templateOption?: TemplateOption | undefined, revoke?: boolean | undefined, conflictStrategy?: ConflictStrategy | undefined) => Promise<void>; /** 执行命令 */ commandExec: (command: string, args: string[], cwd?: string) => Promise<void>; }; globalVariable: { /** * 交互设置 string * @param input * @returns */ setStringByInteractive: (input: { name: string; force?: boolean; message?: string | undefined; }[]) => Promise<{ [x: string]: any; }>; /** 交互设置 boolean */ setBooleanByInteractive: (input: { name: string; force?: boolean; message?: string | undefined; }[]) => Promise<{ [x: string]: any; }>; /** * 设置全局变量 * @param key * @param value */ set: (key: string, value: any) => Promise<void>; /** * 读取全局变量 * @param keyPath * @returns */ get: (keyPath: string) => Promise<any>; }; common: { /** 读取对象数据,可以用来读取节点的 extra 部分 */ getData: (input: Record<string, any>, path: string | number) => Promise<any>; /** 相似度判断,优先进行startsWith判断,再判断距离相似 */ didYouMean: (input: string, list: string[], options: { threshold: number; }) => Promise<string | null>; /** 范围比较: input1 ? input2 */ rangeCompare: (input1: NumberTuple2, type: 'contains' | 'reverse-contains' | 'intersection' | 'equal' | 'not-intersection', input2: NumberTuple2) => Promise<boolean>; }; view: { /** 网格布局 */ grid: (config: { list: GridList; }) => Promise<{ type: string; children: any[]; config: { list: GridType[]; }; }>; /** 一个字符串标签 */ label: (config: { label: string; }) => Promise<{ type: string; config: { label: string; }; }>; /** 输入 */ input: (globalVariable: string, config: { label: string; placeholder?: string | undefined; type: 'input' | 'textarea'; color?: ViewColor | undefined; }) => Promise<{ type: string; bind: string; config: { label: string; placeholder?: string | undefined; type: 'input' | 'textarea'; color?: ViewColor | undefined; }; value: any; }>; /** 复选框 */ checkbox: (globalVariable: string, config: { label?: string; type: '' | 'icon'; color?: ViewColor | undefined; fontSet?: string | undefined; labelPosition?: 'before' | 'after'; icon?: string; }) => Promise<{ type: string; bind: string; config: { label?: string | undefined; type: '' | 'icon'; color?: ViewColor | undefined; fontSet?: string | undefined; labelPosition?: "before" | "after" | undefined; icon?: string | undefined; }; value: any; }>; /** 按钮 */ button: (config: { label: string; color?: ViewColor | undefined; type: '' | 'icon' | 'flat' | 'raised' | 'stroked' | 'fab' | 'mini-fab'; fontSet?: string | undefined; }, callback: (item: any) => Promise<any>) => Promise<{ type: string; callback: (item: any) => Promise<any>; config: { label: string; color?: ViewColor | undefined; type: '' | 'icon' | 'flat' | 'raised' | 'stroked' | 'fab' | 'mini-fab'; fontSet?: string | undefined; }; }>; /** 选择框 */ select: <T_3>(globalVariable: string, config: { label: string; placeholder: string; color?: ViewColor; fontSet?: string; multiple?: boolean; }, list: T_3[], labelMap: (item: T_3) => string | Promise<string>, valueMap: (item: T_3) => any | Promise<any>) => Promise<{ type: string; config: { label: string; placeholder: string; color?: ViewColor | undefined; fontSet?: string | undefined; multiple?: boolean | undefined; }; bind: string; list: { label: string; value: any; }[]; value: any; }>; /** * 数据展示 * node-list: 根据匹配节点展示,选中会保存到 globalVariable 中 * other: 普通的数据展示 */ showData: (globalVariable: string, config: { type: 'node-list' | 'other'; }, data: any) => Promise<{ bind: string; config: { type: 'node-list' | 'other'; }; data: any; type: string; }>; }; os: { /** * 使用 git 按需拉取仓库 * 拉取深度为1 * @param url * @param match 使用 gitignore 风格的语法指定匹配的文件 * @param output 指定读取仓库哪个文件夹 * @param type * @param commit * @returns */ gitClone: (url: string, match?: string[] | string, output?: string, type?: 'branch' | 'tag' | 'commit', commit?: string) => Promise<Record<string, ArrayBuffer>>; }; hint: Hint; }; } /** 覆盖原有的,action初始化用 */ export declare const RunnerOverrideToken: InjectionToken<typeof RuleRunner>; export declare function safeParse(value: string): any; export declare function safeStringify(obj: any): string; export declare function scriptContextRunner(code: string): string; export declare const ScriptCwdToken: InjectionToken<Path>; export declare interface ScriptFunction<T = any> { (util: Util, rule: RuleMap, host: ReadScopedHost, injector: Injector): Promise<T>; } declare function Selector<T = any>(list: TemplateStringsArray, ...args: EachFunction<T>[]): () => { selector: string; eachFunction: Record<string, EachFunction<T>>; }; declare type SelectorType = string | ReturnType<typeof Selector>; export declare type Statement<T = string> = (context: QueryContext) => T | undefined; export declare function statementRunner(input: AutoDATA<[context: QueryContext], string>, context: QueryContext): Promise<any>; export declare const STRING_FORMAT_LIST: readonly [readonly ["upcase", (value: string) => string], readonly ["downcase", (value: string) => string], readonly ["capitalize", (value: string) => string], readonly ["camelcase", (value: string) => string], readonly ["pascalcase", (value: string) => string], readonly ["kebabcase", (value: string) => string]]; export declare function stringSlice(str: string | Statement, start?: number, end?: number): (context: QueryContext) => string; export declare function stringToFileBuffer(str: string): ArrayBuffer; export declare interface TemplateOption { contentTemplate?: 'ejs' | 'handlebars' | 'raw' | '@angular-devkit'; /** 使用不同模板引擎时可以传入该模板引擎不同参数选项调整 */ contentTemplateOptions?: any; /** * [@angular-devkit](https://github.com/angular/angular-cli/blob/ce45522df6af6d9c0288495695473cca70f1a2c5/packages/angular_devkit/schematics/src/rules/template.ts#L78): `__name@toUpper__` 为使用 toUpper 函数传入 name 参数,可以使用 templateContext 传入; * 函数默认[自带](https://github.com/angular/angular-cli/blob/main/packages/angular_devkit/core/src/utils/strings.ts) **/ pathTemplate?: 'raw' | '@angular-devkit'; pathTemplateOptions?: any; templateContext?: Record<string, any>; /** 移除路径的后缀 */ pathTemplateSuffix?: TemplateSuffixItem | TemplateSuffixItem[]; } export declare class TemplateService { #private; /** * 将匹配文件列表写入到指定位置 * * 支持多种模板解析 * * 支持部分模板引擎的变量感知 * * @param fromList * @param to * @param source * @param excludeList * @param templateOption 模板的一些配置 * @param revoke 模板是否撤销 * @param conflictStrategy 如何和当前文件产生冲突如何处理 */ template: (fromList: CopyFormItem[], to: string, source: FileCopyLayer['source'], excludeList?: string[], ignoreList?: string[], templateOption?: TemplateOption, revoke?: boolean, conflictStrategy?: ConflictStrategy) => Promise<void>; } export declare type TemplateSuffixItem = '.template' | '.template.ejs' | '.ejs' | '.handlebars' | '.hbs' | '.template.handlebars' | (string & {}); declare interface TreeOptions { toJsonWithChildren?: boolean; toJsonWithExtra?: boolean; } export declare class Util { #private; filePathGroup: { currentDir: Path; currentPath: Path; root: Path; scriptCwd: Path; }; documentContext: DocumentContext; /** [lodash](https://lodash.com/docs) */ lodash: __2.LoDashStatic; /** 路径相关 */ path: { join: typeof join; normalize: typeof normalize; resolve: typeof resolve; relative: typeof relative; basename: typeof basename; dirname: typeof dirname; isAbsolute: typeof isAbsolute; getSystemPath: typeof getSystemPath; split: typeof split; }; /** 支持的解析器列表 */ parserList: LanguageOption[]; /** 独立的操作调用 */ rule: { call: { script: (filePath: string) => Promise<any>; }; read: { fileResolveByPattern: <T extends boolean = false>(filePattern?: string | undefined, selector?: string | undefined, options?: { ignore?: string[] | undefined; queryMode?: 0 | 1 | -1 | undefined; all: T; languageOption?: LanguageOption | undefined; }) => Promise<(T extends true ? ContentResolveItem[] : ContentResolveItem) | undefined>; fileResolve: <T_1 extends string | string[]>(filePath: T_1, languageOption?: LanguageOption | undefined) => Promise<T_1 extends string[] ? ContentResolveItem[] : ContentResolveItem>; contentResolve: (content: string, languageOption?: LanguageOption | undefined) => Promise<ContentResolveUpdate>; editorInput: (type: "dir" | "path" | "insertRange" | "selectRange" | "workspacePath" | "snippetParameters" | "trigger") => Promise<string | Record<string, any> | Path | { value: string; range: NumberTuple2; }[] | { value: string; range: NumberTuple2; /** 路径相关 */ }[] | undefined>; parseToObject: (filePath: string, type: "json" | "yaml" | "buffer" | "plain") => Promise<any>; setting: (value: string) => Promise<any>; }; query: { selector: <ALL extends boolean = false>(contentResolve: ContentResolveItem, selector: string, all?: ALL, options?: QueryOptions<any> | undefined) => Promise<ALL extends true ? ContentResolveItem[] : ContentResolveItem | undefined>; like: <Count extends number>(contentResolve: ContentResolveItem, selector: string, count: Count, options?: LikeMatchOptions | undefined) => Promise<Count extends 1 ? ContentResolveItem | undefined : ContentResolveItem[]>; }; resolve: { queryStatement: typeof queryStatement; }; operator: { replaceNode: <T_2>(list: T_2[], fileMap: (item: T_2) => ContentResolveItem | Promise<ContentResolveItem>, rangeMap: (item: T_2) => NumberTuple2 | Promise<NumberTuple2>, contentMap: (item: T_2) => string | Promise<string>) => Promise<void>; deleteFile: (filePath: string) => Promise<void>; newFile: (fileName: string, content: string | Buffer) => Promise<void>; renameFile: (oldName: string, newName: string) => Promise<void>; insertSnippet: (input: string, position: NumberTuple2 | NumberTuple2[]) => Promise<never>; template: (fromList: CopyFormItem[], to: string, source: "local" | "git" | undefined, excludeList?: string[] | undefined, ignoreList?: string[] | undefined, templateOption?: TemplateOption | undefined, revoke?: boolean | undefined, conflictStrategy?: ConflictStrategy | undefined) => Promise<void>; commandExec: (command: string, args: string[], cwd?: string | undefined) => Promise<void>; }; globalVariable: { setStringByInteractive: (input: { name: string; force?: boolean | undefined; message?: string | undefined; }[]) => Promise<{ [x: string]: any; }>; setBooleanByInteractive: (input: { name: string; force?: boolean | undefined; message?: string | undefined; }[]) => Promise<{ [x: string]: any; }>; set: (key: string, value: any) => Promise<void>; get: (keyPath: string) => Promise<any>; }; common: { getData: (input: Record<string, any>, path: string | number) => Promise<any>; didYouMean: (input: string, list: string[], options: { threshold: number; }) => Promise<string | null>; rangeCompare: (input1: NumberTuple2, type: "contains" | "reverse-contains" | "intersection" | "equal" | "not-intersection", input2: NumberTuple2) => Promise<boolean>; }; view: { grid: (config: { list: GridList; }) => Promise<{ type: string; children: any[]; config: { list: GridType[]; }; }>; label: (config: { label: string; }) => Promise<{ type: string; config: { label: string; }; }>; input: (globalVariable: string, config: { label: string; placeholder?: string | undefined; type: "input" | "textarea"; color?: ViewColor | undefined; }) => Promise<{ type: string; bind: string; config: { label: string; placeholder?: string | undefined; type: "input" | "textarea"; color?: ViewColor | undefined; }; value: any; }>; checkbox: (globalVariable: string, config: { label?: string | undefined; type: "" | "icon"; color?: ViewColor | undefined; fontSet?: string | undefined; labelPosition?: "before" | "after" | undefined; icon?: string | undefined; }) => Promise<{ type: string; bind: string; config: { label?: string | undefined; type: "" | "icon"; color?: ViewColor | undefined; fontSet?: string | undefined; labelPosition?: "before" | "after" | undefined; icon?: string | undefined; }; value: any; }>; button: (config: { label: string; color?: ViewColor | undefined; type: "" | "flat" | "icon" | "raised" | "stroked" | "fab" | "mini-fab"; fontSet?: string | undefined; }, callback: (item: any) => Promise<any>) => Promise<{ type: string; callback: (item: any) => Promise<any>; config: { label: string; color?: ViewColor | undefined; type: "" | "flat" | "icon" | "raised" | "stroked" | "fab" | "mini-fab"; fontSet?: string | undefined; }; }>; select: <T_3>(globalVariable: string, config: { label: string; placeholder: string; color?: ViewColor | undefined; fontSet?: string | undefined; multiple?: boolean | undefined; }, list: T_3[], labelMap: (item: T_3) => string | Promise<string>, valueMap: (item: T_3) => any) => Promise<{ type: string; config: { label: string; placeholder: string; color?: ViewColor | undefined; fontSet?: string | undefined; multiple?: boolean | undefined; }; bind: string; list: { label: string; value: any; }[]; value: any; }>; showData: (globalVariable: string, config: { type: "node-list" | "other"; }, data: any) => Promise<{ bind: string; config: { type: "node-list" | "other"; }; data: any; type: string; }>; }; os: { gitClone: (url: string, match?: str