├── .clang-format ├── .github ├── FUNDING.yml └── ISSUE_TEMPLATE │ ├── bug_report.md │ └── feature_request.md ├── .gitignore ├── .vscode ├── launch.json ├── settings.json └── tasks.json ├── LICENSE ├── README.md ├── binding.gyp ├── docs ├── breaking-changes.md ├── monitor.md ├── rectangle.md ├── window-manager.md └── window.md ├── example.js ├── lib ├── macos.mm └── windows.cc ├── package.json ├── src ├── classes │ ├── empty-monitor.ts │ ├── monitor.ts │ └── window.ts ├── index.ts └── interfaces │ └── index.ts ├── tsconfig.json ├── tslint.json └── yarn.lock /.clang-format: -------------------------------------------------------------------------------- 1 | AccessModifierOffset: 0 2 | AlignEscapedNewlinesLeft: true 3 | AlignTrailingComments: false 4 | AllowAllParametersOfDeclarationOnNextLine: false 5 | AllowShortFunctionsOnASingleLine: false 6 | AllowShortIfStatementsOnASingleLine: true 7 | AllowShortLoopsOnASingleLine: false 8 | AlwaysBreakBeforeMultilineStrings: false 9 | AlwaysBreakTemplateDeclarations: false 10 | BinPackParameters: false 11 | BreakBeforeBinaryOperators: false 12 | BreakBeforeBraces: Attach 13 | BreakBeforeTernaryOperators: false 14 | BreakConstructorInitializersBeforeComma: false 15 | ColumnLimit: 100 16 | CommentPragmas: '' 17 | ConstructorInitializerAllOnOneLineOrOnePerLine: false 18 | ConstructorInitializerIndentWidth: 0 19 | ContinuationIndentWidth: 0 20 | Cpp11BracedListStyle: false 21 | DerivePointerBinding: false 22 | IndentCaseLabels: false 23 | IndentFunctionDeclarationAfterType: false 24 | IndentWidth: 4 25 | Language: Cpp 26 | MaxEmptyLinesToKeep: 2 27 | NamespaceIndentation: None 28 | ObjCSpaceAfterProperty: true 29 | ObjCSpaceBeforeProtocolList: true 30 | PenaltyBreakBeforeFirstCallParameter: 100 31 | PenaltyBreakComment: 100 32 | PenaltyBreakFirstLessLess: 0 33 | PenaltyBreakString: 100 34 | PenaltyExcessCharacter: 1 35 | PenaltyReturnTypeOnItsOwnLine: 20 36 | PointerBindsToType: true 37 | SpaceBeforeAssignmentOperators: true 38 | SpaceBeforeParens: Always 39 | SpaceInEmptyParentheses: false 40 | SpacesBeforeTrailingComments: 1 41 | SpacesInAngles: false 42 | SpacesInCStyleCastParentheses: false 43 | SpacesInContainerLiterals: false 44 | SpacesInParentheses: false 45 | Standard: Cpp11 46 | TabWidth: 4 47 | UseTab: Never -------------------------------------------------------------------------------- /.github/FUNDING.yml: -------------------------------------------------------------------------------- 1 | # These are supported funding model platforms 2 | 3 | github: sentialx 4 | patreon: sentialx 5 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug_report.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug report 3 | about: Create a report to help us improve 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Bug description** 11 | 12 | 13 | **To Reproduce** 14 | 15 | 16 | **Expected behavior** 17 | 18 | 19 | **Screenshots** 20 | 21 | 22 | **Details:** 23 | - Operating System: 24 | - `node-window-manager` version: 25 | - Last known working `node-window-manager` version: 26 | 27 | **Additional context** 28 | 29 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature_request.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature request 3 | about: Suggest an idea for this project 4 | title: '' 5 | labels: '' 6 | assignees: '' 7 | 8 | --- 9 | 10 | **Is your feature request related to a problem? Please describe.** 11 | 12 | 13 | **Describe the solution you'd like** 14 | 15 | 16 | **Describe alternatives you've considered** 17 | 18 | 19 | **Additional context** 20 | 21 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | *.log* 3 | build 4 | dist 5 | .vscode/ipch 6 | .vscode/c_cpp_properties.json 7 | .build 8 | macos 9 | prebuilds -------------------------------------------------------------------------------- /.vscode/launch.json: -------------------------------------------------------------------------------- 1 | { 2 | // Use IntelliSense to learn about possible attributes. 3 | // Hover to view descriptions of existing attributes. 4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 5 | "version": "0.2.0", 6 | "configurations": [ 7 | { 8 | "type": "lldb", 9 | "request": "launch", 10 | "name": "Debug", 11 | "program": "C://nodejs/node.exe", 12 | "preLaunchTask": "npm: prepublishOnly-dev", 13 | "args": ".//example.js", 14 | "env": { 15 | "NODE_ENV": "dev" 16 | }, 17 | "cwd": "${workspaceFolder}" 18 | } 19 | ] 20 | } -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.associations": { 3 | "xiosbase": "cpp", 4 | "iosfwd": "cpp", 5 | "*.rh": "cpp", 6 | "algorithm": "cpp", 7 | "cmath": "cpp", 8 | "cstddef": "cpp", 9 | "cstdint": "cpp", 10 | "cstdio": "cpp", 11 | "cstdlib": "cpp", 12 | "cstring": "cpp", 13 | "cwchar": "cpp", 14 | "deque": "cpp", 15 | "exception": "cpp", 16 | "fstream": "cpp", 17 | "initializer_list": "cpp", 18 | "ios": "cpp", 19 | "iostream": "cpp", 20 | "istream": "cpp", 21 | "limits": "cpp", 22 | "memory": "cpp", 23 | "new": "cpp", 24 | "ostream": "cpp", 25 | "queue": "cpp", 26 | "stdexcept": "cpp", 27 | "streambuf": "cpp", 28 | "string": "cpp", 29 | "system_error": "cpp", 30 | "tuple": "cpp", 31 | "type_traits": "cpp", 32 | "typeinfo": "cpp", 33 | "utility": "cpp", 34 | "vector": "cpp", 35 | "xfacet": "cpp", 36 | "xlocale": "cpp", 37 | "xlocinfo": "cpp", 38 | "xlocnum": "cpp", 39 | "xmemory": "cpp", 40 | "xmemory0": "cpp", 41 | "xstddef": "cpp", 42 | "xstring": "cpp", 43 | "xtr1common": "cpp", 44 | "xutility": "cpp", 45 | "functional": "cpp", 46 | "list": "cpp", 47 | "unordered_map": "cpp", 48 | "xhash": "cpp", 49 | "map": "cpp", 50 | "xtree": "cpp", 51 | "chrono": "cpp", 52 | "cstdarg": "cpp", 53 | "mutex": "cpp", 54 | "ratio": "cpp", 55 | "thread": "cpp" 56 | } 57 | } 58 | -------------------------------------------------------------------------------- /.vscode/tasks.json: -------------------------------------------------------------------------------- 1 | { 2 | // See https://go.microsoft.com/fwlink/?LinkId=733558 3 | // for the documentation about the tasks.json format 4 | "version": "2.0.0", 5 | "tasks": [ 6 | { 7 | "type": "npm", 8 | "script": "build", 9 | "problemMatcher": [] 10 | }, 11 | { 12 | "type": "npm", 13 | "script": "rebuild", 14 | "problemMatcher": [] 15 | }, 16 | { 17 | "type": "npm", 18 | "script": "prepublishOnly", 19 | "problemMatcher": [], 20 | "group": { 21 | "kind": "build", 22 | "isDefault": true 23 | }, 24 | }, 25 | ] 26 | } -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 Eryk Rakowski 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # node-window-manager 2 | 3 | Manage windows in Windows, macOS and ~~Linux~~(WIP) 4 | 5 | # Install 6 | 7 | To install this package, just run 8 | 9 | ```bash 10 | $ npm install node-window-manager 11 | ``` 12 | 13 | # Quick start 14 | 15 | The following example shows how to get the currently focused window's title and hide it. 16 | 17 | ```javascript 18 | const { windowManager } = require("node-window-manager"); 19 | 20 | const window = windowManager.getActiveWindow(); 21 | 22 | // Prints the currently focused window bounds. 23 | console.log(window.getBounds()); 24 | 25 | // This method has to be called on macOS before changing the window's bounds, otherwise it will throw an error. 26 | // It will prompt an accessibility permission request dialog, if needed. 27 | windowManager.requestAccessibility(); 28 | 29 | // Sets the active window's bounds. 30 | window.setBounds({ x: 0, y: 0 }); 31 | ``` 32 | 33 | # Documentation 34 | 35 | The documentation and API references are located in the [`docs`](docs) directory. 36 | -------------------------------------------------------------------------------- /binding.gyp: -------------------------------------------------------------------------------- 1 | { 2 | "targets": [ 3 | { 4 | "target_name": "addon", 5 | "cflags!": [ "-fno-exceptions" ], 6 | "cflags_cc!": [ "-fno-exceptions" ], 7 | "conditions":[ 8 | ["OS=='win'", { 9 | "sources": [ "lib/windows.cc" ] 10 | }], 11 | ["OS=='mac'", { 12 | "sources": [ "lib/macos.mm" ], 13 | "libraries": [ '-framework AppKit', '-framework ApplicationServices' ] 14 | }] 15 | ], 16 | "include_dirs": [ 17 | " NOTE: Monitors are supported only on `Windows`, but on `macOS` there's a stub object 6 | called `EmptyMonitor` for better cross-platform compatibility without checking whether 7 | a returned monitor is `undefined`. 8 | 9 | ```typescript 10 | import { windowManager } from 'node-window-manager'; 11 | 12 | // Gets height of the primary window working area. 13 | const { height } = windowManager.getPrimaryWindow().getWorkArea(); 14 | ``` 15 | 16 | ### new Monitor(id: number) 17 | 18 | - `id` number - the monitor handle 19 | 20 | ### Instance properties 21 | 22 | - `id` number 23 | 24 | ### Instance methods 25 | 26 | #### monitor.getBounds() `Windows` 27 | 28 | > NOTE: on macOS this method returns `{x: 0, y: 0, width: 0, height: 0}` for compatibility. 29 | 30 | - Returns [`Rectangle`](rectangle.md) 31 | 32 | #### monitor.getWorkArea() `Windows` 33 | 34 | > NOTE: on macOS this method returns `{x: 0, y: 0, width: 0, height: 0}` for compatibility. 35 | 36 | Gets monitor working area bounds. 37 | 38 | Returns [`Rectangle`](rectangle.md) 39 | 40 | #### monitor.isPrimary() `Windows` 41 | 42 | > NOTE: on macOS this method returns `false` for compatibility. 43 | 44 | Whether the monitor is primary. 45 | 46 | Returns `boolean` 47 | 48 | #### monitor.getScaleFactor() `Windows` 49 | 50 | > NOTE: on macOS this method returns `1` for compatibility. 51 | 52 | Gets monitor scale factor (DPI). 53 | 54 | - Returns `number` 55 | 56 | #### monitor.isValid() `Windows` `macOS` 57 | 58 | Returns: 59 | - On `Windows`: `true` 60 | - On `macOS`: `false`, since it's just an `EmptyMonitor` object. 61 | -------------------------------------------------------------------------------- /docs/rectangle.md: -------------------------------------------------------------------------------- 1 | ## Object `Rectangle` 2 | 3 | - `x` number 4 | - `y` number 5 | - `width` number 6 | - `height` number -------------------------------------------------------------------------------- /docs/window-manager.md: -------------------------------------------------------------------------------- 1 | ## `windowManager` 2 | 3 | Get monitors and opened windows. 4 | 5 | ```typescript 6 | import { windowManager } from 'node-window-manager'; 7 | 8 | windowManager.requestAccessibility(); 9 | 10 | const window = windowManager.getActiveWindow(); 11 | 12 | // Prints the currently focused window title. 13 | console.log(window.getTitle()); 14 | ``` 15 | 16 | ### Instance methods 17 | 18 | #### windowManager.requestAccessibility() `macOS` 19 | 20 | If the accessibility permission is not granted on `macOS`, it opens an accessibility permission request dialog. 21 | 22 | The method is required to call before calling the following methods: 23 | 24 | - `window.setBounds` 25 | - `window.maximize` 26 | - `window.minimize` 27 | - `window.restore` 28 | - `window.bringToTop` 29 | - `window.getTitle` 30 | 31 | Returns `boolean` 32 | 33 | #### windowManager.getActiveWindow() `Windows` `macOS` 34 | 35 | Returns [`Window`](window.md) 36 | 37 | #### windowManager.getWindows() `Windows` `macOS` 38 | 39 | Returns [`Window[]`](window.md) 40 | 41 | #### windowManager.getMonitors() `Windows` 42 | 43 | > NOTE: on macOS this method returns `[]` for compatibility. 44 | 45 | - Returns [`Monitor[]`](monitor.md) 46 | 47 | #### windowManager.getPrimaryMonitor() `Windows` 48 | 49 | > NOTE: on macOS this method returns an `EmptyMonitor` object for compatibility. 50 | 51 | - Returns [`Monitor`](monitor.md) 52 | 53 | ### Events 54 | 55 | #### Event 'window-activated' `Windows` `macOS` 56 | 57 | Returns: 58 | 59 | - [`Window`](window.md) 60 | 61 | Emitted when a window has been activated. 62 | -------------------------------------------------------------------------------- /docs/window.md: -------------------------------------------------------------------------------- 1 | ## Class `Window` 2 | 3 | Control open windows. 4 | 5 | We try to keep this class similar to Electron's known [`BrowserWindow`](https://electronjs.org/docs/api/browser-window) class, to keep it simple to use. 6 | 7 | ### new Window(id: number) 8 | 9 | - `id` number 10 | 11 | ### Instance properties 12 | 13 | - `id` number 14 | - `processId` number - process id associated with the window 15 | - `path` string - path to executable associated with the window 16 | 17 | ### Instance methods 18 | 19 | #### win.getBounds() `Windows` `macOS` 20 | 21 | Returns [`Rectangle`](#object-rectangle) 22 | 23 | #### win.setBounds(bounds: Rectangle) `Windows` `macOS` 24 | 25 | Resizes and moves the window to the supplied bounds. Any properties that are not supplied will default to their current values. 26 | 27 | ```javascript 28 | window.setBounds({ height: 50 }); 29 | ``` 30 | 31 | #### win.getTitle() `Windows` `macOS` 32 | 33 | Returns `string` 34 | 35 | #### win.show() `Windows` 36 | 37 | Shows the window. 38 | 39 | #### win.hide() `Windows` 40 | 41 | Hides the window. 42 | 43 | #### win.minimize() `Windows` `macOS` 44 | 45 | Minimizes the window. 46 | 47 | #### win.restore() `Windows` `macOS` 48 | 49 | Restores the window. 50 | 51 | #### win.maximize() `Windows` `macOS` 52 | 53 | Maximizes the window. 54 | 55 | #### win.bringToTop() `Windows` `macOS` 56 | 57 | Brings the window to top and focuses it. 58 | 59 | #### win.setOpacity(opacity: number) `Windows` 60 | 61 | - `opacity` - a value between 0 and 1. 62 | 63 | Sets the window opacity. 64 | 65 | #### win.getOpacity() `Windows` 66 | 67 | Gets the window opacity 68 | 69 | Returns `number` between 0 and 1. 70 | 71 | #### win.getMonitor() `Windows` 72 | 73 | > NOTE: on macOS this method returns an `EmptyMonitor` object for compatibility. 74 | 75 | Gets monitor which the window belongs to. 76 | 77 | Returns [`Monitor`](monitor.md) 78 | 79 | #### win.isWindow() `Windows` `macOS` 80 | 81 | Returns `boolean` - whether the window is a valid window. 82 | 83 | #### win.isVisible() `Windows` 84 | Returns `boolean` - whether the window is visible or not. 85 | 86 | #### win.getOwner() `Windows` 87 | 88 | Returns `Window` 89 | 90 | #### win.setOwner(win: Window | number | null) `Windows` 91 | 92 | - `win` Window | number | null 93 | - pass null to unset window owner. 94 | 95 | #### win.getIcon(size: number) `Windows` `macOS` 96 | 97 | - `size` number - can be `16`, `32`, `64` or `256`. By default it's `64`. 98 | 99 | Returns a png Buffer 100 | -------------------------------------------------------------------------------- /example.js: -------------------------------------------------------------------------------- 1 | const { windowManager } = require("./dist/index"); 2 | 3 | console.log(windowManager.requestAccessibility()); // required on macOS 4 | 5 | const window = windowManager.getActiveWindow(); 6 | console.log(window.getTitle()); 7 | 8 | const bounds = window.getBounds(); 9 | console.log(bounds); 10 | 11 | window.setBounds({ x: 0, y: 0 }); 12 | window.maximize(); 13 | 14 | setTimeout(() => { 15 | window.setBounds(bounds); 16 | }, 1000); 17 | 18 | console.log("Windows list"); 19 | windowManager.getWindows().forEach((window) => { 20 | if (window.isVisible()) { 21 | console.log(window.getTitle(), window.path); 22 | } 23 | }); 24 | 25 | windowManager.on("window-activated", (window) => { 26 | console.log(window.path); 27 | }); 28 | 29 | console.log("Monitors list"); 30 | windowManager.getMonitors().forEach((monitor) => { 31 | console.log(monitor.getWorkArea()); 32 | }); 33 | -------------------------------------------------------------------------------- /lib/macos.mm: -------------------------------------------------------------------------------- 1 | #import 2 | #import 3 | #import 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | 10 | extern "C" AXError _AXUIElementGetWindow(AXUIElementRef, CGWindowID* out); 11 | 12 | // CGWindowID to AXUIElementRef windows map 13 | std::map windowsMap; 14 | 15 | bool _requestAccessibility(bool showDialog) { 16 | NSDictionary* opts = @{static_cast (kAXTrustedCheckOptionPrompt): showDialog ? @YES : @NO}; 17 | return AXIsProcessTrustedWithOptions(static_cast (opts)); 18 | } 19 | 20 | Napi::Boolean requestAccessibility(const Napi::CallbackInfo &info) { 21 | Napi::Env env{info.Env()}; 22 | return Napi::Boolean::New(env, _requestAccessibility(true)); 23 | } 24 | 25 | NSDictionary* getWindowInfo(int handle) { 26 | CGWindowListOption listOptions = kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements; 27 | CFArrayRef windowList = CGWindowListCopyWindowInfo(listOptions, kCGNullWindowID); 28 | 29 | for (NSDictionary *info in (NSArray *)windowList) { 30 | NSNumber *windowNumber = info[(id)kCGWindowNumber]; 31 | 32 | if ([windowNumber intValue] == handle) { 33 | // Retain property list so it doesn't get release w. windowList 34 | CFRetain((CFPropertyListRef)info); 35 | CFRelease(windowList); 36 | return info; 37 | } 38 | } 39 | 40 | if (windowList) { 41 | CFRelease(windowList); 42 | } 43 | return NULL; 44 | } 45 | 46 | AXUIElementRef getAXWindow(int pid, int handle) { 47 | auto app = AXUIElementCreateApplication(pid); 48 | 49 | CFArrayRef windows; 50 | AXUIElementCopyAttributeValues(app, kAXWindowsAttribute, 0, 100, &windows); 51 | 52 | for (id child in (NSArray *)windows) { 53 | AXUIElementRef window = (AXUIElementRef) child; 54 | 55 | CGWindowID windowId; 56 | _AXUIElementGetWindow(window, &windowId); 57 | 58 | if (windowId == handle) { 59 | // Retain returned window so it doesn't get released with rest of list 60 | CFRetain(window); 61 | CFRelease(windows); 62 | return window; 63 | } 64 | } 65 | 66 | if (windows) { 67 | CFRelease(windows); 68 | } 69 | return NULL; 70 | } 71 | 72 | void cacheWindow(int handle, int pid) { 73 | if (_requestAccessibility(false)) { 74 | if (windowsMap.find(handle) == windowsMap.end()) { 75 | windowsMap[handle] = getAXWindow(pid, handle); 76 | } 77 | } 78 | } 79 | 80 | void cacheWindowByInfo(NSDictionary* info) { 81 | if (info) { 82 | NSNumber *ownerPid = info[(id)kCGWindowOwnerPID]; 83 | NSNumber *windowNumber = info[(id)kCGWindowNumber]; 84 | // Release dictionary info property since we're done with it 85 | CFRelease((CFPropertyListRef)info); 86 | cacheWindow([windowNumber intValue], [ownerPid intValue]); 87 | } 88 | } 89 | 90 | void findAndCacheWindow(int handle) { 91 | cacheWindowByInfo(getWindowInfo(handle)); 92 | } 93 | 94 | AXUIElementRef getAXWindowById(int handle) { 95 | auto win = windowsMap[handle]; 96 | 97 | if (!win) { 98 | findAndCacheWindow(handle); 99 | win = windowsMap[handle]; 100 | } 101 | 102 | return win; 103 | } 104 | 105 | Napi::Array getWindows(const Napi::CallbackInfo &info) { 106 | Napi::Env env{info.Env()}; 107 | 108 | CGWindowListOption listOptions = kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements; 109 | CFArrayRef windowList = CGWindowListCopyWindowInfo(listOptions, kCGNullWindowID); 110 | 111 | std::vector vec; 112 | 113 | for (NSDictionary *info in (NSArray *)windowList) { 114 | NSNumber *ownerPid = info[(id)kCGWindowOwnerPID]; 115 | NSNumber *windowNumber = info[(id)kCGWindowNumber]; 116 | 117 | auto app = [NSRunningApplication runningApplicationWithProcessIdentifier: [ownerPid intValue]]; 118 | auto path = app ? [app.bundleURL.path UTF8String] : ""; 119 | 120 | if (app && path != "") { 121 | vec.push_back(Napi::Number::New(env, [windowNumber intValue])); 122 | } 123 | } 124 | 125 | auto arr = Napi::Array::New(env, vec.size()); 126 | 127 | for (int i = 0; i < vec.size(); i++) { 128 | arr[i] = vec[i]; 129 | } 130 | 131 | if (windowList) { 132 | CFRelease(windowList); 133 | } 134 | 135 | return arr; 136 | } 137 | 138 | Napi::Number getActiveWindow(const Napi::CallbackInfo &info) { 139 | Napi::Env env{info.Env()}; 140 | 141 | CGWindowListOption listOptions = kCGWindowListOptionOnScreenOnly | kCGWindowListExcludeDesktopElements; 142 | CFArrayRef windowList = CGWindowListCopyWindowInfo(listOptions, kCGNullWindowID); 143 | 144 | for (NSDictionary *info in (NSArray *)windowList) { 145 | NSNumber *ownerPid = info[(id)kCGWindowOwnerPID]; 146 | NSNumber *windowNumber = info[(id)kCGWindowNumber]; 147 | 148 | auto app = [NSRunningApplication runningApplicationWithProcessIdentifier: [ownerPid intValue]]; 149 | 150 | if (![app isActive]) { 151 | continue; 152 | } 153 | 154 | CFRelease(windowList); 155 | return Napi::Number::New(env, [windowNumber intValue]); 156 | } 157 | 158 | if (windowList) { 159 | CFRelease(windowList); 160 | } 161 | return Napi::Number::New(env, 0); 162 | } 163 | 164 | Napi::Object initWindow(const Napi::CallbackInfo &info) { 165 | Napi::Env env{info.Env()}; 166 | 167 | int handle = info[0].As().Int32Value(); 168 | 169 | auto wInfo = getWindowInfo(handle); 170 | 171 | if (wInfo) { 172 | NSNumber *ownerPid = wInfo[(id)kCGWindowOwnerPID]; 173 | NSRunningApplication *app = [NSRunningApplication runningApplicationWithProcessIdentifier: [ownerPid intValue]]; 174 | 175 | auto obj = Napi::Object::New(env); 176 | obj.Set("processId", [ownerPid intValue]); 177 | obj.Set("path", [app.bundleURL.path UTF8String]); 178 | 179 | cacheWindow(handle, [ownerPid intValue]); 180 | 181 | return obj; 182 | } 183 | 184 | return Napi::Object::New(env); 185 | } 186 | 187 | Napi::String getWindowTitle(const Napi::CallbackInfo &info) { 188 | Napi::Env env{info.Env()}; 189 | 190 | int handle = info[0].As().Int32Value(); 191 | 192 | auto wInfo = getWindowInfo(handle); 193 | 194 | if (wInfo) { 195 | NSString *windowName = wInfo[(id)kCGWindowOwnerName]; 196 | return Napi::String::New(env, [windowName UTF8String]); 197 | } 198 | 199 | return Napi::String::New(env, ""); 200 | } 201 | 202 | Napi::Object getWindowBounds(const Napi::CallbackInfo &info) { 203 | Napi::Env env{info.Env()}; 204 | 205 | int handle = info[0].As().Int32Value(); 206 | 207 | auto wInfo = getWindowInfo(handle); 208 | 209 | if (wInfo) { 210 | CGRect bounds; 211 | CGRectMakeWithDictionaryRepresentation((CFDictionaryRef)wInfo[(id)kCGWindowBounds], &bounds); 212 | 213 | auto obj = Napi::Object::New(env); 214 | obj.Set("x", bounds.origin.x); 215 | obj.Set("y", bounds.origin.y); 216 | obj.Set("width", bounds.size.width); 217 | obj.Set("height", bounds.size.height); 218 | 219 | return obj; 220 | } 221 | 222 | return Napi::Object::New(env); 223 | } 224 | 225 | Napi::Boolean setWindowBounds(const Napi::CallbackInfo &info) { 226 | Napi::Env env{info.Env()}; 227 | 228 | auto handle = info[0].As().Int32Value(); 229 | auto bounds = info[1].As(); 230 | 231 | auto x = bounds.Get("x").As().DoubleValue(); 232 | auto y = bounds.Get("y").As().DoubleValue(); 233 | auto width = bounds.Get("width").As().DoubleValue(); 234 | auto height = bounds.Get("height").As().DoubleValue(); 235 | 236 | auto win = getAXWindowById(handle); 237 | 238 | if (win) { 239 | NSPoint point = NSMakePoint((CGFloat) x, (CGFloat) y); 240 | NSSize size = NSMakeSize((CGFloat) width, (CGFloat) height); 241 | 242 | CFTypeRef positionStorage = (CFTypeRef)(AXValueCreate((AXValueType)kAXValueCGPointType, (const void *)&point)); 243 | AXUIElementSetAttributeValue(win, kAXPositionAttribute, positionStorage); 244 | 245 | CFTypeRef sizeStorage = (CFTypeRef)(AXValueCreate((AXValueType)kAXValueCGSizeType, (const void *)&size)); 246 | AXUIElementSetAttributeValue(win, kAXSizeAttribute, sizeStorage); 247 | } 248 | 249 | return Napi::Boolean::New(env, true); 250 | } 251 | 252 | Napi::Boolean bringWindowToTop(const Napi::CallbackInfo &info) { 253 | Napi::Env env{info.Env()}; 254 | 255 | auto handle = info[0].As().Int32Value(); 256 | auto pid = info[1].As().Int32Value(); 257 | 258 | auto app = AXUIElementCreateApplication(pid); 259 | auto win = getAXWindowById(handle); 260 | 261 | AXUIElementSetAttributeValue(app, kAXFrontmostAttribute, kCFBooleanTrue); 262 | AXUIElementSetAttributeValue(win, kAXMainAttribute, kCFBooleanTrue); 263 | 264 | return Napi::Boolean::New(env, true); 265 | } 266 | 267 | Napi::Boolean setWindowMinimized(const Napi::CallbackInfo &info) { 268 | Napi::Env env{info.Env()}; 269 | 270 | auto handle = info[0].As().Int32Value(); 271 | auto toggle = info[1].As(); 272 | 273 | auto win = getAXWindowById(handle); 274 | 275 | if (win) { 276 | AXUIElementSetAttributeValue(win, kAXMinimizedAttribute, toggle ? kCFBooleanTrue : kCFBooleanFalse); 277 | } 278 | 279 | return Napi::Boolean::New(env, true); 280 | } 281 | 282 | Napi::Boolean setWindowMaximized(const Napi::CallbackInfo &info) { 283 | Napi::Env env{info.Env()}; 284 | auto handle = info[0].As().Int32Value(); 285 | auto win = getAXWindowById(handle); 286 | 287 | if(win) { 288 | NSRect screenSizeRect = [[NSScreen mainScreen] frame]; 289 | int screenWidth = screenSizeRect.size.width; 290 | int screenHeight = screenSizeRect.size.height; 291 | 292 | NSPoint point = NSMakePoint((CGFloat) 0, (CGFloat) 0); 293 | NSSize size = NSMakeSize((CGFloat) screenWidth, (CGFloat) screenHeight); 294 | 295 | CFTypeRef positionStorage = (CFTypeRef)(AXValueCreate((AXValueType)kAXValueCGPointType, (const void *)&point)); 296 | AXUIElementSetAttributeValue(win, kAXPositionAttribute, positionStorage); 297 | 298 | CFTypeRef sizeStorage = (CFTypeRef)(AXValueCreate((AXValueType)kAXValueCGSizeType, (const void *)&size)); 299 | AXUIElementSetAttributeValue(win, kAXSizeAttribute, sizeStorage); 300 | } 301 | 302 | return Napi::Boolean::New(env, true); 303 | } 304 | 305 | 306 | Napi::Object Init(Napi::Env env, Napi::Object exports) { 307 | exports.Set(Napi::String::New(env, "getWindows"), 308 | Napi::Function::New(env, getWindows)); 309 | exports.Set(Napi::String::New(env, "getActiveWindow"), 310 | Napi::Function::New(env, getActiveWindow)); 311 | exports.Set(Napi::String::New(env, "setWindowBounds"), 312 | Napi::Function::New(env, setWindowBounds)); 313 | exports.Set(Napi::String::New(env, "getWindowBounds"), 314 | Napi::Function::New(env, getWindowBounds)); 315 | exports.Set(Napi::String::New(env, "getWindowTitle"), 316 | Napi::Function::New(env, getWindowTitle)); 317 | exports.Set(Napi::String::New(env, "initWindow"), 318 | Napi::Function::New(env, initWindow)); 319 | exports.Set(Napi::String::New(env, "bringWindowToTop"), 320 | Napi::Function::New(env, bringWindowToTop)); 321 | exports.Set(Napi::String::New(env, "setWindowMinimized"), 322 | Napi::Function::New(env, setWindowMinimized)); 323 | exports.Set(Napi::String::New(env, "setWindowMaximized"), 324 | Napi::Function::New(env, setWindowMaximized)); 325 | exports.Set(Napi::String::New(env, "requestAccessibility"), 326 | Napi::Function::New(env, requestAccessibility)); 327 | 328 | return exports; 329 | } 330 | 331 | NODE_API_MODULE(addon, Init) 332 | -------------------------------------------------------------------------------- /lib/windows.cc: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | #include 8 | 9 | typedef int (__stdcall* lp_GetScaleFactorForMonitor) (HMONITOR, DEVICE_SCALE_FACTOR*); 10 | 11 | struct Process { 12 | int pid; 13 | std::string path; 14 | }; 15 | 16 | template 17 | T getValueFromCallbackData (const Napi::CallbackInfo& info, unsigned handleIndex) { 18 | return reinterpret_cast (info[handleIndex].As ().Int64Value ()); 19 | } 20 | 21 | std::wstring get_wstring (const std::string str) { 22 | return std::wstring (str.begin (), str.end ()); 23 | } 24 | 25 | std::string toUtf8 (const std::wstring& str) { 26 | std::string ret; 27 | int len = WideCharToMultiByte (CP_UTF8, 0, str.c_str (), str.length (), NULL, 0, NULL, NULL); 28 | if (len > 0) { 29 | ret.resize (len); 30 | WideCharToMultiByte (CP_UTF8, 0, str.c_str (), str.length (), &ret[0], len, NULL, NULL); 31 | } 32 | return ret; 33 | } 34 | 35 | Process getWindowProcess (HWND handle) { 36 | DWORD pid{ 0 }; 37 | GetWindowThreadProcessId (handle, &pid); 38 | 39 | HANDLE pHandle{ OpenProcess (PROCESS_QUERY_LIMITED_INFORMATION, false, pid) }; 40 | 41 | DWORD dwSize{ MAX_PATH }; 42 | wchar_t exeName[MAX_PATH]{}; 43 | 44 | QueryFullProcessImageNameW (pHandle, 0, exeName, &dwSize); 45 | 46 | CloseHandle(pHandle); 47 | 48 | auto wspath (exeName); 49 | auto path = toUtf8 (wspath); 50 | 51 | return { static_cast (pid), path }; 52 | } 53 | 54 | HWND find_top_window (DWORD pid) { 55 | std::pair params = { 0, pid }; 56 | 57 | BOOL bResult = EnumWindows ( 58 | [] (HWND hwnd, LPARAM lParam) -> BOOL { 59 | auto pParams = (std::pair*)(lParam); 60 | 61 | DWORD processId; 62 | if (GetWindowThreadProcessId (hwnd, &processId) && processId == pParams->second) { 63 | SetLastError (-1); 64 | pParams->first = hwnd; 65 | return FALSE; 66 | } 67 | 68 | return TRUE; 69 | }, 70 | (LPARAM)¶ms); 71 | 72 | if (!bResult && GetLastError () == -1 && params.first) { 73 | return params.first; 74 | } 75 | 76 | return 0; 77 | } 78 | 79 | Napi::Number getProcessMainWindow (const Napi::CallbackInfo& info) { 80 | Napi::Env env{ info.Env () }; 81 | 82 | unsigned long process_id = info[0].ToNumber ().Uint32Value (); 83 | 84 | auto handle = find_top_window (process_id); 85 | 86 | return Napi::Number::New (env, reinterpret_cast (handle)); 87 | } 88 | 89 | Napi::Number createProcess (const Napi::CallbackInfo& info) { 90 | Napi::Env env{ info.Env () }; 91 | 92 | auto path = info[0].ToString ().Utf8Value (); 93 | 94 | std::string cmd = ""; 95 | 96 | if (info[1].IsString ()) { 97 | cmd = info[1].ToString ().Utf8Value (); 98 | } 99 | 100 | STARTUPINFOA sInfo = { sizeof (sInfo) }; 101 | PROCESS_INFORMATION processInfo; 102 | CreateProcessA (path.c_str (), &cmd[0], NULL, NULL, FALSE, 103 | CREATE_NEW_PROCESS_GROUP | CREATE_NEW_CONSOLE, NULL, NULL, &sInfo, &processInfo); 104 | 105 | return Napi::Number::New (env, processInfo.dwProcessId); 106 | } 107 | 108 | Napi::Number getActiveWindow (const Napi::CallbackInfo& info) { 109 | Napi::Env env{ info.Env () }; 110 | 111 | auto handle = GetForegroundWindow (); 112 | 113 | return Napi::Number::New (env, reinterpret_cast (handle)); 114 | } 115 | 116 | std::vector _windows; 117 | 118 | BOOL CALLBACK EnumWindowsProc (HWND hwnd, LPARAM lparam) { 119 | _windows.push_back (reinterpret_cast (hwnd)); 120 | return TRUE; 121 | } 122 | 123 | Napi::Array getWindows (const Napi::CallbackInfo& info) { 124 | Napi::Env env{ info.Env () }; 125 | 126 | _windows.clear (); 127 | EnumWindows (&EnumWindowsProc, NULL); 128 | 129 | auto arr = Napi::Array::New (env); 130 | auto i = 0; 131 | for (auto _win : _windows) { 132 | arr.Set (i++, Napi::Number::New (env, _win)); 133 | } 134 | 135 | return arr; 136 | } 137 | 138 | std::vector _monitors; 139 | 140 | BOOL CALLBACK EnumMonitorsProc (HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { 141 | _monitors.push_back (reinterpret_cast (hMonitor)); 142 | return TRUE; 143 | } 144 | 145 | Napi::Array getMonitors (const Napi::CallbackInfo& info) { 146 | Napi::Env env{ info.Env () }; 147 | 148 | _monitors.clear (); 149 | if (EnumDisplayMonitors (NULL, NULL, &EnumMonitorsProc, NULL)) { 150 | auto arr = Napi::Array::New (env); 151 | auto i = 0; 152 | 153 | for (auto _mon : _monitors) { 154 | 155 | arr.Set (i++, Napi::Number::New (env, _mon)); 156 | } 157 | 158 | return arr; 159 | } 160 | 161 | return Napi::Array::New (env); 162 | } 163 | 164 | Napi::Number getMonitorFromWindow (const Napi::CallbackInfo& info) { 165 | Napi::Env env{ info.Env () }; 166 | 167 | auto handle = getValueFromCallbackData (info, 0); 168 | 169 | return Napi::Number::New (env, reinterpret_cast (MonitorFromWindow (handle, 0))); 170 | } 171 | 172 | Napi::Object initWindow (const Napi::CallbackInfo& info) { 173 | Napi::Env env{ info.Env () }; 174 | 175 | auto handle{ getValueFromCallbackData (info, 0) }; 176 | auto process = getWindowProcess (handle); 177 | 178 | Napi::Object obj{ Napi::Object::New (env) }; 179 | 180 | obj.Set ("processId", process.pid); 181 | obj.Set ("path", process.path); 182 | 183 | return obj; 184 | } 185 | 186 | Napi::Object getWindowBounds (const Napi::CallbackInfo& info) { 187 | Napi::Env env{ info.Env () }; 188 | 189 | auto handle{ getValueFromCallbackData (info, 0) }; 190 | 191 | RECT rect{}; 192 | GetWindowRect (handle, &rect); 193 | 194 | Napi::Object bounds{ Napi::Object::New (env) }; 195 | 196 | bounds.Set ("x", rect.left); 197 | bounds.Set ("y", rect.top); 198 | bounds.Set ("width", rect.right - rect.left); 199 | bounds.Set ("height", rect.bottom - rect.top); 200 | 201 | return bounds; 202 | } 203 | 204 | Napi::String getWindowTitle (const Napi::CallbackInfo& info) { 205 | Napi::Env env{ info.Env () }; 206 | 207 | auto handle{ getValueFromCallbackData (info, 0) }; 208 | 209 | int bufsize = GetWindowTextLengthW (handle) + 1; 210 | LPWSTR t = new WCHAR[bufsize]; 211 | GetWindowTextW (handle, t, bufsize); 212 | 213 | std::wstring ws (t); 214 | std::string title = toUtf8 (ws); 215 | 216 | return Napi::String::New (env, title); 217 | } 218 | 219 | Napi::Number getWindowOpacity (const Napi::CallbackInfo& info) { 220 | Napi::Env env{ info.Env () }; 221 | 222 | auto handle{ getValueFromCallbackData (info, 0) }; 223 | 224 | BYTE opacity{}; 225 | GetLayeredWindowAttributes (handle, NULL, &opacity, NULL); 226 | 227 | return Napi::Number::New (env, static_cast (opacity) / 255.); 228 | } 229 | 230 | Napi::Number getWindowOwner (const Napi::CallbackInfo& info) { 231 | Napi::Env env{ info.Env () }; 232 | 233 | auto handle{ getValueFromCallbackData (info, 0) }; 234 | 235 | return Napi::Number::New (env, GetWindowLongPtrA (handle, GWLP_HWNDPARENT)); 236 | } 237 | 238 | Napi::Number getMonitorScaleFactor (const Napi::CallbackInfo& info) { 239 | Napi::Env env{ info.Env () }; 240 | 241 | HMODULE hShcore{ LoadLibraryA ("SHcore.dll") }; 242 | lp_GetScaleFactorForMonitor f{ ( 243 | lp_GetScaleFactorForMonitor)GetProcAddress (hShcore, "GetScaleFactorForMonitor") }; 244 | 245 | DEVICE_SCALE_FACTOR sf{}; 246 | f (getValueFromCallbackData (info, 0), &sf); 247 | 248 | return Napi::Number::New (env, static_cast (sf) / 100.); 249 | } 250 | 251 | Napi::Boolean toggleWindowTransparency (const Napi::CallbackInfo& info) { 252 | Napi::Env env{ info.Env () }; 253 | 254 | auto handle{ getValueFromCallbackData (info, 0) }; 255 | bool toggle{ info[1].As () }; 256 | LONG_PTR style{ GetWindowLongPtrA (handle, GWL_EXSTYLE) }; 257 | 258 | SetWindowLongPtrA (handle, GWL_EXSTYLE, ((toggle) ? (style | WS_EX_LAYERED) : (style & (~WS_EX_LAYERED)))); 259 | 260 | return Napi::Boolean::New (env, true); 261 | } 262 | 263 | Napi::Boolean setWindowOpacity (const Napi::CallbackInfo& info) { 264 | Napi::Env env{ info.Env () }; 265 | 266 | auto handle{ getValueFromCallbackData (info, 0) }; 267 | double opacity{ info[1].As ().DoubleValue () }; 268 | 269 | SetLayeredWindowAttributes (handle, NULL, opacity * 255., LWA_ALPHA); 270 | 271 | return Napi::Boolean::New (env, true); 272 | } 273 | 274 | Napi::Boolean setWindowBounds (const Napi::CallbackInfo& info) { 275 | Napi::Env env{ info.Env () }; 276 | 277 | Napi::Object bounds{ info[1].As () }; 278 | auto handle{ getValueFromCallbackData (info, 0) }; 279 | 280 | BOOL b{ MoveWindow (handle, bounds.Get ("x").ToNumber (), bounds.Get ("y").ToNumber (), 281 | bounds.Get ("width").ToNumber (), bounds.Get ("height").ToNumber (), true) }; 282 | 283 | return Napi::Boolean::New (env, b); 284 | } 285 | 286 | Napi::Boolean setWindowOwner (const Napi::CallbackInfo& info) { 287 | Napi::Env env{ info.Env () }; 288 | 289 | auto handle{ getValueFromCallbackData (info, 0) }; 290 | auto newOwner{ static_cast (info[1].As ().Int64Value ()) }; 291 | 292 | SetWindowLongPtrA (handle, GWLP_HWNDPARENT, newOwner); 293 | 294 | return Napi::Boolean::New (env, true); 295 | } 296 | 297 | Napi::Boolean showWindow (const Napi::CallbackInfo& info) { 298 | Napi::Env env{ info.Env () }; 299 | 300 | auto handle{ getValueFromCallbackData (info, 0) }; 301 | std::string type{ info[1].As () }; 302 | 303 | DWORD flag{ 0 }; 304 | 305 | if (type == "show") 306 | flag = SW_SHOW; 307 | else if (type == "hide") 308 | flag = SW_HIDE; 309 | else if (type == "minimize") 310 | flag = SW_MINIMIZE; 311 | else if (type == "restore") 312 | flag = SW_RESTORE; 313 | else if (type == "maximize") 314 | flag = SW_MAXIMIZE; 315 | 316 | return Napi::Boolean::New (env, ShowWindow (handle, flag)); 317 | } 318 | 319 | Napi::Boolean bringWindowToTop (const Napi::CallbackInfo& info) { 320 | Napi::Env env{ info.Env () }; 321 | auto handle{ getValueFromCallbackData (info, 0) }; 322 | BOOL b{ SetForegroundWindow (handle) }; 323 | 324 | HWND hCurWnd = ::GetForegroundWindow (); 325 | DWORD dwMyID = ::GetCurrentThreadId (); 326 | DWORD dwCurID = ::GetWindowThreadProcessId (hCurWnd, NULL); 327 | ::AttachThreadInput (dwCurID, dwMyID, TRUE); 328 | ::SetWindowPos (handle, HWND_TOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); 329 | ::SetWindowPos (handle, HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOSIZE | SWP_NOMOVE); 330 | ::SetForegroundWindow (handle); 331 | ::AttachThreadInput (dwCurID, dwMyID, FALSE); 332 | ::SetFocus (handle); 333 | ::SetActiveWindow (handle); 334 | 335 | return Napi::Boolean::New (env, b); 336 | } 337 | 338 | Napi::Boolean redrawWindow (const Napi::CallbackInfo& info) { 339 | Napi::Env env{ info.Env () }; 340 | 341 | auto handle{ getValueFromCallbackData (info, 0) }; 342 | BOOL b{ SetWindowPos (handle, 0, 0, 0, 0, 0, 343 | SWP_FRAMECHANGED | SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | 344 | SWP_NOOWNERZORDER | SWP_NOACTIVATE | SWP_DRAWFRAME | SWP_NOCOPYBITS) }; 345 | 346 | return Napi::Boolean::New (env, b); 347 | } 348 | 349 | Napi::Boolean isWindow (const Napi::CallbackInfo& info) { 350 | Napi::Env env{ info.Env () }; 351 | 352 | auto handle{ getValueFromCallbackData (info, 0) }; 353 | 354 | return Napi::Boolean::New (env, IsWindow (handle)); 355 | } 356 | 357 | Napi::Boolean isWindowVisible (const Napi::CallbackInfo& info) { 358 | Napi::Env env{ info.Env () }; 359 | 360 | auto handle{ getValueFromCallbackData (info, 0) }; 361 | 362 | return Napi::Boolean::New (env, IsWindowVisible (handle)); 363 | } 364 | 365 | Napi::Object getMonitorInfo (const Napi::CallbackInfo& info) { 366 | Napi::Env env{ info.Env () }; 367 | 368 | auto handle{ getValueFromCallbackData (info, 0) }; 369 | 370 | MONITORINFO mInfo; 371 | mInfo.cbSize = sizeof (MONITORINFO); 372 | GetMonitorInfoA (handle, &mInfo); 373 | 374 | Napi::Object bounds{ Napi::Object::New (env) }; 375 | 376 | bounds.Set ("x", mInfo.rcMonitor.left); 377 | bounds.Set ("y", mInfo.rcMonitor.top); 378 | bounds.Set ("width", mInfo.rcMonitor.right - mInfo.rcMonitor.left); 379 | bounds.Set ("height", mInfo.rcMonitor.bottom - mInfo.rcMonitor.top); 380 | 381 | Napi::Object workArea{ Napi::Object::New (env) }; 382 | 383 | workArea.Set ("x", mInfo.rcWork.left); 384 | workArea.Set ("y", mInfo.rcWork.top); 385 | workArea.Set ("width", mInfo.rcWork.right - mInfo.rcWork.left); 386 | workArea.Set ("height", mInfo.rcWork.bottom - mInfo.rcWork.top); 387 | 388 | Napi::Object obj{ Napi::Object::New (env) }; 389 | 390 | obj.Set ("bounds", bounds); 391 | obj.Set ("workArea", workArea); 392 | obj.Set ("isPrimary", (mInfo.dwFlags & MONITORINFOF_PRIMARY) != 0); 393 | 394 | return obj; 395 | } 396 | 397 | Napi::Object Init (Napi::Env env, Napi::Object exports) { 398 | exports.Set (Napi::String::New (env, "getActiveWindow"), Napi::Function::New (env, getActiveWindow)); 399 | exports.Set (Napi::String::New (env, "getMonitorFromWindow"), Napi::Function::New (env, getMonitorFromWindow)); 400 | exports.Set (Napi::String::New (env, "getMonitorScaleFactor"), 401 | Napi::Function::New (env, getMonitorScaleFactor)); 402 | exports.Set (Napi::String::New (env, "setWindowBounds"), Napi::Function::New (env, setWindowBounds)); 403 | exports.Set (Napi::String::New (env, "showWindow"), Napi::Function::New (env, showWindow)); 404 | exports.Set (Napi::String::New (env, "bringWindowToTop"), Napi::Function::New (env, bringWindowToTop)); 405 | exports.Set (Napi::String::New (env, "redrawWindow"), Napi::Function::New (env, redrawWindow)); 406 | exports.Set (Napi::String::New (env, "isWindow"), Napi::Function::New (env, isWindow)); 407 | exports.Set (Napi::String::New (env, "isWindowVisible"), Napi::Function::New (env, isWindowVisible)); 408 | exports.Set (Napi::String::New (env, "setWindowOpacity"), Napi::Function::New (env, setWindowOpacity)); 409 | exports.Set (Napi::String::New (env, "toggleWindowTransparency"), 410 | Napi::Function::New (env, toggleWindowTransparency)); 411 | exports.Set (Napi::String::New (env, "setWindowOwner"), Napi::Function::New (env, setWindowOwner)); 412 | exports.Set (Napi::String::New (env, "initWindow"), Napi::Function::New (env, initWindow)); 413 | exports.Set (Napi::String::New (env, "getWindowBounds"), Napi::Function::New (env, getWindowBounds)); 414 | exports.Set (Napi::String::New (env, "getWindowTitle"), Napi::Function::New (env, getWindowTitle)); 415 | exports.Set (Napi::String::New (env, "getWindowOwner"), Napi::Function::New (env, getWindowOwner)); 416 | exports.Set (Napi::String::New (env, "getWindowOpacity"), Napi::Function::New (env, getWindowOpacity)); 417 | exports.Set (Napi::String::New (env, "getMonitorInfo"), Napi::Function::New (env, getMonitorInfo)); 418 | exports.Set (Napi::String::New (env, "getWindows"), Napi::Function::New (env, getWindows)); 419 | exports.Set (Napi::String::New (env, "getMonitors"), Napi::Function::New (env, getMonitors)); 420 | exports.Set (Napi::String::New (env, "createProcess"), Napi::Function::New (env, createProcess)); 421 | exports.Set (Napi::String::New (env, "getProcessMainWindow"), Napi::Function::New (env, getProcessMainWindow)); 422 | 423 | return exports; 424 | } 425 | 426 | NODE_API_MODULE (addon, Init) 427 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "node-window-manager", 3 | "version": "2.2.4", 4 | "description": "Manage windows in macOS, Windows and Linux", 5 | "main": "dist/index.js", 6 | "types": "dist/index.d.ts", 7 | "scripts": { 8 | "build": "tsc", 9 | "watch": "tsc --watch", 10 | "install": "npm run rebuild", 11 | "rebuild": "node-gyp rebuild", 12 | "rebuild-dev": "npm run rebuild -- --debug", 13 | "prepublishOnly": "npm run rebuild", 14 | "prepare": "npm run build" 15 | }, 16 | "repository": { 17 | "type": "git", 18 | "url": "git+https://github.com/sentialx/node-window-manager.git" 19 | }, 20 | "keywords": [ 21 | "window-manager", 22 | "native", 23 | "macos", 24 | "linux", 25 | "windows" 26 | ], 27 | "author": "sentialx", 28 | "license": "MIT", 29 | "bugs": { 30 | "url": "https://github.com/sentialx/node-window-manager/issues" 31 | }, 32 | "homepage": "https://github.com/sentialx/node-window-manager#readme", 33 | "devDependencies": { 34 | "@types/node": "13.11.1", 35 | "node-gyp": "^6.1.0", 36 | "tslint": "6.1.1", 37 | "typescript": "3.8.3" 38 | }, 39 | "dependencies": { 40 | "extract-file-icon": "^0.3.2", 41 | "node-addon-api": "2.0.0", 42 | "node-gyp-build": "^4.2.1" 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/classes/empty-monitor.ts: -------------------------------------------------------------------------------- 1 | import { IRectangle } from "../interfaces"; 2 | 3 | export class EmptyMonitor { 4 | getBounds(): IRectangle { 5 | return { x: 0, y: 0, width: 0, height: 0 }; 6 | } 7 | 8 | getWorkArea(): IRectangle { 9 | return { x: 0, y: 0, width: 0, height: 0 }; 10 | } 11 | 12 | isPrimary(): boolean { 13 | return false; 14 | } 15 | 16 | getScaleFactor(): number { 17 | return 1; 18 | }; 19 | 20 | isValid(): boolean { 21 | return false; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/classes/monitor.ts: -------------------------------------------------------------------------------- 1 | import { addon } from ".."; 2 | import { IMonitorInfo, IRectangle } from "../interfaces"; 3 | import { release } from "os"; 4 | 5 | const getMonitorInfo = (id: number): IMonitorInfo => { 6 | if (!addon || !addon.getMonitorInfo) return; 7 | return addon.getMonitorInfo(id); 8 | } 9 | 10 | export class Monitor { 11 | public id: number; 12 | 13 | constructor(id: number) { 14 | this.id = id; 15 | } 16 | 17 | getBounds(): IRectangle { 18 | return getMonitorInfo(this.id).bounds; 19 | } 20 | 21 | getWorkArea(): IRectangle { 22 | return getMonitorInfo(this.id).workArea; 23 | } 24 | 25 | isPrimary(): boolean { 26 | return getMonitorInfo(this.id).isPrimary; 27 | } 28 | 29 | getScaleFactor(): number { 30 | if (!addon || !addon.getMonitorScaleFactor) return; 31 | 32 | const numbers = release() 33 | .split(".") 34 | .map(d => parseInt(d, 10)); 35 | 36 | if (numbers[0] > 8 || (numbers[0] === 8 && numbers[1] >= 1)) { 37 | return addon.getMonitorScaleFactor(this.id); 38 | } 39 | 40 | return 1; 41 | }; 42 | 43 | isValid(): boolean { 44 | return addon && addon.getMonitorInfo; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /src/classes/window.ts: -------------------------------------------------------------------------------- 1 | import { addon } from ".."; 2 | import extractFileIcon from "extract-file-icon"; 3 | import { Monitor } from "./monitor"; 4 | import { IRectangle } from "../interfaces"; 5 | import { EmptyMonitor } from "./empty-monitor"; 6 | 7 | export class Window { 8 | public id: number; 9 | 10 | public processId: number; 11 | public path: string; 12 | 13 | constructor(id: number) { 14 | if (!addon) return; 15 | 16 | this.id = id; 17 | const { processId, path } = addon.initWindow(id); 18 | this.processId = processId; 19 | this.path = path; 20 | } 21 | 22 | getBounds(): IRectangle { 23 | if (!addon) return; 24 | 25 | const bounds = addon.getWindowBounds(this.id); 26 | 27 | if (process.platform === "win32") { 28 | const sf = this.getMonitor().getScaleFactor(); 29 | 30 | bounds.x = Math.floor(bounds.x / sf); 31 | bounds.y = Math.floor(bounds.y / sf); 32 | bounds.width = Math.floor(bounds.width / sf); 33 | bounds.height = Math.floor(bounds.height / sf); 34 | } 35 | 36 | return bounds; 37 | } 38 | 39 | setBounds(bounds: IRectangle) { 40 | if (!addon) return; 41 | 42 | const newBounds = { ...this.getBounds(), ...bounds }; 43 | 44 | if (process.platform === "win32") { 45 | const sf = this.getMonitor().getScaleFactor(); 46 | 47 | newBounds.x = Math.floor(newBounds.x * sf); 48 | newBounds.y = Math.floor(newBounds.y * sf); 49 | newBounds.width = Math.floor(newBounds.width * sf); 50 | newBounds.height = Math.floor(newBounds.height * sf); 51 | 52 | addon.setWindowBounds(this.id, newBounds); 53 | } else if (process.platform === "darwin") { 54 | addon.setWindowBounds(this.id, newBounds); 55 | } 56 | } 57 | 58 | getTitle(): string { 59 | if (!addon) return; 60 | return addon.getWindowTitle(this.id); 61 | } 62 | 63 | getMonitor(): Monitor | EmptyMonitor { 64 | if (!addon || !addon.getMonitorFromWindow) return new EmptyMonitor(); 65 | return new Monitor(addon.getMonitorFromWindow(this.id)); 66 | } 67 | 68 | show() { 69 | if (!addon || !addon.showWindow) return; 70 | addon.showWindow(this.id, "show"); 71 | } 72 | 73 | hide() { 74 | if (!addon || !addon.showWindow) return; 75 | addon.showWindow(this.id, "hide"); 76 | } 77 | 78 | minimize() { 79 | if (!addon) return; 80 | 81 | if (process.platform === "win32") { 82 | addon.showWindow(this.id, "minimize"); 83 | } else if (process.platform === "darwin") { 84 | addon.setWindowMinimized(this.id, true); 85 | } 86 | } 87 | 88 | restore() { 89 | if (!addon) return; 90 | 91 | if (process.platform === "win32") { 92 | addon.showWindow(this.id, "restore"); 93 | } else if (process.platform === "darwin") { 94 | addon.setWindowMinimized(this.id, false); 95 | } 96 | } 97 | 98 | maximize() { 99 | if (!addon) return; 100 | 101 | if (process.platform === "win32") { 102 | addon.showWindow(this.id, "maximize"); 103 | } else if (process.platform === "darwin") { 104 | addon.setWindowMaximized(this.id); 105 | } 106 | } 107 | 108 | bringToTop() { 109 | if (!addon) return; 110 | 111 | if (process.platform === "darwin") { 112 | addon.bringWindowToTop(this.id, this.processId); 113 | } else { 114 | addon.bringWindowToTop(this.id); 115 | } 116 | } 117 | 118 | redraw() { 119 | if (!addon || !addon.redrawWindow) return; 120 | addon.redrawWindow(this.id); 121 | } 122 | 123 | isWindow(): boolean { 124 | if (!addon) return; 125 | 126 | if (process.platform === "win32") { 127 | return this.path && this.path !== "" && addon.isWindow(this.id); 128 | } else if (process.platform === "darwin") { 129 | return this.path && this.path !== "" && !!addon.initWindow(this.id); 130 | } 131 | } 132 | 133 | isVisible(): boolean { 134 | if (!addon || !addon.isWindowVisible) return true; 135 | return addon.isWindowVisible(this.id); 136 | } 137 | 138 | toggleTransparency(toggle: boolean) { 139 | if (!addon || !addon.toggleWindowTransparency) return; 140 | addon.toggleWindowTransparency(this.id, toggle); 141 | } 142 | 143 | setOpacity(opacity: number) { 144 | if (!addon || !addon.setWindowOpacity) return; 145 | addon.setWindowOpacity(this.id, opacity); 146 | } 147 | 148 | getOpacity() { 149 | if (!addon || !addon.getWindowOpacity) return 1; 150 | return addon.getWindowOpacity(this.id); 151 | } 152 | 153 | getIcon(size: 16 | 32 | 64 | 256 = 64) { 154 | return extractFileIcon(this.path, size); 155 | } 156 | 157 | setOwner(window: Window | null | number) { 158 | if (!addon || !addon.setWindowOwner) return; 159 | 160 | let handle = window; 161 | 162 | if (window instanceof Window) { 163 | handle = window.id; 164 | } else if (!window) { 165 | handle = 0; 166 | } 167 | 168 | addon.setWindowOwner(this.id, handle); 169 | } 170 | 171 | getOwner() { 172 | if (!addon || !addon.getWindowOwner) return; 173 | return new Window(addon.getWindowOwner(this.id)); 174 | } 175 | } 176 | -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { Window } from "./classes/window"; 2 | import { EventEmitter } from "events"; 3 | import { platform } from "os"; 4 | import { Monitor } from "./classes/monitor"; 5 | import { EmptyMonitor } from "./classes/empty-monitor"; 6 | import { resolve } from 'path'; 7 | 8 | let addon: any; 9 | 10 | if (platform() === "win32" || platform() === "darwin") { 11 | const ADDON_PATH = (process.env.NODE_ENV != "dev") ? "Release" : "Debug"; 12 | addon = require(`node-gyp-build`)(resolve(__dirname, '..')); 13 | } 14 | 15 | let interval: any = null; 16 | 17 | let registeredEvents: string[] = []; 18 | 19 | class WindowManager extends EventEmitter { 20 | constructor() { 21 | super(); 22 | 23 | let lastId: number; 24 | 25 | if (!addon) return; 26 | 27 | this.on("newListener", event => { 28 | if (event === 'window-activated') { 29 | lastId = addon.getActiveWindow(); 30 | } 31 | 32 | if (registeredEvents.indexOf(event) !== -1) return; 33 | 34 | if (event === "window-activated") { 35 | interval = setInterval(async () => { 36 | const win = addon.getActiveWindow(); 37 | 38 | if (lastId !== win) { 39 | lastId = win; 40 | this.emit("window-activated", new Window(win)); 41 | } 42 | }, 50); 43 | } else { 44 | return; 45 | } 46 | 47 | registeredEvents.push(event); 48 | }); 49 | 50 | this.on("removeListener", event => { 51 | if (this.listenerCount(event) > 0) return; 52 | 53 | if (event === "window-activated") { 54 | clearInterval(interval); 55 | } 56 | 57 | registeredEvents = registeredEvents.filter(x => x !== event); 58 | }); 59 | } 60 | 61 | requestAccessibility = () => { 62 | if (!addon || !addon.requestAccessibility) return true; 63 | return addon.requestAccessibility(); 64 | } 65 | 66 | getActiveWindow = () => { 67 | if (!addon) return; 68 | return new Window(addon.getActiveWindow()); 69 | }; 70 | 71 | getWindows = (): Window[] => { 72 | if (!addon || !addon.getWindows) return []; 73 | return addon.getWindows().map((win: any) => new Window(win)).filter((x: Window) => x.isWindow()); 74 | }; 75 | 76 | getMonitors = (): Monitor[] => { 77 | if (!addon || !addon.getMonitors) return []; 78 | return addon.getMonitors().map((mon: any) => new Monitor(mon)); 79 | }; 80 | 81 | getPrimaryMonitor = (): Monitor | EmptyMonitor => { 82 | if (process.platform === 'win32') { 83 | return this.getMonitors().find(x => x.isPrimary); 84 | } else { 85 | return new EmptyMonitor(); 86 | } 87 | } 88 | 89 | createProcess = (path: string, cmd = ""): number => { 90 | if (!addon || !addon.createProcess) return; 91 | return addon.createProcess(path, cmd); 92 | }; 93 | } 94 | 95 | const windowManager = new WindowManager(); 96 | 97 | export { windowManager, Window, addon }; 98 | -------------------------------------------------------------------------------- /src/interfaces/index.ts: -------------------------------------------------------------------------------- 1 | export interface IRectangle { 2 | x?: number; 3 | y?: number; 4 | width?: number; 5 | height?: number; 6 | } 7 | 8 | export interface IMonitorInfo { 9 | id: number; 10 | bounds?: IRectangle; 11 | isPrimary?: boolean; 12 | workArea?: IRectangle; 13 | } 14 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "outDir": "./dist/", 4 | "typeRoots": ["./node_modules/@types"], 5 | "noImplicitAny": true, 6 | "module": "commonjs", 7 | "target": "es2015", 8 | "sourceMap": true, 9 | "moduleResolution": "node", 10 | "allowSyntheticDefaultImports": true, 11 | "esModuleInterop": true, 12 | "declaration": true, 13 | "types": ["node"] 14 | }, 15 | "include": ["./src/**/*.ts"], 16 | "exclude": ["node_modules/**/*"] 17 | } 18 | -------------------------------------------------------------------------------- /tslint.json: -------------------------------------------------------------------------------- 1 | { 2 | "extends": ["tslint-config-airbnb"], 3 | "rules": { 4 | "no-increment-decrement": false, 5 | "max-line-length": false, 6 | "variable-name": [ 7 | true, 8 | "ban-keywords", 9 | "check-format", 10 | "allow-pascal-case", 11 | "allow-leading-underscore" 12 | ], 13 | "import-name": false, 14 | "ter-arrow-parens": false, 15 | "no-parameter-reassignment": false, 16 | "object-shorthand-properties-first": false, 17 | "semicolon": false, 18 | "align": false, 19 | "no-this-assignment": false 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /yarn.lock: -------------------------------------------------------------------------------- 1 | # THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. 2 | # yarn lockfile v1 3 | 4 | 5 | "@babel/code-frame@^7.0.0": 6 | version "7.8.3" 7 | resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.8.3.tgz#33e25903d7481181534e12ec0a25f16b6fcf419e" 8 | integrity sha512-a9gxpmdXtZEInkCSHUJDLHZVBgb1QS0jhss4cPP93EW7s+uC5bikET2twEF3KV+7rDblJcmNvTR7VJejqd2C2g== 9 | dependencies: 10 | "@babel/highlight" "^7.8.3" 11 | 12 | "@babel/helper-validator-identifier@^7.9.0": 13 | version "7.9.5" 14 | resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.9.5.tgz#90977a8e6fbf6b431a7dc31752eee233bf052d80" 15 | integrity sha512-/8arLKUFq882w4tWGj9JYzRpAlZgiWUJ+dtteNTDqrRBz9Iguck9Rn3ykuBDoUwh2TO4tSAJlrxDUOXWklJe4g== 16 | 17 | "@babel/highlight@^7.8.3": 18 | version "7.9.0" 19 | resolved "https://registry.yarnpkg.com/@babel/highlight/-/highlight-7.9.0.tgz#4e9b45ccb82b79607271b2979ad82c7b68163079" 20 | integrity sha512-lJZPilxX7Op3Nv/2cvFdnlepPXDxi29wxteT57Q965oc5R9v86ztx0jfxVrTcBk8C2kcPkkDa2Z4T3ZsPPVWsQ== 21 | dependencies: 22 | "@babel/helper-validator-identifier" "^7.9.0" 23 | chalk "^2.0.0" 24 | js-tokens "^4.0.0" 25 | 26 | "@types/node@13.11.1": 27 | version "13.11.1" 28 | resolved "https://registry.yarnpkg.com/@types/node/-/node-13.11.1.tgz#49a2a83df9d26daacead30d0ccc8762b128d53c7" 29 | integrity sha512-eWQGP3qtxwL8FGneRrC5DwrJLGN4/dH1clNTuLfN81HCrxVtxRjygDTUoZJ5ASlDEeo0ppYFQjQIlXhtXpOn6g== 30 | 31 | abbrev@1: 32 | version "1.1.1" 33 | resolved "https://registry.yarnpkg.com/abbrev/-/abbrev-1.1.1.tgz#f8f2c887ad10bf67f634f005b6987fed3179aac8" 34 | integrity sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q== 35 | 36 | ajv@^6.5.5: 37 | version "6.12.0" 38 | resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.0.tgz#06d60b96d87b8454a5adaba86e7854da629db4b7" 39 | integrity sha512-D6gFiFA0RRLyUbvijN74DWAjXSFxWKaWP7mldxkVhyhAV3+SWA9HEJPHQ2c9soIeTFJqcSdFDGFgdqs1iUU2Hw== 40 | dependencies: 41 | fast-deep-equal "^3.1.1" 42 | fast-json-stable-stringify "^2.0.0" 43 | json-schema-traverse "^0.4.1" 44 | uri-js "^4.2.2" 45 | 46 | ansi-regex@^2.0.0: 47 | version "2.1.1" 48 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-2.1.1.tgz#c3b33ab5ee360d86e0e628f0468ae7ef27d654df" 49 | integrity sha1-w7M6te42DYbg5ijwRorn7yfWVN8= 50 | 51 | ansi-regex@^3.0.0: 52 | version "3.0.0" 53 | resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-3.0.0.tgz#ed0317c322064f79466c02966bddb605ab37d998" 54 | integrity sha1-7QMXwyIGT3lGbAKWa922Bas32Zg= 55 | 56 | ansi-styles@^3.2.1: 57 | version "3.2.1" 58 | resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-3.2.1.tgz#41fbb20243e50b12be0f04b8dedbf07520ce841d" 59 | integrity sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA== 60 | dependencies: 61 | color-convert "^1.9.0" 62 | 63 | aproba@^1.0.3: 64 | version "1.2.0" 65 | resolved "https://registry.yarnpkg.com/aproba/-/aproba-1.2.0.tgz#6802e6264efd18c790a1b0d517f0f2627bf2c94a" 66 | integrity sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw== 67 | 68 | are-we-there-yet@~1.1.2: 69 | version "1.1.5" 70 | resolved "https://registry.yarnpkg.com/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz#4b35c2944f062a8bfcda66410760350fe9ddfc21" 71 | integrity sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w== 72 | dependencies: 73 | delegates "^1.0.0" 74 | readable-stream "^2.0.6" 75 | 76 | argparse@^1.0.7: 77 | version "1.0.10" 78 | resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" 79 | integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== 80 | dependencies: 81 | sprintf-js "~1.0.2" 82 | 83 | asn1@~0.2.3: 84 | version "0.2.4" 85 | resolved "https://registry.yarnpkg.com/asn1/-/asn1-0.2.4.tgz#8d2475dfab553bb33e77b54e59e880bb8ce23136" 86 | integrity sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg== 87 | dependencies: 88 | safer-buffer "~2.1.0" 89 | 90 | assert-plus@1.0.0, assert-plus@^1.0.0: 91 | version "1.0.0" 92 | resolved "https://registry.yarnpkg.com/assert-plus/-/assert-plus-1.0.0.tgz#f12e0f3c5d77b0b1cdd9146942e4e96c1e4dd525" 93 | integrity sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= 94 | 95 | asynckit@^0.4.0: 96 | version "0.4.0" 97 | resolved "https://registry.yarnpkg.com/asynckit/-/asynckit-0.4.0.tgz#c79ed97f7f34cb8f2ba1bc9790bcc366474b4b79" 98 | integrity sha1-x57Zf380y48robyXkLzDZkdLS3k= 99 | 100 | aws-sign2@~0.7.0: 101 | version "0.7.0" 102 | resolved "https://registry.yarnpkg.com/aws-sign2/-/aws-sign2-0.7.0.tgz#b46e890934a9591f2d2f6f86d7e6a9f1b3fe76a8" 103 | integrity sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= 104 | 105 | aws4@^1.8.0: 106 | version "1.9.1" 107 | resolved "https://registry.yarnpkg.com/aws4/-/aws4-1.9.1.tgz#7e33d8f7d449b3f673cd72deb9abdc552dbe528e" 108 | integrity sha512-wMHVg2EOHaMRxbzgFJ9gtjOOCrI80OHLG14rxi28XwOW8ux6IiEbRCGGGqCtdAIg4FQCbW20k9RsT4y3gJlFug== 109 | 110 | balanced-match@^1.0.0: 111 | version "1.0.0" 112 | resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.0.tgz#89b4d199ab2bee49de164ea02b89ce462d71b767" 113 | integrity sha1-ibTRmasr7kneFk6gK4nORi1xt2c= 114 | 115 | bcrypt-pbkdf@^1.0.0: 116 | version "1.0.2" 117 | resolved "https://registry.yarnpkg.com/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz#a4301d389b6a43f9b67ff3ca11a3f6637e360e9e" 118 | integrity sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= 119 | dependencies: 120 | tweetnacl "^0.14.3" 121 | 122 | bl@^1.0.0: 123 | version "1.2.2" 124 | resolved "https://registry.yarnpkg.com/bl/-/bl-1.2.2.tgz#a160911717103c07410cef63ef51b397c025af9c" 125 | integrity sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA== 126 | dependencies: 127 | readable-stream "^2.3.5" 128 | safe-buffer "^5.1.1" 129 | 130 | brace-expansion@^1.1.7: 131 | version "1.1.11" 132 | resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" 133 | integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== 134 | dependencies: 135 | balanced-match "^1.0.0" 136 | concat-map "0.0.1" 137 | 138 | buffer-alloc-unsafe@^1.1.0: 139 | version "1.1.0" 140 | resolved "https://registry.yarnpkg.com/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz#bd7dc26ae2972d0eda253be061dba992349c19f0" 141 | integrity sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg== 142 | 143 | buffer-alloc@^1.2.0: 144 | version "1.2.0" 145 | resolved "https://registry.yarnpkg.com/buffer-alloc/-/buffer-alloc-1.2.0.tgz#890dd90d923a873e08e10e5fd51a57e5b7cce0ec" 146 | integrity sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow== 147 | dependencies: 148 | buffer-alloc-unsafe "^1.1.0" 149 | buffer-fill "^1.0.0" 150 | 151 | buffer-fill@^1.0.0: 152 | version "1.0.0" 153 | resolved "https://registry.yarnpkg.com/buffer-fill/-/buffer-fill-1.0.0.tgz#f8f78b76789888ef39f205cd637f68e702122b2c" 154 | integrity sha1-+PeLdniYiO858gXNY39o5wISKyw= 155 | 156 | builtin-modules@^1.1.1: 157 | version "1.1.1" 158 | resolved "https://registry.yarnpkg.com/builtin-modules/-/builtin-modules-1.1.1.tgz#270f076c5a72c02f5b65a47df94c5fe3a278892f" 159 | integrity sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8= 160 | 161 | caseless@~0.12.0: 162 | version "0.12.0" 163 | resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" 164 | integrity sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= 165 | 166 | chalk@^2.0.0, chalk@^2.3.0: 167 | version "2.4.2" 168 | resolved "https://registry.yarnpkg.com/chalk/-/chalk-2.4.2.tgz#cd42541677a54333cf541a49108c1432b44c9424" 169 | integrity sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ== 170 | dependencies: 171 | ansi-styles "^3.2.1" 172 | escape-string-regexp "^1.0.5" 173 | supports-color "^5.3.0" 174 | 175 | chownr@^1.0.1, chownr@^1.1.1: 176 | version "1.1.4" 177 | resolved "https://registry.yarnpkg.com/chownr/-/chownr-1.1.4.tgz#6fc9d7b42d32a583596337666e7d08084da2cc6b" 178 | integrity sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg== 179 | 180 | code-point-at@^1.0.0: 181 | version "1.1.0" 182 | resolved "https://registry.yarnpkg.com/code-point-at/-/code-point-at-1.1.0.tgz#0d070b4d043a5bea33a2f1a40e2edb3d9a4ccf77" 183 | integrity sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c= 184 | 185 | color-convert@^1.9.0: 186 | version "1.9.3" 187 | resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-1.9.3.tgz#bb71850690e1f136567de629d2d5471deda4c1e8" 188 | integrity sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg== 189 | dependencies: 190 | color-name "1.1.3" 191 | 192 | color-name@1.1.3: 193 | version "1.1.3" 194 | resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.3.tgz#a7d0558bd89c42f795dd42328f740831ca53bc25" 195 | integrity sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= 196 | 197 | combined-stream@^1.0.6, combined-stream@~1.0.6: 198 | version "1.0.8" 199 | resolved "https://registry.yarnpkg.com/combined-stream/-/combined-stream-1.0.8.tgz#c3d45a8b34fd730631a110a8a2520682b31d5a7f" 200 | integrity sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg== 201 | dependencies: 202 | delayed-stream "~1.0.0" 203 | 204 | commander@^2.12.1: 205 | version "2.20.3" 206 | resolved "https://registry.yarnpkg.com/commander/-/commander-2.20.3.tgz#fd485e84c03eb4881c20722ba48035e8531aeb33" 207 | integrity sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ== 208 | 209 | concat-map@0.0.1: 210 | version "0.0.1" 211 | resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" 212 | integrity sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= 213 | 214 | console-control-strings@^1.0.0, console-control-strings@~1.1.0: 215 | version "1.1.0" 216 | resolved "https://registry.yarnpkg.com/console-control-strings/-/console-control-strings-1.1.0.tgz#3d7cf4464db6446ea644bf4b39507f9851008e8e" 217 | integrity sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4= 218 | 219 | core-util-is@1.0.2, core-util-is@~1.0.0: 220 | version "1.0.2" 221 | resolved "https://registry.yarnpkg.com/core-util-is/-/core-util-is-1.0.2.tgz#b5fd54220aa2bc5ab57aab7140c940754503c1a7" 222 | integrity sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= 223 | 224 | dashdash@^1.12.0: 225 | version "1.14.1" 226 | resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0" 227 | integrity sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= 228 | dependencies: 229 | assert-plus "^1.0.0" 230 | 231 | delayed-stream@~1.0.0: 232 | version "1.0.0" 233 | resolved "https://registry.yarnpkg.com/delayed-stream/-/delayed-stream-1.0.0.tgz#df3ae199acadfb7d440aaae0b29e2272b24ec619" 234 | integrity sha1-3zrhmayt+31ECqrgsp4icrJOxhk= 235 | 236 | delegates@^1.0.0: 237 | version "1.0.0" 238 | resolved "https://registry.yarnpkg.com/delegates/-/delegates-1.0.0.tgz#84c6e159b81904fdca59a0ef44cd870d31250f9a" 239 | integrity sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o= 240 | 241 | diff@^4.0.1: 242 | version "4.0.2" 243 | resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" 244 | integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== 245 | 246 | ecc-jsbn@~0.1.1: 247 | version "0.1.2" 248 | resolved "https://registry.yarnpkg.com/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz#3a83a904e54353287874c564b7549386849a98c9" 249 | integrity sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= 250 | dependencies: 251 | jsbn "~0.1.0" 252 | safer-buffer "^2.1.0" 253 | 254 | end-of-stream@^1.0.0, end-of-stream@^1.1.0: 255 | version "1.4.4" 256 | resolved "https://registry.yarnpkg.com/end-of-stream/-/end-of-stream-1.4.4.tgz#5ae64a5f45057baf3626ec14da0ca5e4b2431eb0" 257 | integrity sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q== 258 | dependencies: 259 | once "^1.4.0" 260 | 261 | env-paths@^2.2.0: 262 | version "2.2.0" 263 | resolved "https://registry.yarnpkg.com/env-paths/-/env-paths-2.2.0.tgz#cdca557dc009152917d6166e2febe1f039685e43" 264 | integrity sha512-6u0VYSCo/OW6IoD5WCLLy9JUGARbamfSavcNXry/eu8aHVFei6CD3Sw+VGX5alea1i9pgPHW0mbu6Xj0uBh7gA== 265 | 266 | escape-string-regexp@^1.0.5: 267 | version "1.0.5" 268 | resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz#1b61c0562190a8dff6ae3bb2cf0200ca130b86d4" 269 | integrity sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= 270 | 271 | esprima@^4.0.0: 272 | version "4.0.1" 273 | resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" 274 | integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== 275 | 276 | execspawn@^1.0.1: 277 | version "1.0.1" 278 | resolved "https://registry.yarnpkg.com/execspawn/-/execspawn-1.0.1.tgz#8286f9dde7cecde7905fbdc04e24f368f23f8da6" 279 | integrity sha1-gob53efOzeeQX73ATiTzaPI/jaY= 280 | dependencies: 281 | util-extend "^1.0.1" 282 | 283 | extend@~3.0.2: 284 | version "3.0.2" 285 | resolved "https://registry.yarnpkg.com/extend/-/extend-3.0.2.tgz#f8b1136b4071fbd8eb140aff858b1019ec2915fa" 286 | integrity sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g== 287 | 288 | extract-file-icon@^0.3.2: 289 | version "0.3.2" 290 | resolved "https://registry.yarnpkg.com/extract-file-icon/-/extract-file-icon-0.3.2.tgz#9d95bf1aef4125c6a5844b1898492847868e569e" 291 | integrity sha512-We5/HaMDlioOx3c9zDjit8RtKWEvT94sJF8jTujaKVOyWL8Kkqu4QGnwDr5fID6XsbKvWT0JJNuWuV2Tmr7yiw== 292 | dependencies: 293 | node-addon-api "1.7.1" 294 | 295 | extsprintf@1.3.0: 296 | version "1.3.0" 297 | resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.3.0.tgz#96918440e3041a7a414f8c52e3c574eb3c3e1e05" 298 | integrity sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= 299 | 300 | extsprintf@^1.2.0: 301 | version "1.4.0" 302 | resolved "https://registry.yarnpkg.com/extsprintf/-/extsprintf-1.4.0.tgz#e2689f8f356fad62cca65a3a91c5df5f9551692f" 303 | integrity sha1-4mifjzVvrWLMplo6kcXfX5VRaS8= 304 | 305 | fast-deep-equal@^3.1.1: 306 | version "3.1.1" 307 | resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.1.tgz#545145077c501491e33b15ec408c294376e94ae4" 308 | integrity sha512-8UEa58QDLauDNfpbrX55Q9jrGHThw2ZMdOky5Gl1CDtVeJDPVrG4Jxx1N8jw2gkWaff5UUuX1KJd+9zGe2B+ZA== 309 | 310 | fast-json-stable-stringify@^2.0.0: 311 | version "2.1.0" 312 | resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" 313 | integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== 314 | 315 | forever-agent@~0.6.1: 316 | version "0.6.1" 317 | resolved "https://registry.yarnpkg.com/forever-agent/-/forever-agent-0.6.1.tgz#fbc71f0c41adeb37f96c577ad1ed42d8fdacca91" 318 | integrity sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= 319 | 320 | form-data@~2.3.2: 321 | version "2.3.3" 322 | resolved "https://registry.yarnpkg.com/form-data/-/form-data-2.3.3.tgz#dcce52c05f644f298c6a7ab936bd724ceffbf3a6" 323 | integrity sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ== 324 | dependencies: 325 | asynckit "^0.4.0" 326 | combined-stream "^1.0.6" 327 | mime-types "^2.1.12" 328 | 329 | fs-constants@^1.0.0: 330 | version "1.0.0" 331 | resolved "https://registry.yarnpkg.com/fs-constants/-/fs-constants-1.0.0.tgz#6be0de9be998ce16af8afc24497b9ee9b7ccd9ad" 332 | integrity sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow== 333 | 334 | fs-minipass@^1.2.5: 335 | version "1.2.7" 336 | resolved "https://registry.yarnpkg.com/fs-minipass/-/fs-minipass-1.2.7.tgz#ccff8570841e7fe4265693da88936c55aed7f7c7" 337 | integrity sha512-GWSSJGFy4e9GUeCcbIkED+bgAoFyj7XF1mV8rma3QW4NIqX9Kyx79N/PF61H5udOV3aY1IaMLs6pGbH71nlCTA== 338 | dependencies: 339 | minipass "^2.6.0" 340 | 341 | fs.realpath@^1.0.0: 342 | version "1.0.0" 343 | resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" 344 | integrity sha1-FQStJSMVjKpA20onh8sBQRmU6k8= 345 | 346 | gauge@~2.7.3: 347 | version "2.7.4" 348 | resolved "https://registry.yarnpkg.com/gauge/-/gauge-2.7.4.tgz#2c03405c7538c39d7eb37b317022e325fb018bf7" 349 | integrity sha1-LANAXHU4w51+s3sxcCLjJfsBi/c= 350 | dependencies: 351 | aproba "^1.0.3" 352 | console-control-strings "^1.0.0" 353 | has-unicode "^2.0.0" 354 | object-assign "^4.1.0" 355 | signal-exit "^3.0.0" 356 | string-width "^1.0.1" 357 | strip-ansi "^3.0.1" 358 | wide-align "^1.1.0" 359 | 360 | getpass@^0.1.1: 361 | version "0.1.7" 362 | resolved "https://registry.yarnpkg.com/getpass/-/getpass-0.1.7.tgz#5eff8e3e684d569ae4cb2b1282604e8ba62149fa" 363 | integrity sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= 364 | dependencies: 365 | assert-plus "^1.0.0" 366 | 367 | glob@^7.1.1, glob@^7.1.3, glob@^7.1.4: 368 | version "7.1.6" 369 | resolved "https://registry.yarnpkg.com/glob/-/glob-7.1.6.tgz#141f33b81a7c2492e125594307480c46679278a6" 370 | integrity sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA== 371 | dependencies: 372 | fs.realpath "^1.0.0" 373 | inflight "^1.0.4" 374 | inherits "2" 375 | minimatch "^3.0.4" 376 | once "^1.3.0" 377 | path-is-absolute "^1.0.0" 378 | 379 | graceful-fs@^4.2.2: 380 | version "4.2.3" 381 | resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.3.tgz#4a12ff1b60376ef09862c2093edd908328be8423" 382 | integrity sha512-a30VEBm4PEdx1dRB7MFK7BejejvCvBronbLjht+sHuGYj8PHs7M/5Z+rt5lw551vZ7yfTCj4Vuyy3mSJytDWRQ== 383 | 384 | har-schema@^2.0.0: 385 | version "2.0.0" 386 | resolved "https://registry.yarnpkg.com/har-schema/-/har-schema-2.0.0.tgz#a94c2224ebcac04782a0d9035521f24735b7ec92" 387 | integrity sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= 388 | 389 | har-validator@~5.1.3: 390 | version "5.1.3" 391 | resolved "https://registry.yarnpkg.com/har-validator/-/har-validator-5.1.3.tgz#1ef89ebd3e4996557675eed9893110dc350fa080" 392 | integrity sha512-sNvOCzEQNr/qrvJgc3UG/kD4QtlHycrzwS+6mfTrrSq97BvaYcPZZI1ZSqGSPR73Cxn4LKTD4PttRwfU7jWq5g== 393 | dependencies: 394 | ajv "^6.5.5" 395 | har-schema "^2.0.0" 396 | 397 | has-flag@^3.0.0: 398 | version "3.0.0" 399 | resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-3.0.0.tgz#b5d454dc2199ae225699f3467e5a07f3b955bafd" 400 | integrity sha1-tdRU3CGZriJWmfNGfloH87lVuv0= 401 | 402 | has-unicode@^2.0.0: 403 | version "2.0.1" 404 | resolved "https://registry.yarnpkg.com/has-unicode/-/has-unicode-2.0.1.tgz#e0e6fe6a28cf51138855e086d1691e771de2a8b9" 405 | integrity sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk= 406 | 407 | http-signature@~1.2.0: 408 | version "1.2.0" 409 | resolved "https://registry.yarnpkg.com/http-signature/-/http-signature-1.2.0.tgz#9aecd925114772f3d95b65a60abb8f7c18fbace1" 410 | integrity sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= 411 | dependencies: 412 | assert-plus "^1.0.0" 413 | jsprim "^1.2.2" 414 | sshpk "^1.7.0" 415 | 416 | inflight@^1.0.4: 417 | version "1.0.6" 418 | resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" 419 | integrity sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= 420 | dependencies: 421 | once "^1.3.0" 422 | wrappy "1" 423 | 424 | inherits@2, inherits@~2.0.3: 425 | version "2.0.4" 426 | resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" 427 | integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== 428 | 429 | is-fullwidth-code-point@^1.0.0: 430 | version "1.0.0" 431 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz#ef9e31386f031a7f0d643af82fde50c457ef00cb" 432 | integrity sha1-754xOG8DGn8NZDr4L95QxFfvAMs= 433 | dependencies: 434 | number-is-nan "^1.0.0" 435 | 436 | is-fullwidth-code-point@^2.0.0: 437 | version "2.0.0" 438 | resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz#a3b30a5c4f199183167aaab93beefae3ddfb654f" 439 | integrity sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= 440 | 441 | is-typedarray@~1.0.0: 442 | version "1.0.0" 443 | resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" 444 | integrity sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= 445 | 446 | isarray@~1.0.0: 447 | version "1.0.0" 448 | resolved "https://registry.yarnpkg.com/isarray/-/isarray-1.0.0.tgz#bb935d48582cba168c06834957a54a3e07124f11" 449 | integrity sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= 450 | 451 | isexe@^2.0.0: 452 | version "2.0.0" 453 | resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" 454 | integrity sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= 455 | 456 | isstream@~0.1.2: 457 | version "0.1.2" 458 | resolved "https://registry.yarnpkg.com/isstream/-/isstream-0.1.2.tgz#47e63f7af55afa6f92e1500e690eb8b8529c099a" 459 | integrity sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= 460 | 461 | js-tokens@^4.0.0: 462 | version "4.0.0" 463 | resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" 464 | integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== 465 | 466 | js-yaml@^3.13.1: 467 | version "3.13.1" 468 | resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.13.1.tgz#aff151b30bfdfa8e49e05da22e7415e9dfa37847" 469 | integrity sha512-YfbcO7jXDdyj0DGxYVSlSeQNHbD7XPWvrVWeVUujrQEoZzWJIRrCPoyk6kL6IAjAG2IolMK4T0hNUe0HOUs5Jw== 470 | dependencies: 471 | argparse "^1.0.7" 472 | esprima "^4.0.0" 473 | 474 | jsbn@~0.1.0: 475 | version "0.1.1" 476 | resolved "https://registry.yarnpkg.com/jsbn/-/jsbn-0.1.1.tgz#a5e654c2e5a2deb5f201d96cefbca80c0ef2f513" 477 | integrity sha1-peZUwuWi3rXyAdls77yoDA7y9RM= 478 | 479 | json-schema-traverse@^0.4.1: 480 | version "0.4.1" 481 | resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" 482 | integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== 483 | 484 | json-schema@0.2.3: 485 | version "0.2.3" 486 | resolved "https://registry.yarnpkg.com/json-schema/-/json-schema-0.2.3.tgz#b480c892e59a2f05954ce727bd3f2a4e882f9e13" 487 | integrity sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM= 488 | 489 | json-stringify-safe@~5.0.1: 490 | version "5.0.1" 491 | resolved "https://registry.yarnpkg.com/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz#1296a2d58fd45f19a0f6ce01d65701e2c735b6eb" 492 | integrity sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= 493 | 494 | jsprim@^1.2.2: 495 | version "1.4.1" 496 | resolved "https://registry.yarnpkg.com/jsprim/-/jsprim-1.4.1.tgz#313e66bc1e5cc06e438bc1b7499c2e5c56acb6a2" 497 | integrity sha1-MT5mvB5cwG5Di8G3SZwuXFastqI= 498 | dependencies: 499 | assert-plus "1.0.0" 500 | extsprintf "1.3.0" 501 | json-schema "0.2.3" 502 | verror "1.10.0" 503 | 504 | mime-db@1.43.0: 505 | version "1.43.0" 506 | resolved "https://registry.yarnpkg.com/mime-db/-/mime-db-1.43.0.tgz#0a12e0502650e473d735535050e7c8f4eb4fae58" 507 | integrity sha512-+5dsGEEovYbT8UY9yD7eE4XTc4UwJ1jBYlgaQQF38ENsKR3wj/8q8RFZrF9WIZpB2V1ArTVFUva8sAul1NzRzQ== 508 | 509 | mime-types@^2.1.12, mime-types@~2.1.19: 510 | version "2.1.26" 511 | resolved "https://registry.yarnpkg.com/mime-types/-/mime-types-2.1.26.tgz#9c921fc09b7e149a65dfdc0da4d20997200b0a06" 512 | integrity sha512-01paPWYgLrkqAyrlDorC1uDwl2p3qZT7yl806vW7DvDoxwXi46jsjFbg+WdwotBIk6/MbEhO/dh5aZ5sNj/dWQ== 513 | dependencies: 514 | mime-db "1.43.0" 515 | 516 | minimatch@^3.0.4: 517 | version "3.0.4" 518 | resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.0.4.tgz#5166e286457f03306064be5497e8dbb0c3d32083" 519 | integrity sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA== 520 | dependencies: 521 | brace-expansion "^1.1.7" 522 | 523 | minimist@^1.2.0, minimist@^1.2.5: 524 | version "1.2.5" 525 | resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602" 526 | integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw== 527 | 528 | minipass@^2.6.0, minipass@^2.8.6, minipass@^2.9.0: 529 | version "2.9.0" 530 | resolved "https://registry.yarnpkg.com/minipass/-/minipass-2.9.0.tgz#e713762e7d3e32fed803115cf93e04bca9fcc9a6" 531 | integrity sha512-wxfUjg9WebH+CUDX/CdbRlh5SmfZiy/hpkxaRI16Y9W56Pa75sWgd/rvFilSgrauD9NyFymP/+JFV3KwzIsJeg== 532 | dependencies: 533 | safe-buffer "^5.1.2" 534 | yallist "^3.0.0" 535 | 536 | minizlib@^1.2.1: 537 | version "1.3.3" 538 | resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-1.3.3.tgz#2290de96818a34c29551c8a8d301216bd65a861d" 539 | integrity sha512-6ZYMOEnmVsdCeTJVE0W9ZD+pVnE8h9Hma/iOwwRDsdQoePpoX56/8B6z3P9VNwppJuBKNRuFDRNRqRWexT9G9Q== 540 | dependencies: 541 | minipass "^2.9.0" 542 | 543 | mkdirp@^0.5.0, mkdirp@^0.5.1, mkdirp@^0.5.3: 544 | version "0.5.5" 545 | resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.5.tgz#d91cefd62d1436ca0f41620e251288d420099def" 546 | integrity sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ== 547 | dependencies: 548 | minimist "^1.2.5" 549 | 550 | node-abi@^2.0.0: 551 | version "2.15.0" 552 | resolved "https://registry.yarnpkg.com/node-abi/-/node-abi-2.15.0.tgz#51d55cc711bd9e4a24a572ace13b9231945ccb10" 553 | integrity sha512-FeLpTS0F39U7hHZU1srAK4Vx+5AHNVOTP+hxBNQknR/54laTHSFIJkDWDqiquY1LeLUgTfPN7sLPhMubx0PLAg== 554 | dependencies: 555 | semver "^5.4.1" 556 | 557 | node-addon-api@1.7.1: 558 | version "1.7.1" 559 | resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-1.7.1.tgz#cf813cd69bb8d9100f6bdca6755fc268f54ac492" 560 | integrity sha512-2+DuKodWvwRTrCfKOeR24KIc5unKjOh8mz17NCzVnHWfjAdDqbfbjqh7gUT+BkXBRQM52+xCHciKWonJ3CbJMQ== 561 | 562 | node-addon-api@2.0.0: 563 | version "2.0.0" 564 | resolved "https://registry.yarnpkg.com/node-addon-api/-/node-addon-api-2.0.0.tgz#f9afb8d777a91525244b01775ea0ddbe1125483b" 565 | integrity sha512-ASCL5U13as7HhOExbT6OlWJJUV/lLzL2voOSP1UVehpRD8FbSrSDjfScK/KwAvVTI5AS6r4VwbOMlIqtvRidnA== 566 | 567 | node-gyp-build@^4.2.1: 568 | version "4.2.1" 569 | resolved "https://registry.yarnpkg.com/node-gyp-build/-/node-gyp-build-4.2.1.tgz#f28f0d3d3ab268d48ab76c6f446f19bc3d0db9dc" 570 | integrity sha512-XyCKXsqZfLqHep1hhsMncoXuUNt/cXCjg1+8CLbu69V1TKuPiOeSGbL9n+k/ByKH8UT0p4rdIX8XkTRZV0i7Sw== 571 | 572 | node-gyp@^6.1.0: 573 | version "6.1.0" 574 | resolved "https://registry.yarnpkg.com/node-gyp/-/node-gyp-6.1.0.tgz#64e31c61a4695ad304c1d5b82cf6b7c79cc79f3f" 575 | integrity sha512-h4A2zDlOujeeaaTx06r4Vy+8MZ1679lU+wbCKDS4ZtvY2A37DESo37oejIw0mtmR3+rvNwts5B6Kpt1KrNYdNw== 576 | dependencies: 577 | env-paths "^2.2.0" 578 | glob "^7.1.4" 579 | graceful-fs "^4.2.2" 580 | mkdirp "^0.5.1" 581 | nopt "^4.0.1" 582 | npmlog "^4.1.2" 583 | request "^2.88.0" 584 | rimraf "^2.6.3" 585 | semver "^5.7.1" 586 | tar "^4.4.12" 587 | which "^1.3.1" 588 | 589 | nopt@^4.0.1: 590 | version "4.0.3" 591 | resolved "https://registry.yarnpkg.com/nopt/-/nopt-4.0.3.tgz#a375cad9d02fd921278d954c2254d5aa57e15e48" 592 | integrity sha512-CvaGwVMztSMJLOeXPrez7fyfObdZqNUK1cPAEzLHrTybIua9pMdmmPR5YwtfNftIOMv3DPUhFaxsZMNTQO20Kg== 593 | dependencies: 594 | abbrev "1" 595 | osenv "^0.1.4" 596 | 597 | npm-run-path@^3.1.0: 598 | version "3.1.0" 599 | resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-3.1.0.tgz#7f91be317f6a466efed3c9f2980ad8a4ee8b0fa5" 600 | integrity sha512-Dbl4A/VfiVGLgQv29URL9xshU8XDY1GeLy+fsaZ1AA8JDSfjvr5P5+pzRbWqRSBxk6/DW7MIh8lTM/PaGnP2kg== 601 | dependencies: 602 | path-key "^3.0.0" 603 | 604 | npmlog@^4.1.2: 605 | version "4.1.2" 606 | resolved "https://registry.yarnpkg.com/npmlog/-/npmlog-4.1.2.tgz#08a7f2a8bf734604779a9efa4ad5cc717abb954b" 607 | integrity sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg== 608 | dependencies: 609 | are-we-there-yet "~1.1.2" 610 | console-control-strings "~1.1.0" 611 | gauge "~2.7.3" 612 | set-blocking "~2.0.0" 613 | 614 | number-is-nan@^1.0.0: 615 | version "1.0.1" 616 | resolved "https://registry.yarnpkg.com/number-is-nan/-/number-is-nan-1.0.1.tgz#097b602b53422a522c1afb8790318336941a011d" 617 | integrity sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0= 618 | 619 | oauth-sign@~0.9.0: 620 | version "0.9.0" 621 | resolved "https://registry.yarnpkg.com/oauth-sign/-/oauth-sign-0.9.0.tgz#47a7b016baa68b5fa0ecf3dee08a85c679ac6455" 622 | integrity sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ== 623 | 624 | object-assign@^4.1.0: 625 | version "4.1.1" 626 | resolved "https://registry.yarnpkg.com/object-assign/-/object-assign-4.1.1.tgz#2109adc7965887cfc05cbbd442cac8bfbb360863" 627 | integrity sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= 628 | 629 | once@^1.3.0, once@^1.3.1, once@^1.4.0: 630 | version "1.4.0" 631 | resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" 632 | integrity sha1-WDsap3WWHUsROsF9nFC6753Xa9E= 633 | dependencies: 634 | wrappy "1" 635 | 636 | os-homedir@^1.0.0: 637 | version "1.0.2" 638 | resolved "https://registry.yarnpkg.com/os-homedir/-/os-homedir-1.0.2.tgz#ffbc4988336e0e833de0c168c7ef152121aa7fb3" 639 | integrity sha1-/7xJiDNuDoM94MFox+8VISGqf7M= 640 | 641 | os-tmpdir@^1.0.0: 642 | version "1.0.2" 643 | resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" 644 | integrity sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= 645 | 646 | osenv@^0.1.4: 647 | version "0.1.5" 648 | resolved "https://registry.yarnpkg.com/osenv/-/osenv-0.1.5.tgz#85cdfafaeb28e8677f416e287592b5f3f49ea410" 649 | integrity sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g== 650 | dependencies: 651 | os-homedir "^1.0.0" 652 | os-tmpdir "^1.0.0" 653 | 654 | path-is-absolute@^1.0.0: 655 | version "1.0.1" 656 | resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" 657 | integrity sha1-F0uSaHNVNP+8es5r9TpanhtcX18= 658 | 659 | path-key@^3.0.0: 660 | version "3.1.1" 661 | resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" 662 | integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== 663 | 664 | path-parse@^1.0.6: 665 | version "1.0.6" 666 | resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.6.tgz#d62dbb5679405d72c4737ec58600e9ddcf06d24c" 667 | integrity sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw== 668 | 669 | performance-now@^2.1.0: 670 | version "2.1.0" 671 | resolved "https://registry.yarnpkg.com/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" 672 | integrity sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= 673 | 674 | prebuildify@^3.0.4: 675 | version "3.0.4" 676 | resolved "https://registry.yarnpkg.com/prebuildify/-/prebuildify-3.0.4.tgz#64eae6eab5a539986e04745f60a62fcd58cd17ae" 677 | integrity sha512-bNf66/MgPl1S/u41BXVUGlsj3seKO34ree0w4acE+y/jKBfpY4fc1o+chcN5KV345s/RnvT563VllGUQF+SSCw== 678 | dependencies: 679 | execspawn "^1.0.1" 680 | minimist "^1.2.0" 681 | mkdirp "^0.5.1" 682 | node-abi "^2.0.0" 683 | npm-run-path "^3.1.0" 684 | pump "^3.0.0" 685 | tar-fs "^1.16.2" 686 | xtend "^4.0.1" 687 | 688 | process-nextick-args@~2.0.0: 689 | version "2.0.1" 690 | resolved "https://registry.yarnpkg.com/process-nextick-args/-/process-nextick-args-2.0.1.tgz#7820d9b16120cc55ca9ae7792680ae7dba6d7fe2" 691 | integrity sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag== 692 | 693 | psl@^1.1.28: 694 | version "1.8.0" 695 | resolved "https://registry.yarnpkg.com/psl/-/psl-1.8.0.tgz#9326f8bcfb013adcc005fdff056acce020e51c24" 696 | integrity sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ== 697 | 698 | pump@^1.0.0: 699 | version "1.0.3" 700 | resolved "https://registry.yarnpkg.com/pump/-/pump-1.0.3.tgz#5dfe8311c33bbf6fc18261f9f34702c47c08a954" 701 | integrity sha512-8k0JupWme55+9tCVE+FS5ULT3K6AbgqrGa58lTT49RpyfwwcGedHqaC5LlQNdEAumn/wFsu6aPwkuPMioy8kqw== 702 | dependencies: 703 | end-of-stream "^1.1.0" 704 | once "^1.3.1" 705 | 706 | pump@^3.0.0: 707 | version "3.0.0" 708 | resolved "https://registry.yarnpkg.com/pump/-/pump-3.0.0.tgz#b4a2116815bde2f4e1ea602354e8c75565107a64" 709 | integrity sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww== 710 | dependencies: 711 | end-of-stream "^1.1.0" 712 | once "^1.3.1" 713 | 714 | punycode@^2.1.0, punycode@^2.1.1: 715 | version "2.1.1" 716 | resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.1.1.tgz#b58b010ac40c22c5657616c8d2c2c02c7bf479ec" 717 | integrity sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A== 718 | 719 | qs@~6.5.2: 720 | version "6.5.2" 721 | resolved "https://registry.yarnpkg.com/qs/-/qs-6.5.2.tgz#cb3ae806e8740444584ef154ce8ee98d403f3e36" 722 | integrity sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA== 723 | 724 | readable-stream@^2.0.6, readable-stream@^2.3.0, readable-stream@^2.3.5: 725 | version "2.3.7" 726 | resolved "https://registry.yarnpkg.com/readable-stream/-/readable-stream-2.3.7.tgz#1eca1cf711aef814c04f62252a36a62f6cb23b57" 727 | integrity sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw== 728 | dependencies: 729 | core-util-is "~1.0.0" 730 | inherits "~2.0.3" 731 | isarray "~1.0.0" 732 | process-nextick-args "~2.0.0" 733 | safe-buffer "~5.1.1" 734 | string_decoder "~1.1.1" 735 | util-deprecate "~1.0.1" 736 | 737 | request@^2.88.0: 738 | version "2.88.2" 739 | resolved "https://registry.yarnpkg.com/request/-/request-2.88.2.tgz#d73c918731cb5a87da047e207234146f664d12b3" 740 | integrity sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw== 741 | dependencies: 742 | aws-sign2 "~0.7.0" 743 | aws4 "^1.8.0" 744 | caseless "~0.12.0" 745 | combined-stream "~1.0.6" 746 | extend "~3.0.2" 747 | forever-agent "~0.6.1" 748 | form-data "~2.3.2" 749 | har-validator "~5.1.3" 750 | http-signature "~1.2.0" 751 | is-typedarray "~1.0.0" 752 | isstream "~0.1.2" 753 | json-stringify-safe "~5.0.1" 754 | mime-types "~2.1.19" 755 | oauth-sign "~0.9.0" 756 | performance-now "^2.1.0" 757 | qs "~6.5.2" 758 | safe-buffer "^5.1.2" 759 | tough-cookie "~2.5.0" 760 | tunnel-agent "^0.6.0" 761 | uuid "^3.3.2" 762 | 763 | resolve@^1.3.2: 764 | version "1.15.1" 765 | resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.15.1.tgz#27bdcdeffeaf2d6244b95bb0f9f4b4653451f3e8" 766 | integrity sha512-84oo6ZTtoTUpjgNEr5SJyzQhzL72gaRodsSfyxC/AXRvwu0Yse9H8eF9IpGo7b8YetZhlI6v7ZQ6bKBFV/6S7w== 767 | dependencies: 768 | path-parse "^1.0.6" 769 | 770 | rimraf@^2.6.3: 771 | version "2.7.1" 772 | resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-2.7.1.tgz#35797f13a7fdadc566142c29d4f07ccad483e3ec" 773 | integrity sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w== 774 | dependencies: 775 | glob "^7.1.3" 776 | 777 | safe-buffer@^5.0.1, safe-buffer@^5.1.1, safe-buffer@^5.1.2: 778 | version "5.2.0" 779 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.0.tgz#b74daec49b1148f88c64b68d49b1e815c1f2f519" 780 | integrity sha512-fZEwUGbVl7kouZs1jCdMLdt95hdIv0ZeHg6L7qPeciMZhZ+/gdesW4wgTARkrFWEpspjEATAzUGPG8N2jJiwbg== 781 | 782 | safe-buffer@~5.1.0, safe-buffer@~5.1.1: 783 | version "5.1.2" 784 | resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.1.2.tgz#991ec69d296e0313747d59bdfd2b745c35f8828d" 785 | integrity sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g== 786 | 787 | safer-buffer@^2.0.2, safer-buffer@^2.1.0, safer-buffer@~2.1.0: 788 | version "2.1.2" 789 | resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" 790 | integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== 791 | 792 | semver@^5.3.0, semver@^5.4.1, semver@^5.7.1: 793 | version "5.7.1" 794 | resolved "https://registry.yarnpkg.com/semver/-/semver-5.7.1.tgz#a954f931aeba508d307bbf069eff0c01c96116f7" 795 | integrity sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ== 796 | 797 | set-blocking@~2.0.0: 798 | version "2.0.0" 799 | resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" 800 | integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= 801 | 802 | signal-exit@^3.0.0: 803 | version "3.0.3" 804 | resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" 805 | integrity sha512-VUJ49FC8U1OxwZLxIbTTrDvLnf/6TDgxZcK8wxR8zs13xpx7xbG60ndBlhNrFi2EMuFRoeDoJO7wthSLq42EjA== 806 | 807 | sprintf-js@~1.0.2: 808 | version "1.0.3" 809 | resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" 810 | integrity sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= 811 | 812 | sshpk@^1.7.0: 813 | version "1.16.1" 814 | resolved "https://registry.yarnpkg.com/sshpk/-/sshpk-1.16.1.tgz#fb661c0bef29b39db40769ee39fa70093d6f6877" 815 | integrity sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg== 816 | dependencies: 817 | asn1 "~0.2.3" 818 | assert-plus "^1.0.0" 819 | bcrypt-pbkdf "^1.0.0" 820 | dashdash "^1.12.0" 821 | ecc-jsbn "~0.1.1" 822 | getpass "^0.1.1" 823 | jsbn "~0.1.0" 824 | safer-buffer "^2.0.2" 825 | tweetnacl "~0.14.0" 826 | 827 | string-width@^1.0.1: 828 | version "1.0.2" 829 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-1.0.2.tgz#118bdf5b8cdc51a2a7e70d211e07e2b0b9b107d3" 830 | integrity sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M= 831 | dependencies: 832 | code-point-at "^1.0.0" 833 | is-fullwidth-code-point "^1.0.0" 834 | strip-ansi "^3.0.0" 835 | 836 | "string-width@^1.0.2 || 2": 837 | version "2.1.1" 838 | resolved "https://registry.yarnpkg.com/string-width/-/string-width-2.1.1.tgz#ab93f27a8dc13d28cac815c462143a6d9012ae9e" 839 | integrity sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw== 840 | dependencies: 841 | is-fullwidth-code-point "^2.0.0" 842 | strip-ansi "^4.0.0" 843 | 844 | string_decoder@~1.1.1: 845 | version "1.1.1" 846 | resolved "https://registry.yarnpkg.com/string_decoder/-/string_decoder-1.1.1.tgz#9cf1611ba62685d7030ae9e4ba34149c3af03fc8" 847 | integrity sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg== 848 | dependencies: 849 | safe-buffer "~5.1.0" 850 | 851 | strip-ansi@^3.0.0, strip-ansi@^3.0.1: 852 | version "3.0.1" 853 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-3.0.1.tgz#6a385fb8853d952d5ff05d0e8aaf94278dc63dcf" 854 | integrity sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= 855 | dependencies: 856 | ansi-regex "^2.0.0" 857 | 858 | strip-ansi@^4.0.0: 859 | version "4.0.0" 860 | resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-4.0.0.tgz#a8479022eb1ac368a871389b635262c505ee368f" 861 | integrity sha1-qEeQIusaw2iocTibY1JixQXuNo8= 862 | dependencies: 863 | ansi-regex "^3.0.0" 864 | 865 | supports-color@^5.3.0: 866 | version "5.5.0" 867 | resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-5.5.0.tgz#e2e69a44ac8772f78a1ec0b35b689df6530efc8f" 868 | integrity sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow== 869 | dependencies: 870 | has-flag "^3.0.0" 871 | 872 | tar-fs@^1.16.2: 873 | version "1.16.3" 874 | resolved "https://registry.yarnpkg.com/tar-fs/-/tar-fs-1.16.3.tgz#966a628841da2c4010406a82167cbd5e0c72d509" 875 | integrity sha512-NvCeXpYx7OsmOh8zIOP/ebG55zZmxLE0etfWRbWok+q2Qo8x/vOR/IJT1taADXPe+jsiu9axDb3X4B+iIgNlKw== 876 | dependencies: 877 | chownr "^1.0.1" 878 | mkdirp "^0.5.1" 879 | pump "^1.0.0" 880 | tar-stream "^1.1.2" 881 | 882 | tar-stream@^1.1.2: 883 | version "1.6.2" 884 | resolved "https://registry.yarnpkg.com/tar-stream/-/tar-stream-1.6.2.tgz#8ea55dab37972253d9a9af90fdcd559ae435c555" 885 | integrity sha512-rzS0heiNf8Xn7/mpdSVVSMAWAoy9bfb1WOTYC78Z0UQKeKa/CWS8FOq0lKGNa8DWKAn9gxjCvMLYc5PGXYlK2A== 886 | dependencies: 887 | bl "^1.0.0" 888 | buffer-alloc "^1.2.0" 889 | end-of-stream "^1.0.0" 890 | fs-constants "^1.0.0" 891 | readable-stream "^2.3.0" 892 | to-buffer "^1.1.1" 893 | xtend "^4.0.0" 894 | 895 | tar@^4.4.12: 896 | version "4.4.13" 897 | resolved "https://registry.yarnpkg.com/tar/-/tar-4.4.13.tgz#43b364bc52888d555298637b10d60790254ab525" 898 | integrity sha512-w2VwSrBoHa5BsSyH+KxEqeQBAllHhccyMFVHtGtdMpF4W7IRWfZjFiQceJPChOeTsSDVUpER2T8FA93pr0L+QA== 899 | dependencies: 900 | chownr "^1.1.1" 901 | fs-minipass "^1.2.5" 902 | minipass "^2.8.6" 903 | minizlib "^1.2.1" 904 | mkdirp "^0.5.0" 905 | safe-buffer "^5.1.2" 906 | yallist "^3.0.3" 907 | 908 | to-buffer@^1.1.1: 909 | version "1.1.1" 910 | resolved "https://registry.yarnpkg.com/to-buffer/-/to-buffer-1.1.1.tgz#493bd48f62d7c43fcded313a03dcadb2e1213a80" 911 | integrity sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg== 912 | 913 | tough-cookie@~2.5.0: 914 | version "2.5.0" 915 | resolved "https://registry.yarnpkg.com/tough-cookie/-/tough-cookie-2.5.0.tgz#cd9fb2a0aa1d5a12b473bd9fb96fa3dcff65ade2" 916 | integrity sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g== 917 | dependencies: 918 | psl "^1.1.28" 919 | punycode "^2.1.1" 920 | 921 | tslib@^1.10.0, tslib@^1.8.1: 922 | version "1.11.1" 923 | resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.11.1.tgz#eb15d128827fbee2841549e171f45ed338ac7e35" 924 | integrity sha512-aZW88SY8kQbU7gpV19lN24LtXh/yD4ZZg6qieAJDDg+YBsJcSmLGK9QpnUjAKVG/xefmvJGd1WUmfpT/g6AJGA== 925 | 926 | tslint@6.1.1: 927 | version "6.1.1" 928 | resolved "https://registry.yarnpkg.com/tslint/-/tslint-6.1.1.tgz#ac03fbd17f85bfefaae348b353b25a88efe10cde" 929 | integrity sha512-kd6AQ/IgPRpLn6g5TozqzPdGNZ0q0jtXW4//hRcj10qLYBaa3mTUU2y2MCG+RXZm8Zx+KZi0eA+YCrMyNlF4UA== 930 | dependencies: 931 | "@babel/code-frame" "^7.0.0" 932 | builtin-modules "^1.1.1" 933 | chalk "^2.3.0" 934 | commander "^2.12.1" 935 | diff "^4.0.1" 936 | glob "^7.1.1" 937 | js-yaml "^3.13.1" 938 | minimatch "^3.0.4" 939 | mkdirp "^0.5.3" 940 | resolve "^1.3.2" 941 | semver "^5.3.0" 942 | tslib "^1.10.0" 943 | tsutils "^2.29.0" 944 | 945 | tsutils@^2.29.0: 946 | version "2.29.0" 947 | resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-2.29.0.tgz#32b488501467acbedd4b85498673a0812aca0b99" 948 | integrity sha512-g5JVHCIJwzfISaXpXE1qvNalca5Jwob6FjI4AoPlqMusJ6ftFE7IkkFoMhVLRgK+4Kx3gkzb8UZK5t5yTTvEmA== 949 | dependencies: 950 | tslib "^1.8.1" 951 | 952 | tunnel-agent@^0.6.0: 953 | version "0.6.0" 954 | resolved "https://registry.yarnpkg.com/tunnel-agent/-/tunnel-agent-0.6.0.tgz#27a5dea06b36b04a0a9966774b290868f0fc40fd" 955 | integrity sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= 956 | dependencies: 957 | safe-buffer "^5.0.1" 958 | 959 | tweetnacl@^0.14.3, tweetnacl@~0.14.0: 960 | version "0.14.5" 961 | resolved "https://registry.yarnpkg.com/tweetnacl/-/tweetnacl-0.14.5.tgz#5ae68177f192d4456269d108afa93ff8743f4f64" 962 | integrity sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= 963 | 964 | typescript@3.8.3: 965 | version "3.8.3" 966 | resolved "https://registry.yarnpkg.com/typescript/-/typescript-3.8.3.tgz#409eb8544ea0335711205869ec458ab109ee1061" 967 | integrity sha512-MYlEfn5VrLNsgudQTVJeNaQFUAI7DkhnOjdpAp4T+ku1TfQClewlbSuTVHiA+8skNBgaf02TL/kLOvig4y3G8w== 968 | 969 | uri-js@^4.2.2: 970 | version "4.2.2" 971 | resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.2.2.tgz#94c540e1ff772956e2299507c010aea6c8838eb0" 972 | integrity sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ== 973 | dependencies: 974 | punycode "^2.1.0" 975 | 976 | util-deprecate@~1.0.1: 977 | version "1.0.2" 978 | resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" 979 | integrity sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= 980 | 981 | util-extend@^1.0.1: 982 | version "1.0.3" 983 | resolved "https://registry.yarnpkg.com/util-extend/-/util-extend-1.0.3.tgz#a7c216d267545169637b3b6edc6ca9119e2ff93f" 984 | integrity sha1-p8IW0mdUUWljeztu3GypEZ4v+T8= 985 | 986 | uuid@^3.3.2: 987 | version "3.4.0" 988 | resolved "https://registry.yarnpkg.com/uuid/-/uuid-3.4.0.tgz#b23e4358afa8a202fe7a100af1f5f883f02007ee" 989 | integrity sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A== 990 | 991 | verror@1.10.0: 992 | version "1.10.0" 993 | resolved "https://registry.yarnpkg.com/verror/-/verror-1.10.0.tgz#3a105ca17053af55d6e270c1f8288682e18da400" 994 | integrity sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= 995 | dependencies: 996 | assert-plus "^1.0.0" 997 | core-util-is "1.0.2" 998 | extsprintf "^1.2.0" 999 | 1000 | which@^1.3.1: 1001 | version "1.3.1" 1002 | resolved "https://registry.yarnpkg.com/which/-/which-1.3.1.tgz#a45043d54f5805316da8d62f9f50918d3da70b0a" 1003 | integrity sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ== 1004 | dependencies: 1005 | isexe "^2.0.0" 1006 | 1007 | wide-align@^1.1.0: 1008 | version "1.1.3" 1009 | resolved "https://registry.yarnpkg.com/wide-align/-/wide-align-1.1.3.tgz#ae074e6bdc0c14a431e804e624549c633b000457" 1010 | integrity sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA== 1011 | dependencies: 1012 | string-width "^1.0.2 || 2" 1013 | 1014 | wrappy@1: 1015 | version "1.0.2" 1016 | resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" 1017 | integrity sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= 1018 | 1019 | xtend@^4.0.0, xtend@^4.0.1: 1020 | version "4.0.2" 1021 | resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" 1022 | integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== 1023 | 1024 | yallist@^3.0.0, yallist@^3.0.3: 1025 | version "3.1.1" 1026 | resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" 1027 | integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== 1028 | --------------------------------------------------------------------------------