Skip to content
This repository has been archived by the owner on Dec 25, 2022. It is now read-only.

Commit

Permalink
use umi-plugin-types
Browse files Browse the repository at this point in the history
  • Loading branch information
imhele committed Jan 23, 2019
1 parent a0be281 commit a86b56f
Show file tree
Hide file tree
Showing 5 changed files with 41 additions and 83 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "umi-plugin-oss",
"version": "1.1.1",
"version": "1.1.2",
"main": "./lib/index.js",
"types": "./lib/index.d.ts",
"typings": "./lib/index.d.ts",
Expand Down Expand Up @@ -59,6 +59,7 @@
"tslint": "^5.12.0",
"tslint-eslint-rules": "^5.4.0",
"typescript": "~3.2.2",
"umi-plugin-types": "^0.3.0",
"umi-test": "~1.3.0"
}
}
44 changes: 6 additions & 38 deletions src/index.ts
Original file line number Diff line number Diff line change
@@ -1,40 +1,8 @@
import path from 'path';
import { IApi } from 'umi-plugin-types';
import { readdirSync, statSync } from 'fs';
import SyncFiles, { ACLType, OSSOptions, FileInfo } from './syncFiles';

export interface UmiApi {
config: {
base?: string;
publicPath?: string;
cssPublicPath?: string;
};
paths: {
outputPath: string;
absOutputPath: string;
pagesPath: string;
absPagesPath: string;
tmpDirPath: string;
absTmpDirPath: string;
absSrcPath: string;
cwd: string;
};
routes: Array<{
path: string;
component: string;
[key: string]: any;
}>;
registerCommand: (name: string, options: {}, fun: (args: string[]) => void) => void; // @TODO
log: {
success: (...messages: string[]) => void;
error: (...messages: string[]) => void;
debug: (...messages: string[]) => void;
pending: (...messages: string[]) => void;
watch: (...messages: string[]) => void;
};
debug: (message: string) => void;
onBuildSuccess: (callback: () => void) => void;
}

export interface ACLRule {
private?: RegExp | string[];
publicRead?: RegExp | string[];
Expand Down Expand Up @@ -82,7 +50,7 @@ export const handleAcl = (rule: RegExp | string[], fileInfoArr: FileInfo[], acl:
}
};

export default function (api: UmiApi, options?: UmiPluginOssOptions) {
export default function (api: IApi, options?: UmiPluginOssOptions) {
api.onBuildSuccess((): void => {
// default value
options = {
Expand Down Expand Up @@ -147,13 +115,13 @@ export default function (api: UmiApi, options?: UmiPluginOssOptions) {

// list exists files
if (options.bijection || options.ignore.existsInOss) {
const existsFileArr = await syncFiles.list(prefix, api.log);
const existsFileArr = await syncFiles.list(prefix, api);
if (options.bijection) {
const delFileArr = existsFileArr.filter(filename => {
return fileInfoArr.some(fileInfo => fileInfo[0] === filename);
});
api.log.debug(`The following files will be delete:\n${delFileArr.join('\n')}`);
const deleteCosts = await syncFiles.upload(prefix, fileInfoArr, api.log);
api.debug(`The following files will be delete:\n${delFileArr.join('\n')}`);
const deleteCosts = await syncFiles.upload(prefix, fileInfoArr, api);
api.log.success(`Deleted in ${deleteCosts / 1000}s`);
}
if (options.ignore.existsInOss) {
Expand Down Expand Up @@ -189,7 +157,7 @@ export default function (api: UmiApi, options?: UmiPluginOssOptions) {
fileInfoArr.map(fileInfo => `${fileInfo[0]} ${fileInfo[2]}`).join('\n')
}`);

const uploadCosts = await syncFiles.upload(prefix, fileInfoArr, api.log);
const uploadCosts = await syncFiles.upload(prefix, fileInfoArr, api);
api.log.success(`Uploaded in ${uploadCosts / 1000}s`);
})();
});
Expand Down
31 changes: 14 additions & 17 deletions src/syncFiles.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
import OSS from 'ali-oss';
import { createReadStream } from 'fs';
import { IApi } from 'umi-plugin-types';

export type ACLType = 'public-read-write' | 'public-read' | 'private';

export type FileInfo = [string, string, ACLType];

export interface OssHeaders {
'Cache-Control'?: string;
'Content-Disposition'?: string;
Expand All @@ -13,6 +16,7 @@ export interface OssHeaders {
'x-oss-object-acl'?: ACLType;
[key: string]: string;
}

export interface OSSOptions {
accessKeyId?: string;
accessKeySecret?: string;
Expand All @@ -27,20 +31,13 @@ export interface OSSOptions {
};
headers?: OssHeaders;
}

export interface SyncFilesOptions extends OSSOptions {
cname?: boolean;
waitBeforeDelete?: number;
waitBeforeUpload?: number;
}

interface Log {
success: (...messages: string[]) => void;
error: (...messages: string[]) => void;
debug: (...messages: string[]) => void;
pending: (...messages: string[]) => void;
watch: (...messages: string[]) => void;
}

export const wait = async function (seconds: number = 0): Promise<any> {
if (seconds)
return new Promise(resolve => setTimeout(resolve, seconds * 1000));
Expand All @@ -65,28 +62,28 @@ export default class SyncFiles {
this.options = options;
this.oss = new OSS(ossOptions);
}
public async upload(prefix: string, fileInfoArr: FileInfo[], log: Log): Promise<number> {
public async upload(prefix: string, fileInfoArr: FileInfo[], api: IApi): Promise<number> {
await wait(this.options.waitBeforeUpload);
const globalStartTime = Date.now();
for (const fileInfo of fileInfoArr) {
const startTime = Date.now();
const targetKey = `${prefix}${fileInfo[0]}`;
log.pending(`Uploading ${targetKey}...`);
api.log.pending(`Uploading ${targetKey}...`);
const stream = createReadStream(fileInfo[1]);
const headers: OssHeaders = {
...this.options.headers,
'x-oss-object-acl': fileInfo[2],
};
const result = await this.oss.putStream(targetKey, stream, { headers });
if (result.res.status === 200) {
log.success(targetKey, `${(Date.now() - startTime) / 100}s`);
api.log.success(targetKey, `${(Date.now() - startTime) / 100}s`);
} else {
log.error(targetKey, JSON.stringify(result.res));
api.log.error(targetKey, JSON.stringify(result.res));
}
}
return new Promise(resolve => resolve(Date.now() - globalStartTime));
}
public async list(prefix: string, log: Log): Promise<string[]> {
public async list(prefix: string, api: IApi): Promise<string[]> {
let marker: string | null = prefix;
const existsFileArr: string[] = [];
while (typeof marker === 'string') {
Expand All @@ -95,15 +92,15 @@ export default class SyncFiles {
existsFileArr.push(...result.objects.map((obj: any) => obj.name));
marker = result.nextMarker;
} else {
log.error(JSON.stringify(result.res));
api.log.error(JSON.stringify(result.res));
break;
}
}
return new Promise(resolve => {
resolve(existsFileArr.map(targetKey => targetKey.replace(prefix, '')));
});
}
public async delete(prefix: string, delFileArr: string[], log: Log): Promise<number> {
public async delete(prefix: string, delFileArr: string[], api: IApi): Promise<number> {
await wait(this.options.waitBeforeDelete);
const globalStartTime = Date.now();
delFileArr = delFileArr.map(filename => `${prefix}${filename}`);
Expand All @@ -113,10 +110,10 @@ export default class SyncFiles {
return !(<string[]>(result.deleted)).includes(targetKey);
});
if (failed.length) {
log.error(`Delete failed:\n${failed.join('\n')}`);
api.log.error(`Delete failed:\n${failed.join('\n')}`);
}
} else {
log.error(JSON.stringify(result.res));
api.log.error(JSON.stringify(result.res));
}
return new Promise(resolve => resolve(Date.now() - globalStartTime));
}
Expand Down
32 changes: 12 additions & 20 deletions test/index.test.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import 'jest';
import { IApi, IOnBuildSuccessFunc } from 'umi-plugin-types';
import { FileInfo } from '../src/syncFiles';
import UmiPluginOss, { handleAcl, UmiApi } from '../src/index';
import UmiPluginOss, { handleAcl } from '../src/index';

jest.mock('fs');
jest.mock('path');
Expand All @@ -9,11 +10,9 @@ jest.mock('syncFiles');

export let messageQueue: Map<string, string[]> = new Map();

export const umiApi: UmiApi = {
export const umiApi = {
config: {
base: undefined,
publicPath: 'https://cdn.imhele.com/',
cssPublicPath: undefined,
},
paths: {
outputPath: '/dist/',
Expand All @@ -25,7 +24,6 @@ export const umiApi: UmiApi = {
absSrcPath: '',
cwd: '',
},
routes: [],
registerCommand: () => { },
log: {
success: (...messages: string[]) => {
Expand All @@ -34,20 +32,14 @@ export const umiApi: UmiApi = {
error: (...messages: string[]) => {
messageQueue.set(`${Date.now()}.${Math.random()}|error`, messages);
},
debug: (...messages: string[]) => {
messageQueue.set(`${Date.now()}.${Math.random()}|debug`, messages);
},
pending: (...messages: string[]) => {
messageQueue.set(`${Date.now()}.${Math.random()}|pending`, messages);
},
watch: (...messages: string[]) => {
messageQueue.set(`${Date.now()}.${Math.random()}|watch`, messages);
},
},
debug: (message: string) => {
messageQueue.set(`${Date.now()}.${Math.random()}|debug`, [message]);
},
onBuildSuccess: (callback) => { callback(); },
onBuildSuccess: (callback: IOnBuildSuccessFunc) => { callback(undefined); },
};

describe('test index', () => {
Expand All @@ -70,15 +62,15 @@ describe('test index', () => {
test('UmiPluginOss without params', () => {
messageQueue.clear();
expect(() => {
UmiPluginOss(umiApi, {});
UmiPluginOss(umiApi as any, {});
}).toThrow();
expect(messageQueue.size).toBe(0);
});

test('UmiPluginOss with default options', () => {
messageQueue.clear();
expect(() => {
UmiPluginOss(umiApi, {
UmiPluginOss(umiApi as any, {
accessKeyId: 'test',
accessKeySecret: 'test',
});
Expand All @@ -101,7 +93,7 @@ describe('test index', () => {
...umiApi.config,
publicPath: undefined,
},
},
} as any,
{
accessKeyId: 'test',
accessKeySecret: 'test',
Expand All @@ -123,7 +115,7 @@ describe('test index', () => {
...umiApi.config,
publicPath: undefined,
},
},
} as any,
{
accessKeyId: 'test',
accessKeySecret: 'test',
Expand All @@ -145,7 +137,7 @@ describe('test index', () => {
test('UmiPluginOss with RegExp acl rule', () => {
messageQueue.clear();
expect(() => {
UmiPluginOss(umiApi, {
UmiPluginOss(umiApi as any, {
accessKeyId: 'test',
accessKeySecret: 'test',
acl: {
Expand All @@ -164,7 +156,7 @@ describe('test index', () => {
test('UmiPluginOss with ignore filter', () => {
messageQueue.clear();
expect(() => {
UmiPluginOss(umiApi, {
UmiPluginOss(umiApi as any, {
accessKeyId: 'test',
accessKeySecret: 'test',
ignore: {
Expand All @@ -182,7 +174,7 @@ describe('test index', () => {
test('UmiPluginOss with bijection', () => {
messageQueue.clear();
expect(() => {
UmiPluginOss(umiApi, {
UmiPluginOss(umiApi as any, {
accessKeyId: 'test',
accessKeySecret: 'test',
bijection: true,
Expand All @@ -201,7 +193,7 @@ describe('test index', () => {
test('UmiPluginOss with ignore existsInOss', () => {
messageQueue.clear();
expect(() => {
UmiPluginOss(umiApi, {
UmiPluginOss(umiApi as any, {
accessKeyId: 'test',
accessKeySecret: 'test',
ignore: {
Expand Down
14 changes: 7 additions & 7 deletions test/syncFiles.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -24,11 +24,11 @@ describe('test syncFiles', () => {
},
};
const instance = new SyncFiles(options);
await instance.upload('', [], umiApi.log);
await instance.upload('', [], umiApi as any);
const time = await instance.upload('', [
['200', '/home/notexist/umi.js', 'private'],
['403', '/home/notexist/umi.js', 'private'],
], umiApi.log);
], umiApi as any);
expect(typeof time === 'number').toBe(true);
const keys = Array.from(messageQueue.keys());
const error = keys.find(k => k.endsWith('error'));
Expand All @@ -46,8 +46,8 @@ describe('test syncFiles', () => {
},
};
const instance = new SyncFiles(options);
const existsFileArr = await instance.list('test/in/syncFiles/', umiApi.log);
const existsFileArrB = await instance.list('404', umiApi.log);
const existsFileArr = await instance.list('test/in/syncFiles/', umiApi as any);
const existsFileArrB = await instance.list('404', umiApi as any);
expect(existsFileArr).toMatchObject(['test.png']);
expect(existsFileArrB.length).toBe(0);
expect(messageQueue.size).toBe(1);
Expand All @@ -63,9 +63,9 @@ describe('test syncFiles', () => {
},
};
const instance = new SyncFiles(options);
await instance.delete('dir/', ['umi.js'], umiApi.log);
await instance.delete('dir/', ['IGONRE_ME'], umiApi.log);
await instance.delete('', ['404'], umiApi.log);
await instance.delete('dir/', ['umi.js'], umiApi as any);
await instance.delete('dir/', ['IGONRE_ME'], umiApi as any);
await instance.delete('', ['404'], umiApi as any);
const values: string[][] = Array.from(messageQueue.values());
expect(values.some(k => k[0].includes('404'))).toBe(true);
expect(values.some(k => k[0].includes('Delete failed'))).toBe(true);
Expand Down

0 comments on commit a86b56f

Please sign in to comment.