-
-
Notifications
You must be signed in to change notification settings - Fork 676
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(cli): init cli #488
feat(cli): init cli #488
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,41 @@ | ||
{ | ||
"name": "laf-cli", | ||
"version": "1.0.0", | ||
"description": "", | ||
"main": "dist/main.js", | ||
"bin": { | ||
"laf": "dist/main.js" | ||
}, | ||
"scripts": { | ||
"dev": "tsc -w", | ||
"watch": "tsc -w", | ||
"build": "tsc", | ||
"prepublishOnly": "npm run build" | ||
}, | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/labring/laf.git" | ||
}, | ||
"keywords": [ | ||
"laf" | ||
], | ||
"author": "", | ||
"license": "ISC", | ||
"bugs": { | ||
"url": "https://github.com/labring/laf/issues" | ||
}, | ||
"devDependencies": { | ||
"@types/cli-table2": "^0.2.3", | ||
"@types/mime": "^2.0.3", | ||
"@types/node": "^17.0.31" | ||
}, | ||
"dependencies": { | ||
"axios": "^1.2.1", | ||
"class-transformer": "^0.5.1", | ||
"cli-table3": "^0.6.3", | ||
"commander": "^9.3.0", | ||
"reflect-metadata": "^0.1.13", | ||
"typescript": "^4.7.4", | ||
"yaml": "^2.1.3" | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,45 @@ | ||
import { getHomeDir, writeYamlFile, ensureDirectory } from '../../utils/path'; | ||
import * as path from 'node:path' | ||
import * as fs from 'node:fs' | ||
import { getApplicationByAppid, listApplication } from '../../apis/application'; | ||
import * as Table from 'cli-table3'; | ||
import { ApplicationMetadata } from '../../templates/application'; | ||
import { APPLICATION_METADATA_FILE_NAME, FUNCTIONS_DIRECTORY_NAME } from '../../utils/constant' | ||
|
||
|
||
export async function handleInitApplication(appid: string, options: { sync: boolean }) { | ||
const applicationYamlPath = path.join(getHomeDir(), APPLICATION_METADATA_FILE_NAME) | ||
if (fs.existsSync(applicationYamlPath)) { | ||
console.log('The application configuration file already exists in the current directory, unable to initialize the application') | ||
return | ||
} | ||
const res = await getApplicationByAppid(appid); | ||
const applicationMetadata: ApplicationMetadata = { | ||
appid: res.data.appid, | ||
name: res.data.name, | ||
regionName: res.data.regionName, | ||
bundleName: res.data.bundleName, | ||
} | ||
writeYamlFile(applicationYamlPath, applicationMetadata); | ||
|
||
// init directory | ||
ensureDirectory(path.join(getHomeDir(), FUNCTIONS_DIRECTORY_NAME)) | ||
|
||
|
||
// if sync is true, load remote data in local | ||
if (options.sync) { | ||
|
||
} | ||
|
||
} | ||
|
||
export async function handleListApplication() { | ||
const table = new Table({ | ||
head: ['appid', 'name', 'region', 'bundle', 'runtime'], | ||
}) | ||
const res = await listApplication(); | ||
for (let app of res.data) { | ||
table.push([app.appid, app.name, app.regionName, app.bundleName, app.runtimeName]) | ||
} | ||
console.log(table.toString()); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
import { requestData } from "../utils/request" | ||
|
||
/** | ||
* 根据 appid 获取应用 | ||
* @param {string} appid | ||
* @returns 返回应用数据 | ||
*/ | ||
export async function getApplicationByAppid(appid: string) { | ||
const res = await requestData({ | ||
url: `/v1/applications/${appid}`, | ||
method: 'get' | ||
}) | ||
return res.data | ||
} | ||
|
||
/** | ||
* 获取应用列表 | ||
* @returns 返回应用数据 | ||
*/ | ||
export async function listApplication() { | ||
const url = `/v1/applications` | ||
const obj = { | ||
method: "GET", | ||
url | ||
} | ||
const result = await requestData(obj) | ||
return result.data | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
import { program, Command } from 'commander' | ||
|
||
import {handleInitApplication, handleListApplication} from '../../actions/application/application' | ||
|
||
export function applicationCommand(): Command { | ||
const app = program.command('app') | ||
|
||
app | ||
.command('init <appid>') | ||
.description('Initialize application') | ||
.option('-s, --sync', 'Sync application', "false") | ||
.action((appid, options) => { | ||
handleInitApplication(appid, options) | ||
}) | ||
|
||
app.command('list') | ||
.description('List application') | ||
.action(() => { | ||
handleListApplication() | ||
}) | ||
|
||
return app | ||
} | ||
|
||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
import { Command } from 'commander' | ||
import { applicationCommand } from './commands/application/application' | ||
|
||
|
||
const program = new Command() | ||
program | ||
.option('-v, --version', 'output version') | ||
.action(() => { | ||
const version = require('../package.json').version | ||
console.log(version) | ||
}) | ||
|
||
program.addCommand(applicationCommand()) | ||
|
||
program.parse(process.argv) |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
|
||
export interface ApplicationMetadata { | ||
maslow marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
name: string; | ||
|
||
appid: string; | ||
|
||
regionName?: string; | ||
|
||
bundleName?: string; | ||
|
||
runtimeName?: string; | ||
|
||
createdAt?: string; | ||
|
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
|
||
export const APPLICATION_METADATA_FILE_NAME = 'laf.yaml'; | ||
|
||
export const FUNCTIONS_DIRECTORY_NAME = 'functions'; | ||
|
||
export const FUNCTIONS_METADATA_FILE_SUFFIX_NAME = '.meta.yaml'; | ||
|
||
export const COLLECTIONS_DIRECTORY_NAME = 'collections'; | ||
|
||
export const COLLECTIONS_METADATA_FILE_SUFFIX_NAME = '.meta.yaml'; |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
import * as fs from 'node:fs' | ||
import { stringify, parse } from 'yaml' | ||
|
||
export function getHomeDir() { | ||
return "/Users/mac/Work/laf-cli-test/"; | ||
} | ||
|
||
export function ensureDirectory(dir: string) { | ||
try { | ||
fs.accessSync(dir, fs.constants.R_OK | fs.constants.W_OK) | ||
} catch (err) { | ||
fs.mkdirSync(dir, { recursive: true }) | ||
} | ||
} | ||
|
||
export function exist(fp: string): boolean { | ||
return fs.existsSync(fp); | ||
} | ||
|
||
export function loadYamlFile(filePath: string): any { | ||
const metadataStr = fs.readFileSync(filePath, 'utf-8') | ||
const yamlData = parse(metadataStr); | ||
return yamlData; | ||
} | ||
|
||
export function writeYamlFile(filePath: string, data: any) { | ||
const yamlData = stringify(data); | ||
fs.writeFileSync(filePath, yamlData); | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
import axios from 'axios' | ||
import { getRemoteServer } from './token' | ||
import { getAccessToken } from './token' | ||
Comment on lines
+2
to
+3
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. combine into one line |
||
|
||
|
||
export const request = axios.create({ | ||
// set baseURL | ||
baseURL: getRemoteServer() | ||
}) | ||
|
||
// http request | ||
request.interceptors.request.use( | ||
async (config) => { | ||
const token = await getAccessToken() | ||
if (token) { | ||
config.headers = { | ||
...config.headers, | ||
Authorization: `Bearer ${token}` | ||
}; | ||
} else { | ||
console.error("please login first: `laf login -u username -p password`") | ||
process.exit(1) | ||
} | ||
return config | ||
}, | ||
(error) => { | ||
// 错误抛到业务代码 | ||
error.data = {} | ||
error.data.msg = '服务器异常,请联系管理员!' | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 代码中的中文,还是在写的时候 统一 去除掉 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 好的 |
||
return Promise.resolve(error) | ||
}, | ||
) | ||
|
||
|
||
|
||
request.interceptors.response.use( | ||
/** | ||
* If you want to get http information such as headers or status | ||
* Please return response => response | ||
*/ | ||
|
||
/** | ||
* Determine the request status by custom code | ||
* Here is just an example | ||
* You can also judge the status by HTTP Status Code | ||
*/ | ||
response => { | ||
return response | ||
}, | ||
error => { | ||
const status = error.response.status | ||
|
||
if (status === 401) { | ||
console.error(error.response.data) | ||
process.exit(1) | ||
|
||
} | ||
if (status === 403) { | ||
console.error(error.response.data) | ||
process.exit(1) | ||
} | ||
if (status === 404) { | ||
console.error(error.response.data) | ||
process.exit(1) | ||
} | ||
if (status === 422) { | ||
console.error(error.response.data) | ||
process.exit(1) | ||
} | ||
|
||
// showError(error.message) | ||
return Promise.reject(error) | ||
} | ||
) | ||
|
||
|
||
|
||
/** | ||
* 描述 axios request 请求 | ||
* @param {Object} obj | ||
*/ | ||
export function requestData(obj: object) { | ||
return request.request(obj) | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
|
||
|
||
export function getAccessToken(): string { | ||
return 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiI2MzhkZDdhNTBlZTVjMGViNjk2NWU2NzIiLCJpYXQiOjE2NzAzMTE2ODksImV4cCI6MTY3MDkxNjQ4OX0.2UtpV0WC5kvtoPynvhXCSnrh9vadKQ7crLBMSxnI3A8' | ||
} | ||
|
||
export function getRemoteServer(): string { | ||
return 'http://localhost:3000' | ||
Comment on lines
+4
to
+8
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 这些是不是应该弄到配置文件? |
||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
{ | ||
"compileOnSave": true, | ||
"compilerOptions": { | ||
"allowJs": false, | ||
"allowUnreachableCode": false, | ||
"allowUnusedLabels": false, | ||
"charset": "utf8", | ||
"declaration": true, | ||
"experimentalDecorators": true, | ||
"emitDecoratorMetadata": true, | ||
"importHelpers": false, | ||
"module": "commonjs", | ||
"declarationMap": true, | ||
// "declarationDir": "types", | ||
"noEmitOnError": false, | ||
"noFallthroughCasesInSwitch": true, | ||
"noImplicitAny": false, | ||
"noUnusedLocals": true, | ||
"noUnusedParameters": true, | ||
"outDir": "dist", | ||
"pretty": true, | ||
"removeComments": true, | ||
"stripInternal": true, | ||
"skipDefaultLibCheck": true, | ||
"skipLibCheck": true, | ||
"target": "es2017", | ||
"alwaysStrict": true, | ||
"lib": [ | ||
"es2015", | ||
"es6" | ||
] | ||
}, | ||
"include": [ | ||
"src/**/*", | ||
], | ||
"exclude": [ | ||
"tests", | ||
] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@types/cli-table: '^0.3.1' ?