Commit 3341614e authored by nano's avatar nano

complete

parent f64e6e2b
.env
node_modules/
test/
*.js
*.map
\ No newline at end of file
This diff is collapsed.
#!/usr/bin/env node
const {bundle} = require('../package/main')
bundle(process.argv[2], process.argv[3])
import * as path from 'path'
export default {
upload_path: path.join(__dirname, "./test/upload")
}
\ No newline at end of file
import * as _fs from 'fs'
import * as path from 'path'
import * as fs from 'fs-extra-promise'
import {mongodb} from '../src/models/iridium'
import {crawlPath, caculateSHA256, archive, archiveSingle, untar} from "./utils";
const upload_path = path.join(__dirname, '../test/upload')
const release_path = path.join(__dirname, '../test/release')
const app_path = path.join(__dirname, '../test/apps')
export async function bundle(...args) {
const [package_id] = args
console.log(`package ${package_id}`);
await fs.ensureDirAsync(release_path)
await fs.ensureDirAsync(app_path)
await fs.ensureDirAsync(upload_path)
const archive_path = path.join(release_path, 'downloads', package_id)
const package_path = path.join(app_path, package_id);
const uploadFile_path = path.join(upload_path, package_id)
const full_path = path.join(archive_path, 'full')
const sand_path = path.join(archive_path, 'sand')
await fs.ensureDirAsync(archive_path)
await fs.ensureDirAsync(package_path)
await fs.ensureDirAsync(full_path)
await fs.ensureDirAsync(sand_path)
// untar upload package
await untar(uploadFile_path, package_path)
let hashes = new Map<string, object>();
// let hashes = {}
await crawlPath(package_path, {
onFile: async (file) => {
let hash = await caculateSHA256(file)
hashes.set(file, {
file: file,
hash: hash,
size: (await fs.statAsync(file)).size.toString()
})
// hashes[file] = {
// file: file,
// hash: hash,
// size: (await fs.statAsync(file)).size.toString()
// }
let sand_file = path.join(sand_path, `${hash}.tar.gz`)
await archiveSingle(sand_file, [file], package_path)
},
onDir: async (files, _path, depth) => {
},
})
// TODO: 上传checksum: hashes
const full_file = path.join(full_path, `${package_id}.tar.gz`)
await fs.removeAsync(full_file)
await archive(full_file, await fs.readdirAsync(package_path), package_path)
// TODO: 上传meta
const full_hash = await caculateSHA256(full_file)
const full_size = (await fs.statAsync(full_file)).size.toString()
// TODO: 增量包
return {
files: Array.from(hashes.values())
}
}
import * as fs from 'fs-extra-promise'
import * as _fs from 'fs'
import * as crypto from 'crypto'
import * as child_process from 'child_process'
// import * as tar from 'tar-stream'
// import * as fstream from 'fstream'
interface crawOptions {
onDir: (files: string | string[], _path: string, depth: number) => Promise<void>;
onFile: (file: string) => Promise<void>;
}
export async function crawlPath(_path, options: crawOptions, depth = 0) {
if (await isDir(_path)) {
depth += 1
const files = await fs.readdirAsync(_path)
await options.onDir(files, _path, depth)
if (files) {
for (let fileName of files) {
const file = `${_path}/${fileName}`
if (await isDir(file)) {
await crawlPath(file, options, depth)
} else if (await isFile(file)) {
await options.onFile(file)
}
}
}
} else if (await isFile(_path)) {
await options.onFile(_path)
}
}
export async function isDir(path) {
return (await fs.lstatAsync(path)).isDirectory()
}
export async function isFile(path) {
return (await fs.lstatAsync(path)).isFile()
}
export function archiveSingle(archive: string, files: string[], directory: string): Promise<void> {
// const dir = fs.createWriteStream(archive)
// const pack = tar.Pack()
// .on('error', () => console.log('error'))
// .on('end',() => {})
// fstream.Reader({type: 'File', path: file})
// .pipe(pack)
// .pipe(dir)
// return tar.pack(file).pipe(_fs.createWriteStream(archive))
return new Promise<void>((resolve, reject) => {
let child = child_process.spawn("tar", ["-czf", archive, '-P', '-C', directory].concat(files), {stdio: 'inherit'});
child.on('exit', (code) => {
if (code == 0) {
resolve()
} else {
reject(code);
}
});
child.on('error', (error) => {
reject(error);
})
});
}
export function archive(archive: string, files: string[], directory: string): Promise<void> {
return new Promise<void>((resolve, reject) => {
let child = child_process.spawn("tar", ["-vczf", archive, '-C', directory].concat(files), {stdio: 'inherit'});
child.on('exit', (code) => {
if (code == 0) {
resolve()
} else {
reject(code);
}
});
child.on('error', (error) => {
reject(error);
})
});
}
export function untar(archive: string, directory: string): Promise<void> {
return new Promise<void>((resolve, reject) => {
let child = child_process.spawn("tar", ["-xvf", archive, '-C', directory], {stdio: 'inherit'});
child.on('exit', (code) => {
if (code == 0) {
resolve()
} else {
reject(code);
}
});
child.on('error', (error) => {
reject(error);
})
});
}
export function caculateSHA256(file: string): Promise<string> {
return new Promise((resolve, reject) => {
let input = _fs.createReadStream(file);
const hash = crypto.createHash("sha256");
hash.on("error", (error: Error) => {
reject(error)
});
input.on("error", (error: Error) => {
reject(error);
});
hash.on('readable', () => {
let data = hash.read();
if (data) {
resolve((<Buffer>data).toString("hex"));
}
});
input.pipe(hash);
});
}
\ No newline at end of file
......@@ -47,7 +47,7 @@ export interface App {
icon?: string;
cover?: string;
background?: string;
packages?: Package[];
// packages?: Package[];
created_at: Date;
}
......@@ -98,14 +98,13 @@ export class AppSchema extends Instance<App, AppSchema> implements App {
cover?: string;
@Property(String, false)
background?: string;
@Property(Array, false)
packages?: Package[];
// @Property(Array, false)
// packages?: Package[];
@Property(Date, false)
created_at: Date;
static onCreating(app: App){
app.created_at = new Date()
app.packages = []
}
handleUpdate(data: App) {
......
......@@ -21,9 +21,11 @@ export interface Package {
name: string;
appId: string;
version: string;
status: string;
type: string;
locales: Locale[];
platforms: Platform[];
files: File[];
files?: File[];
}
......@@ -36,6 +38,10 @@ export class PackageSchema extends Instance<Package, PackageSchema> implements P
name: string;
@Property(String, false)
appId: string;
@Property(String, true)
type: string;
@Property(String, true)
status: string;
@Property(String, false)
version: string;
@Property(Array, false)
......@@ -45,6 +51,10 @@ export class PackageSchema extends Instance<Package, PackageSchema> implements P
@Property(Array, false)
files: File[];
static onCreating(pack: Package){
pack.status = pack.status || 'init'
}
handleUpdate(data: Package) {
Object.assign(this, data)
}
......
import Router = require('koa-router');
import {toObjectID} from 'iridium'
import {mongodb} from '../models/iridium'
import {App, AppSchema} from "../models/App";
import * as vercomp from 'vercomp'
import {Context} from "koa";
import {Package} from "../models/Package";
const router = new Router();
// router.get('/apps', async (ctx: Context, next) => {
// ctx.body = await mongodb.Apps.find({})
// .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('/apps', async (ctx: Context, next) => {
ctx.body = await mongodb.Apps.find({})
.map(async app => {
if(Array.isArray(app.packages) && app.packages.length > 0){
app.packages = await Promise.all(app.packages.map(async p => {
return await mongodb.Packages.findOne({id: p})
}))
}
return app
})
});
ctx.body = await mongodb.Apps.find({}).toArray()
})
router.post('/apps/:id', async (ctx: Context, next) => {
if (!ctx.request.body.id || ctx.params.id !== ctx.request.body.id) {
......@@ -33,7 +44,7 @@ router.post('/apps/:id', async (ctx: Context, next) => {
})
router.patch('/apps/:id', async (ctx: Context, next) => {
let data = ctx.request.body
let _app: App = ctx.request.body
let app: AppSchema | null = await mongodb.Apps.findOne({id: ctx.params.id});
if (!app) {
ctx.throw(400, `App ${ctx.params.id} Not Found `);
......@@ -42,23 +53,141 @@ router.patch('/apps/:id', async (ctx: Context, next) => {
ctx.throw(400, `Can not change AppID`)
}
if(Array.isArray(data.packages)) {
data.packages = await Promise.all(data.packages.map(async _p => {
const p = await mongodb.Packages.findOne({id: _p.id})
if(p) {
p.handleUpdate(_p)
await p.save()
return p.id
} else {
const newP = await mongodb.Packages.insert(_p)
return newP.id
}
}))
}
// if(Array.isArray(data.packages)) {
// data.packages = await Promise.all(data.packages.map(async _p => {
// if(_p._id) {
// const p = await mongodb.Packages.findOne({_id: toObjectID(_p._id)})
//
// if(!_p.platforms) {
// ctx.throw(400, `请填写支持的平台:${_p.id}`)
// }
// else if(!_p.locales) {
// ctx.throw(400, `请填写支持的语言:${_p.id}`)
// }
// else if(!_p.version) {
// ctx.throw(400, `请填写版本号:${_p.id}`)
// }
// else if(vercomp(_p.version, p.version) == -1){
// ctx.throw(400, `版本号有误 :${_p.id}`)
// }
//
// if(p.status == 'init') {
// p.handleUpdate(_p)
// await p.save()
// return p._id
// }
// else {
// return p._id
// }
//
// } else {
// let pack: Package = {
// id: _p.id,
// name: _p.name,
// version: _p.version,
// appId: ctx.params.id,
// locales: _p.locales,
// platforms: _p.platforms,
// status: 'init'
// }
// const newP = await mongodb.Packages.insert(pack)
// return newP._id
// }
// }))
// }
app!.handleUpdate(data)
app!.handleUpdate(_app)
ctx.body = await app!.save()
})
router.get('/packages/ready', async (ctx: Context, next) => {
if (!ctx.request.query.appId) {
ctx.throw(400, "appId must be required!")
}
let packs = await mongodb.Packages.find({appId: ctx.request.query.appId, status: 'uploaded'})
ctx.body = {
[ctx.request.query.appId]: packs
}
})
router.get('/packages/manage', async (ctx: Context, next) => {
if (!ctx.request.query.appId) {
ctx.throw(400, "appId must be required!")
}
let packs = await mongodb.Packages.find({appId: ctx.request.query.appId, type: 'editing'}).toArray()
ctx.body = {
[ctx.request.query.appId]: packs
}
})
router.post('/packages', async (ctx: Context, next) => {
const _p: Package = ctx.request.body
if (!_p.id) {
ctx.throw(400, `id 参数缺失:${_p.id}`)
}
if (!_p.platforms) {
ctx.throw(400, `请填写支持的平台:${_p.id}`)
}
else if (!_p.locales) {
ctx.throw(400, `请填写支持的语言:${_p.id}`)
}
else if (!_p.version) {
ctx.throw(400, `请填写版本号:${_p.id}`)
}
await mongodb.Packages.update({id: _p.id}, {$set: { type: 'edited' }}, {multi: true})
let _pack: Package = {
id: _p.id,
name: _p.name,
version: _p.version,
appId: _p.appId,
locales: _p.locales,
platforms: _p.platforms,
status: 'init',
type: 'editing'
}
ctx.body = await mongodb.Packages.insert(_pack)
})
router.patch('/packages', async (ctx: Context, next) => {
const _p: Package = ctx.request.body
const p = await mongodb.Packages.findOne({_id: toObjectID(_p._id)})
if (!_p.id) {
ctx.throw(400, `id 参数缺失:${_p.id}`)
}
if (!_p.platforms) {
ctx.throw(400, `请填写支持的平台:${_p.id}`)
}
else if (!_p.locales) {
ctx.throw(400, `请填写支持的语言:${_p.id}`)
}
else if (!_p.version) {
ctx.throw(400, `请填写版本号:${_p.id}`)
}
if (p.status == 'init') {
p.handleUpdate(_p)
ctx.body = await p.save()
} else {
ctx.throw(400, `非法操作:${_p.id}`)
}
})
router.delete('/packages', async(ctx: Context, next) => {
const _p: Package = ctx.request.body
const p = await mongodb.Packages.findOne({_id: toObjectID(_p._id)})
p.type = 'edited'
p.status = 'delete'
await p.save()
ctx.body = {
message: 'delete successful'
}
})
export default router
\ No newline at end of file
import { Context } from 'koa';
import { OSS } from 'aliyun-sdk';
import {Context} from 'koa';
import {OSS} from 'aliyun-sdk';
import * as busboy from 'async-busboy';
import * as mime from 'mime';
import * as uuid from 'uuid';
import * as Client from 'aliyun-oss-upload-stream';
import * as fs from 'fs-extra-promise'
import * as path from 'path'
import * as Aria2 from 'aria2'
import {bundle} from '../../package/main'
import {mongodb} from '../models/iridium'
import {toObjectID} from 'iridium'
import config from '../../config'
// const Aria2Options = {
// host: 'localhost',
// port: 6800,
// secure: false,
// secret: '',
// path: path.join(__dirname, '../../test/upload')
// }
import Router = require('koa-router');
const ossStream = Client(new OSS({
accessKeyId: process.env["OSS_ACCESS_ID"],
......@@ -16,7 +33,7 @@ const router = new Router()
const UploadImage = async (ctx: Context) => {
try {
const { files } = await busboy(ctx.req);
const {files} = await busboy(ctx.req);
ctx.body = await Promise.all(files.map(async file => {
const ext = mime.extension(file.mime);
......@@ -32,8 +49,6 @@ const UploadImage = async (ctx: Context) => {
ContentType: file.mimeType
});
upload.minPartSize(1048576); // 1M,表示每块part大小至少大于1M
file.pipe(upload);
return await new Promise((resolve, reject) => {
......@@ -46,8 +61,117 @@ const UploadImage = async (ctx: Context) => {
}
};
export const UploadPackage = async (ctx: Context) => {
try {
const {files} = await busboy(ctx.req);
ctx.body = await Promise.all(files.map(async file => {
const ext = mime.extension(file.mime);
if (['zip', 'gz', 'rar', '7z'].indexOf(ext) === -1) {
throw new Error('Unsupported file type');
}
const filename = uuid.v1()
const archive_path = path.join(__dirname, '../../test/upload')
await fs.ensureDirAsync(archive_path)
const archive = fs.createWriteStream(path.join(archive_path, filename))
let pack = await mongodb.Packages.findOne({_id: toObjectID(ctx.params.id)})
return await new Promise((resolve, reject) => {
file.pipe(archive)
file.on('close', async() => {
pack.status = 'uploading'
await pack.save()
resolve(pack)
// 上传完, 打包
const bundled = await bundle(filename)
pack.files = bundled.files
pack.status = 'uploaded'
await pack.save()
// 打包完,上传阿里云
})
file.on('error', async (error) => {
pack.status = 'failed'
await pack.save()
reject(error)
})
})
}));
} catch (err) {
ctx.throw(403, err);
}
}
const uploadPackageUrl = async (ctx: Context) => {
if(!ctx.request.body.url) {
ctx.throw(400, "params error")
}
//testUrl: https://r.my-card.in/release/dist/0c16a3ecb115fd7cf575ccdd64f62a8f3edc635b087950e4ed4f3f781972bbfd.tar.gz
const downloader = new Aria2
let pack = await mongodb.Packages.findOne({_id: toObjectID(ctx.request.body._id)})
await downloader.open()
downloader.onDownloadStart = async() => {
pack.status = 'uploading'
await pack.save()
}
downloader.onDownloadComplete = async(m) => {
const { files } = await downloader.send('tellStatus', m.gid)
const [file] = files
// 打包
const bundled = await bundle(path.basename(file.path))
// 打包完, 上传阿里云
pack.files = bundled.files
pack.status = 'uploaded'
await pack.save()
}
downloader.onDownloadError = async(err) => {
// console.log(await downloader.send('tellStatus', err.gid))
pack.status = 'failed'
await pack.save()
}
ctx.body = await new Promise((resolve, reject) => {
downloader.onmessage = m => {
if(m["error"]) {
reject(m["error"])
} else {
resolve(m)
}
}
downloader.send('addUri', [ctx.request.body.url], {dir: config.upload_path})
})
}
router.post('/upload/image', UploadImage)
router.post('/upload/package/:id', UploadPackage)
router.post('/upload/packageUrl', uploadPackageUrl)
export default router
......@@ -6,13 +6,19 @@
version "1.3.1"
resolved "https://registry.yarnpkg.com/@types/accepts/-/accepts-1.3.1.tgz#e5959c500fde65e4bd18a78d8b7f9392ccb9aab4"
"@types/bluebird@*", "@types/bluebird@^3.5.2":
version "3.5.2"
resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.2.tgz#ecf1104217495e50fe0b588d538146cd6f733b89"
"@types/bluebird@^3.5.0":
version "3.5.0"
resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.0.tgz#2633470a4eabe9a47cd9a45fdb20ed5f93407bca"
"@types/bluebird@^3.5.2":
version "3.5.2"
resolved "https://registry.yarnpkg.com/@types/bluebird/-/bluebird-3.5.2.tgz#ecf1104217495e50fe0b588d538146cd6f733b89"
"@types/busboy@^0.2.3":
version "0.2.3"
resolved "https://registry.yarnpkg.com/@types/busboy/-/busboy-0.2.3.tgz#6697ad29873246c530f09a3ff5a40861824230d5"
dependencies:
"@types/node" "*"
"@types/chai@^3.4.35":
version "3.5.0"
......@@ -38,6 +44,20 @@
"@types/express-serve-static-core" "*"
"@types/serve-static" "*"
"@types/fs-extra-promise@^0.0.32":
version "0.0.32"
resolved "https://registry.yarnpkg.com/@types/fs-extra-promise/-/fs-extra-promise-0.0.32.tgz#38be021eee89ad7fc9346eadd305f259042f790b"
dependencies:
"@types/bluebird" "*"
"@types/fs-extra" "*"
"@types/node" "*"
"@types/fs-extra@*":
version "2.1.0"
resolved "https://registry.yarnpkg.com/@types/fs-extra/-/fs-extra-2.1.0.tgz#8b350239c0455d92b8d3c626edac193860ff395f"
dependencies:
"@types/node" "*"
"@types/http-assert@*":
version "1.2.0"
resolved "https://registry.yarnpkg.com/@types/http-assert/-/http-assert-1.2.0.tgz#0b82993036e86c6ff2944e033b73b57e85ccdcab"
......@@ -56,9 +76,9 @@
version "3.2.0"
resolved "https://registry.yarnpkg.com/@types/koa-compose/-/koa-compose-3.2.0.tgz#9cb907923f33da1b14c564eaa7e63d8ea38b65ff"
"@types/koa-router@^7.0.21":
version "7.0.21"
resolved "https://registry.yarnpkg.com/@types/koa-router/-/koa-router-7.0.21.tgz#8d462a631181022472e6a9a690934bbaa9a3e7a5"
"@types/koa-router@^7.0.22":
version "7.0.22"
resolved "https://registry.yarnpkg.com/@types/koa-router/-/koa-router-7.0.22.tgz#92b4b533f074036250892fe35bb6329ee9242def"
dependencies:
"@types/koa" "*"
......@@ -215,6 +235,15 @@ are-we-there-yet@~1.1.2:
delegates "^1.0.0"
readable-stream "^2.0.0 || ^1.1.13"
aria2@^3.0.0:
version "3.0.0"
resolved "https://registry.yarnpkg.com/aria2/-/aria2-3.0.0.tgz#3363b9812fcf4aa3b5615beca34a24eeb76b72cd"
dependencies:
commander "^2.9.0"
node-fetch "^1.6.3"
polygoat "^1.1.4"
ws "^1.1.1"
arr-diff@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/arr-diff/-/arr-diff-2.0.0.tgz#8f3b827f955a8bd669697e4a4256ac3ceae356cf"
......@@ -256,6 +285,10 @@ assert-plus@^0.2.0:
version "0.2.0"
resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-0.2.0.tgz#d74e1b87e7affc0db8aadb7021f3fe48101ab234"
assertion-error@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.0.0.tgz#c7f85438fdd466bc7ca16ab90c81513797a5d23b"
async-busboy@^0.3.4:
version "0.3.4"
resolved "https://registry.yarnpkg.com/async-busboy/-/async-busboy-0.3.4.tgz#1311af58c32b07440d626b7acc6e38b751580e7d"
......@@ -493,6 +526,13 @@ caseless@~0.12.0:
version "0.12.0"
resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc"
chai@^2.2.0:
version "2.3.0"
resolved "https://registry.yarnpkg.com/chai/-/chai-2.3.0.tgz#8a2f6a34748da801090fd73287b2aa739a4e909a"
dependencies:
assertion-error "1.0.0"
deep-eql "0.1.3"
chalk@0.5.1:
version "0.5.1"
resolved "https://registry.yarnpkg.com/chalk/-/chalk-0.5.1.tgz#663b3a648b68b55d04690d49167aa837858f2174"
......@@ -571,11 +611,11 @@ combined-stream@^1.0.5, combined-stream@~1.0.5:
dependencies:
delayed-stream "~1.0.0"
commander@2.6.0, commander@^2.2.0:
commander@2.6.0:
version "2.6.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.6.0.tgz#9df7e52fb2a0cb0fb89058ee80c3104225f37e1d"
commander@^2.9.0:
commander@^2.2.0, commander@^2.9.0:
version "2.9.0"
resolved "https://registry.yarnpkg.com/commander/-/commander-2.9.0.tgz#9c99094176e12240cb22d6c5146098400fe0f7d4"
dependencies:
......@@ -719,6 +759,12 @@ decamelize@^1.0.0, decamelize@^1.1.1:
version "1.2.0"
resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290"
deep-eql@0.1.3:
version "0.1.3"
resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-0.1.3.tgz#ef558acab8de25206cd713906d74e56930eb69f2"
dependencies:
type-detect "0.1.1"
deep-equal@~1.0.0:
version "1.0.1"
resolved "https://registry.yarnpkg.com/deep-equal/-/deep-equal-1.0.1.tgz#f5d260292b660e084eff4cdbc9f08ad3247448b5"
......@@ -815,6 +861,12 @@ encodeurl@~1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.1.tgz#79e3d58655346909fe6f0f45a5de68103b294d20"
encoding@^0.1.11:
version "0.1.12"
resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.12.tgz#538b66f3ee62cd1ab51ec323829d1f9480c74beb"
dependencies:
iconv-lite "~0.4.13"
end-of-stream@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.0.0.tgz#d4596e702734a93e40e9af864319eabd99ff2f0e"
......@@ -1020,6 +1072,13 @@ from@~0:
version "0.1.7"
resolved "https://registry.yarnpkg.com/from/-/from-0.1.7.tgz#83c60afc58b9c56997007ed1a768b3ab303a44fe"
fs-extra-promise@^1.0.1:
version "1.0.1"
resolved "https://registry.yarnpkg.com/fs-extra-promise/-/fs-extra-promise-1.0.1.tgz#b6ed1ace97b10e06b95f458d051b7f05c6613ee6"
dependencies:
bluebird "^3.5.0"
fs-extra "^2.1.2"
fs-extra@1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-1.0.0.tgz#cd3ce5f7e7cb6145883fcae3191e9877f8587950"
......@@ -1028,6 +1087,13 @@ fs-extra@1.0.0:
jsonfile "^2.1.0"
klaw "^1.0.0"
fs-extra@^2.1.2:
version "2.1.2"
resolved "https://registry.yarnpkg.com/fs-extra/-/fs-extra-2.1.2.tgz#046c70163cef9aad46b0e4a7fa467fb22d71de35"
dependencies:
graceful-fs "^4.1.2"
jsonfile "^2.1.0"
fs.realpath@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f"
......@@ -1269,7 +1335,7 @@ http-signature@~1.1.0:
jsprim "^1.2.2"
sshpk "^1.7.0"
iconv-lite@0.4.13:
iconv-lite@0.4.13, iconv-lite@~0.4.13:
version "0.4.13"
resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.13.tgz#1f88aba4ab0b1508e8312acc39345f36e992e2f2"
......@@ -1439,7 +1505,7 @@ is-redirect@^1.0.0:
version "1.0.0"
resolved "https://registry.yarnpkg.com/is-redirect/-/is-redirect-1.0.0.tgz#1d03dded53bd8db0f30c26e4f95d36fc7c87dc24"
is-stream@^1.0.0:
is-stream@^1.0.0, is-stream@^1.0.1:
version "1.1.0"
resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-1.1.0.tgz#12d4a3dd4e68e0b79ceb8dbc84173ae80d91ca44"
......@@ -1932,6 +1998,13 @@ nested-error-stacks@^1.0.0:
dependencies:
inherits "~2.0.1"
node-fetch@^1.6.3:
version "1.6.3"
resolved "https://registry.yarnpkg.com/node-fetch/-/node-fetch-1.6.3.tgz#dc234edd6489982d58e8f0db4f695029abcd8c04"
dependencies:
encoding "^0.1.11"
is-stream "^1.0.1"
node-pre-gyp@^0.6.29:
version "0.6.33"
resolved "https://registry.yarnpkg.com/node-pre-gyp/-/node-pre-gyp-0.6.33.tgz#640ac55198f6a925972e0c16c4ac26a034d5ecc9"
......@@ -2205,6 +2278,10 @@ pinkie@^2.0.0:
version "2.0.4"
resolved "https://registry.yarnpkg.com/pinkie/-/pinkie-2.0.4.tgz#72556b80cfa0d48a974e80e77248e80ed4f7f870"
polygoat@^1.1.4:
version "1.1.4"
resolved "https://registry.yarnpkg.com/polygoat/-/polygoat-1.1.4.tgz#329f9a0d1b2d4a45149e2539523c6f7dfd850a5f"
pomelo-protobuf@^0.4.0:
version "0.4.0"
resolved "https://registry.yarnpkg.com/pomelo-protobuf/-/pomelo-protobuf-0.4.0.tgz#e45e9a0a446eb18667e0c6e13eeb53d47addbda8"
......@@ -2856,6 +2933,10 @@ tweetnacl@^0.14.3, tweetnacl@~0.14.0:
version "0.14.5"
resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64"
type-detect@0.1.1:
version "0.1.1"
resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-0.1.1.tgz#0ba5ec2a885640e470ea4e8505971900dac58822"
type-is@^1.5.5, type-is@~1.6.6:
version "1.6.14"
resolved "https://registry.yarnpkg.com/type-is/-/type-is-1.6.14.tgz#e219639c17ded1ca0789092dd54a03826b817cb2"
......@@ -2937,6 +3018,12 @@ vary@^1.0.0:
version "1.1.0"
resolved "https://registry.yarnpkg.com/vary/-/vary-1.1.0.tgz#e1e5affbbd16ae768dd2674394b9ad3022653140"
vercomp@^1.0.2:
version "1.0.2"
resolved "https://registry.yarnpkg.com/vercomp/-/vercomp-1.0.2.tgz#725fd292c099014d919ad9e9e05d3d25c7cff491"
dependencies:
chai "^2.2.0"
verror@1.3.6:
version "1.3.6"
resolved "https://registry.yarnpkg.com/verror/-/verror-1.3.6.tgz#cff5df12946d297d2baaefaa2689e25be01c005c"
......@@ -2996,7 +3083,7 @@ write-file-atomic@^1.1.2:
imurmurhash "^0.1.4"
slide "^1.1.5"
ws@1.1.1:
ws@1.1.1, ws@^1.1.1:
version "1.1.1"
resolved "https://registry.yarnpkg.com/ws/-/ws-1.1.1.tgz#082ddb6c641e85d4bb451f03d52f06eabdb1f018"
dependencies:
......
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