diff --git a/.gitignore b/.gitignore index 57ce947d..287811b3 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,4 @@ -node_modules lib +node_modules *.log tsconfig.tsbuildinfo diff --git a/.vscode/settings.json b/.vscode/settings.json index a51972ee..6cbc54ff 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -15,6 +15,7 @@ "reimplement", "sendrecv", "streamsaver", + "struct", "tcpip", "uifabric", "webadb", diff --git a/packages/adb-backend-web/package-lock.json b/packages/adb-backend-web/package-lock.json index 55502620..43c80f0f 100644 --- a/packages/adb-backend-web/package-lock.json +++ b/packages/adb-backend-web/package-lock.json @@ -1,24 +1,24 @@ { - "name": "@yume-chan/adb-backend-web", - "version": "0.0.1", - "lockfileVersion": 1, - "requires": true, - "dependencies": { - "@types/w3c-web-usb": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@types/w3c-web-usb/-/w3c-web-usb-1.0.4.tgz", - "integrity": "sha512-aaOB3EL5WCWBBOYX7W1MKuzspOM9ZJI9s3iziRVypr1N+QyvIgXzCM4lm1iiOQ1VFzZioUPX9bsa23myCbKK4A==" - }, - "tslib": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz", - "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==" - }, - "typescript": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.2.tgz", - "integrity": "sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ==", - "dev": true - } - } + "name": "@yume-chan/adb-backend-web", + "version": "0.0.1", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@types/w3c-web-usb": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@types/w3c-web-usb/-/w3c-web-usb-1.0.4.tgz", + "integrity": "sha512-aaOB3EL5WCWBBOYX7W1MKuzspOM9ZJI9s3iziRVypr1N+QyvIgXzCM4lm1iiOQ1VFzZioUPX9bsa23myCbKK4A==" + }, + "tslib": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.0.1.tgz", + "integrity": "sha512-SgIkNheinmEBgx1IUNirK0TUD4X9yjjBRTqqjggWCU3pUEqIk3/Uwl3yRixYKT6WjQuGiwDv4NomL3wqRCj+CQ==" + }, + "typescript": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-4.0.2.tgz", + "integrity": "sha512-e4ERvRV2wb+rRZ/IQeb3jm2VxBsirQLpQhdxplZ2MEzGvDkkMmPglecnNDfSUBivMjP93vRbngYYDQqQ/78bcQ==", + "dev": true + } + } } diff --git a/packages/adb-backend-web/src/index.ts b/packages/adb-backend-web/src/index.ts index d7283d8c..1b2ea546 100644 --- a/packages/adb-backend-web/src/index.ts +++ b/packages/adb-backend-web/src/index.ts @@ -136,7 +136,8 @@ export default class AdbWebBackend implements AdbBackend { await this._device.clearHalt('in', this._inEndpointNumber); } - return result.data!.buffer; + const { buffer } = result.data!; + return buffer; } catch (e) { if (e instanceof Error && e.name === 'NotFoundError') { this.onDisconnectedEvent.fire(); diff --git a/packages/adb-backend-web/tsconfig.json b/packages/adb-backend-web/tsconfig.json index a104adf0..3c1a4140 100644 --- a/packages/adb-backend-web/tsconfig.json +++ b/packages/adb-backend-web/tsconfig.json @@ -1,19 +1,16 @@ { - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "lib", // /* Redirect output structure to the directory. */ - "rootDir": "./src", // /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - "lib": [ - "ESNext", - "DOM" + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "lib", // /* Redirect output structure to the directory. */ + "rootDir": "./src", // /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + "lib": [ + "ESNext", + "DOM" + ] + }, + "references": [ + { + "path": "../adb/tsconfig.json" + } ] - }, - "include": [ - "src" - ], - "references": [ - { - "path": "../adb/tsconfig.json" - } - ] } diff --git a/packages/adb/README.md b/packages/adb/README.md index 4dfe1d79..85d433e3 100644 --- a/packages/adb/README.md +++ b/packages/adb/README.md @@ -185,8 +185,6 @@ Supported on devices with `ls_v2` feature. #### STAT -*(Not Implemented)* - Request server to return the information of a file. If path is a symbolic link, the returned information is about the link itself. diff --git a/packages/adb/src/sync.ts b/packages/adb/src/sync.ts index 3d01f238..920fe258 100644 --- a/packages/adb/src/sync.ts +++ b/packages/adb/src/sync.ts @@ -1,8 +1,7 @@ import { AutoDisposable } from '@yume-chan/event'; -import { AdbBackend } from './backend'; import { AdbBufferedStream } from './buffered-stream'; import { AdbStream } from './stream'; -import { AutoResetEvent } from './utils'; +import { AutoResetEvent, Struct, StructInitType, StructReader } from './utils'; export enum AdbSyncRequestId { List = 'LIST', @@ -15,74 +14,26 @@ export enum AdbSyncRequestId { export enum AdbSyncResponseId { Entry = 'DENT', + Stat = 'STAT', Done = 'DONE', Data = 'DATA', Ok = 'OKAY', -} - -export abstract class AdbSyncRequestBase { - public readonly id: T; - - public constructor(id: T) { - this.id = id; - } - - public abstract toBuffer(backend: AdbBackend): ArrayBuffer; + Fail = 'FAIL', } export type AdbSyncNumberRequestId = AdbSyncRequestId.Done; -export class AdbSyncNumberRequest extends AdbSyncRequestBase { - public readonly value: number; - - public constructor(id: AdbSyncNumberRequestId, value: number) { - super(id); - this.value = value; - } - - public toBuffer(backend: AdbBackend): ArrayBuffer { - const array = new Uint8Array(8); - - const idBuffer = backend.encodeUtf8(this.id); - array.set(new Uint8Array(idBuffer)); - - const view = new DataView(array.buffer); - view.setUint32(4, this.value, true); - - return array.buffer; - } -} - export type AdbSyncStringRequestId = AdbSyncRequestId.List | AdbSyncRequestId.Send | AdbSyncRequestId.Stat | AdbSyncRequestId.Receive; -export class AdbSyncStringRequest extends AdbSyncRequestBase { - public value: string; - - public constructor(id: AdbSyncStringRequestId, value: string) { - super(id); - this.value = value; - } - - public toBuffer(backend: AdbBackend) { - const valueBuffer = backend.encodeUtf8(this.value); - const array = new Uint8Array(8 + valueBuffer.byteLength); - - const idBuffer = backend.encodeUtf8(this.id); - array.set(new Uint8Array(idBuffer)); - - const view = new DataView(array.buffer); - view.setUint32(4, valueBuffer.byteLength, true); - - array.set(new Uint8Array(valueBuffer), 8); - - return array.buffer; - } -} +const AdbSyncStringRequest = + new Struct(true) + .fixedLengthString('id', 4, undefined as any as AdbSyncStringRequestId) + .lengthPrefixedString('value', 'int32'); // https://github.com/python/cpython/blob/4e581d64b8aff3e2eda99b12f080c877bb78dfca/Lib/stat.py#L36 export enum LinuxFileType { @@ -91,16 +42,51 @@ export enum LinuxFileType { Link = 0o12, } +const AdbSyncStatResponseStruct = + new Struct(true) + .int32('mode') + .int32('size') + .int32('lastModifiedTime') + +export class AdbSyncStatResponse { + public static readonly size = AdbSyncStatResponseStruct.size; + + public static async parse(reader: StructReader): Promise { + const struct = await AdbSyncStatResponseStruct.parse(reader); + if (struct.mode === 0 && struct.size === 0 && struct.lastModifiedTime === 0) { + throw new Error('lstat failed'); + } + return new AdbSyncStatResponse(struct.mode, struct.size, struct.lastModifiedTime); + } + + public readonly id = AdbSyncResponseId.Stat; + + public readonly type: LinuxFileType; + + public readonly mode: number; + + public readonly size: number; + + public readonly lastModifiedTime: number; + + public constructor(mode: number, size: number, lastModifiedTime: number) { + this.type = mode >> 12 as LinuxFileType; + this.mode = mode & 0b00001111_11111111; + this.size = size; + this.lastModifiedTime = lastModifiedTime; + } +} + +const AdbSyncEntryResponseStruct = + AdbSyncStatResponseStruct + .lengthPrefixedString('name', 'int32'); + export class AdbSyncEntryResponse { - public static async parse(stream: AdbBufferedStream): Promise { - const buffer = await stream.read(16); - const view = new DataView(buffer); - const mode = view.getUint32(0, true); - const size = view.getUint32(4, true); - const lastModifiedTime = view.getUint32(8, true); - const nameLength = view.getUint32(12, true); - const name = stream.backend.decodeUtf8(await stream.read(nameLength)); - return new AdbSyncEntryResponse(mode, size, lastModifiedTime, name); + public static readonly size = AdbSyncEntryResponseStruct.size; + + public static async parse(reader: StructReader): Promise { + const struct = await AdbSyncEntryResponseStruct.parse(reader); + return new AdbSyncEntryResponse(struct.mode, struct.size, struct.lastModifiedTime, struct.name); } public readonly id = AdbSyncResponseId.Entry; @@ -111,8 +97,6 @@ export class AdbSyncEntryResponse { public readonly size: number; - public readonly logicalSize: number; - public readonly lastModifiedTime: number; public readonly name: string; @@ -121,46 +105,57 @@ export class AdbSyncEntryResponse { this.type = mode >> 12 as LinuxFileType; this.mode = mode & 0b00001111_11111111; this.size = size; - this.logicalSize = this.type === LinuxFileType.File ? this.size : 0; this.lastModifiedTime = lastModifiedTime; this.name = name; } } -export class AdbSyncDataResponse { - public static async parse(stream: AdbBufferedStream): Promise { - const buffer = await stream.read(4); - const view = new DataView(buffer); - const length = view.getUint32(0, true); - const data = await stream.read(length); - return new AdbSyncDataResponse(data); - } - - public readonly id = AdbSyncResponseId.Data; - - public readonly data: ArrayBuffer; - - public constructor(data: ArrayBuffer) { - this.data = data; - } -} +const AdbSyncDataResponse = + new Struct(true) + .lengthPrefixedBuffer('data', 'int32') + .extra({ id: AdbSyncResponseId.Data } as const); export class AdbSyncDoneResponse { + public static readonly instance = new AdbSyncDoneResponse(); + public readonly id = AdbSyncResponseId.Done; } -async function parseResponse(stream: AdbBufferedStream) { +const AdbSyncFailResponseStruct = + new Struct(true) + .lengthPrefixedString('message', 'int32'); + +class AdbSyncFailResponse { + public static async parse(reader: StructReader): Promise { + const struct = await AdbSyncFailResponseStruct.parse(reader); + throw new Error(struct.message); + } +} + +async function parseResponse(stream: AdbBufferedStream, size: number) { + // DONE responses' size are always same as the request's normal response. + // For example DONE responses for LIST requests are 16 bytes (same as DENT responses), + // but DONE responses for STAT requests are 12 bytes (same as STAT responses) + // So we need to know responses' size in advance. const id = stream.backend.decodeUtf8(await stream.read(4)) as AdbSyncResponseId; + const structReader = { + read: stream.read.bind(stream), + decodeUtf8: stream.backend.decodeUtf8.bind(stream.backend), + }; switch (id) { case AdbSyncResponseId.Entry: - return AdbSyncEntryResponse.parse(stream); + return AdbSyncEntryResponse.parse(structReader); + case AdbSyncResponseId.Stat: + return AdbSyncStatResponse.parse(structReader); case AdbSyncResponseId.Data: - return AdbSyncDataResponse.parse(stream); + return AdbSyncDataResponse.parse(structReader); case AdbSyncResponseId.Done: - await stream.read(4); - return new AdbSyncDoneResponse(); + await stream.read(size); + return AdbSyncDoneResponse.instance; + case AdbSyncResponseId.Fail: + return AdbSyncFailResponse.parse(structReader); default: - throw new Error(''); + throw new Error('Unexpected response id'); } } @@ -175,14 +170,29 @@ export class AdbSync extends AutoDisposable { this.stream = new AdbBufferedStream(stream); } + public async lstat(path: string) { + await this.sendLock.wait(); + + try { + await this.write(AdbSyncStringRequest, { id: AdbSyncRequestId.Stat, value: path }); + const response = await parseResponse(this.stream, AdbSyncStatResponse.size); + if (response.id !== AdbSyncResponseId.Stat) { + throw new Error('Unexpected response id'); + } + return response; + } finally { + this.sendLock.notify(); + } + } + public async *iterate(path: string) { await this.sendLock.wait(); try { - await this.write(new AdbSyncStringRequest(AdbSyncRequestId.List, path)); + await this.write(AdbSyncStringRequest, { id: AdbSyncRequestId.List, value: path }); while (true) { - const response = await parseResponse(this.stream); + const response = await parseResponse(this.stream, AdbSyncEntryResponse.size); switch (response.id) { case AdbSyncResponseId.Entry: yield response; @@ -210,9 +220,9 @@ export class AdbSync extends AutoDisposable { await this.sendLock.wait(); try { - await this.write(new AdbSyncStringRequest(AdbSyncRequestId.Receive, path)); + await this.write(AdbSyncStringRequest, { id: AdbSyncRequestId.Receive, value: path }); while (true) { - const response = await parseResponse(this.stream); + const response = await parseResponse(this.stream, AdbSyncDataResponse.size); switch (response.id) { case AdbSyncResponseId.Data: yield response.data; @@ -233,7 +243,7 @@ export class AdbSync extends AutoDisposable { this.stream.close(); } - private write(request: AdbSyncRequestBase) { - return this.stream.write(request.toBuffer(this.stream.backend)); + private write>(type: T, value: StructInitType) { + return this.stream.write(type.toBuffer(value, this.stream.backend)); } } diff --git a/packages/adb/src/utils/index.ts b/packages/adb/src/utils/index.ts index dd33d06f..5d7d3c1f 100644 --- a/packages/adb/src/utils/index.ts +++ b/packages/adb/src/utils/index.ts @@ -1,3 +1,5 @@ export * from './auto-reset-event'; export * from './base64'; export * from './event-iterator'; +export * from './struct'; +export { default as Struct } from './struct'; diff --git a/packages/adb/src/utils/struct.ts b/packages/adb/src/utils/struct.ts new file mode 100644 index 00000000..d7f877ee --- /dev/null +++ b/packages/adb/src/utils/struct.ts @@ -0,0 +1,259 @@ +const enum StructFieldType { + Int32, + FixedLengthString, + LengthPrefixedBuffer, +} + +interface StructFieldBase { + type: StructFieldType; + + name: PropertyKey; +} + +interface StructInt32Field extends StructFieldBase { + type: StructFieldType.Int32; + + signed: boolean; +} + +interface StructFixedLengthStringField extends StructFieldBase { + type: StructFieldType.FixedLengthString; + + length: number; +} + +interface StructLengthPrefixedBufferField extends StructFieldBase { + type: StructFieldType.LengthPrefixedBuffer; + + lengthType: 'int32'; + + subType: 'buffer' | 'string'; +} + +type StructField = + StructInt32Field | + StructFixedLengthStringField | + StructLengthPrefixedBufferField; + +export interface StructReader { + decodeUtf8(buffer: ArrayBuffer): string; + + read(length: number): Promise; +} + +export interface StructWriter { + encodeUtf8(input: string): ArrayBuffer; +} + +type KeyOfType = { [K in keyof T]: T[K] extends U ? K : never }[keyof T]; + +export type StructValueType> = + T extends { parse(reader: StructReader): Promise } ? R : never; + +export type StructInitType> = + T extends { create(value: infer R): any } ? R : never; + +export default class Struct { + private littleEndian: boolean; + + private _size = 0; + public get size() { return this._size; } + + private fields: StructField[] = []; + + private _extra?: any; + + public constructor(littleEndian = false) { + this.littleEndian = littleEndian; + } + + private clone(): Struct { + const result = new Struct(this.littleEndian); + result.fields = this.fields.slice(); + result._size = this._size; + result._extra = this._extra; + return result; + } + + public int32(name: K): Struct< + T & { [KK in K]: number }, + T & { [KK in K]: number } + > { + const result = this.clone(); + result.fields.push({ type: StructFieldType.Int32, name, signed: true }); + result._size += 4; + return result; + } + + public uint32(name: K): Struct< + T & { [KK in K]: number }, + T & { [KK in K]: number } + > { + const result = this.clone(); + result.fields.push({ type: StructFieldType.Int32, name, signed: false }); + result._size += 4; + return result; + } + + public fixedLengthString( + name: K, + length: number, + _type?: U + ): Struct< + T & { [KK in K]: U }, + T & { [KK in K]: U } + > { + const result = this.clone(); + result.fields.push({ type: StructFieldType.FixedLengthString, name, length }); + result._size += 4; + return result; + } + + public lengthPrefixedBuffer( + name: K, + lengthType: 'int32', + ): Struct< + T & { [KK in K]: ArrayBuffer }, + T & { [KK in K]: ArrayBuffer } + > { + const result = this.clone(); + result.fields.push({ + type: StructFieldType.LengthPrefixedBuffer, + name, + lengthType, + subType: 'buffer' + }); + result._size += 4; + return result; + } + + public lengthPrefixedString( + name: K, + lengthType: 'int32', + _type?: U + ): Struct< + T & { [KK in K]: U }, + T & { [KK in K]: U } + > { + const result = this.clone(); + result.fields.push({ + type: StructFieldType.LengthPrefixedBuffer, + name, + lengthType, + subType: 'string', + }); + result._size += 4; + return result; + } + + public extra(value: U): Struct { + const result = this.clone(); + result._extra = { ...result._extra, value }; + return result; + } + + public create(value: TInit): T { + return { ...value, ...this._extra } as any; + } + + public async parse(reader: StructReader): Promise { + const result: any = {}; + let buffer: ArrayBuffer; + let view: DataView; + let length: number; + for (const field of this.fields) { + switch (field.type) { + case StructFieldType.Int32: + buffer = await reader.read(4); + view = new DataView(buffer); + if (field.signed) { + result[field.name] = view.getInt32(0, this.littleEndian); + } else { + result[field.name] = view.getUint32(0, this.littleEndian); + } + break; + case StructFieldType.FixedLengthString: + buffer = await reader.read(field.length); + result[field.name] = reader.decodeUtf8(buffer); + break; + case StructFieldType.LengthPrefixedBuffer: + switch (field.lengthType) { + case 'int32': + buffer = await reader.read(4); + view = new DataView(buffer); + length = view.getUint32(0, this.littleEndian); + break; + default: + throw new Error(); + } + buffer = await reader.read(length); + switch (field.subType) { + case 'buffer': + result[field.name] = buffer; + break; + case 'string': + result[field.name] = reader.decodeUtf8(buffer); + break; + } + break; + } + } + return { ...result, ...this._extra }; + } + + public toBuffer(init: TInit, writer: StructWriter): ArrayBuffer { + const value = this.create(init) as any; + + let size = this._size; + for (const field of this.fields) { + switch (field.type) { + case StructFieldType.FixedLengthString: + value[field.name] = writer.encodeUtf8(value[field.name]).slice(0, field.length); + break; + case StructFieldType.LengthPrefixedBuffer: + switch (field.subType) { + case 'string': + const buffer = writer.encodeUtf8(value[field.name]); + value[field.name] = buffer; + break; + } + size += value[field.name].byteLength; + break; + } + } + + const result = new Uint8Array(size); + const view = new DataView(result.buffer); + let offset = 0; + let buffer: ArrayBuffer; + let length: number; + for (const field of this.fields) { + switch (field.type) { + case StructFieldType.Int32: + if (field.signed) { + view.setInt32(offset, value[field.name], this.littleEndian); + } else { + view.setUint32(offset, value[field.name], this.littleEndian); + } + offset += 4; + break; + case StructFieldType.LengthPrefixedBuffer: + buffer = value[field.name]; + + length = buffer.byteLength; + view.setUint32(offset, length, this.littleEndian); + offset += 4; + + result.set(new Uint8Array(buffer), offset); + offset += buffer.byteLength; + break; + case StructFieldType.FixedLengthString: + buffer = value[field.name]; + result.set(new Uint8Array(buffer), offset); + offset += buffer.byteLength; + break; + } + } + return result; + } +} diff --git a/packages/adb/tsconfig.json b/packages/adb/tsconfig.json index a8d58164..fc6f450a 100644 --- a/packages/adb/tsconfig.json +++ b/packages/adb/tsconfig.json @@ -1,15 +1,12 @@ { - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "lib", // /* Redirect output structure to the directory. */ - "rootDir": "./src", // /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - }, - "include": [ - "src" - ], - "references": [ - { - "path": "../event/tsconfig.json" - } - ] + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "lib", // /* Redirect output structure to the directory. */ + "rootDir": "./src", // /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + }, + "references": [ + { + "path": "../event/tsconfig.json" + } + ] } diff --git a/packages/demo/README.md b/packages/demo/README.md index 3016cb34..36340bf3 100644 --- a/packages/demo/README.md +++ b/packages/demo/README.md @@ -2,22 +2,16 @@ ## Start -In `demo` folder: - -```sh -npm start -``` - -Or in root folder: +From root folder: ```sh npm run start:demo ``` -## Watch changes in `webadb` - -From another shell, run in root folder: +From this folder: ```sh -npm run build:watch +npm start ``` + +Then navigate to `http://localhost:9000`. diff --git a/packages/demo/package-lock.json b/packages/demo/package-lock.json index 430e5c6b..d1974d20 100644 --- a/packages/demo/package-lock.json +++ b/packages/demo/package-lock.json @@ -13,18 +13,27 @@ } }, "@fluentui/date-time-utilities": { - "version": "7.8.0", - "resolved": "https://registry.npmjs.org/@fluentui/date-time-utilities/-/date-time-utilities-7.8.0.tgz", - "integrity": "sha512-qzlTp3t+PghebJsLK9JwZr91qBRZ/fOml8TQCIjdtsEn4mH6/ciCwir7Fj8iOEkwwTC0iKsEr1jfsITtJKWSmA==", + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/@fluentui/date-time-utilities/-/date-time-utilities-7.8.1.tgz", + "integrity": "sha512-2FsR7scZ6yS9h7MEUAunpLLYpHp4z7+DVgGlIBlNeL7YD5Vl0msj4pn7zRd1pcGfvoQfkWz3+ju3rBBl4LV4wQ==", "requires": { - "@uifabric/set-version": "^7.0.22", + "@uifabric/set-version": "^7.0.23", + "tslib": "^1.10.0" + } + }, + "@fluentui/dom-utilities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@fluentui/dom-utilities/-/dom-utilities-1.1.1.tgz", + "integrity": "sha512-w40gi8fzCpwa7U8cONiuu8rszPStkVOL/weDf5pCbYEb1gdaV7MDPSNkgM6IV0Kz+k017noDgK9Fv4ru1Dwz1g==", + "requires": { + "@uifabric/set-version": "^7.0.23", "tslib": "^1.10.0" } }, "@fluentui/keyboard-key": { - "version": "0.2.11", - "resolved": "https://registry.npmjs.org/@fluentui/keyboard-key/-/keyboard-key-0.2.11.tgz", - "integrity": "sha512-4iG5vNlRD3PrLaMfDTimHNOP1x6V3Dad0fXOwtvBBMsfdySPE9zlY+G+0aqCFcgjymOriFOk0ANZVBpK7XrnTg==", + "version": "0.2.12", + "resolved": "https://registry.npmjs.org/@fluentui/keyboard-key/-/keyboard-key-0.2.12.tgz", + "integrity": "sha512-t3yIbbPKJubb22vQ/FIWwS9vFAzaPYzFxKWPHVWLtxs/P+5yL+LD3B16DRtYreWAdl9CZvEbos58ChLZ0KHwSQ==", "requires": { "tslib": "^1.10.0" } @@ -40,53 +49,53 @@ } }, "@fluentui/react-focus": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-focus/-/react-focus-7.16.0.tgz", - "integrity": "sha512-TwB4Av7ID70ejisDIGkCZGKOxlquSazr6W+9Jv1JQAvsBLuj5XOspFJH4/Igjniw1LeO9QmAvFZeh/XRShiObw==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@fluentui/react-focus/-/react-focus-7.16.5.tgz", + "integrity": "sha512-FlRqYSzkptXuKvsIiI9m1tf7g5pRcbu9S9rK6c8pHax/kDRsBuDRW2OajxjVYR36B6IyAgYjylWdk6zBJI5oSQ==", "requires": { - "@fluentui/keyboard-key": "^0.2.11", - "@uifabric/merge-styles": "^7.18.0", - "@uifabric/set-version": "^7.0.22", - "@uifabric/styling": "^7.16.0", - "@uifabric/utilities": "^7.31.0", + "@fluentui/keyboard-key": "^0.2.12", + "@uifabric/merge-styles": "^7.19.1", + "@uifabric/set-version": "^7.0.23", + "@uifabric/styling": "^7.16.5", + "@uifabric/utilities": "^7.32.2", "tslib": "^1.10.0" } }, "@fluentui/react-icons": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-0.3.0.tgz", - "integrity": "sha512-QDrIhLUpkxM5q5bFE4pkweJJsfaNswdfDoc+X6cmr22Dii+anDFTpOcePEJiTtILxdlEmH0968OcZ4BGZF/joQ==", + "version": "0.3.4", + "resolved": "https://registry.npmjs.org/@fluentui/react-icons/-/react-icons-0.3.4.tgz", + "integrity": "sha512-/6xyGL7EQVCn9TP1eV+VjKS0HuC7WGZHs0t604E40LEE1HCIbXx7Jm1KDlMqP36n1W8XVDgyEZlffTmEOVGRkg==", "requires": { "@microsoft/load-themed-styles": "^1.10.26", - "@uifabric/set-version": "^7.0.22", - "@uifabric/utilities": "^7.31.0", + "@uifabric/set-version": "^7.0.23", + "@uifabric/utilities": "^7.32.2", "tslib": "^1.10.0" } }, "@fluentui/react-window-provider": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@fluentui/react-window-provider/-/react-window-provider-0.3.0.tgz", - "integrity": "sha512-zHeH1PAmoFB3OkgU8f51E3oGHrL/CjuvdPBlb1SGpByUGNihAgH/CwvJohV9z0yPDkq+chfNUmxWA/oDVpbh6Q==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@fluentui/react-window-provider/-/react-window-provider-0.3.3.tgz", + "integrity": "sha512-MVPf2hqOQ17LAZsuvGcr3oOHksAskUm+fCYdXFhbVoAgsCDVTIuH6i8XgHFd6YjBtzjZmI4+k/3NTQfDqBX8EQ==", "requires": { - "@uifabric/set-version": "^7.0.22", + "@uifabric/set-version": "^7.0.23", "tslib": "^1.10.0" } }, "@fluentui/theme": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@fluentui/theme/-/theme-0.2.0.tgz", - "integrity": "sha512-L5OwqymTdxTVwBa3ifkQLF1A3YU6WMkMTk6PFIMfOonjt8LJ3yMMqZgz+KQR3sF/tzgy4wzW4oBmrxtTfJS2EQ==", + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@fluentui/theme/-/theme-0.3.2.tgz", + "integrity": "sha512-Yt4VK2NKTc+Sao0+ZguXiQ0ZpN74h+7c+7YAyxaao2R/nwSHSnmH42VVlzBN+aL5kYDrbQ4P9Z8zPIwKEZ1u3A==", "requires": { - "@uifabric/merge-styles": "^7.18.0", - "@uifabric/set-version": "^7.0.22", - "@uifabric/utilities": "^7.31.0", + "@uifabric/merge-styles": "^7.19.1", + "@uifabric/set-version": "^7.0.23", + "@uifabric/utilities": "^7.32.2", "tslib": "^1.10.0" } }, "@microsoft/load-themed-styles": { - "version": "1.10.86", - "resolved": "https://registry.npmjs.org/@microsoft/load-themed-styles/-/load-themed-styles-1.10.86.tgz", - "integrity": "sha512-4C6EelO32Li6qVGO+Bna3glNSyT9iDcatYinvFyGLoCboGyMBdBVgyJC2uyF+31n3++Q7Htt6CAZmdd8JxKjjQ==" + "version": "1.10.93", + "resolved": "https://registry.npmjs.org/@microsoft/load-themed-styles/-/load-themed-styles-1.10.93.tgz", + "integrity": "sha512-iziiQyDJmyP8QE33hYjuVsj18RvtzRMdON1QLDkJSrs9xisXWgEjK8U12UsEkBYpYXzxPxqq5+X+fK8Vs6g8vQ==" }, "@nodelib/fs.scandir": { "version": "2.1.3", @@ -140,9 +149,9 @@ } }, "@types/history": { - "version": "4.7.7", - "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.7.tgz", - "integrity": "sha512-2xtoL22/3Mv6a70i4+4RB7VgbDDORoWwjcqeNysojZA0R7NK17RbY5Gof/2QiFfJgX+KkWghbwJ+d/2SB8Ndzg==", + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.8.tgz", + "integrity": "sha512-S78QIYirQcUoo6UJZx9CSP0O2ix9IaeAXwQi26Rhr/+mg7qqPy8TzaxHSUut7eGjL8WmLccT7/MXf304WjqHcA==", "dev": true }, "@types/html-minifier-terser": { @@ -164,9 +173,9 @@ "dev": true }, "@types/node": { - "version": "14.6.4", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.4.tgz", - "integrity": "sha512-Wk7nG1JSaMfMpoMJDKUsWYugliB2Vy55pdjLpmLixeyMi7HizW2I/9QoxsPCkXl3dO+ZOVqPumKaDUv5zJu2uQ==", + "version": "14.11.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.11.1.tgz", + "integrity": "sha512-oTQgnd0hblfLsJ6BvJzzSL+Inogp3lq9fGgqRkMB/ziKMgEUaFl801OncOzUmalfzt14N0oPHMK47ipl+wbTIw==", "dev": true }, "@types/prop-types": { @@ -280,33 +289,33 @@ } }, "@uifabric/foundation": { - "version": "7.9.0", - "resolved": "https://registry.npmjs.org/@uifabric/foundation/-/foundation-7.9.0.tgz", - "integrity": "sha512-4gdPwx0HV59aWvPKIw6yIje60CYwJZmTJsdLRXqh8Np1tWp2EsbA8U/IHQL1V91rEN0DlQhASqCDFhfQoD1jUw==", + "version": "7.9.5", + "resolved": "https://registry.npmjs.org/@uifabric/foundation/-/foundation-7.9.5.tgz", + "integrity": "sha512-r4KjYJAjSRgBGqeJXGKogYgzJS55/zcxmU3Gsps0BCMP8SCn55KZ31KiMYmjxoNnJAlGnhIq+h5zUEVRhpHN/Q==", "requires": { - "@uifabric/merge-styles": "^7.18.0", - "@uifabric/set-version": "^7.0.22", - "@uifabric/styling": "^7.16.0", - "@uifabric/utilities": "^7.31.0", + "@uifabric/merge-styles": "^7.19.1", + "@uifabric/set-version": "^7.0.23", + "@uifabric/styling": "^7.16.5", + "@uifabric/utilities": "^7.32.2", "tslib": "^1.10.0" } }, "@uifabric/icons": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/@uifabric/icons/-/icons-7.5.0.tgz", - "integrity": "sha512-RINA9VkajlCnlwEBbqiwLBaaGn38Bf9UvjOuwrrja4B9lclLeQzZuGrG/kp7CnDtIO+LC19OYl/7E3jW7yIihA==", + "version": "7.5.5", + "resolved": "https://registry.npmjs.org/@uifabric/icons/-/icons-7.5.5.tgz", + "integrity": "sha512-lErlirRm3D4Lv63oxa/JFx+JUyHRX/pqNoolLQKlPKqNauHFcrcEEDRuZdtfSOJtF/1a09ZvIyirij3XwZjNBw==", "requires": { - "@uifabric/set-version": "^7.0.22", - "@uifabric/styling": "^7.16.0", + "@uifabric/set-version": "^7.0.23", + "@uifabric/styling": "^7.16.5", "tslib": "^1.10.0" } }, "@uifabric/merge-styles": { - "version": "7.18.0", - "resolved": "https://registry.npmjs.org/@uifabric/merge-styles/-/merge-styles-7.18.0.tgz", - "integrity": "sha512-805WIbN7lAJATXKxZjjRbIgN7raRMwWYWeDkJJ52PCPuCesOvbpdr0GkH8rC6GQ7EB0MB7YM2i6Fiye7SFewbw==", + "version": "7.19.1", + "resolved": "https://registry.npmjs.org/@uifabric/merge-styles/-/merge-styles-7.19.1.tgz", + "integrity": "sha512-yqUwmk62Kgu216QNPE9vOfS3h0kiSbTvoqM5QcZi+IzpqsBOlzZx3A9Er9UiDaqHRd5lsYF5pO/jeUULmBWF/A==", "requires": { - "@uifabric/set-version": "^7.0.22", + "@uifabric/set-version": "^7.0.23", "tslib": "^1.10.0" } }, @@ -322,33 +331,34 @@ } }, "@uifabric/set-version": { - "version": "7.0.22", - "resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.22.tgz", - "integrity": "sha512-IG35UNJNxqI7NC2eYuobGTD+v4W0VHQcC3bYd5Na9EgoC9jVgguS8n6EXUtP/lC1vJEYEyPEZdVwhPxKw4F4Sw==", + "version": "7.0.23", + "resolved": "https://registry.npmjs.org/@uifabric/set-version/-/set-version-7.0.23.tgz", + "integrity": "sha512-9E+YKtnH2kyMKnK9XZZsqyM8OCxEJIIfxtaThTlQpYOzrWAGJxQADFbZ7+Usi0U2xHnWNPFROjq+B9ocEzhqMA==", "requires": { "tslib": "^1.10.0" } }, "@uifabric/styling": { - "version": "7.16.0", - "resolved": "https://registry.npmjs.org/@uifabric/styling/-/styling-7.16.0.tgz", - "integrity": "sha512-yO404ws8Wl4fjBwG4T58TFJjeU/K+SpWJ4w+WeNMDlJcYe4zXaWn2lbOJtKtQiMl324RAEjFSOuNkXzPb0uOGQ==", + "version": "7.16.5", + "resolved": "https://registry.npmjs.org/@uifabric/styling/-/styling-7.16.5.tgz", + "integrity": "sha512-mJcPam0ivtGfC8NEUQgpJFs8uG4ZRY1ml1RY9rOY6py5pTEno15xaq11yfRxv3ACxkuK9D9qZM23x0q8sWsCdg==", "requires": { - "@fluentui/theme": "^0.2.0", + "@fluentui/theme": "^0.3.2", "@microsoft/load-themed-styles": "^1.10.26", - "@uifabric/merge-styles": "^7.18.0", - "@uifabric/set-version": "^7.0.22", - "@uifabric/utilities": "^7.31.0", + "@uifabric/merge-styles": "^7.19.1", + "@uifabric/set-version": "^7.0.23", + "@uifabric/utilities": "^7.32.2", "tslib": "^1.10.0" } }, "@uifabric/utilities": { - "version": "7.31.0", - "resolved": "https://registry.npmjs.org/@uifabric/utilities/-/utilities-7.31.0.tgz", - "integrity": "sha512-m4Yeyn4gyW7xS8LvOnCesokPModYS2YuE9GQmO++MDZ/vC5RRNlvlyktUZDuxCZ84cNCiXyTQ8nImBaPGnxHVQ==", + "version": "7.32.2", + "resolved": "https://registry.npmjs.org/@uifabric/utilities/-/utilities-7.32.2.tgz", + "integrity": "sha512-x47zJIjezkfed17EfNRTr9wP6hHR+i0pBbr3eQYetpcVsAXcbZsd+D6divwy+kQOsdLQ8TozWqoVk3ySe6RfSw==", "requires": { - "@uifabric/merge-styles": "^7.18.0", - "@uifabric/set-version": "^7.0.22", + "@fluentui/dom-utilities": "^1.1.1", + "@uifabric/merge-styles": "^7.19.1", + "@uifabric/set-version": "^7.0.23", "prop-types": "^15.7.2", "tslib": "^1.10.0" } @@ -541,9 +551,9 @@ "dev": true }, "abab": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.4.tgz", - "integrity": "sha512-Eu9ELJWCz/c1e9gTiCY+FceWxcqzjYEbqMgtndnuSqZSUCOL73TWNK2mHfIj4Cw2E/ongOp+JISVNCmovt2KYQ==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz", + "integrity": "sha512-9IK9EadsbHo6jLWIpxpR6pL0sazTXV6+SQv25ZB+F7Bj9mJNaOc4nCRabwd5M/JwmUa8idz6Eci6eKfJryPs6Q==", "dev": true }, "accepts": { @@ -579,9 +589,9 @@ } }, "ajv": { - "version": "6.12.4", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.4.tgz", - "integrity": "sha512-eienB2c9qVQs2KWexhkrdMLVDoIQCz5KSeLxwg9Lzk4DOfBtIK9PQwwufcsn1jjGuf9WZmqPMbGxOzfcuphJCQ==", + "version": "6.12.5", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.5.tgz", + "integrity": "sha512-lRF8RORchjpKG50/WFf8xmg7sgCLFiYNNnqdKflk63whMQcWR5ngGjiSXkL9bjxy6B2npOK2HSMN49jEBMSkag==", "dev": true, "requires": { "fast-deep-equal": "^3.1.1", @@ -1951,9 +1961,9 @@ }, "dependencies": { "domelementtype": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz", - "integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==", + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.2.tgz", + "integrity": "sha512-wFwTwCVebUrMgGeAwRL/NhZtHAUyT9n9yg4IMDwf10+6iCMxSkVq9MGCVEH+QZWo1nNidy8kNvwmv4zWHDTqvA==", "dev": true } } @@ -3668,9 +3678,9 @@ "dev": true }, "is-callable": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.0.tgz", - "integrity": "sha512-pyVD9AaGLxtg6srb2Ng6ynWJqkHU9bEM087AKck0w8QwDarTfNcpIYoU8x8Hv2Icm8u6kFJM18Dag8lyqGkviw==", + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.1.tgz", + "integrity": "sha512-wliAfSzx6V+6WfMOmus1xy0XvSgf/dlStkvTfq7F0g4bOIW0PSUbnyse3NhDwdyYS1ozfUtAAySqTws3z9Eqgg==", "dev": true }, "is-data-descriptor": { @@ -3745,6 +3755,12 @@ "is-extglob": "^2.1.1" } }, + "is-negative-zero": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.0.tgz", + "integrity": "sha1-lVOxIbD6wohp2p7UWeIMdUN4hGE=", + "dev": true + }, "is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", @@ -4279,12 +4295,6 @@ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true }, - "moment": { - "version": "2.28.0", - "resolved": "https://registry.npmjs.org/moment/-/moment-2.28.0.tgz", - "integrity": "sha512-Z5KOjYmnHyd/ukynmFd/WwyXHd7L4J9vTI/nn5Ap9AVUgaAE15VvQ9MOGmJJygEUklupqIrFnor/tjTwRU+tQw==", - "dev": true - }, "move-concurrently": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz", @@ -4380,9 +4390,9 @@ } }, "node-forge": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.9.0.tgz", - "integrity": "sha512-7ASaDa3pD+lJ3WvXFsxekJQelBKRpne+GOVbLbtHYdd7pFspyeuJHnWfLplGf3SwKGbfs/aYl5V/JCIaHVUKKQ==", + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz", + "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==", "dev": true }, "node-libs-browser": { @@ -4566,15 +4576,37 @@ } }, "object.assign": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", - "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.1.tgz", + "integrity": "sha512-VT/cxmx5yaoHSOTSyrCygIDFco+RsibY2NM0a4RdEeY/4KgqezwFtK1yr3U67xYhqJSlASm2pKhLVzPj2lr4bA==", "dev": true, "requires": { - "define-properties": "^1.1.2", - "function-bind": "^1.1.1", - "has-symbols": "^1.0.0", - "object-keys": "^1.0.11" + "define-properties": "^1.1.3", + "es-abstract": "^1.18.0-next.0", + "has-symbols": "^1.0.1", + "object-keys": "^1.1.1" + }, + "dependencies": { + "es-abstract": { + "version": "1.18.0-next.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.0-next.0.tgz", + "integrity": "sha512-elZXTZXKn51hUBdJjSZGYRujuzilgXo8vSPQzjGYXLvSlGiCo8VO8ZGV3kjo9a0WNJJ57hENagwbtlRuHuzkcQ==", + "dev": true, + "requires": { + "es-to-primitive": "^1.2.1", + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-symbols": "^1.0.1", + "is-callable": "^1.2.0", + "is-negative-zero": "^2.0.0", + "is-regex": "^1.1.1", + "object-inspect": "^1.8.0", + "object-keys": "^1.1.1", + "object.assign": "^4.1.0", + "string.prototype.trimend": "^1.0.1", + "string.prototype.trimstart": "^1.0.1" + } + } } }, "object.getownpropertydescriptors": { @@ -4603,34 +4635,34 @@ "dev": true }, "office-ui-fabric-react": { - "version": "7.137.1", - "resolved": "https://registry.npmjs.org/office-ui-fabric-react/-/office-ui-fabric-react-7.137.1.tgz", - "integrity": "sha512-6m1M9m5psaJqhWwroVp1L0G8q66scLMsQRi+gQ/fY3f75ipGSABGeQ86d4P0ilKaYcLVYIzosocPIZKLbBVpnQ==", + "version": "7.138.0", + "resolved": "https://registry.npmjs.org/office-ui-fabric-react/-/office-ui-fabric-react-7.138.0.tgz", + "integrity": "sha512-HW4ugd+x7Jg96yBWxmUNMfkTS0U8RMwf5mGsHBAvW9s5l1ektjTjKnb5beHxNrddXKqcjz9ZThdTk/Gxds0jig==", "requires": { - "@fluentui/date-time-utilities": "^7.8.0", - "@fluentui/react-focus": "^7.16.0", - "@fluentui/react-icons": "^0.3.0", - "@fluentui/react-window-provider": "^0.3.0", + "@fluentui/date-time-utilities": "^7.8.1", + "@fluentui/react-focus": "^7.16.5", + "@fluentui/react-icons": "^0.3.4", + "@fluentui/react-window-provider": "^0.3.3", "@microsoft/load-themed-styles": "^1.10.26", - "@uifabric/foundation": "^7.9.0", - "@uifabric/icons": "^7.5.0", - "@uifabric/merge-styles": "^7.18.0", - "@uifabric/react-hooks": "^7.13.0", - "@uifabric/set-version": "^7.0.22", - "@uifabric/styling": "^7.16.0", - "@uifabric/utilities": "^7.31.0", + "@uifabric/foundation": "^7.9.5", + "@uifabric/icons": "^7.5.5", + "@uifabric/merge-styles": "^7.19.1", + "@uifabric/react-hooks": "^7.13.4", + "@uifabric/set-version": "^7.0.23", + "@uifabric/styling": "^7.16.5", + "@uifabric/utilities": "^7.32.2", "prop-types": "^15.7.2", "tslib": "^1.10.0" }, "dependencies": { "@uifabric/react-hooks": { - "version": "7.13.0", - "resolved": "https://registry.npmjs.org/@uifabric/react-hooks/-/react-hooks-7.13.0.tgz", - "integrity": "sha512-A7K0YFHHr10hB/txsqpPX6PhNhHEv8U7JpY3O81oqlZwSsHroJklQdd897JkAYJUUR+gWe2kQyXkkcaMDdqXjg==", + "version": "7.13.4", + "resolved": "https://registry.npmjs.org/@uifabric/react-hooks/-/react-hooks-7.13.4.tgz", + "integrity": "sha512-hyL3eQqbS7DrZCpkF1QDrC0TX+dV+yZZr5UgT3wAZMtzEMBFVgaiPHdv0zHgUbiQv5ktbQoY7yQp7clfVN65DA==", "requires": { - "@fluentui/react-window-provider": "^0.3.0", - "@uifabric/set-version": "^7.0.22", - "@uifabric/utilities": "^7.31.0", + "@fluentui/react-window-provider": "^0.3.3", + "@uifabric/set-version": "^7.0.23", + "@uifabric/utilities": "^7.32.2", "tslib": "^1.10.0" } } @@ -4995,9 +5027,9 @@ "dev": true }, "postcss": { - "version": "7.0.32", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.32.tgz", - "integrity": "sha512-03eXong5NLnNCD05xscnGKGDZ98CyzoqPSMjOe6SuoQY7Z2hIj0Ld1g/O/UQRuOle2aRtiIRDg9tDcTGAkLfKw==", + "version": "7.0.34", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.34.tgz", + "integrity": "sha512-H/7V2VeNScX9KE83GDrDZNiGT1m2H+UTnlinIzhjlLX9hfMUn1mHNnGeX81a1c8JSBdBvqk7c2ZOG6ZPn5itGw==", "dev": true, "requires": { "chalk": "^2.4.2", @@ -5573,12 +5605,12 @@ "dev": true }, "selfsigned": { - "version": "1.10.7", - "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.7.tgz", - "integrity": "sha512-8M3wBCzeWIJnQfl43IKwOmC4H/RAp50S8DF60znzjW5GVqTcSe2vWclt7hmYVPkKPlHWOu5EaWOMZ2Y6W8ZXTA==", + "version": "1.10.8", + "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.8.tgz", + "integrity": "sha512-2P4PtieJeEwVgTU9QEcwIRDQ/mXJLX8/+I3ur+Pg16nS8oNbrGxEso9NyYWy8NAmXiNl4dlAp5MwoNeCWzON4w==", "dev": true, "requires": { - "node-forge": "0.9.0" + "node-forge": "^0.10.0" } }, "semver": { @@ -7996,58 +8028,6 @@ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=", "dev": true }, - "write-file-atomic": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-2.4.3.tgz", - "integrity": "sha512-GaETH5wwsX+GcnzhPgKcKjJ6M2Cq3/iZp1WyY/X1CSqrW+jVNM9Y7D8EC2sM4ZG/V8wZlSniJnCKWPmBYAucRQ==", - "dev": true, - "requires": { - "graceful-fs": "^4.1.11", - "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.2" - } - }, - "write-file-webpack-plugin": { - "version": "4.5.1", - "resolved": "https://registry.npmjs.org/write-file-webpack-plugin/-/write-file-webpack-plugin-4.5.1.tgz", - "integrity": "sha512-AZ7qJUvhTCBiOtG21aFJUcNuLVo2FFM6JMGKvaUGAH+QDqQAp2iG0nq3GcuXmJOFQR2JjpjhyYkyPrbFKhdjNQ==", - "dev": true, - "requires": { - "chalk": "^2.4.0", - "debug": "^3.1.0", - "filesize": "^3.6.1", - "lodash": "^4.17.13", - "mkdirp": "^0.5.1", - "moment": "^2.22.1", - "write-file-atomic": "^2.3.0" - }, - "dependencies": { - "debug": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", - "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", - "dev": true, - "requires": { - "ms": "^2.1.1" - } - }, - "mkdirp": { - "version": "0.5.5", - "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz", - "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==", - "dev": true, - "requires": { - "minimist": "^1.2.5" - } - }, - "ms": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", - "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", - "dev": true - } - } - }, "ws": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz", diff --git a/packages/demo/package.json b/packages/demo/package.json index 472dbb36..10197120 100644 --- a/packages/demo/package.json +++ b/packages/demo/package.json @@ -11,7 +11,7 @@ "url": "git+https://github.com/yume-chan/ya-webadb.git" }, "scripts": { - "start": "webpack-dev-server", + "start": "webpack-dev-server --info-verbosity verbose", "build": "webpack --mode production", "build:dev": "webpack" }, @@ -33,8 +33,7 @@ "webpack": "4.44.1", "webpack-bundle-analyzer": "3.9.0", "webpack-cli": "3.3.12", - "webpack-dev-server": "3.11.0", - "write-file-webpack-plugin": "4.5.1" + "webpack-dev-server": "3.11.0" }, "dependencies": { "@fluentui/react": "7.137.1", diff --git a/packages/demo/src/routes/file-manager.tsx b/packages/demo/src/routes/file-manager.tsx index c1dc58eb..2a098b8b 100644 --- a/packages/demo/src/routes/file-manager.tsx +++ b/packages/demo/src/routes/file-manager.tsx @@ -138,13 +138,15 @@ export default withDisplayName('FileManager', ({ setLoading(true); const sync = await device.sync(); - let items: ListItem[] = []; + const items: ListItem[] = []; + const linkItems: AdbSyncEntryResponse[] = []; const intervalId = setInterval(() => { setItems(items.slice()); }, 1000); try { let lastBreak = Date.now(); + for await (const entry of sync.iterate(currentPath)) { if (currentPath !== currentPathRef.current) { break; @@ -154,7 +156,11 @@ export default withDisplayName('FileManager', ({ continue; } - items.push(toListItem(entry)); + if (entry.type === LinuxFileType.Link) { + linkItems.push(entry); + } else { + items.push(toListItem(entry)); + } const now = Date.now(); if (now - lastBreak > 16) { @@ -163,6 +169,24 @@ export default withDisplayName('FileManager', ({ } } + for (const entry of linkItems) { + try { + const followLinkPath = path.resolve(currentPath, entry.name) + '/'; + console.log(followLinkPath); + await sync.lstat(followLinkPath); + items.push(toListItem(entry)); + console.log(entry); + } catch (e) { + console.log(e); + items.push(toListItem(new AdbSyncEntryResponse( + (LinuxFileType.File << 12) | entry.mode, + 0, + entry.lastModifiedTime, + entry.name + ))); + } + } + setItems(items); listRef.current?.scrollToIndex(0); } finally { @@ -258,7 +282,7 @@ export default withDisplayName('FileManager', ({ minWidth: 0, onRender(item: AdbSyncEntryResponse) { if (item.type === LinuxFileType.File) { - return formatSize(item.logicalSize); + return formatSize(item.size); } return ''; } @@ -345,7 +369,7 @@ export default withDisplayName('FileManager', ({ let contextMenuItems: IContextualMenuItem[] = []; - if (selectedItems.length === 0 && + if (selectedItems.length === 1 && selectedItems[0].type === LinuxFileType.File) { contextMenuItems.push({ key: 'download', @@ -361,6 +385,8 @@ export default withDisplayName('FileManager', ({ size: selectedItems[0].size, }); await readableStream.pipeTo(writeableStream); + } catch (e) { + showErrorDialog(e.message); } finally { sync.dispose(); } diff --git a/packages/demo/tsconfig.json b/packages/demo/tsconfig.json index 197607e6..7732697d 100644 --- a/packages/demo/tsconfig.json +++ b/packages/demo/tsconfig.json @@ -1,17 +1,13 @@ { "extends": "../../tsconfig.base.json", "compilerOptions": { - "outDir": "lib", // /* Redirect output structure to the directory. */ "rootDir": "./src", // /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ "lib": [ "ESNext", "DOM" ], - "jsx": "react" // /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ + "jsx": "react", // /* Specify JSX code generation: 'preserve', 'react-native', or 'react'. */ }, - "include": [ - "src" - ], "references": [ { "path": "../adb-backend-web/tsconfig.json" diff --git a/packages/demo/webpack.config.js b/packages/demo/webpack.config.js index 023e7a89..41897f0e 100644 --- a/packages/demo/webpack.config.js +++ b/packages/demo/webpack.config.js @@ -6,7 +6,6 @@ const html_webpack_plugin_1 = tslib_1.__importDefault(require("html-webpack-plug const mini_css_extract_plugin_1 = tslib_1.__importDefault(require("mini-css-extract-plugin")); const path_1 = tslib_1.__importDefault(require("path")); const webpack_bundle_analyzer_1 = require("webpack-bundle-analyzer"); -const write_file_webpack_plugin_1 = tslib_1.__importDefault(require("write-file-webpack-plugin")); const context = path_1.default.resolve(process.cwd()); const plugins = [ new clean_webpack_plugin_1.CleanWebpackPlugin(), @@ -27,7 +26,6 @@ const plugins = [ template: 'www/index.html', scriptLoading: 'defer', }), - new write_file_webpack_plugin_1.default(), ]; if (process.env.ANALYZE) { plugins.push(new webpack_bundle_analyzer_1.BundleAnalyzerPlugin()); @@ -69,7 +67,12 @@ const config = (env, argv) => ({ }, devServer: { contentBase: path_1.default.resolve(context, 'lib'), - port: 9000 + port: 9000, + watchOptions: { + ignored: [ + /.(js|d.ts|map|tsbuildinfo|css|html)/ + ] + } }, }); module.exports = config; diff --git a/packages/event/tsconfig.json b/packages/event/tsconfig.json index 24c2f66f..f7135645 100644 --- a/packages/event/tsconfig.json +++ b/packages/event/tsconfig.json @@ -1,10 +1,7 @@ { - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "outDir": "lib", // /* Redirect output structure to the directory. */ - "rootDir": "./src", // /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - }, - "include": [ - "src" - ] + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "outDir": "lib", // /* Redirect output structure to the directory. */ + "rootDir": "./src" // /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + } } diff --git a/packages/webpack-config/package-lock.json b/packages/webpack-config/package-lock.json index 1563adfa..3fb599d8 100644 --- a/packages/webpack-config/package-lock.json +++ b/packages/webpack-config/package-lock.json @@ -161,9 +161,9 @@ "dev": true }, "@types/qs": { - "version": "6.9.4", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.4.tgz", - "integrity": "sha512-+wYo+L6ZF6BMoEjtf8zB2esQsqdV6WsjRK/GP9WOgLPrq87PbNWgIxS76dS5uvl/QXtHGakZmwTznIfcPXcKlQ==", + "version": "6.9.5", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.5.tgz", + "integrity": "sha512-/JHkVHtx/REVG0VVToGRGH2+23hsYLHdyG+GrvoUGlGAd0ErauXDyvHtRI/7H7mzLm+tBCKA7pfcpkQ1lf58iQ==", "dev": true }, "@types/range-parser": { @@ -264,15 +264,6 @@ } } }, - "@types/write-file-webpack-plugin": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/@types/write-file-webpack-plugin/-/write-file-webpack-plugin-4.5.0.tgz", - "integrity": "sha512-uTUXNNhuE+mJ0BjQD3W9bIOYnmAsLumgLy6ktSHVsFwvr4g+g/KhxSSLf31/KlsSVKovfaLVaUw49ZR0SPVlXw==", - "dev": true, - "requires": { - "@types/webpack": "*" - } - }, "array-union": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", diff --git a/packages/webpack-config/package.json b/packages/webpack-config/package.json index f696dee1..52a11d22 100644 --- a/packages/webpack-config/package.json +++ b/packages/webpack-config/package.json @@ -24,7 +24,6 @@ "@types/webpack": "4.41.22", "@types/webpack-bundle-analyzer": "3.8.0", "@types/webpack-dev-server": "3.11.0", - "@types/write-file-webpack-plugin": "4.5.0", "clean-webpack-plugin": "3.0.0", "typescript": "4.0.2" } diff --git a/packages/webpack-config/src/webpack.config.ts b/packages/webpack-config/src/webpack.config.ts index 997ffa10..fadbf7f3 100644 --- a/packages/webpack-config/src/webpack.config.ts +++ b/packages/webpack-config/src/webpack.config.ts @@ -3,9 +3,8 @@ import CopyPlugin from 'copy-webpack-plugin'; import HtmlWebpackPlugin from 'html-webpack-plugin'; import MiniCssExtractPlugin from 'mini-css-extract-plugin'; import path from 'path'; -import type webpack from 'webpack'; +import webpack from 'webpack'; import { BundleAnalyzerPlugin } from 'webpack-bundle-analyzer'; -import WriteFileWebpackPlugin from 'write-file-webpack-plugin'; const context = path.resolve(process.cwd()); @@ -28,7 +27,6 @@ const plugins: webpack.Plugin[] = [ template: 'www/index.html', scriptLoading: 'defer', }), - new WriteFileWebpackPlugin(), ]; if (process.env.ANALYZE) { @@ -75,7 +73,7 @@ const config: webpack.ConfigurationFactory = ( }, devServer: { contentBase: path.resolve(context, 'lib'), - port: 9000 + port: 9000, }, }); diff --git a/packages/webpack-config/tsconfig.json b/packages/webpack-config/tsconfig.json index dcaaa01d..623e6c47 100644 --- a/packages/webpack-config/tsconfig.json +++ b/packages/webpack-config/tsconfig.json @@ -1,19 +1,19 @@ { - "extends": "../../tsconfig.base.json", - "compilerOptions": { - "module": "CommonJS", // /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ - "lib": [ // /* Specify library files to be included in the compilation. */ - "ESNext" - ], - "declaration": false, // /* Generates corresponding '.d.ts' file. */ - "declarationMap": false, // /* Generates a sourcemap for each corresponding '.d.ts' file. */ - "sourceMap": false, // /* Generates corresponding '.map' file. */ - "outDir": "../demo", // /* Redirect output structure to the directory. */ - "rootDir": "./src", // /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ - "composite": false, // /* Enable project compilation */ - "tsBuildInfoFile": "./tsconfig.tsbuildinfo", ///* Specify file to store incremental compilation information */ - }, - "include": [ - "src" - ] + "extends": "../../tsconfig.base.json", + "compilerOptions": { + "module": "CommonJS", // /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', or 'ESNext'. */ + "lib": [ // /* Specify library files to be included in the compilation. */ + "ESNext" + ], + "declaration": false, // /* Generates corresponding '.d.ts' file. */ + "declarationMap": false, // /* Generates a sourcemap for each corresponding '.d.ts' file. */ + "sourceMap": false, // /* Generates corresponding '.map' file. */ + "outDir": "../demo", // /* Redirect output structure to the directory. */ + "rootDir": "./src", // /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + "composite": false, // /* Enable project compilation */ + "tsBuildInfoFile": "./tsconfig.tsbuildinfo", /* Specify file to store incremental compilation information */ + }, + "include": [ + "src" + ] } diff --git a/tsconfig.base.json b/tsconfig.base.json index 4dce0fca..cf963d1c 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -14,14 +14,14 @@ "declarationMap": true, // /* Generates a sourcemap for each corresponding '.d.ts' file. */ "sourceMap": true, // /* Generates corresponding '.map' file. */ // "outFile": "lib/index.js", // /* Concatenate and emit output to single file. */ - "outDir": "lib", // /* Redirect output structure to the directory. */ - "rootDir": "./src", // /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ + // "outDir": "lib", /* Redirect output structure to the directory. */ + // "rootDir": "./src", // /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */ "composite": true, // /* Enable project compilation */ // "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */ // "removeComments": true, /* Do not emit comments to output. */ // "noEmit": true, /* Do not emit outputs. */ "importHelpers": true, // /* Import emit helpers from 'tslib'. */ - "downlevelIteration": true, // /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ + // "downlevelIteration": true, // /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */ // "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */ /* Strict Type-Checking Options */ "strict": true, // /* Enable all strict type-checking options. */