Commit 3f0e93d4 authored by nano's avatar nano

fix lint

parent 24bbadbe
# http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.md]
max_line_length = 0
trim_trailing_whitespace = false
# Indentation override
#[lib/**.js]
#[{package.json,.travis.yml}]
#[**/**.js]
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectCodeStyleSettingsManager">
<option name="PER_PROJECT_SETTINGS">
<value>
<DBN-PSQL>
<case-options enabled="false">
<option name="KEYWORD_CASE" value="lower" />
<option name="FUNCTION_CASE" value="lower" />
<option name="PARAMETER_CASE" value="lower" />
<option name="DATATYPE_CASE" value="lower" />
<option name="OBJECT_CASE" value="preserve" />
</case-options>
<formatting-settings enabled="false" />
</DBN-PSQL>
<DBN-SQL>
<case-options enabled="false">
<option name="KEYWORD_CASE" value="lower" />
<option name="FUNCTION_CASE" value="lower" />
<option name="PARAMETER_CASE" value="lower" />
<option name="DATATYPE_CASE" value="lower" />
<option name="OBJECT_CASE" value="preserve" />
</case-options>
<formatting-settings enabled="false">
<option name="STATEMENT_SPACING" value="one_line" />
<option name="CLAUSE_CHOP_DOWN" value="chop_down_if_statement_long" />
<option name="ITERATION_ELEMENTS_WRAPPING" value="chop_down_if_not_single" />
</formatting-settings>
</DBN-SQL>
<TypeScriptCodeStyleSettings>
<option name="FORCE_SEMICOLON_STYLE" value="true" />
<option name="USE_DOUBLE_QUOTES" value="false" />
<option name="FORCE_QUOTE_STYlE" value="true" />
</TypeScriptCodeStyleSettings>
<codeStyleSettings language="JavaScript">
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
<codeStyleSettings language="TypeScript">
<option name="RIGHT_MARGIN" value="100" />
<indentOptions>
<option name="INDENT_SIZE" value="2" />
<option name="CONTINUATION_INDENT_SIZE" value="2" />
<option name="TAB_SIZE" value="2" />
</indentOptions>
</codeStyleSettings>
</value>
</option>
<option name="USE_PER_PROJECT_SETTINGS" value="true" />
</component>
</project>
\ No newline at end of file
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="TsLint" enabled="true" level="ERROR" enabled_by_default="true" />
</profile>
</component>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectTasksOptions" suppressed-tasks="Babel" />
</project>
\ No newline at end of file
This diff is collapsed.
import * as _fs from 'fs' import * as path from 'path';
import * as path from 'path' import * as fs from 'fs-extra-promise';
import * as fs from 'fs-extra-promise' import {archive, archiveSingle, caculateSHA256, crawlPath, untar} from './utils';
import {mongodb} from '../src/models/iridium' import {Archive, File} from '../src/models/Package';
import {crawlPath, caculateSHA256, archive, archiveSingle, untar} from "./utils";
import {Archive, File} from "../src/models/Package";
import {file} from "tmp";
const upload_path = path.join(__dirname, '../test/upload') const upload_path = path.join(__dirname, '../test/upload');
const release_path = path.join(__dirname, '../test/release') const release_path = path.join(__dirname, '../test/release');
const app_path = path.join(__dirname, '../test/apps') const app_path = path.join(__dirname, '../test/apps');
export async function bundle(...args) { export async function bundle(...args) {
const [package_id] = args const [package_id] = args;
console.log(`package ${package_id}`); console.log(`package ${package_id}`);
await fs.ensureDirAsync(release_path) await fs.ensureDirAsync(release_path);
await fs.ensureDirAsync(app_path) await fs.ensureDirAsync(app_path);
await fs.ensureDirAsync(upload_path) await fs.ensureDirAsync(upload_path);
const archive_path = path.join(release_path, 'downloads', package_id) const archive_path = path.join(release_path, 'downloads', package_id);
const package_path = path.join(app_path, package_id); const package_path = path.join(app_path, package_id);
const uploadFile_path = path.join(upload_path, package_id) const uploadFile_path = path.join(upload_path, package_id);
const full_path = path.join(archive_path, 'full') const full_path = path.join(archive_path, 'full');
const sand_path = path.join(archive_path, 'sand') const sand_path = path.join(archive_path, 'sand');
await fs.ensureDirAsync(archive_path) await fs.ensureDirAsync(archive_path);
await fs.ensureDirAsync(package_path) await fs.ensureDirAsync(package_path);
await fs.ensureDirAsync(full_path) await fs.ensureDirAsync(full_path);
await fs.ensureDirAsync(sand_path) await fs.ensureDirAsync(sand_path);
// untar upload package // untar upload package
await untar(uploadFile_path, package_path) await untar(uploadFile_path, package_path);
let files = new Map<string, File>(); let files = new Map<string, File>();
let archives = new Map<string, Archive>(); let archives = new Map<string, Archive>();
...@@ -39,52 +36,51 @@ export async function bundle(...args) { ...@@ -39,52 +36,51 @@ export async function bundle(...args) {
await crawlPath(package_path, { await crawlPath(package_path, {
relative: true,
onFile: async (file) => { onFile: async (file) => {
let file_hash = await caculateSHA256(file) let file_hash = await caculateSHA256(file);
files.set(file, { files.set(file, {
path: path.relative(package_path,file), path: path.relative(package_path, file),
hash: file_hash, hash: file_hash,
size: (await fs.statAsync(file)).size size: (await fs.statAsync(file)).size
}) });
let sand_file = path.join(sand_path, `${file_hash}.tar.gz`) let sand_file = path.join(sand_path, `${file_hash}.tar.gz`);
await archiveSingle(sand_file, [file], package_path) await archiveSingle(sand_file, [file], package_path);
let sand_hash = await caculateSHA256(sand_file) let sand_hash = await caculateSHA256(sand_file);
archives.set(sand_file, { archives.set(sand_file, {
path: path.relative(sand_path, sand_file), path: path.relative(sand_path, sand_file),
hash: sand_hash, hash: sand_hash,
size: (await fs.statAsync(sand_file)).size size: (await fs.statAsync(sand_file)).size
}) });
await fs.renameAsync(sand_file, path.join(path.dirname(sand_file), `${sand_hash}.tar.gz`)) await fs.renameAsync(sand_file, path.join(path.dirname(sand_file), `${sand_hash}.tar.gz`));
}, },
onDir: async (_files, _path, depth) => { onDir: async (_files, _path, depth) => {
files.set(_path, { files.set(_path, {
path: path.relative(package_path, _path), path: path.relative(package_path, _path),
}) });
}, },
}) });
let filePath = path.join(full_path, `${package_id}.tar.gz`) let filePath = path.join(full_path, `${package_id}.tar.gz`);
await fs.removeAsync(filePath) await fs.removeAsync(filePath);
await archive(filePath, await fs.readdirAsync(package_path), package_path) await archive(filePath, await fs.readdirAsync(package_path), package_path);
const fullHash = await caculateSHA256(filePath) const fullHash = await caculateSHA256(filePath);
const fullSize = (await fs.statAsync(filePath)).size const fullSize = (await fs.statAsync(filePath)).size;
let fullPath = path.join(path.dirname(filePath), `${fullHash}.tar.gz`) let fullPath = path.join(path.dirname(filePath), `${fullHash}.tar.gz`);
await fs.renameAsync(filePath, fullPath) await fs.renameAsync(filePath, fullPath);
return { return {
files: Array.from(files.values()), files: Array.from(files.values()),
archives: Array.from(archives.values()), archives: Array.from(archives.values()),
fullSize, fullSize,
fullHash fullHash
} };
} }
import * as fs from 'fs-extra-promise' import * as fs from 'fs-extra-promise';
import * as _fs from 'fs' import * as _fs from 'fs';
import * as crypto from 'crypto' import * as crypto from 'crypto';
import * as child_process from 'child_process' import * as child_process from 'child_process';
// import * as tar from 'tar-stream'
// import * as fstream from 'fstream'
interface crawOptions { interface crawOptions {
onDir: (files: string | string[], _path: string, depth: number) => Promise<void>; onDir: (files: string | string[], _path: string, depth: number) => Promise<void>;
...@@ -12,32 +11,32 @@ interface crawOptions { ...@@ -12,32 +11,32 @@ interface crawOptions {
export async function crawlPath(_path, options: crawOptions, depth = 0) { export async function crawlPath(_path, options: crawOptions, depth = 0) {
if (await isDir(_path)) { if (await isDir(_path)) {
depth += 1 depth += 1;
const files = await fs.readdirAsync(_path) const files = await fs.readdirAsync(_path);
await options.onDir(files, _path, depth) await options.onDir(files, _path, depth);
if (files) { if (files) {
for (let fileName of files) { for (let fileName of files) {
const file = `${_path}/${fileName}` const file = `${_path}/${fileName}`;
if (await isDir(file)) { if (await isDir(file)) {
await crawlPath(file, options, depth) await crawlPath(file, options, depth);
} else if (await isFile(file)) { } else if (await isFile(file)) {
await options.onFile(file) await options.onFile(file);
} }
} }
} }
} else if (await isFile(_path)) { } else if (await isFile(_path)) {
await options.onFile(_path) await options.onFile(_path);
} }
} }
export async function isDir(path) { export async function isDir(path) {
return (await fs.lstatAsync(path)).isDirectory() return (await fs.lstatAsync(path)).isDirectory();
} }
export async function isFile(path) { export async function isFile(path) {
return (await fs.lstatAsync(path)).isFile() return (await fs.lstatAsync(path)).isFile();
} }
...@@ -54,14 +53,14 @@ export function archiveSingle(archive: string, files: string[], directory: strin ...@@ -54,14 +53,14 @@ export function archiveSingle(archive: string, files: string[], directory: strin
let child = child_process.spawn("tar", ["-czf", archive, '-P', '-C', directory].concat(files), {stdio: 'inherit'}); let child = child_process.spawn("tar", ["-czf", archive, '-P', '-C', directory].concat(files), {stdio: 'inherit'});
child.on('exit', (code) => { child.on('exit', (code) => {
if (code == 0) { if (code == 0) {
resolve() resolve();
} else { } else {
reject(code); reject(code);
} }
}); });
child.on('error', (error) => { child.on('error', (error) => {
reject(error); reject(error);
}) });
}); });
} }
...@@ -70,14 +69,14 @@ export function archive(archive: string, files: string[], directory: string): Pr ...@@ -70,14 +69,14 @@ export function archive(archive: string, files: string[], directory: string): Pr
let child = child_process.spawn("tar", ["-vczf", archive, '-C', directory].concat(files), {stdio: 'inherit'}); let child = child_process.spawn("tar", ["-vczf", archive, '-C', directory].concat(files), {stdio: 'inherit'});
child.on('exit', (code) => { child.on('exit', (code) => {
if (code == 0) { if (code == 0) {
resolve() resolve();
} else { } else {
reject(code); reject(code);
} }
}); });
child.on('error', (error) => { child.on('error', (error) => {
reject(error); reject(error);
}) });
}); });
} }
...@@ -86,14 +85,14 @@ export function untar(archive: string, directory: string): Promise<void> { ...@@ -86,14 +85,14 @@ export function untar(archive: string, directory: string): Promise<void> {
let child = child_process.spawn("tar", ["-xvf", archive, '-C', directory], {stdio: 'inherit'}); let child = child_process.spawn("tar", ["-xvf", archive, '-C', directory], {stdio: 'inherit'});
child.on('exit', (code) => { child.on('exit', (code) => {
if (code == 0) { if (code == 0) {
resolve() resolve();
} else { } else {
reject(code); reject(code);
} }
}); });
child.on('error', (error) => { child.on('error', (error) => {
reject(error); reject(error);
}) });
}); });
} }
...@@ -102,7 +101,7 @@ export function caculateSHA256(file: string): Promise<string> { ...@@ -102,7 +101,7 @@ export function caculateSHA256(file: string): Promise<string> {
let input = _fs.createReadStream(file); let input = _fs.createReadStream(file);
const hash = crypto.createHash("sha256"); const hash = crypto.createHash("sha256");
hash.on("error", (error: Error) => { hash.on("error", (error: Error) => {
reject(error) reject(error);
}); });
input.on("error", (error: Error) => { input.on("error", (error: Error) => {
reject(error); reject(error);
......
if(process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== 'production') {
require('dotenv').config() require('dotenv').config();
} }
import * as Koa from 'koa' import * as Koa from 'koa';
import * as log4js from 'log4js' import * as log4js from 'log4js';
import * as bodyParser from 'koa-bodyparser' import * as bodyParser from 'koa-bodyparser';
import * as hbs from 'koa-hbs' import * as hbs from 'koa-hbs';
import { mongodb } from './src/models/iridium' import {mongodb} from './src/models/iridium';
// import index from './routes/index'; // import index from './routes/index';
import upload from './src/routes/upload'; import upload from './src/routes/upload';
// import users from './src/routes/users'; // import users from './src/routes/users';
import package from './src/routes/package' import pack from './src/routes/package';
import apps from './src/routes/app'; import apps from './src/routes/app';
// import packages from './routes/packages'; // import packages from './routes/packages';
...@@ -23,7 +22,7 @@ app.use(hbs.middleware({ ...@@ -23,7 +22,7 @@ app.use(hbs.middleware({
viewPath: __dirname + '/views', viewPath: __dirname + '/views',
})); }));
app.use(async(ctx, next) => { app.use(async (ctx, next) => {
const start = new Date(); const start = new Date();
await next(); await next();
const ms = Date.now() - start.getTime(); const ms = Date.now() - start.getTime();
...@@ -31,7 +30,7 @@ app.use(async(ctx, next) => { ...@@ -31,7 +30,7 @@ app.use(async(ctx, next) => {
}); });
// 错误处理 // 错误处理
app.use(async(ctx, next) => { app.use(async (ctx, next) => {
try { try {
await next(); await next();
} catch (err) { } catch (err) {
...@@ -53,7 +52,7 @@ app.use(async(ctx, next) => { ...@@ -53,7 +52,7 @@ app.use(async(ctx, next) => {
}); });
// 跨域 // 跨域
app.use(async(ctx, next) => { app.use(async (ctx, next) => {
ctx.set('Access-Control-Allow-Origin', '*'); ctx.set('Access-Control-Allow-Origin', '*');
ctx.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH'); ctx.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, PATCH');
ctx.set('Access-Control-Allow-Headers', 'Content-Type, X-Requested-With',); ctx.set('Access-Control-Allow-Headers', 'Content-Type, X-Requested-With',);
...@@ -70,13 +69,13 @@ app.use(bodyParser()); ...@@ -70,13 +69,13 @@ app.use(bodyParser());
// app.use(users.routes()); // app.use(users.routes());
app.use(apps.routes()); app.use(apps.routes());
app.use(upload.routes()); app.use(upload.routes());
app.use(package.routes()); app.use(pack.routes());
// app.use(packages.routes()); // app.use(packages.routes());
mongodb.connect().then(() => { mongodb.connect().then(() => {
app.listen(8001, () => { app.listen(8001, () => {
console.log("app listening port 8001") console.log('app listening port 8001');
}); });
}) });
/**
* Created by zh99998 on 2017/4/21.
*/
export function renderChecksum(files: { path: string, hash?: string }[]) {
return files.map(({ path, hash }) => `${hash || ''} ${path}`).join('\n');
}
// 用法示例
// const example = [
// { path: 'README', hash: '11111111111111111111111111111111', size: 1 },
// { path: 'main.exe', hash: '22222222222222222222222222222222', size: 2 },
// { path: 'assets' }, // 对于目录,置 hash 为空 (undefiend 或 不存在)
// { path: 'assets/1.png', hash: '33333333333333333333333333333333', size: 3 }
// ];
//
// console.log(renderChecksum(example));
import { Container } from 'inversify' import {Container} from 'inversify';
import TYPES from './types'
const container = new Container() const container = new Container();
export default container export default container;
\ No newline at end of file
import {Core, Model, Instance, Collection, Index, Property, ObjectID} from 'iridium' import {Collection, Index, Instance, Property} from 'iridium';
import {handleImg} from '../utils' import {handleImg} from '../utils';
interface I18n<T> { interface I18n<T> {
[locale: string]: T; [locale: string]: T;
...@@ -9,7 +9,7 @@ interface Platform<T> { ...@@ -9,7 +9,7 @@ interface Platform<T> {
[platform: string]: T; [platform: string]: T;
} }
interface Package{ interface Package {
id: string; id: string;
name: string; name: string;
platforms: Platform<string[]>; platforms: Platform<string[]>;
...@@ -27,9 +27,9 @@ interface File { ...@@ -27,9 +27,9 @@ interface File {
export interface App { export interface App {
id: string; id: string;
name?: I18n<string>; name?: I18n<string>;
description?: I18n<string> description?: I18n<string>;
developers?: I18n<[{ name: string, url: string }]> developers?: I18n<[{ name: string, url: string }]>;
publishers?: I18n<[{ name: string, url: string }]> publishers?: I18n<[{ name: string, url: string }]>;
released_at?: string; released_at?: string;
category?: string; category?: string;
parent?: string; parent?: string;
...@@ -38,10 +38,10 @@ export interface App { ...@@ -38,10 +38,10 @@ export interface App {
references?: Platform<string[]>; references?: Platform<string[]>;
homepage?: string; homepage?: string;
locales?: string[]; locales?: string[];
actions?: Platform<{[key: string]: {execuate: string, args: string[], env: {[key: string]: string}}}>; actions?: Platform<{ [key: string]: { execuate: string, args: string[], env: { [key: string]: string } } }>;
files?: {[key: string]: { sync: boolean}} files?: { [key: string]: { sync: boolean } };
version?: Platform<string>; version?: Platform<string>;
news?: I18n<{title: string, url: string, image: string}[]>; news?: I18n<{ title: string, url: string, image: string }[]>;
conference?: string; conference?: string;
data?: any; data?: any;
icon?: string; icon?: string;
...@@ -52,18 +52,18 @@ export interface App { ...@@ -52,18 +52,18 @@ export interface App {
} }
@Collection('apps') @Collection('apps')
@Index({id: 1}, { unique: true }) @Index({id: 1}, {unique: true})
export class AppSchema extends Instance<App, AppSchema> implements App { export class AppSchema extends Instance<App, AppSchema> implements App {
@Property(String, true) @Property(String, true)
id: string; id: string;
@Property(Object, false) @Property(Object, false)
name?: I18n<string>; name?: I18n<string>;
@Property(Object, false) @Property(Object, false)
description?: I18n<string> description?: I18n<string>;
@Property(Object, false) @Property(Object, false)
developers?: I18n<[{ name: string, url: string }]> developers?: I18n<[{ name: string, url: string }]>;
@Property(Object, false) @Property(Object, false)
publishers?: I18n<[{ name: string, url: string }]> publishers?: I18n<[{ name: string, url: string }]>;
@Property(String, false) @Property(String, false)
released_at?: string; released_at?: string;
@Property(String, false) @Property(String, false)
...@@ -81,13 +81,13 @@ export class AppSchema extends Instance<App, AppSchema> implements App { ...@@ -81,13 +81,13 @@ export class AppSchema extends Instance<App, AppSchema> implements App {
@Property(Array, false) @Property(Array, false)
locales?: string[]; locales?: string[];
@Property(Object, false) @Property(Object, false)
actions?: Platform<{[key: string]: {execuate: string, args: string[], env: {[key: string]: string}}}>; actions?: Platform<{ [key: string]: { execuate: string, args: string[], env: { [key: string]: string } } }>;
@Property(Object, false) @Property(Object, false)
files?: {[key: string]: { sync: boolean}} files?: { [key: string]: { sync: boolean } };
@Property(Object, false) @Property(Object, false)
version?: Platform<string>; version?: Platform<string>;
@Property(Object, false) @Property(Object, false)
news?: I18n<{title: string, url: string, image: string}[]>; news?: I18n<{ title: string, url: string, image: string }[]>;
@Property(String, false) @Property(String, false)
conference?: string; conference?: string;
@Property(Object, false) @Property(Object, false)
...@@ -103,23 +103,23 @@ export class AppSchema extends Instance<App, AppSchema> implements App { ...@@ -103,23 +103,23 @@ export class AppSchema extends Instance<App, AppSchema> implements App {
@Property(Date, false) @Property(Date, false)
created_at: Date; created_at: Date;
static onCreating(app: App){ static onCreating(app: App) {
app.created_at = new Date() app.created_at = new Date();
} }
handleUpdate(data: App) { handleUpdate(data: App) {
Object.assign(this, data) Object.assign(this, data);
} }
toJSON() { toJSON() {
this.Convert() this.Convert();
return JSON.parse(this) return {...<Object>this};
} }
Convert() { Convert() {
this.icon = handleImg(this.icon), this.icon = handleImg(this.icon),
this.cover = handleImg(this.cover), this.cover = handleImg(this.cover),
this.background = handleImg(this.background) this.background = handleImg(this.background);
} }
} }
import {Core, Model} from "iridium"; import {Core, Model} from 'iridium';
import {App, AppSchema} from "./App"; import {App, AppSchema} from './App';
import {Package, PackageSchema} from "./Package"; import {Package, PackageSchema} from './Package';
export class MongoDB extends Core { export class MongoDB extends Core {
Apps = new Model<App, AppSchema>(this, AppSchema) Apps = new Model<App, AppSchema>(this, AppSchema);
Packages = new Model<Package, PackageSchema>(this,PackageSchema) Packages = new Model<Package, PackageSchema>(this, PackageSchema);
} }
export const mongodb = new MongoDB(process.env["MONGODB"]) export const mongodb = new MongoDB(process.env['MONGODB']);
import {Core, Model, Instance, Collection, Index, Property, ObjectID} from 'iridium' import {Collection, Index, Instance, Property} from 'iridium';
type Locale = 'zh-CN' | 'en-US' | 'ja-JP' type Locale = 'zh-CN' | 'en-US' | 'ja-JP';
type Platform = 'win32' | 'linux' | 'darwin' type Platform = 'win32' | 'linux' | 'darwin';
export interface Action { export interface Action {
execute: string; execute: string;
...@@ -26,8 +26,8 @@ export interface Package { ...@@ -26,8 +26,8 @@ export interface Package {
id: string; id: string;
name: string; name: string;
appId: string; appId: string;
fullSize: number; fullSize?: number;
fullHash: string; fullHash?: string;
version: string; version: string;
status: string; status: string;
type: string; type: string;
...@@ -38,8 +38,8 @@ export interface Package { ...@@ -38,8 +38,8 @@ export interface Package {
} }
@Collection("packages") @Collection('packages')
@Index({id: 1}, { unique: true }) @Index({id: 1}, {unique: true})
export class PackageSchema extends Instance<Package, PackageSchema> implements Package { export class PackageSchema extends Instance<Package, PackageSchema> implements Package {
@Property(String, true) @Property(String, true)
id: string; id: string;
...@@ -66,11 +66,11 @@ export class PackageSchema extends Instance<Package, PackageSchema> implements P ...@@ -66,11 +66,11 @@ export class PackageSchema extends Instance<Package, PackageSchema> implements P
@Property(Array, false) @Property(Array, false)
archives: Archive[]; archives: Archive[];
static onCreating(pack: Package){ static onCreating(pack: Package) {
pack.status = pack.status || 'init' pack.status = pack.status || 'init';
} }
handleUpdate(data: Package) { handleUpdate(data: Package) {
Object.assign(this, data) Object.assign(this, data);
} }
} }
import Router = require('koa-router'); import Router = require('koa-router');
import {mongodb} from '../models/iridium' import {mongodb} from '../models/iridium';
import {App, AppSchema} from "../models/App"; import {App, AppSchema} from '../models/App';
import {Context} from "koa"; import {Context} from 'koa';
const router = new Router(); const router = new Router();
// router.get('/apps', async (ctx: Context, next) => { router.get('/v2/apps', async (ctx: Context, next) => {
// ctx.body = await mongodb.Apps.find({}) ctx.body = await mongodb.Apps.find({}).toArray();
// .map(async app => { });
// if(Array.isArray(app.packages) && app.packages.length > 0){
// app.packages = await Promise.all(app.packages.map(async p => {
// try {
// return await mongodb.Packages.findOne({_id: toObjectID(p)})
// } catch (e) {
// console.log(p)
// }
// }))
// }
// return app
// })
// });
router.get('/v2/apps', async(ctx: Context, next) => {
ctx.body = await mongodb.Apps.find({}).toArray()
})
router.get('/v1/apps', async (ctx: Context, next) => { router.get('/v1/apps', async (ctx: Context, next) => {
let payload = ctx.request.query let payload = ctx.request.query;
if((!payload.author && !payload.admin)) { if ((!payload.author && !payload.admin)) {
ctx.throw(400, 'params error') ctx.throw(400, 'params error');
} }
let apps = {} let apps = {};
if(payload.admin == 'true') { if (payload.admin == 'true') {
apps = await mongodb.Apps.find({}).toArray() apps = await mongodb.Apps.find({}).toArray();
} else { } else {
apps = await mongodb.Apps.find({author: payload.author}).toArray() apps = await mongodb.Apps.find({author: payload.author}).toArray();
} }
ctx.body = apps ctx.body = apps;
}) });
router.post('/v1/app/:id', async (ctx: Context, next) => { router.post('/v1/app/:id', async (ctx: Context, next) => {
let payload = ctx.request.body let payload = ctx.request.body;
if(!payload.id) { if (!payload.id) {
ctx.throw(400, 'params error') ctx.throw(400, 'params error');
} }
if (ctx.params.id !== payload.id) { if (ctx.params.id !== payload.id) {
ctx.throw(400, "App is not same") ctx.throw(400, 'App is not same');
} }
let exists = await mongodb.Apps.findOne({id: payload.id}); let exists = await mongodb.Apps.findOne({id: payload.id});
if (exists) { if (exists) {
ctx.throw(400, "App is exists") ctx.throw(400, 'App is exists');
} }
try { try {
ctx.body = await mongodb.Apps.insert(payload) ctx.body = await mongodb.Apps.insert(payload);
} catch (e) { } catch (e) {
ctx.throw(400, e) ctx.throw(400, e);
} }
}) });
router.patch('/v1/app/:id', async (ctx: Context, next) => { router.patch('/v1/app/:id', async (ctx: Context, next) => {
let _app: App = ctx.request.body let _app: App = ctx.request.body;
let app: AppSchema | null = await mongodb.Apps.findOne({id: ctx.params.id}); let app: AppSchema | null = await mongodb.Apps.findOne({id: ctx.params.id});
if (!app) { if (!app) {
ctx.throw(400, `App ${ctx.params.id} Not Found `); ctx.throw(400, `App ${ctx.params.id} Not Found `);
} }
if (!ctx.request.body.id || ctx.request.body.id !== app!.id) { if (!ctx.request.body.id || ctx.request.body.id !== app!.id) {
ctx.throw(400, `Can not change AppID`) ctx.throw(400, `Can not change AppID`);
} }
app!.handleUpdate(_app) app!.handleUpdate(_app);
ctx.body = await app!.save() ctx.body = await app!.save();
}) });
export default router export default router;
\ No newline at end of file
import Router = require('koa-router'); import Router = require('koa-router');
import {toObjectID} from 'iridium' import {toObjectID} from 'iridium';
import {mongodb} from '../models/iridium' import {mongodb} from '../models/iridium';
import {Context} from "koa"; import {Context} from 'koa';
import config from '../../config' import config from '../../config';
import {Archive, Package} from "../models/Package"; import {Archive, Package} from '../models/Package';
import {renderChecksum} from "../utils"; import {renderChecksum} from '../utils';
const router = new Router(); const router = new Router();
router.get('/v2/packages', async (ctx: Context, next) => { router.get('/v2/packages', async (ctx: Context, next) => {
if (!ctx.request.query.appId) { if (!ctx.request.query.appId) {
ctx.throw(400, "appId must be required!") ctx.throw(400, 'appId must be required!');
} }
let packs = await mongodb.Packages.find({appId: ctx.request.query.appId, status: 'uploaded'}).toArray() let packs = await mongodb.Packages.find({
appId: ctx.request.query.appId,
status: 'uploaded'
}).toArray();
ctx.body = { ctx.body = {
[ctx.request.query.appId]: packs [ctx.request.query.appId]: packs
} };
}) });
router.get('/v2/package/:id/checksum', async(ctx: Context, next) => { router.get('/v2/package/:id/checksum', async (ctx: Context, next) => {
let pack = await mongodb.Packages.findOne({id: ctx.params.id, status: 'uploaded'}) let pack = await mongodb.Packages.findOne({id: ctx.params.id, status: 'uploaded'});
if(!pack) { if (!pack) {
return ctx.throw(400, 'pack error') return ctx.throw(400, 'pack error');
} }
ctx.body = renderChecksum(pack.files) ctx.body = renderChecksum(pack.files);
}) });
router.get('/v2/package/:id/meta', async(ctx: Context, next) => { router.get('/v2/package/:id/meta', async (ctx: Context, next) => {
let pack = await mongodb.Packages.findOne({id: ctx.params.id, status: 'uploaded'}) let pack = await mongodb.Packages.findOne({id: ctx.params.id, status: 'uploaded'});
if(!pack) { if (!pack) {
return ctx.throw(400, 'pack error') return ctx.throw(400, 'pack error');
} }
await ctx['render']('update', {files: { await ctx['render']('update', {
files: {
name: pack.id, name: pack.id,
size: pack.fullSize, size: pack.fullSize,
hash: pack.fullHash hash: pack.fullHash
}}) }
}) });
});
router.post('/v2/package/:id/update', async (ctx: Context, next) => { router.post('/v2/package/:id/update', async (ctx: Context, next) => {
const package_id = ctx.params.id const package_id = ctx.params.id;
const download_path = config.download_path const request_overhead = 1024 * 1024;
const request_overhead = 1024 * 1024 let sandSize = ctx.request.body.length * request_overhead;
let sandSize = ctx.request.body.length * request_overhead
let pack = await mongodb.Packages.findOne({id: package_id, status: 'uploaded'}) let pack = await mongodb.Packages.findOne({id: package_id, status: 'uploaded'});
let {fullSize, fullPath} = pack! if (!pack) {
return ctx.throw(400, 'pack not exists');
}
let {fullSize} = pack;
let files let files;
let fullFiles = new Map<string, Archive>() let fullFiles = new Map<string, Archive>();
pack!.archives.map((f) => { pack.archives.map((f) => {
fullFiles.set(f.path, f) fullFiles.set(f.path, f);
}) });
if(fullSize > sandSize) { if (fullSize > sandSize) {
files = ctx.request.body.map((_file) => { files = ctx.request.body.map((_file) => {
const file: Archive|undefined = fullFiles.get(_file) const file: Archive | undefined = fullFiles.get(_file);
if(!file) { if (!file) {
// return ctx.throw(400, '');
} }
sandSize += file.size sandSize += file.size;
return { return {
path: file.path, path: file.path,
size: file.size, size: file.size,
hash: file.hash hash: file.hash
} };
}) });
} }
if( sandSize <= fullSize ) { if (sandSize <= fullSize) {
files = [{ files = [{
path: pack.id, path: pack.id,
size: pack.fullSize, size: pack.fullSize,
hash: pack.fullHash hash: pack.fullHash
}] }];
} }
await ctx['render']('update', {files}) await ctx['render']('update', {files});
}) });
router.get('/v1/packages', async (ctx: Context, next) => { router.get('/v1/packages', async (ctx: Context, next) => {
if (!ctx.request.query.appId) { if (!ctx.request.query.appId) {
ctx.throw(400, "appId must be required!") ctx.throw(400, 'appId must be required!');
} }
let packs = await mongodb.Packages.find({appId: ctx.request.query.appId, type: 'editing'}).toArray() let packs = await mongodb.Packages.find({
appId: ctx.request.query.appId,
type: 'editing'
}).toArray();
ctx.body = { ctx.body = {
[ctx.request.query.appId]: packs [ctx.request.query.appId]: packs
} };
}) });
router.post('/v1/package', async (ctx: Context, next) => { router.post('/v1/package', async (ctx: Context, next) => {
const _p: Package = ctx.request.body const _p: Package = ctx.request.body;
if (!_p.id) { if (!_p.id) {
ctx.throw(400, `id 参数缺失:${_p.id}`) ctx.throw(400, `id 参数缺失:${_p.id}`);
} }
if (!_p.platforms || _p.platforms.length == 0) { if (!_p.platforms || _p.platforms.length == 0) {
ctx.throw(400, `请填写支持的平台:${_p.id}`) ctx.throw(400, `请填写支持的平台:${_p.id}`);
} } else if (!_p.locales || _p.locales.length == 0) {
else if (!_p.locales || _p.locales.length == 0) { ctx.throw(400, `请填写支持的语言:${_p.id}`);
ctx.throw(400, `请填写支持的语言:${_p.id}`) } else if (!_p.version) {
} ctx.throw(400, `请填写版本号:${_p.id}`);
else if (!_p.version) {
ctx.throw(400, `请填写版本号:${_p.id}`)
} }
let exists_platform = await mongodb.Packages.find({ id: {$ne: _p.id}, appId: _p.appId, platforms: { $in: _p.platforms }, type: 'editing' }).count() let existsPlatform = await mongodb.Packages.find({
if(exists_platform) { id: {$ne: _p.id},
console.log(exists_platform) appId: _p.appId,
ctx.throw(400, '平台已存在') platforms: {$in: _p.platforms},
type: 'editing'
}).count();
if (existsPlatform) {
console.log(existsPlatform);
ctx.throw(400, '平台已存在');
} }
let exists_locales = await mongodb.Packages.find({ id: {$ne: _p.id}, appId: _p.appId, locales: { $in: _p.locales }, type: 'editing' }).count() let existsLocales = await mongodb.Packages.find({
if(exists_locales) { id: {$ne: _p.id},
console.log(exists_locales) appId: _p.appId,
ctx.throw(400, '语言已存在') locales: {$in: _p.locales},
type: 'editing'
}).count();
if (existsLocales) {
console.log(existsLocales);
ctx.throw(400, '语言已存在');
} }
await mongodb.Packages.update({id: _p.id}, {$set: { type: 'edited' }}, {multi: true}) await mongodb.Packages.update({id: _p.id}, {$set: {type: 'edited'}}, {multi: true});
let _pack: Package = { let _pack: Package = {
id: _p.id, id: _p.id,
...@@ -134,59 +152,73 @@ router.post('/v1/package', async (ctx: Context, next) => { ...@@ -134,59 +152,73 @@ router.post('/v1/package', async (ctx: Context, next) => {
platforms: _p.platforms, platforms: _p.platforms,
status: 'init', status: 'init',
type: 'editing' type: 'editing'
} };
ctx.body = await mongodb.Packages.insert(_pack) ctx.body = await mongodb.Packages.insert(_pack);
}) });
router.patch('/v1/package', async (ctx: Context, next) => { router.patch('/v1/package', async (ctx: Context, next) => {
const _p: Package = ctx.request.body const _p = ctx.request.body;
const p = await mongodb.Packages.findOne({_id: toObjectID(_p._id)}) const p = await mongodb.Packages.findOne({_id: toObjectID(_p._id)});
if (!p) {
return ctx.throw(400, 'pack not exists');
}
if (!_p.id) { if (!_p.id) {
ctx.throw(400, `id 参数缺失:${_p.id}`) ctx.throw(400, `id 参数缺失:${_p.id}`);
} }
if (!_p.platforms || _p.platforms.length == 0) { if (!_p.platforms || _p.platforms.length == 0) {
ctx.throw(400, `请填写支持的平台:${_p.id}`) ctx.throw(400, `请填写支持的平台:${_p.id}`);
} } else if (!_p.locales || _p.locales.length == 0) {
else if (!_p.locales || _p.locales.length == 0) { ctx.throw(400, `请填写支持的语言:${_p.id}`);
ctx.throw(400, `请填写支持的语言:${_p.id}`) } else if (!_p.version) {
} ctx.throw(400, `请填写版本号:${_p.id}`);
else if (!_p.version) {
ctx.throw(400, `请填写版本号:${_p.id}`)
} }
let exists_platform = await mongodb.Packages.find({ id: {$ne: _p.id}, appId: _p.appId, platforms: { $in: _p.platforms }, type: 'editing' }).count() let existsPlatform = await mongodb.Packages.find({
if(exists_platform) { id: {$ne: _p.id},
console.log(exists_platform) appId: _p.appId,
ctx.throw(400, '平台已存在') platforms: {$in: _p.platforms},
type: 'editing'
}).count();
if (existsPlatform) {
console.log(existsPlatform);
ctx.throw(400, '平台已存在');
} }
let exists_locales = await mongodb.Packages.find({ id: {$ne: _p.id}, appId: _p.appId, locales: { $in: _p.locales }, type: 'editing' }).count() let existsLocales = await mongodb.Packages.find({
if(exists_locales) { id: {$ne: _p.id},
console.log(exists_locales) appId: _p.appId,
ctx.throw(400, '语言已存在') locales: {$in: _p.locales},
type: 'editing'
}).count();
if (existsLocales) {
console.log(existsLocales);
ctx.throw(400, '语言已存在');
} }
if (p.status == 'init') { if (p.status == 'init') {
p.handleUpdate(_p) p.handleUpdate(_p);
ctx.body = await p.save() ctx.body = await p.save();
} else { } else {
ctx.throw(400, `非法操作:${_p.id}`) ctx.throw(400, `非法操作:${_p.id}`);
} }
}) });
router.delete('/v1/package', async(ctx: Context, next) => { router.delete('/v1/package', async (ctx: Context, next) => {
const _p: Package = ctx.request.body const _p = ctx.request.body;
const p = await mongodb.Packages.findOne({_id: toObjectID(_p._id)}) const p = await mongodb.Packages.findOne({_id: toObjectID(_p._id)});
if (!p) {
return ctx.throw(400, 'pack not exists');
}
p.type = 'edited' p.type = 'edited';
p.status = 'delete' p.status = 'delete';
await p.save() await p.save();
ctx.body = { ctx.body = {
message: 'delete successful' message: 'delete successful'
} };
}) });
export default router export default router;
\ No newline at end of file
...@@ -4,13 +4,13 @@ import * as busboy from 'async-busboy'; ...@@ -4,13 +4,13 @@ import * as busboy from 'async-busboy';
import * as mime from 'mime'; import * as mime from 'mime';
import * as uuid from 'uuid'; import * as uuid from 'uuid';
import * as Client from 'aliyun-oss-upload-stream'; import * as Client from 'aliyun-oss-upload-stream';
import * as fs from 'fs-extra-promise' import * as fs from 'fs-extra-promise';
import * as path from 'path' import * as path from 'path';
import * as Aria2 from 'aria2' import * as Aria2 from 'aria2';
import {bundle} from '../../package/main' import {bundle} from '../../package/main';
import {mongodb} from '../models/iridium' import {mongodb} from '../models/iridium';
import {toObjectID} from 'iridium' import {toObjectID} from 'iridium';
import config from '../../config' import config from '../../config';
// const Aria2Options = { // const Aria2Options = {
// host: 'localhost', // host: 'localhost',
...@@ -21,29 +21,28 @@ import config from '../../config' ...@@ -21,29 +21,28 @@ import config from '../../config'
// } // }
const checkPackage = async (file) => { const checkPackage = async (file) => {
// const ext = mime.extension(file.mime);
if (['zip', 'gz', 'rar', '7z', 'application/x-gzip'].indexOf(file.mime) === -1) { if (['zip', 'gz', 'rar', '7z', 'application/x-gzip'].indexOf(file.mime) === -1) {
throw new Error('Unsupported file type'); throw new Error('Unsupported file type');
} }
} };
const checkImage = async (file) => { const checkImage = async (file) => {
const ext = mime.extension(file.mime); const ext = mime.extension(file.mime);
if (['png', 'jpg', 'jpeg', 'gif', 'webp'].indexOf(ext) === -1) { if (['png', 'jpg', 'jpeg', 'gif', 'webp'].indexOf(ext) === -1) {
throw new Error('Unsupported file type'); throw new Error('Unsupported file type');
} }
} };
import Router = require('koa-router'); import Router = require('koa-router');
const ossStream = Client(new OSS({ const ossStream = Client(new OSS({
accessKeyId: process.env["OSS_ACCESS_ID"], accessKeyId: process.env['OSS_ACCESS_ID'],
secretAccessKey: process.env["OSS_ACCESS_KEY"], secretAccessKey: process.env['OSS_ACCESS_KEY'],
endpoint: process.env["OSS_ENDPOINT"], endpoint: process.env['OSS_ENDPOINT'],
apiVersion: '2013-10-15' apiVersion: '2013-10-15'
})); }));
const router = new Router() const router = new Router();
const UploadImage = async (ctx: Context) => { const UploadImage = async (ctx: Context) => {
...@@ -51,12 +50,12 @@ const UploadImage = async (ctx: Context) => { ...@@ -51,12 +50,12 @@ const UploadImage = async (ctx: Context) => {
const {files} = await busboy(ctx.req); const {files} = await busboy(ctx.req);
ctx.body = await Promise.all(files.map(async file => { ctx.body = await Promise.all(files.map(async file => {
await checkImage(file) await checkImage(file);
const filename = `test/${uuid.v1()}`; const filename = `test/${uuid.v1()}`;
const upload = ossStream.upload({ const upload = ossStream.upload({
Bucket: process.env["OSS_BUCKET"], Bucket: process.env['OSS_BUCKET'],
Key: filename, Key: filename,
ContentType: file.mimeType ContentType: file.mimeType
}); });
...@@ -78,130 +77,136 @@ export const UploadPackage = async (ctx: Context) => { ...@@ -78,130 +77,136 @@ export const UploadPackage = async (ctx: Context) => {
const {files} = await busboy(ctx.req); const {files} = await busboy(ctx.req);
ctx.body = await Promise.all(files.map(async file => { ctx.body = await Promise.all(files.map(async file => {
await checkPackage(file) await checkPackage(file);
const filename = uuid.v1() const filename = uuid.v1();
const archive_path = path.join(__dirname, '../../test/upload') const archive_path = path.join(__dirname, '../../test/upload');
await fs.ensureDirAsync(archive_path) await fs.ensureDirAsync(archive_path);
const archive = fs.createWriteStream(path.join(archive_path, filename)) const archive = fs.createWriteStream(path.join(archive_path, filename));
let pack = await mongodb.Packages.findOne({_id: toObjectID(ctx.params.id)}) let pack = await mongodb.Packages.findOne({_id: toObjectID(ctx.params.id)});
if (!pack) {
return ctx.throw(400, 'pack not exists');
}
return await new Promise((resolve, reject) => { return await new Promise((resolve, reject) => {
file.pipe(archive) file.pipe(archive);
file.on('close', async() => { file.on('close', async () => {
try { try {
pack.status = 'uploading' pack!.status = 'uploading';
await pack.save() await pack!.save();
resolve(pack) resolve(pack!);
// 上传完, 打包 // 上传完, 打包
const bundled = await bundle(filename) const bundled = await bundle(filename);
Object.assign(pack, bundled) Object.assign(pack, bundled);
pack.status = 'uploaded' pack!.status = 'uploaded';
await mongodb.Packages.update({id: pack.id}, {$set: { status: 'deprecated' }}, {multi: true}) await mongodb.Packages.update({id: pack!.id}, {$set: {status: 'deprecated'}}, {multi: true});
await pack.save() await pack!.save();
// 打包完,上传阿里云 // 打包完,上传阿里云
} catch (e) { } catch (e) {
pack.status = 'failed' pack!.status = 'failed';
await pack.save() await pack!.save();
console.log(e) console.log(e);
} }
}) });
file.on('error', async (error) => { file.on('error', async (error) => {
pack.status = 'failed' pack!.status = 'failed';
await pack.save() await pack!.save();
reject(error) reject(error);
}) });
}) });
})); }));
} catch (err) { } catch (err) {
ctx.throw(403, err); ctx.throw(403, err);
} }
} };
const uploadPackageUrl = async (ctx: Context) => { const uploadPackageUrl = async (ctx: Context) => {
if(!ctx.request.body.url) { if (!ctx.request.body.url) {
ctx.throw(400, "params error") ctx.throw(400, 'params error');
} }
//testUrl: https://r.my-card.in/release/dist/0c16a3ecb115fd7cf575ccdd64f62a8f3edc635b087950e4ed4f3f781972bbfd.tar.gz // testUrl: https://r.my-card.in/release/dist/0c16a3ecb115fd7cf575ccdd64f62a8f3edc635b087950e4ed4f3f781972bbfd.tar.gz
const downloader = new Aria2 const downloader = new Aria2;
let pack = await mongodb.Packages.findOne({_id: toObjectID(ctx.request.body._id)}) let pack = await mongodb.Packages.findOne({_id: toObjectID(ctx.request.body._id)});
if (!pack) {
return ctx.throw(400, 'pack not exists');
}
await downloader.open() await downloader.open();
downloader.onDownloadStart = async() => { downloader.onDownloadStart = async () => {
pack.status = 'uploading' pack!.status = 'uploading';
await pack.save() await pack!.save();
} };
downloader.onDownloadComplete = async(m) => { downloader.onDownloadComplete = async (m) => {
const { files } = await downloader.send('tellStatus', m.gid) const {files} = await downloader.send('tellStatus', m.gid);
const [file] = files const [file] = files;
try { try {
await checkPackage(file) await checkPackage(file);
// 打包 // 打包
const bundled = await bundle(path.basename(file.path)) const bundled = await bundle(path.basename(file.path));
// 打包完, 上传阿里云 // 打包完, 上传阿里云
Object.assign(pack, bundled) Object.assign(pack, bundled);
pack.status = 'uploaded' pack!.status = 'uploaded';
await mongodb.Packages.update({id: pack.id}, {$set: { status: 'deprecated' }}, {multi: true}) await mongodb.Packages.update({id: pack!.id}, {$set: {status: 'deprecated'}}, {multi: true});
await pack.save() await pack!.save();
} catch (e) { } catch (e) {
pack.status = 'failed' pack!.status = 'failed';
await pack.save() await pack!.save();
}
} }
};
downloader.onDownloadError = async(err) => { downloader.onDownloadError = async (err) => {
// console.log(await downloader.send('tellStatus', err.gid)) // console.log(await downloader.send('tellStatus', err.gid))
pack.status = 'failed' pack!.status = 'failed';
await pack.save() await pack!.save();
console.log(err) console.log(err);
} };
ctx.body = await new Promise((resolve, reject) => { ctx.body = await new Promise((resolve, reject) => {
downloader.onmessage = m => { downloader.onmessage = m => {
if(m["error"]) { if (m['error']) {
reject(m["error"]) reject(m['error']);
} else { } else {
resolve(m) resolve(m);
}
} }
};
downloader.send('addUri', [ctx.request.body.url], {dir: config.upload_path}) downloader.send('addUri', [ctx.request.body.url], {dir: config.upload_path});
}) });
} };
router.post('/v1/upload/image', UploadImage) router.post('/v1/upload/image', UploadImage);
router.post('/v1/upload/package/:id', UploadPackage) router.post('/v1/upload/package/:id', UploadPackage);
router.post('/v1/upload/packageUrl', uploadPackageUrl) router.post('/v1/upload/packageUrl', uploadPackageUrl);
export default router export default router;
const TYPES = { const TYPES = {};
} export default TYPES;
export default TYPES
\ No newline at end of file
import { URL } from 'url'; import {URL} from 'url';
export const handleImg = (img) => { export const handleImg = (img) => {
if (img) { if (img) {
...@@ -12,8 +12,8 @@ export const handleImg = (img) => { ...@@ -12,8 +12,8 @@ export const handleImg = (img) => {
} else { } else {
return 'https://cdn01.moecube.com/accounts/default_avatar.jpg'; return 'https://cdn01.moecube.com/accounts/default_avatar.jpg';
} }
} };
export function renderChecksum(files: { path: string, hash?: string }[]) { export function renderChecksum(files: { path: string, hash?: string }[]) {
return files.map(({ path, hash }) => `${hash || ''} ${path}`).join('\n'); return files.map(({path, hash}) => `${hash || ''} ${path}`).join('\n');
} }
{
"rules": {
"max-line-length": [true, 140],
"no-inferrable-types": true,
"class-name": true,
"comment-format": [
true,
"check-space"
],
"indent": [
true,
"spaces"
],
"eofline": true,
"no-duplicate-variable": true,
"no-eval": true,
"no-arg": true,
"no-internal-module": true,
"no-trailing-whitespace": true,
"no-bitwise": true,
"no-unused-expression": true,
"no-var-keyword": true,
"one-line": [
true,
"check-catch",
"check-else",
"check-open-brace",
"check-whitespace"
],
"quotemark": [
true,
"single",
"avoid-escape"
],
"semicolon": [true, "always"],
"typedef-whitespace": [
true,
{
"call-signature": "nospace",
"index-signature": "nospace",
"parameter": "nospace",
"property-declaration": "nospace",
"variable-declaration": "nospace"
}
],
"curly": true,
"whitespace": [
true,
"check-branch",
"check-decl",
"check-operator",
"check-separator",
"check-type"
]
}
}
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment