import * as path from 'path'; import * as babel from '@babel/core'; import * as compiler from 'vue-template-compiler'; import * as fs from 'fs-extra'; import * as os from 'os'; import * as vfs from '../fs'; import * as utils from '../utils'; import * as rc from '../rc'; import * as download from './download'; import * as _ from 'lodash'; import FormData = require('form-data'); import * as semver from 'semver'; import Block from './Block'; import Component from './Component'; import Template from './Template'; export { download, Block, Component, Template }; import axios, { AxiosInstance } from 'axios'; let platformAxios: AxiosInstance; const getPlatformAxios = (prefix = '/internal'): Promise => { return new Promise((res, rej) => { if (platformAxios) return res(platformAxios); const config = rc.configurator.load(); platformAxios = axios.create({ baseURL: config.platform + prefix, headers: { 'access-token': config.access_token, }, maxContentLength: 1024 * 1024 * 50, }); res(platformAxios); }); } export function getCacheDir(subPath: string = '') { const cacheDir = path.join(os.homedir(), '.vusion', subPath); if (!fs.existsSync(cacheDir)) fs.ensureDirSync(cacheDir); return cacheDir; } export function getRunControl() { const rcPath = path.join(os.homedir(), '.vusion'); return rcPath; } export interface FormFile { name: string, path: string, [prop: string]: any, }; export const upload = { getFormData(files: string | FormFile | Array): FormData { if (!Array.isArray(files)) files = [files]; files = files.map((file) => { if (typeof file === 'string') return { name: path.basename(file), path: file }; else return file; }); const formData = new FormData(); files.forEach((file: FormFile, index: number) => { formData.append('files', fs.createReadStream(file.path), { filepath: file.name, // filepath 在 Form 提交的时候是 name }); }); return formData; }, async nos(files: string | FormFile | Array) { const formData = upload.getFormData(files); const pfAxios = await getPlatformAxios(); return pfAxios.post('api/v1/nos/upload', formData, { headers: formData.getHeaders(), }).then((res) => res.data); }, async micro(files: string | FormFile | Array, prefix?: string) { const formData = upload.getFormData(files); const pfAxios = await getPlatformAxios(prefix); return pfAxios.post('api/v1/micro/upload', formData, { headers: formData.getHeaders(), }).then((res) => res.data); }, async framework(files: string | FormFile | Array, framework: string) { const formData = upload.getFormData(files); formData.append('ui', framework); const pfAxios = await getPlatformAxios(); return pfAxios.post('api/v1/framework/upload', formData, { headers: formData.getHeaders(), }).then((res) => res.data); }, } /** * 获取最新的区块模板 */ export async function fetchLatestBlockTemplate() { const cacheDir = getCacheDir('templates'); return download.npm({ registry: rc.configurator.getDownloadRegistry(), name: '@vusion-templates/block', }, cacheDir); } /** * 获取最新的组件模板 */ export async function fetchLatestComponentTemplate() { const cacheDir = getCacheDir('templates'); return download.npm({ registry: rc.configurator.getDownloadRegistry(), name: '@vusion-templates/component', }, cacheDir); } const defaultFormatter = (content: string, params: object) => { return _.template(content)(params); } export async function formatTemplate(src: string, params: object = {}, formatter: (content: string, params: object) => string = defaultFormatter) { return Promise.all(vfs.listAllFiles(src, { type: 'file', dot: true, patterns: ['!**/node_modules', '!**/.git'], }).map((filePath) => { return fs.readFile(filePath, 'utf8').then((content) => { try { content = formatter(content, params); } catch(e) { throw new Error(filePath + '\n' + e); } return fs.writeFile(filePath, content); }); })); } export function formatTemplateTo(src: string, dest: string, params: object = {}, formatter: (content: string, params: object) => string = defaultFormatter) { return Promise.all(vfs.listAllFiles(src, { type: 'file', dot: true, patterns: ['!**/node_modules', '!**/.git'], }).map((filePath) => { return fs.readFile(filePath, 'utf8').then((content) => { try { content = formatter(content, params); } catch(e) { throw new Error(filePath + '\n' + e); } return fs.outputFile(path.join(dest, path.relative(src, filePath)), content); }); })); } export interface MaterialSource { type: string, registry: string, name: string, // source.name, npm name, repo name path?: string, version?: string, commit?: string, fileName?: string, baseName?: string, }; export interface MaterialOptions { /** * file: ./templates/componentA * file: /Users/alice/templates/componentA * npm: s-basic-form * npm: s-basic-form.vue * npm: s-basic-form.vue@0.3.2 * disable: npm: s-basic-form.vue@0.3.2:some/directory * npm: @cloud-ui/s-basic-form.vue * npm: @cloud-ui/s-basic-form.vue:some/directory * cnpm: cnpm:@cloud-ui/s-basic-form.vue * nnpm: nnpm:@cloud-ui/s-basic-form.vue * github: github:user/repo * disable: gitlab: gitlab:user/repo#master:some/directory */ source: string | MaterialSource, target: string, name: string, title?: string, }; export interface ProcessedMaterialOptions { /** * file: ./templates/componentA * file: /Users/alice/templates/componentA * npm: s-basic-form * npm: s-basic-form.vue * npm: s-basic-form.vue@0.3.2 * disable: npm: s-basic-form.vue@0.3.2:some/directory * npm: @cloud-ui/s-basic-form.vue * npm: @cloud-ui/s-basic-form.vue:some/directory * cnpm: cnpm:@cloud-ui/s-basic-form.vue * nnpm: nnpm:@cloud-ui/s-basic-form.vue * github: github:user/repo * disable: gitlab: gitlab:user/repo#master:some/directory */ source: MaterialSource, target: string, name: string, title?: string, }; export function processOptions(options: MaterialOptions): ProcessedMaterialOptions { const result: ProcessedMaterialOptions = { source: { type: 'file', registry: '', name: '', path: '', version: '', commit: '', fileName: '', baseName: '', }, target: options.target, name: options.name, title: options.title, }; let source = options.source; if (typeof source !== 'string') { result.source = source; // const fileName = result.source.fileName = path.basename(result.source.name); // result.source.baseName = path.basename(fileName, path.extname(fileName)); return result; } if (source[0] === '.' || source[0] === '~' || source[0] === '/') { result.source.type = 'file'; result.source.path = source; const fileName = result.source.fileName = path.basename(source); result.source.baseName = path.basename(fileName, path.extname(fileName)); } else { const repoRE = /^\w+:/; const cap = repoRE.exec(source); if (cap) { result.source.type = cap[0].slice(0, -1); source = source.slice(cap[0].length); } else result.source.type = 'npm'; const arr = source.split(':'); result.source.path = arr[1]; let name = arr[0]; if (name.includes('#')) { const arr2 = name.split('#'); result.source.name = arr2[0]; result.source.commit = arr2[1]; } else if (name.includes('@')) { const arr2 = name.split('@'); result.source.name = arr2[0]; result.source.version = arr2[1]; } else { result.source.name = name; } const fileName = result.source.fileName = path.basename(result.source.name); result.source.baseName = path.basename(fileName, path.extname(fileName)); } return result; } export async function getTemplate(packageName: string): Promise