无咖啡因的Utils模块
一个全面的TypeScript工具库,为命令行接口,输入处理,输出管理,文件系统操作,HTTP请求,文本处理等提供了强大的工具. 这个模块是建立强大的CLI应用程序的基础,具有标准化的输入解析,灵活的输出格式,以及丰富的一套公用功能.
现有文件 这里
最小尺寸: 34.4 KB kb gziped
说明
无咖啡因Utils模块是一个全面的TypeScript通用库,旨在将API标准化到整个寄存器,并为构建指令行界面(CLI)应用程序提供坚实的基础. 图书馆由几个关键组成部分组成:
CLI 模块
CLI模块为创建命令行应用程序提供了一个结构化的框架:
- 摘要
Command用于执行自定义的 CLI 指令的分类,并附有标准化的输入处理、记录和执行流程 - 命令选项处理,支持普通旗帜,如动词,版本,帮助等.
- 标准化命令执行流程,并妥善处理错误
输入模块
输入模块提供了处理用户输入和命令行参数的工具:
UserInput类,用于创建包含各种输入类型(文本、数字、确认等)的交互式提示- 支持输入验证、格式化和默认值
- 命令行参数分析类型检查和验证
- 在收到有效答复之前反复征求投入的方法
Utils 模块
Utils模块包含广泛的公用功能:
- 文件系统操作: 阅读、撰写、复制和删除文件和目录
- 软件包管理: 获取软件包信息,管理依赖性,以及版本处理
- HTTP 公用事业: 从 URL 下载文件的简单客户端
- 文本处理:字符串插值、大小写转换(骆驼案、蛇案等)和正则表达式工具
- 环境处理: 处理环境变量和配置
作家模块
Writers模块提供了处理命令输出的不同策略:
OutputWriter界面定义输出处理的标准合同StandardOutputWriter用于处理有正确记录的标准命令行输出RegexpOutputWriter用于处理带有正则表达式和模式匹配的输出
输出模块
产出单元为产出的格式和显示提供各种设施:
- 共同产出格式化功能
- 屏蔽显示能力
测试助手
测试辅助工具在 @decaf-ts/for-testing; 此套件不再导出 @decaf-ts/utils/tests。 。 。 .
这个库作为无咖啡因CLI工具的轻版,为建设强大的命令行应用程序提供所有必要的基本公用事业,并有一致的输入处理,输出格式化和出错管理.
如何使用
实例
CLI 模块
创建自定义命令
指令类为创建自定义的CLI指令提供基础,并有标准化的输入处理和执行流程.
import { Command, CommandOptions } from '@decaf-ts/utils';
// Define input options interface
interface MyCommandOptions {
filename: string;
dryRun: boolean;
}
// Create a custom command class
class MyCommand extends Command<MyCommandOptions, string> {
constructor() {
// Define command options with their configurations
const options: CommandOptions<MyCommandOptions> = {
filename: {
type: 'string',
short: 'f',
default: 'output.txt'
},
dryRun: {
type: 'boolean',
short: 'd',
default: false
}
};
super('my-command', options);
}
// Override the help method to provide custom help information
protected help(): void {
this.log.info(`
Usage: my-command [options]
Options:
-f, --filename Specify output filename (default: output.txt)
-d, --dryRun Run without making changes (default: false)
-h, --help Show help information
-v, --version Show version information
`);
}
// Implement the run method to define command behavior
protected async run(answers: { filename: string; dryRun: boolean }): Promise<string> {
this.log.info(`Running command with filename: ${answers.filename}, dryRun: ${answers.dryRun}`);
// Command implementation here
return 'Command executed successfully';
}
}
// Execute the command
async function main() {
const command = new MyCommand();
const result = await command.execute();
console.log(result);
}
main().catch(console.error);
与全权证书委员会管理机密
这个 CredentialsCommand 提供一种安全、跨平台的管理符的方法
以及发布脚本、CI管道和当地发展所使用的其他秘密.
它取代了将信使存储在平版文件的旧做法(.npmtoken, (中文(简体) ),
.token, (中文(简体) ), .confluence-token)与OS键链存储同时保存
向后兼容 .
决议令 (按此顺序排列) get 编号 : resolveSecret():
- 环境变量 ——最高优先级;这是CI的用法
- OS 键链 – macOS keychain, Linux libsecret, Linux Python 密钥环, Windows 证书管理器
- 遗留的纯文本文件 ——有警告的被贬后退
内设机密:
| 名称 | 新闻 var | 键链服务 | 账户 | 遗留文件 |
|---|---|---|---|---|
npm | NPM_TOKEN | decaf-ts:npm | 发布 | .npmtoken |
github | GH_TOKEN | decaf-ts:github | gi | .token |
confluence | ATLASSIAN_API_TOKEN | decaf-ts:confluence | api 密码 | .confluence-token |
自定义秘密名称也被支持 – env var 默认为
<NAME>_TOKEN,服务 decaf-ts:<name>,以及遗留文件
.<name>-token。 。 。 .
CLI 使用量( 单独)
# Resolve the npm publish token (prints to stdout, no trailing newline)
credentials --action get --name npm
# Resolve the github token using a non-default env var name
credentials --action get --name github --envVar GH_PAT
# Store a secret in the OS keychain
credentials --action store --name github --value ghp_xxxxxxxxxxxx
# Store a custom secret with fully overridden metadata
credentials --action store --name my-api \
--envVar MY_API_TOKEN \
--service "my-app:api" \
--account "ci" \
--value "sk_live_xxx"
# Interactive one-time setup (prompts for all built-in secrets, configures git helper)
credentials --action setup
# Setup and auto-delete legacy plaintext token files (.npmtoken, .token, .confluence-token)
credentials --action setup --rm
# Configure only the git credential helper (no secret enrollment)
credentials --action git-helper
# Use in a shell pipeline (e.g., set npm auth for publish)
npm config set //registry.npmjs.org/:_authToken "$(credentials --action get --name npm)"
CLI(通过无咖啡因CLI)的使用
# All subcommands are also available under the decaf CLI
decaf utils credentials get --name npm
decaf utils credentials store --name github --value ghp_xxxxxxxxxxxx
decaf utils credentials setup
decaf utils credentials setup --rm # auto-deletes legacy token files
decaf utils credentials git-helper
# View help for any subcommand
decaf utils credentials --help
decaf utils credentials get --help
CI 使用( GitHub 动作 / GitLab CI)
CI中不需要键链访问——简单地将环境变量设定为
保密和 resolveSecret() 立即捡起它:
# .github/workflows/release.yml
- name: Publish to npm
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: |
npm config set //registry.npmjs.org/:_authToken "$NPM_TOKEN"
npm publish
发行脚本( E) :tag-release, (中文(简体) ), npm publish, (中文(简体) ), git push(电话)
resolveSecret("npm") 财务报告和审定财务报表 resolveSecret("github") 内部,所以他们
在 CI 和键链中自动偏好 env vars .
程序使用( TypeScript)
import { resolveSecret, hasSecret } from '@decaf-ts/utils';
// Resolves using the same order: env var -> keychain -> legacy file
// Throws if no source provides a value.
const token = resolveSecret('npm');
// Non-throwing check
if (hasSecret('github')) {
const ghToken = resolveSecret('github');
}
// Custom secret with overrides
const apiKey = resolveSecret('my-api', {
envVar: 'MY_API_TOKEN',
service: 'my-app:api',
account: 'ci',
legacyFile: '.my-api-token',
});
本地设置走过
# 1. Run interactive setup with --rm (enrolls npm, github, confluence in the keychain
# and auto-deletes legacy plaintext files)
credentials --action setup --rm
# 2. Verify resolution works
credentials --action get --name npm # should print the token
credentials --action get --name github # should print the token
# 3. Future release scripts will now use the keychain automatically
建造和出版总库
这个 BundleCommand 替换遗留根 bin/bundle.js 脚本: 读取
bundles.json 财务报告和审定财务报表 package-template.json (单份复制命令资产已运出)
内 @decaf-ts/utils),生成一个 @decaf-ts/dist-* 包件总数
bundles.json 条目 --target (默认) <base-path>/bin/releases, (中文(简体) ),
从工作空间解析每个捆绑的依赖的版本, 合并 npm
覆盖, 然后运行 npm install 财务报告和审定财务报表 npm publish --access public 每个
生成捆绑文件夹(等待) --timeout 出版之间的秒).
通过证书解析器(env var - > OS 键链 - >
遗留文件),并且从未被登录. --dry-run (或 DRY_RUN=1生成
仅显出.
# Preview the generated manifests without installing or publishing
bundle --dry-run
# Full run from the workspace root, custom target and publish pacing
bundle --target ./releases --timeout 30
# Via the decaf CLI wrapper
decaf utils bundle --dry-run
decaf utils bundle --base-path . --target ./releases --timeout 30
显示文档文件夹
这个 BuildDocsCommand 替换遗留 bin/build-docs.sh 脚本:它
删除并重新创建文件文件夹( 默认) <base-path>/docs)和副本
读取( 默认) <base-path>/README.md成为它 docs/README.md。 。 。 .
build-docs
build-docs --base-path ./integrations
# Via the decaf CLI wrapper
decaf utils build-docs
decaf utils build-docs --base-path ./integrations
输入模块
创建交互式提示
用户输入类允许您为收集用户输入创建交互式提示.
import { UserInput } from '@decaf-ts/utils';
async function collectUserInfo() {
// Create a text input for name
const nameInput = new UserInput('name')
.setMessage('What is your name?')
.setInitial('User');
// Create a number input for age with validation
const ageInput = new UserInput('age')
.setType('number')
.setMessage('How old are you?')
.setMin(0)
.setMax(120)
.setValidate(value => {
if (value < 18) return 'You must be at least 18 years old';
return true;
});
// Create a confirmation input
const confirmInput = new UserInput('confirm')
.setType('confirm')
.setMessage('Is this information correct?')
.setInitial(true);
// Ask for all inputs and get the answers
const answers = await UserInput.ask([nameInput, ageInput, confirmInput]);
console.log(`Hello ${answers.name}, you are ${answers.age} years old.`);
console.log(`Information confirmed: ${answers.confirm ? 'Yes' : 'No'}`);
return answers;
}
collectUserInfo().catch(console.error);
使用方便输入方法
用户输入为常见输入情景提供了静态方便方法.
import { UserInput } from '@decaf-ts/utils';
async function quickInputExample() {
// Ask for text input
const name = await UserInput.askText('name', 'What is your name?', undefined, 'User');
// Ask for number input
const age = await UserInput.askNumber('age', 'How old are you?', 0, 120);
// Ask for confirmation
const confirm = await UserInput.askConfirmation('confirm', 'Is this information correct?', true);
// Ask for text with validation and retry until valid
const email = await UserInput.insistForText(
'email',
'What is your email address?',
(value) => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value),
undefined,
undefined,
false,
3 // Maximum 3 attempts
);
console.log(`Name: ${name}, Age: ${age}, Email: ${email}, Confirmed: ${confirm}`);
}
quickInputExample().catch(console.error);
解析命令行参数
import { UserInput, ParseArgsOptionsConfig } from '@decaf-ts/utils';
// Define command-line options
const options: ParseArgsOptionsConfig = {
verbose: {
type: 'boolean',
short: 'V',
default: false
},
output: {
type: 'string',
short: 'o',
default: 'output.txt'
},
count: {
type: 'string',
short: 'c',
default: '10'
}
};
// Parse command-line arguments
const args = UserInput.parseArgs(options);
console.log('Parsed arguments:', args.values);
console.log('Positional arguments:', args.positionals);
Utils 模块
文件系统操作
import {
readFile,
writeFile,
patchFile,
getAllFiles,
copyFile,
renameFile,
deletePath
} from '@decaf-ts/utils';
// Read a file
const content = readFile('./config.json');
console.log('File content:', content);
// Write to a file
writeFile('./output.txt', 'Hello, world!');
// Patch a file with replacements
patchFile('./template.txt', {
'{{name}}': 'John Doe',
'{{date}}': new Date().toISOString()
});
// Get all files in a directory
const files = getAllFiles('./src', (file) => file.endsWith('.ts'));
console.log('TypeScript files:', files);
// Copy a file
copyFile('./source.txt', './destination.txt');
// Rename a file
renameFile('./old-name.txt', './new-name.txt');
// Delete a file or directory
deletePath('./temp');
软件包管理
import {
getPackage,
getPackageVersion,
setPackageAttribute,
getDependencies,
installDependencies
} from '@decaf-ts/utils';
// Get package information
const pkg = getPackage();
console.log('Package:', pkg);
// Get package version
const version = getPackageVersion();
console.log('Version:', version);
// Set a package attribute
setPackageAttribute('version', '1.0.1');
// Get dependencies
async function manageDependencies() {
const deps = await getDependencies();
console.log('Production dependencies:', deps.prod);
console.log('Development dependencies:', deps.dev);
console.log('Peer dependencies:', deps.peer);
// Install dependencies
await installDependencies({
prod: ['lodash', 'axios'],
dev: ['typescript', 'jest']
});
}
manageDependencies().catch(console.error);
HTTP 公用事业
import { HttpClient } from '@decaf-ts/utils';
async function downloadExample() {
try {
// Download a file from a URL
const content = await HttpClient.downloadFile('https://example.com/api/data.json');
console.log('Downloaded content:', content);
// Parse JSON content
const data = JSON.parse(content);
console.log('Parsed data:', data);
return data;
} catch (error) {
console.error('Download failed:', error);
throw error;
}
}
downloadExample().catch(console.error);
文本处理
import {
padEnd,
patchPlaceholders,
patchString,
toCamelCase,
toSnakeCase,
toKebabCase,
toPascalCase,
toENVFormat
} from '@decaf-ts/utils';
// Pad a string
const padded = padEnd('Hello', 10, '-');
console.log(padded); // 'Hello-----'
// Replace placeholders
const template = 'Hello, ${name}! Today is ${day}.';
const filled = patchPlaceholders(template, {
name: 'Alice',
day: 'Monday'
});
console.log(filled); // 'Hello, Alice! Today is Monday.'
// Replace strings
const patched = patchString('Hello, world!', {
'world': 'universe'
});
console.log(patched); // 'Hello, universe!'
// Case conversion
const text = 'hello world';
console.log(toCamelCase(text)); // 'helloWorld'
console.log(toSnakeCase(text)); // 'hello_world'
console.log(toKebabCase(text)); // 'hello-world'
console.log(toPascalCase(text)); // 'HelloWorld'
console.log(toENVFormat(text)); // 'HELLO_WORLD'
测试助手
测试辅助工具在 @decaf-ts/for-testing; 此软件包不再提供 @decaf-ts/utils/tests 子路径.
作家模块
使用标准输出Writer
import { StandardOutputWriter } from '@decaf-ts/utils';
// Create a promise executor
const executor = {
resolve: (value: string) => console.log(`Command succeeded with: ${value}`),
reject: (error: Error) => console.error(`Command failed with: ${error.message}`)
};
// Create a standard output writer
const writer = new StandardOutputWriter('ls -la', executor);
// Handle command output
writer.data('File list output...');
writer.data('file1.txt');
writer.data('file2.txt');
// Handle command completion
writer.exit(0, ['Command executed successfully']);
使用 RegexpOutputWriter
import { RegexpOutputWriter } from '@decaf-ts/utils';
// Create a promise executor
const executor = {
resolve: (value: string) => console.log(`Found version: ${value}`),
reject: (error: Error) => console.error(`Error: ${error.message}`)
};
// Create a regexp output writer that matches version numbers
const writer = new RegexpOutputWriter('node --version', executor, /v(\d+\.\d+\.\d+)/);
// Process output that contains a version number
writer.data('v14.17.0'); // This will automatically resolve with "v14.17.0"
// Process error output
writer.error('Command not found: node'); // This will be logged as an error
编码原则
- 在文件夹中分组类似的功能( 与命名空间对应, 但没有任何命名空间声明)
- 每个文件一个类别;
- 每个文件一个接口(除非接口只是用作类型);
- 组合类型作为每个文件夹的.ts文件类型中的其他接口;
- 每个文件夹中的常数或常数组;
- 每个文件夹中的装饰器组;
- 总是从特定文件导入, 绝不从文件夹或索引文件导入( 其他软件包的依赖性除外 );
- 在适用的情况下,更倾向于使用既定的设计样板:
- Singleton(可以是反派. * 谨慎使用;
- 工厂;
- 观察员;
- 战略;
- 建造者;
- 诸如此类;
相关
社会
语文
获得帮助
如果您有错误报告, 请回答问题或建议 创建一个新问题。 。 。 .
捐款
我感谢对这一项目作出的任何贡献。 请阅读 这个 要开始.
支助
第一种最简单的方法就是支持它 捐款. 甚至在文档中找到打字很重要.
财政支持总是受到欢迎,帮助我和该项目保持生命和健康.
所以,如果你可以, 如果这个项目以任何方式。 要么通过学习 要么只是帮助你 节省宝贵的时间, 请考虑捐赠.
许可证
这个项目将在 MIT 许可证。 。 。 .
由开发者为开发者...