🚨 Active Supply Chain Attack:node-ipc Package Compromised.Learn More
Socket
Book a DemoSign in
Socket

@cloudbase/cli

Package Overview
Dependencies
Maintainers
15
Versions
578
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@cloudbase/cli - npm Package Compare versions

Comparing version
3.0.0-alpha.9
to
3.0.0-alpha.10
+255
runtime/nodejs/bootstrap.js
/* eslint-disable */
var runtime = require('./runtime')
var util = require('util')
var initHandlerFault = 'function initialization failed'
var maxRetMsgLen = 6 * 1024 * 1024 // byte
var maxRetMsgLenExceedError = 'body size is too long'
var httpHandler, eventHandler
var _result, _fault
var _user_exception = false
function wrapLog(invokeId) {
console.log = console.info = function prettyConsoleLog() {
var message = `${util.format.apply(this, arguments)}`
runtime.console_log(message)
}
console.error = console.warn = function prettyConsoleLogErr() {
var message = `${util.format.apply(this, arguments)}`
runtime.console_log(message, (err = true))
}
}
function main() {
if (0 != runtime.init()) {
console.log('runtime init failed')
return
}
runtime.log('init succ')
cleanEnv()
process.on('beforeExit', () => {
runtime.log('catch exit')
finish(null, null, false)
})
process.on('uncaughtException', err => {
runtime.log('catch exception')
finish(err, null, false)
})
waitForInvoke()
}
function cleanEnv() {
var envToDelete = ['SOCKETPATH', 'CONTAINERID']
for (var k in process.env) {
if (k.startsWith('KUBERNETES')) {
envToDelete.push(k)
}
}
envToDelete.forEach(e => {
delete process.env[e]
})
}
function waitForInvoke() {
runtime.log('wait for invoke')
var invokeInfo = runtime.wait_for_invoke()
setTimeout(() => {
runtime.log('timed out, invoke')
invoke(invokeInfo)
}, 0)
}
function invoke(invokeInfo) {
if (invokeInfo.cmd === 'RELOAD') {
runtime.log(`get reload request: ${invokeInfo.context}`)
// 路径中可能包含 . 符号
var ff = invokeInfo.globalHandler.split('.')
initHandler(invokeInfo.filePath + ff[0], ff[1])
runtime.log('handlers reloaded')
_result = 'reload'
finish(null, null, false)
return
}
_result = undefined
_fault = undefined
runtime.report_running()
var ev, ctx
if (invokeInfo.event || invokeInfo.context) {
try {
ev = JSON.parse(invokeInfo.event)
ctx = JSON.parse(invokeInfo.context)
} catch (err) {
_fault = `eval event[${invokeInfo.event}] or context [${invokeInfo.context}] failed\n${err}`
return
}
}
ctx['environ'].split(';').forEach(e => {
if (e == '') return
var kv = e.split('=', 2)
process.env[kv[0]] = kv[1]
})
runtime.log(`request[${ctx['request_id']}] invoked`)
if (!httpHandler && !eventHandler) {
_fault = initHandlerFault
return
}
wrapLog(ctx['request_id'])
if (invokeInfo.cmd === 'HTTP') {
httpHandler.handle(invokeInfo.sockfd)
} else if (invokeInfo.cmd === 'EVENT') {
eventHandler.handle(ev, ctx)
} else {
_fault = `recv unknown task type: ${invokeInfo.cmd}`
runtime.log(`recv unknown task type: ${invokeInfo.cmd}`)
}
runtime.log('process finished')
}
function initHandler(file, func) {
try {
var path = require('path')
var current_path = path.dirname(file)
process.chdir(current_path)
runtime.log(`working directory: ${process.cwd()}`)
for (var item in require.cache) {
delete require.cache[item]
}
var usermod = require(file)
httpHandler = new HttpHandler(usermod[func])
eventHandler = new EventHandler(usermod[func])
} catch (err) {
runtime.log(`get user function[${file}:${func}] failed`)
runtime.log(err.stack)
initHandlerFault = err.message
_user_exception = true
}
}
function finish(err, data, wait) {
runtime.log('finish')
runtime.log(wait ? 'wait' : 'not wait')
if (_result === undefined) {
if (err == null) {
try {
_result = JSON.stringify(data === undefined ? null : data)
} catch (err) {
_result = 'faulted'
_fault = `stringify response to json failed: ${err.message}`
return
}
} else {
_result = 'faulted'
if (err instanceof Error) {
runtime.console_log(err.stack, true)
_fault = err.message
} else {
var errStr = String(err)
_fault = `${errStr}(callback err is not instance of Error)`
}
}
}
if (wait) {
return
}
runtime.log(_result)
process.nextTick(() => {
if (_result == 'reload') {
// reload response, do nothing
} else if (_fault !== undefined) {
_user_exception = true
var errType = _user_exception ? 2 : 1
runtime.report_fail(_fault, 0, errType)
} else if (_result.length > maxRetMsgLen) {
runtime.report_fail(maxRetMsgLenExceedError, 0, 1)
} else {
runtime.report_done(_result, 0)
}
waitForInvoke()
})
}
class HttpHandler {
constructor(func) {
this.realHandler = func
}
handle(fd) {}
}
class EventHandler {
constructor(func) {
this.realHandler = func
}
handle(ev, ctx) {
var called = false
var wait = true
var callback = (err, data) => {
if (called) {
return
}
called = true
finish(err, data, wait)
}
var ctxx = Object.assign(
{
set callbackWaitsForEmptyEventLoop(value) {
wait = value
},
get callbackWaitsForEmptyEventLoop() {
return wait
},
getContext() {
return ctx
},
done: function(err, data) {
wait = false
callback(err, data)
},
succeed: function(data) {
ctxx.done(null, data)
},
fail: function(err) {
ctxx.done(err, null)
}
},
ctx
)
try {
_user_exception = false
var ret = this.realHandler(ev, ctxx, callback)
if (
ret &&
ret.then !== undefined &&
typeof ret.then === 'function'
) {
ret.then(ctxx.succeed, ctxx.fail)
}
} catch (err) {
runtime.console_log(err.stack, true)
_fault = err.stack
_user_exception = true
}
}
}
main()
/* eslint-disable */
const fs = require('fs')
const crypto = require('crypto')
var GLOBAL_FUNCTION_HANDLER = process.argv[2] || process.env.SCF_FUNCTION_HANDLER || 'index.main'
var GLOBAL_FUNCTION_NAME = process.env.SCF_FUNCTION_NAME || 'main'
var GLOBAL_EVENT_BODY =
process.argv[3] ||
process.env.SCF_EVENT_BODY ||
(process.env.DOCKER_USE_STDIN && fs.readFileSync('/dev/stdin', 'utf8')) ||
'{}'
var GLOBAL_USER_FILE_PATH = process.env.GLOBAL_USER_FILE_PATH || ''
var GLOBAL_VERSION = process.env.SCF_FUNCTION_VERSION || '$LATEST'
var GLOBAL_MEM_SIZE = process.env.SCF_FUNCTION_MEMORY_SIZE || '256'
var GLOBAL_TIMEOUT = process.env.SCF_FUNCTION_TIMEOUT || '3'
var GLOBAL_ENVIRON = process.env.SCF_FUNCTION_ENVIRON || ''
var GLOBAL_IS_QUIET = process.env.SCF_DISPLAY_IS_QUIET === 'True' || false
var GLOBAL_REQUEST_ID = uuid()
var GLOBAL_START_TIME = process.hrtime()
var GLOBAL_SOCK = -1
var GLOBAL_STAGE = 0
module.exports = {
init: function() {
if (!GLOBAL_IS_QUIET) {
consoleLog('开始本地执行云函数,受环境影响,执行结果可能与云端存在一定差异!')
consoleLog('START RequestId: ' + GLOBAL_REQUEST_ID)
}
return 0
},
wait_for_invoke: function() {
var invokeInfo = []
GLOBAL_STAGE += 1
switch (GLOBAL_STAGE) {
case 1:
invokeInfo.cmd = 'RELOAD'
invokeInfo.context = GLOBAL_USER_FILE_PATH + GLOBAL_FUNCTION_HANDLER
invokeInfo.globalHandler = GLOBAL_FUNCTION_HANDLER
invokeInfo.filePath = GLOBAL_USER_FILE_PATH
break
case 2:
invokeInfo.cmd = 'EVENT'
invokeInfo.sockfd = GLOBAL_SOCK
invokeInfo.event = GLOBAL_EVENT_BODY
invokeInfo.context = initContext()
break
default:
process.exit()
}
return invokeInfo
},
log: function(str) {
// consoleLog(formatSystem(str))
},
console_log: function(str, err = false) {
if (!GLOBAL_IS_QUIET) {
if (err === false) {
consoleLog(formatConsole(str))
} else {
consoleLogErr(formatConsole(str))
}
}
},
report_fail: function(stackTrace, errNum, errType = 0) {
const result = {}
result['errorCode'] = 1
result['errorMessage'] = 'user code exception caught'
if (stackTrace) {
result['stackTrace'] = stackTrace
}
reportDone('', (errType = 1))
// console.dir(result);
consoleLogErr(JSON.stringify(result))
},
report_running: function() {
GLOBAL_START_TIME = process.hrtime()
},
report_done: function(resultStr, errType = 0) {
reportDone(resultStr, errType)
}
}
function initContext() {
var context = {}
context['function_version'] = GLOBAL_VERSION
context['function_name'] = GLOBAL_FUNCTION_NAME
context['time_limit_in_ms'] = GLOBAL_TIMEOUT
context['memory_limit_in_mb'] = GLOBAL_MEM_SIZE
context['request_id'] = GLOBAL_REQUEST_ID
context['environ'] = GLOBAL_ENVIRON
return JSON.stringify(context)
}
function reportDone(resultStr, errType = 0) {
if (GLOBAL_IS_QUIET) {
if (typeof resultStr === 'string') {
if (errType === 0) consoleLog(resultStr)
else consoleLogErr(resultStr)
}
return
}
var diffMs = hrTimeMs(process.hrtime(GLOBAL_START_TIME))
var billedMs = Math.min(100 * (Math.floor(diffMs / 100) + 1), GLOBAL_TIMEOUT * 1000)
if (errType === 0) {
consoleLog('END RequestId: ' + GLOBAL_REQUEST_ID)
consoleLog(
[
'运行信息:',
'REPORT RequestId: ' + GLOBAL_REQUEST_ID,
'Duration: ' + diffMs.toFixed(2) + ' ms',
'Billed Duration: ' + billedMs + ' ms',
'Memory Size: ' + GLOBAL_MEM_SIZE + ' MB',
'Max Memory Used: ' + Math.round(process.memoryUsage().rss / (1024 * 1024)) + ' MB'
].join('\n')
)
} else {
consoleLogErr(
[
'运行信息:',
'REPORT RequestId: ' + GLOBAL_REQUEST_ID,
'Duration: ' + diffMs.toFixed(2) + ' ms',
'Billed Duration: ' + billedMs + ' ms',
'Memory Size: ' + GLOBAL_MEM_SIZE + ' MB',
'Max Memory Used: ' + Math.round(process.memoryUsage().rss / (1024 * 1024)) + ' MB'
].join('\n')
)
}
if (typeof resultStr === 'string') {
if (errType === 0) {
consoleLog('返回结果:\n' + resultStr)
} else {
consoleLogErr('返回结果:\n' + resultStr)
}
}
}
function consoleLog(str) {
process.stdout.write(str + '\n')
}
function consoleLogErr(str) {
process.stderr.write(str + '\n')
}
function formatConsole(str) {
return str.replace(/^[0-9TZ:.-]+\t[0-9a-f-]+\t/, '\u001b[34m$&\u001b[0m')
}
function formatSystem(str) {
return '\u001b[32m' + str + '\u001b[0m'
}
function hrTimeMs(hrtime) {
return (hrtime[0] * 1e9 + hrtime[1]) / 1e6
}
function uuid() {
return (
crypto.randomBytes(4).toString('hex') +
'-' +
crypto.randomBytes(2).toString('hex') +
'-' +
crypto
.randomBytes(2)
.toString('hex')
.replace(/^./, '1') +
'-' +
crypto.randomBytes(2).toString('hex') +
'-' +
crypto.randomBytes(6).toString('hex')
)
}
+3
-2
{
"name": "@cloudbase/cli",
"version": "3.0.0-alpha.9",
"version": "3.0.0-alpha.10",
"description": "CLI for Tencent CloudBase (standalone bundle)",

@@ -14,5 +14,6 @@ "bin": {

"dist/standalone",
"dist/fonts"
"dist/fonts",
"runtime/nodejs"
],
"license": "ISC"
}

@@ -45,4 +45,34 @@ # CloudBase 命令行工具 ![npm (tag)](https://img.shields.io/npm/v/@cloudbase/cli)

## 退出码说明
CloudBase CLI 使用结构化退出码帮助 CI/CD 流水线和 AI Agent 精确处理错误:
| 退出码 | 含义 | 典型场景 | 应对策略 |
|--------|------|----------|----------|
| 0 | 成功 | 命令正常执行 | - |
| 1 | 通用错误 | 未分类的异常 | 查看错误信息,手动排查 |
| 2 | 认证失败 | 未登录、token 过期、无权限 | 执行 `tcb login` 重新登录 |
| 3 | 参数错误 | 缺少必填参数、格式非法、枚举值错误 | 检查命令参数,参考 `tcb <cmd> --help` |
| 4 | 资源不存在 | 环境 ID/函数名无效、集合不存在 | 确认资源名称,用 `tcb env list` / `tcb fn list` 验证 |
| 5 | 云 API 错误 | CloudBase API 返回错误、网络超时 | 检查网络连接,查看 API 错误详情,必要时重试 |
| 6 | 本地文件错误 | cloudbaserc.json 缺失/损坏、路径不存在 | 检查配置文件,用 `tcb init` 重新初始化 |
**CI/CD 脚本示例**:
```bash
# 根据退出码自动重试
tcb fn deploy || {
code=$?
case $code in
2) echo "Auth failed, retrying..." && tcb login && tcb fn deploy ;;
5) echo "API error, retrying in 30s..." && sleep 30 && tcb fn deploy ;;
*) echo "Unrecoverable error (code $code)" && exit $code ;;
esac
}
```
完整定义参见:[src/exit-codes.ts](./src/exit-codes.ts)
## 意见反馈
您可以到 GitHub Repo 新建一个 [issue](https://github.com/TencentCloudBase/cloudbase-cli/issues) 反馈您在使用过程中遇到的问题或建议。

Sorry, the diff of this file is too big to display