refactor: move tailchat-cli into tailchat

pull/49/head
moonrailgun 3 years ago
parent c057d2afc3
commit 160547a156

@ -5,7 +5,9 @@ on:
branches:
- master
paths:
- "./client/**"
- "./client/web/**"
- "./client/shared/**"
- "./client/packages/design/**"
workflow_dispatch:
jobs:

@ -2,10 +2,10 @@
"src/*.{json,less}": [
"prettier --write --config ./.prettierrc.json"
],
"**/*.js": [
"./**/*.js": [
"prettier --write --config ./.prettierrc.json"
],
"**/*.{ts,tsx}": [
"./**/*.{ts,tsx}": [
"eslint --fix",
"prettier --write --config ./.prettierrc.json"
]

@ -7,20 +7,5 @@
"trailingComma": "es5",
"bracketSpacing": true,
"arrowParens": "always",
"parser": "babel",
"jsxBracketSameLine": false,
"overrides": [
{
"files": "*.{tsx,ts}",
"options": {
"parser": "typescript"
}
},
{
"files": "*.less",
"options": {
"parser": "less"
}
}
]
"jsxBracketSameLine": false
}

@ -0,0 +1,107 @@
lib
plugins
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
# Runtime data
pids
*.pid
*.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# TypeScript v1 declaration files
typings/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variables file
.env
.env.test
# parcel-bundler cache (https://parceljs.org/)
.cache
# Next.js build output
.next
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
.cache/
# Comment in the public line in if your project uses Gatsby and *not* Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port

@ -0,0 +1,2 @@
# https://npmmirror.com/
registry = https://registry.npmmirror.com

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 MsgByte
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

@ -0,0 +1,15 @@
# tailchat-cli
A Command line interface of tailchat
```bash
tailchat <command>
Commands:
tailchat create [template] 创建 Tailchat 项目代码
tailchat connect 连接到 Tailchat 节点网络
tailchat declaration [source] Tailchat 插件类型声明
Options:
--version Show version number [boolean]
-h, --help Show help [boolean]
```

@ -0,0 +1,3 @@
#!/usr/bin/env node
require('../lib')

@ -0,0 +1,55 @@
{
"name": "tailchat-cli",
"version": "1.3.0",
"description": "A Command line interface of tailchat",
"bin": {
"tailchat": "./bin/cli"
},
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
"files": [
"lib",
"bin",
"templates"
],
"scripts": {
"dev": "ts-node ./src/index.ts",
"build": "rm -rf lib && tsc",
"prepare": "npm run build",
"release": "npm publish --registry https://registry.npmjs.com/",
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "git+https://github.com/msgbyte/tailchat-cli.git"
},
"keywords": [
"tailchat"
],
"author": "moonrailgun",
"license": "MIT",
"bugs": {
"url": "https://github.com/msgbyte/tailchat-cli/issues"
},
"homepage": "https://github.com/msgbyte/tailchat-cli#readme",
"dependencies": {
"dotenv": "^16.0.0",
"fs-extra": "^10.1.0",
"got": "11.8.5",
"inquirer": "^8.2.2",
"lodash": "^4.17.21",
"node-plop": "^0.26.3",
"ora": "5.4.1",
"plop": "^3.0.5",
"tailchat-server-sdk": "^0.0.12",
"yargs": "^17.4.0"
},
"devDependencies": {
"@types/fs-extra": "^9.0.13",
"@types/inquirer": "^8.2.1",
"@types/node": "16.11.7",
"@types/yargs": "^17.0.10",
"ts-node": "^10.7.0",
"typescript": "^4.6.3"
}
}

File diff suppressed because it is too large Load Diff

@ -0,0 +1,20 @@
import { CommandModule } from 'yargs';
import { TcBroker } from 'tailchat-server-sdk';
import defaultBrokerConfig from 'tailchat-server-sdk/dist/runner/moleculer.config';
import { config } from 'dotenv';
export const connectCommand: CommandModule = {
command: 'connect',
describe: '连接到 Tailchat 节点网络',
builder: undefined,
async handler(args) {
config();
const broker = new TcBroker({
...defaultBrokerConfig,
transporter: process.env.TRANSPORTER,
});
await broker.start();
broker.repl();
},
};

@ -0,0 +1,44 @@
import { CommandModule } from 'yargs';
import nodePlop from 'node-plop';
import path from 'path';
import inquirer from 'inquirer';
const plop = nodePlop(path.resolve(__dirname, '../../templates/plopfile.js'));
export const createCommand: CommandModule = {
command: 'create [template]',
describe: '创建 Tailchat 项目代码',
builder: (yargs) =>
yargs.positional('template', {
demandOption: true,
description: '代码模板名',
type: 'string',
choices: plop.getGeneratorList().map((v) => v.name),
}),
async handler(args) {
let template: string;
if (!args.template) {
const res = await inquirer.prompt([
{
type: 'list',
name: 'template',
message: '选择代码模板',
choices: plop.getGeneratorList().map((v) => ({
name: `${v.name} (${v.description})`,
value: v.name,
})),
},
]);
template = String(res.template);
} else {
template = String(args.template);
}
const basic = plop.getGenerator(template);
const answers = await basic.runPrompts();
const results = await basic.runActions(answers);
console.log('results', results);
},
};

@ -0,0 +1,65 @@
import inquirer from 'inquirer';
import { CommandModule } from 'yargs';
import fs, { mkdirp } from 'fs-extra';
import path from 'path';
import ora from 'ora';
import got from 'got';
export const declarationCommand: CommandModule = {
command: 'declaration [source]',
describe: 'Tailchat 插件类型声明',
builder: (yargs) =>
yargs.positional('source', {
demandOption: true,
description: '声明类型来源',
type: 'string',
choices: ['empty', 'github'],
}),
async handler(args) {
let source = String(args.source);
if (!source) {
const res = await inquirer.prompt([
{
type: 'list',
name: 'source',
message: '选择类型来源',
choices: [
{
name: '空',
value: 'empty',
},
{
name: '从 Github 下载完整声明',
value: 'github',
},
],
},
]);
source = String(res.source);
}
let content = '';
if (source === 'empty') {
content =
"declare module '@capital/common';\ndeclare module '@capital/component';\n";
} else if (source === 'github') {
const spinner = ora('正在从 Github 下载插件类型声明').start();
content = await got
.get(
'https://raw.githubusercontent.com/msgbyte/tailchat/master/web/tailchat.d.ts'
)
.then((res) => res.body);
spinner.succeed('声明文件下载完毕');
}
if (content !== '') {
const target = path.resolve(process.cwd(), './types/tailchat.d.ts');
await mkdirp(path.dirname(target));
await fs.writeFile(target, content);
console.log('写入类型文件完毕:', target);
}
},
};

@ -0,0 +1,13 @@
import yargs from 'yargs';
import { createCommand } from './commands/create';
import { connectCommand } from './commands/connect';
import { declarationCommand } from './commands/declaration';
yargs
.demandCommand()
.command(createCommand)
.command(connectCommand)
.command(declarationCommand)
.alias('h', 'help')
.scriptName('tailchat')
.parse();

@ -0,0 +1,85 @@
const path = require('path');
const _ = require('lodash')
function pickPluginName(text) {
const [_1, _2, ...others] = text.split('.');
return others.join('-');
}
function upperFirst(text) {
return _.upperFirst(_.camelCase(text));
}
module.exports = function (
/** @type {import('plop').NodePlopAPI} */
plop
) {
plop.setHelper('pickPluginName', pickPluginName);
plop.setHelper('pickPluginNameUp', (text) => {
return upperFirst(pickPluginName(text));
});
const serverPrompts = [
{
type: 'input',
name: 'id',
require: true,
default: 'com.msgbyte.example',
message: '插件唯一id, 以反域名格式的唯一字符串',
},
{
type: 'input',
name: 'author',
message: '插件作者',
default: 'anonymous',
},
{
type: 'input',
name: 'desc',
message: '插件描述',
default: '',
},
];
// 服务端插件的前端模板代码
plop.setGenerator('server-plugin', {
description: '服务端插件模板代码',
prompts: serverPrompts,
actions: [
{
type: 'addMany',
destination: path.resolve(process.cwd(), './plugins'),
base: './server-plugin',
templateFiles: ['./server-plugin/**/*'],
skipIfExists: true,
globOptions: {},
},
],
});
// 服务端插件的前端模板代码
plop.setGenerator('server-plugin-web', {
description: '服务端插件的前端模板代码',
prompts: [
{
type: 'input',
name: 'name',
require: true,
message: '插件名称',
},
...serverPrompts,
],
actions: [
{
type: 'addMany',
destination: path.resolve(process.cwd(), './plugins'),
base: './server-plugin-web',
templateFiles: [
'./server-plugin-web/**/*',
'./server-plugin-web/*/.ministarrc.js',
],
skipIfExists: true,
globOptions: {},
},
],
});
};

@ -0,0 +1,7 @@
const path = require('path');
module.exports = {
externalDeps: ['react'],
pluginRoot: path.resolve(__dirname, './web'),
outDir: path.resolve(__dirname, '../../public'),
};

@ -0,0 +1,20 @@
import { db } from 'tailchat-server-sdk';
const { getModelForClass, prop, modelOptions, TimeStamps } = db;
@modelOptions({
options: {
customName: 'p_{{pickPluginName id}}',
},
})
export class {{pickPluginNameUp id}} extends TimeStamps implements db.Base {
_id: db.Types.ObjectId;
id: string;
}
export type {{pickPluginNameUp id}}Document = db.DocumentType<{{pickPluginNameUp id}}>;
const model = getModelForClass({{pickPluginNameUp id}});
export type {{pickPluginNameUp id}}Model = typeof model;
export default model;

@ -0,0 +1,12 @@
{
"name": "tailchat-plugin-{{pickPluginName id}}",
"version": "1.0.0",
"main": "index.js",
"author": "{{author}}",
"description": "{{desc}}",
"license": "MIT",
"private": true,
"scripts": {},
"devDependencies": {},
"dependencies": {}
}

@ -0,0 +1,20 @@
import { TcService, TcDbService } from 'tailchat-server-sdk';
import type { {{pickPluginNameUp id}}Document, {{pickPluginNameUp id}}Model } from '../models/{{pickPluginName id}}';
/**
*
*/
interface {{pickPluginNameUp id}}Service
extends TcService,
TcDbService<{{pickPluginNameUp id}}Document, {{pickPluginNameUp id}}Model> {}
class {{pickPluginNameUp id}}Service extends TcService {
get serviceName() {
return 'plugin:{{id}}';
}
onInit() {
this.registerLocalDb(require('../models/{{pickPluginName id}}').default);
}
}
export default {{pickPluginNameUp id}}Service;

@ -0,0 +1,15 @@
{
"compilerOptions": {
"target": "ES6",
"module": "commonjs",
"rootDir": "src",
"outDir": "lib",
"allowSyntheticDefaultImports": true,
"strict": true,
"esModuleInterop": true,
"moduleResolution": "node",
"skipLibCheck": true,
"noEmit": false
},
"exclude": ["./templates"]
}
Loading…
Cancel
Save