@ohos-ports/redux-devtools-cli 5.0.0-beta.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE.md +21 -0
- package/README.md +162 -0
- package/app/electron.cjs +29 -0
- package/app/index.html +46 -0
- package/app/package.json +8 -0
- package/bin/redux-devtools.js +3 -0
- package/defaultDbOptions.json +7 -0
- package/dist/api/schema.d.ts +16 -0
- package/dist/api/schema.js +12 -0
- package/dist/api/schema_def.graphql +60 -0
- package/dist/bin/injectServer.d.ts +6 -0
- package/dist/bin/injectServer.js +78 -0
- package/dist/bin/openApp.d.ts +2 -0
- package/dist/bin/openApp.js +40 -0
- package/dist/bin/redux-devtools.d.ts +2 -0
- package/dist/bin/redux-devtools.js +73 -0
- package/dist/db/connector.d.ts +3 -0
- package/dist/db/connector.js +49 -0
- package/dist/db/migrations/index.d.ts +3 -0
- package/dist/db/migrations/index.js +84 -0
- package/dist/db/seeds/index.d.ts +2 -0
- package/dist/db/seeds/index.js +10 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.js +125 -0
- package/dist/options.d.ts +29 -0
- package/dist/options.js +29 -0
- package/dist/routes.d.ts +5 -0
- package/dist/routes.js +100 -0
- package/dist/store.d.ts +57 -0
- package/dist/store.js +97 -0
- package/package.json +97 -0
- package/src/api/schema.ts +26 -0
- package/src/api/schema_def.graphql +60 -0
- package/src/bin/injectServer.ts +104 -0
- package/src/bin/openApp.ts +53 -0
- package/src/bin/redux-devtools.ts +94 -0
- package/src/db/connector.ts +67 -0
- package/src/db/migrations/index.ts +87 -0
- package/src/db/seeds/index.ts +12 -0
- package/src/index.ts +137 -0
- package/src/options.ts +68 -0
- package/src/routes.ts +144 -0
- package/src/store.ts +164 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2016 Mihail Diordiev
|
|
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.
|
package/README.md
ADDED
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# Redux DevTools Command Line Interface
|
|
2
|
+
|
|
3
|
+
Bridge for remote debugging via [Redux DevTools extension](https://github.com/zalmoxisus/redux-devtools-extension), [Remote Redux DevTools](https://github.com/zalmoxisus/remote-redux-devtools) or [RemoteDev](https://github.com/zalmoxisus/remotedev).
|
|
4
|
+
|
|
5
|
+
### Usage
|
|
6
|
+
|
|
7
|
+
#### Install the package globally
|
|
8
|
+
|
|
9
|
+
with npm:
|
|
10
|
+
|
|
11
|
+
```
|
|
12
|
+
npm install -g @redux-devtools/cli
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
or with yarn:
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
yarn global add @redux-devtools/cli
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
and start as:
|
|
22
|
+
|
|
23
|
+
```
|
|
24
|
+
redux-devtools --hostname=localhost --port=8000
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
> Note the package is called `@redux-devtools/cli` not `redux-devtools` (the latter is a React component).
|
|
28
|
+
|
|
29
|
+
#### Or add in your project
|
|
30
|
+
|
|
31
|
+
with npm:
|
|
32
|
+
|
|
33
|
+
```
|
|
34
|
+
npm install --save-dev @redux-devtools/cli
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
or with yarn:
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
yarn add --dev @redux-devtools/cli
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
and add to `package.json`:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
"scripts": {
|
|
47
|
+
"redux-devtools": "redux-devtools --hostname=localhost --port=8000"
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
So, you can start redux-devtools server by running `npm run redux-devtools`.
|
|
52
|
+
|
|
53
|
+
##### Import in your `server.js` script you use for starting a development server:
|
|
54
|
+
|
|
55
|
+
```js
|
|
56
|
+
var reduxDevTools = require('@redux-devtools/cli');
|
|
57
|
+
reduxDevTools({ hostname: 'localhost', port: 8000 });
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
So, you can start redux-devtools server together with your dev server.
|
|
61
|
+
|
|
62
|
+
### Open Redux DevTools
|
|
63
|
+
|
|
64
|
+
You can add `--open` argument (or set it as `electron`) to open Redux DevTools as a standalone application:
|
|
65
|
+
|
|
66
|
+
```
|
|
67
|
+
redux-devtools --open
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
Set it as `browser` to open as a web app in the default browser instead:
|
|
71
|
+
|
|
72
|
+
```
|
|
73
|
+
redux-devtools --open=browser
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
To specify the browser:
|
|
77
|
+
|
|
78
|
+
```
|
|
79
|
+
redux-devtools --open=firefox
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Connection settings
|
|
83
|
+
|
|
84
|
+
Set `hostname` and `port` to the values you want. `hostname` by default is `localhost` and `port` is `8000`.
|
|
85
|
+
|
|
86
|
+
To use WSS, set `protocol` argument to `https` and provide `key`, `cert` and `passphrase` arguments.
|
|
87
|
+
|
|
88
|
+
#### Available options
|
|
89
|
+
|
|
90
|
+
| Console argument | description | default value |
|
|
91
|
+
| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------- |
|
|
92
|
+
| `--hostname` | hostname | localhost |
|
|
93
|
+
| `--port` | port | 8000 |
|
|
94
|
+
| `--protocol` | protocol | http |
|
|
95
|
+
| `--key` | the key file for [running an https server](https://github.com/SocketCluster/socketcluster#using-over-https) (`--protocol` must be set to 'https') | - |
|
|
96
|
+
| `--cert` | the cert file for [running an https server](https://github.com/SocketCluster/socketcluster#using-over-https) (`--protocol` must be set to 'https') | - |
|
|
97
|
+
| `--passphrase` | the key passphrase for [running an https server](https://github.com/SocketCluster/socketcluster#using-over-https) (`--protocol` must be set to 'https') | - |
|
|
98
|
+
| `--dbOptions` | database configuration, can be whether an object or a path (string) to json configuration file (by default it uses our `./defaultDbOptions.json` file. Set `migrate` key to `true` to use our migrations file. [More details bellow](#save-reports-and-logs). | - |
|
|
99
|
+
| `--logLevel` | the socket server log level - 0=none, 1=error, 2=warn, 3=info | 3 |
|
|
100
|
+
| `--wsEngine` | the socket server web socket engine - ws or uws (sc-uws) | ws |
|
|
101
|
+
| `--open` | open Redux DevTools as a standalone application or as web app. See [Open Redux DevTools](#open-redux-devtools) for details. | false |
|
|
102
|
+
|
|
103
|
+
### Inject to React Native local server
|
|
104
|
+
|
|
105
|
+
##### Add in your React Native app's `package.json`:
|
|
106
|
+
|
|
107
|
+
```
|
|
108
|
+
"scripts": {
|
|
109
|
+
"redux-devtools": "redux-devtools --hostname=localhost --port=8000 --injectserver=reactnative"
|
|
110
|
+
}
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
The `injectserver` value can be `reactnative` or `macos` ([react-native-macos](https://github.com/ptmt/react-native-macos)), it used `reactnative` by default.
|
|
114
|
+
|
|
115
|
+
Then, we can start React Native server and Redux DevTools server with one command (`npm start`).
|
|
116
|
+
|
|
117
|
+
##### Revert the injection
|
|
118
|
+
|
|
119
|
+
Add in your React Native app's `package.json`:
|
|
120
|
+
|
|
121
|
+
```
|
|
122
|
+
"scripts": {
|
|
123
|
+
"redux-devtools-revert": "redux-devtools --revert=reactnative"
|
|
124
|
+
}
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
Or just run `$(npm bin)/redux-devtools --revert`.
|
|
128
|
+
|
|
129
|
+
### Connect from Android device or emulator
|
|
130
|
+
|
|
131
|
+
> Note that if you're using `injectserver` argument explained above, this step is not necessary.
|
|
132
|
+
|
|
133
|
+
If you're running an Android 5.0+ device connected via USB or an Android emulator, use [adb command line tool](http://developer.android.com/tools/help/adb.html) to setup port forwarding from the device to your computer:
|
|
134
|
+
|
|
135
|
+
```
|
|
136
|
+
adb reverse tcp:8000 tcp:8000
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
If you're still use Android 4.0, you should use `10.0.2.2` (Genymotion: `10.0.3.2`) instead of `localhost` in [remote-redux-devtools](https://github.com/zalmoxisus/remote-redux-devtools#storeconfigurestorejs) or [remotedev](https://github.com/zalmoxisus/remotedev#usage).
|
|
140
|
+
|
|
141
|
+
### Save reports and logs
|
|
142
|
+
|
|
143
|
+
You can store reports via [`redux-remotedev`](https://github.com/zalmoxisus/redux-remotedev) and get them replicated with [Redux DevTools extension](https://github.com/zalmoxisus/redux-devtools-extension) or [Remote Redux DevTools](https://github.com/zalmoxisus/remote-redux-devtools). You can get action history right in the extension just by clicking the link from a report. Open `http://localhost:8000/graphql` (assuming you're using `localhost` as host and `8000`) to explore in GraphQL. Reports are posted to `http://localhost:8000/`. See examples in [tests](https://github.com/zalmoxisus/remotedev-server/blob/937cfa1f0ac9dc12ebf7068eeaa8b03022ec33bc/test/integration.spec.js#L110-L165).
|
|
144
|
+
|
|
145
|
+
Redux DevTools server is database agnostic using `knex` schema. By default everything is stored in the memory using sqlite database. See [`defaultDbOptions.json`](https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-cli/defaultDbOptions.json) for example of sqlite. You can replace `"connection": { "filename": ":memory:" },` with your file name (instead of `:memory:`) to persist teh database. Here's an example for PostgreSQL:
|
|
146
|
+
|
|
147
|
+
```
|
|
148
|
+
{
|
|
149
|
+
"client": "pg",
|
|
150
|
+
"connection": { "user": "myuser", "password": "mypassword", "database": "mydb" },
|
|
151
|
+
"debug": false,
|
|
152
|
+
"migrate": true
|
|
153
|
+
}
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Advanced
|
|
157
|
+
|
|
158
|
+
- [Writing your integration for a native application](https://github.com/reduxjs/redux-devtools/blob/master/docs/Integrations/Remote.md)
|
|
159
|
+
|
|
160
|
+
### License
|
|
161
|
+
|
|
162
|
+
MIT
|
package/app/electron.cjs
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// Based on https://github.com/electron/electron-quick-start
|
|
2
|
+
|
|
3
|
+
const { app, BrowserWindow } = require('electron');
|
|
4
|
+
const argv = require('minimist')(process.argv.slice(2));
|
|
5
|
+
|
|
6
|
+
function createWindow() {
|
|
7
|
+
const mainWindow = new BrowserWindow({
|
|
8
|
+
width: 800,
|
|
9
|
+
height: 600,
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const port = argv.port ? argv.port : 8000;
|
|
13
|
+
const host = argv.host ? argv.host : 'localhost';
|
|
14
|
+
const protocol = argv.protocol ? argv.protocol : 'http';
|
|
15
|
+
|
|
16
|
+
mainWindow.loadURL(protocol + '://' + host + ':' + port);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
app.whenReady().then(() => {
|
|
20
|
+
createWindow();
|
|
21
|
+
|
|
22
|
+
app.on('activate', function () {
|
|
23
|
+
if (BrowserWindow.getAllWindows().length === 0) createWindow();
|
|
24
|
+
});
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
app.on('window-all-closed', function () {
|
|
28
|
+
if (process.platform !== 'darwin') app.quit();
|
|
29
|
+
});
|
package/app/index.html
ADDED
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
<!doctype html>
|
|
2
|
+
<html>
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<title>Redux DevTools</title>
|
|
6
|
+
<style>
|
|
7
|
+
html {
|
|
8
|
+
min-width: 350px;
|
|
9
|
+
min-height: 300px;
|
|
10
|
+
}
|
|
11
|
+
body {
|
|
12
|
+
position: fixed;
|
|
13
|
+
overflow: hidden;
|
|
14
|
+
height: 100%;
|
|
15
|
+
width: 100%;
|
|
16
|
+
margin: 0;
|
|
17
|
+
padding: 0;
|
|
18
|
+
}
|
|
19
|
+
#root {
|
|
20
|
+
height: 100%;
|
|
21
|
+
}
|
|
22
|
+
#root > div {
|
|
23
|
+
height: 100%;
|
|
24
|
+
}
|
|
25
|
+
</style>
|
|
26
|
+
<link href="/redux-devtools-app.min.css" rel="stylesheet" />
|
|
27
|
+
</head>
|
|
28
|
+
<body>
|
|
29
|
+
<div id="root"></div>
|
|
30
|
+
<script src="/react.production.min.js"></script>
|
|
31
|
+
<script src="/react-dom.production.min.js"></script>
|
|
32
|
+
<script src="/redux-devtools-app.min.js"></script>
|
|
33
|
+
<script src="/port.js"></script>
|
|
34
|
+
<script>
|
|
35
|
+
const container = document.querySelector('#root');
|
|
36
|
+
const element = React.createElement(ReduxDevToolsApp.Root, {
|
|
37
|
+
socketOptions: {
|
|
38
|
+
hostname: location.hostname,
|
|
39
|
+
port: reduxDevToolsPort,
|
|
40
|
+
autoReconnect: true,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
ReactDOM.createRoot(container).render(element);
|
|
44
|
+
</script>
|
|
45
|
+
</body>
|
|
46
|
+
</html>
|
package/app/package.json
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Store } from '../store.js';
|
|
2
|
+
export declare const schema: string;
|
|
3
|
+
export declare const resolvers: {
|
|
4
|
+
Query: {
|
|
5
|
+
reports: (source: unknown, args: unknown, context: {
|
|
6
|
+
store: Store;
|
|
7
|
+
}) => Promise<import("../store.js").Report[]>;
|
|
8
|
+
report: (source: unknown, args: {
|
|
9
|
+
id: string;
|
|
10
|
+
}, context: {
|
|
11
|
+
store: Store;
|
|
12
|
+
}) => Promise<import("../store.js").Report | {
|
|
13
|
+
error: string;
|
|
14
|
+
}>;
|
|
15
|
+
};
|
|
16
|
+
};
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
export const schema = fs.readFileSync(new URL('./schema_def.graphql', import.meta.url), 'utf8');
|
|
3
|
+
export const resolvers = {
|
|
4
|
+
Query: {
|
|
5
|
+
reports: function report(source, args, context) {
|
|
6
|
+
return context.store.listAll();
|
|
7
|
+
},
|
|
8
|
+
report: function report(source, args, context) {
|
|
9
|
+
return context.store.get(args.id);
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
};
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# A list of options for the type of the report
|
|
2
|
+
enum ReportType {
|
|
3
|
+
STATE
|
|
4
|
+
ACTION
|
|
5
|
+
STATES
|
|
6
|
+
ACTIONS
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
type Report {
|
|
10
|
+
# Report ID
|
|
11
|
+
id: ID!
|
|
12
|
+
# Type of the report, can be: STATE, ACTION, STATES, ACTIONS
|
|
13
|
+
type: ReportType
|
|
14
|
+
# Briefly what happened
|
|
15
|
+
title: String
|
|
16
|
+
# Details supplied by the user
|
|
17
|
+
description: String
|
|
18
|
+
# The last dispatched action before the report was sent
|
|
19
|
+
action: String
|
|
20
|
+
# Stringified actions or the state or both, which should be loaded the application to reproduce the exact behavior
|
|
21
|
+
payload: String
|
|
22
|
+
# Stringified preloaded state object. Could be the initial state of the app or committed state (after dispatching COMMIT action or reaching maxAge)
|
|
23
|
+
preloadedState: String
|
|
24
|
+
# Screenshot url or blob as a string
|
|
25
|
+
screenshot: String
|
|
26
|
+
# User Agent String
|
|
27
|
+
userAgent: String
|
|
28
|
+
# Application version to group the reports and versioning
|
|
29
|
+
version: String
|
|
30
|
+
# Used to identify the user who sent the report
|
|
31
|
+
userId: String
|
|
32
|
+
# More detailed data about the user, usually it's a stringified object
|
|
33
|
+
user: String
|
|
34
|
+
# Everything else you want to send
|
|
35
|
+
meta: String
|
|
36
|
+
# Error message which invoked sending the report
|
|
37
|
+
exception: String
|
|
38
|
+
# Id to identify the store in case there are multiple stores
|
|
39
|
+
instanceId: String
|
|
40
|
+
# Timestamp when the report was added
|
|
41
|
+
added: String
|
|
42
|
+
# Id to identify the application (from apps table)
|
|
43
|
+
appId: ID
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
# Explore GraphQL query schema
|
|
47
|
+
type Query {
|
|
48
|
+
# List all reports
|
|
49
|
+
reports: [Report]
|
|
50
|
+
# Get a report by ID
|
|
51
|
+
report(
|
|
52
|
+
# Report ID
|
|
53
|
+
id: ID!
|
|
54
|
+
): Report
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
schema {
|
|
58
|
+
query: Query
|
|
59
|
+
#mutation: Mutation
|
|
60
|
+
}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import type { Options } from '../options.js';
|
|
2
|
+
export declare const dir = "local-cli/server";
|
|
3
|
+
export declare const file = "server.js";
|
|
4
|
+
export declare const fullPath: string;
|
|
5
|
+
export declare function inject(modulePath: string, options: Options, moduleName: string): boolean;
|
|
6
|
+
export declare function revert(modulePath: string, options: Options, moduleName: string): boolean;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import semver from 'semver';
|
|
4
|
+
const name = '@redux-devtools/cli';
|
|
5
|
+
const startFlag = '/* ' + name + ' start */';
|
|
6
|
+
const endFlag = '/* ' + name + ' end */';
|
|
7
|
+
const serverFlags = {
|
|
8
|
+
'react-native': {
|
|
9
|
+
'0.0.1': ' _server(argv, config, resolve, reject);',
|
|
10
|
+
'0.31.0': " runServer(args, config, () => console.log('\\nReact packager ready.\\n'));",
|
|
11
|
+
'0.44.0-rc.0': ' runServer(args, config, startedCallback, readyCallback);',
|
|
12
|
+
'0.46.0-rc.0': ' runServer(runServerArgs, configT, startedCallback, readyCallback);',
|
|
13
|
+
'0.57.0': ' runServer(args, configT);',
|
|
14
|
+
},
|
|
15
|
+
'react-native-desktop': {
|
|
16
|
+
'0.0.1': ' _server(argv, config, resolve, reject);',
|
|
17
|
+
},
|
|
18
|
+
};
|
|
19
|
+
function getModuleVersion(modulePath) {
|
|
20
|
+
return JSON.parse(fs.readFileSync(path.join(modulePath, 'package.json'), 'utf-8')).version;
|
|
21
|
+
}
|
|
22
|
+
function getServerFlag(moduleName, version) {
|
|
23
|
+
const flags = serverFlags[moduleName || 'react-native'];
|
|
24
|
+
const versions = Object.keys(flags);
|
|
25
|
+
let flag;
|
|
26
|
+
for (let i = 0; i < versions.length; i++) {
|
|
27
|
+
if (semver.gte(version, versions[i])) {
|
|
28
|
+
flag = flags[versions[i]];
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
return flag;
|
|
32
|
+
}
|
|
33
|
+
export const dir = 'local-cli/server';
|
|
34
|
+
export const file = 'server.js';
|
|
35
|
+
export const fullPath = path.join(dir, file);
|
|
36
|
+
export function inject(modulePath, options, moduleName) {
|
|
37
|
+
const filePath = path.join(modulePath, fullPath);
|
|
38
|
+
if (!fs.existsSync(filePath))
|
|
39
|
+
return false;
|
|
40
|
+
const serverFlag = getServerFlag(moduleName, getModuleVersion(modulePath));
|
|
41
|
+
const code = [
|
|
42
|
+
startFlag,
|
|
43
|
+
' require("' + name + '")(' + JSON.stringify(options) + ')',
|
|
44
|
+
' .then(_remotedev =>',
|
|
45
|
+
' _remotedev.ready.then(() => {',
|
|
46
|
+
' if (!_remotedev.portAlreadyUsed) console.log("-".repeat(80));',
|
|
47
|
+
' ' + serverFlag,
|
|
48
|
+
' })',
|
|
49
|
+
' );',
|
|
50
|
+
endFlag,
|
|
51
|
+
].join('\n');
|
|
52
|
+
const serverCode = fs.readFileSync(filePath, 'utf-8');
|
|
53
|
+
let start = serverCode.indexOf(startFlag); // already injected ?
|
|
54
|
+
let end = serverCode.indexOf(endFlag) + endFlag.length;
|
|
55
|
+
if (start === -1) {
|
|
56
|
+
start = serverCode.indexOf(serverFlag);
|
|
57
|
+
end = start + serverFlag.length;
|
|
58
|
+
}
|
|
59
|
+
fs.writeFileSync(filePath, serverCode.substr(0, start) +
|
|
60
|
+
code +
|
|
61
|
+
serverCode.substr(end, serverCode.length));
|
|
62
|
+
return true;
|
|
63
|
+
}
|
|
64
|
+
export function revert(modulePath, options, moduleName) {
|
|
65
|
+
const filePath = path.join(modulePath, fullPath);
|
|
66
|
+
if (!fs.existsSync(filePath))
|
|
67
|
+
return false;
|
|
68
|
+
const serverFlag = getServerFlag(moduleName, getModuleVersion(modulePath));
|
|
69
|
+
const serverCode = fs.readFileSync(filePath, 'utf-8');
|
|
70
|
+
const start = serverCode.indexOf(startFlag); // already injected ?
|
|
71
|
+
const end = serverCode.indexOf(endFlag) + endFlag.length;
|
|
72
|
+
if (start !== -1) {
|
|
73
|
+
fs.writeFileSync(filePath, serverCode.substr(0, start) +
|
|
74
|
+
serverFlag +
|
|
75
|
+
serverCode.substr(end, serverCode.length));
|
|
76
|
+
}
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import open from 'open';
|
|
2
|
+
import path from 'path';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import { createRequire } from 'module';
|
|
5
|
+
import spawn from 'cross-spawn';
|
|
6
|
+
const require = createRequire(import.meta.url);
|
|
7
|
+
export default async function openApp(app, options) {
|
|
8
|
+
if (app === true || app === 'electron') {
|
|
9
|
+
try {
|
|
10
|
+
const port = options.port ? `--port=${options.port}` : '';
|
|
11
|
+
const host = options.host ? `--host=${options.host}` : '';
|
|
12
|
+
const protocol = options.protocol ? `--protocol=${options.protocol}` : '';
|
|
13
|
+
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
14
|
+
spawn(require('electron'), [
|
|
15
|
+
path.join(path.dirname(fileURLToPath(import.meta.url)), '..', '..', 'app'),
|
|
16
|
+
port,
|
|
17
|
+
host,
|
|
18
|
+
protocol,
|
|
19
|
+
]);
|
|
20
|
+
}
|
|
21
|
+
catch (error) {
|
|
22
|
+
/* eslint-disable no-console */
|
|
23
|
+
if (error.message === "Cannot find module 'electron'") {
|
|
24
|
+
// TODO: Move electron to dev-dependences to make our package installation faster when not needed.
|
|
25
|
+
console.log(' \x1b[1;31m[Warn]\x1b[0m Electron module not installed.\n');
|
|
26
|
+
/*
|
|
27
|
+
We will use "npm" to install Electron via "npm install -D".
|
|
28
|
+
Do you want to install 'electron' (yes/no): yes
|
|
29
|
+
Installing 'electron' (running 'npm install -D webpack-cli')...
|
|
30
|
+
*/
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
console.log(error);
|
|
34
|
+
}
|
|
35
|
+
/* eslint-enable no-console */
|
|
36
|
+
}
|
|
37
|
+
return;
|
|
38
|
+
}
|
|
39
|
+
await open(`${options.protocol}://${options.host ?? 'localhost'}:${options.port}/`, app !== 'browser' ? { app: { name: app } } : undefined);
|
|
40
|
+
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
#! /usr/bin/env node
|
|
2
|
+
import fs from 'fs';
|
|
3
|
+
import path from 'path';
|
|
4
|
+
import parseArgs from 'minimist';
|
|
5
|
+
import chalk from 'chalk';
|
|
6
|
+
import * as injectServer from './injectServer.js';
|
|
7
|
+
import getOptions from '../options.js';
|
|
8
|
+
import server from '../index.js';
|
|
9
|
+
import openApp from './openApp.js';
|
|
10
|
+
const argv = parseArgs(process.argv.slice(2));
|
|
11
|
+
const options = getOptions(argv);
|
|
12
|
+
function readFile(filePath) {
|
|
13
|
+
return fs.readFileSync(path.resolve(process.cwd(), filePath), 'utf-8');
|
|
14
|
+
}
|
|
15
|
+
if (argv.protocol === 'https') {
|
|
16
|
+
argv.key = argv.key ? readFile(argv.key) : null;
|
|
17
|
+
argv.cert = argv.cert ? readFile(argv.cert) : null;
|
|
18
|
+
}
|
|
19
|
+
function log(pass, msg) {
|
|
20
|
+
const prefix = pass ? chalk.green.bgBlack('PASS') : chalk.red.bgBlack('FAIL');
|
|
21
|
+
const color = pass ? chalk.blue : chalk.red;
|
|
22
|
+
console.log(prefix, color(msg)); // eslint-disable-line no-console
|
|
23
|
+
}
|
|
24
|
+
function getModuleName(type) {
|
|
25
|
+
switch (type) {
|
|
26
|
+
case 'macos':
|
|
27
|
+
return 'react-native-macos';
|
|
28
|
+
// react-native-macos is renamed from react-native-desktop
|
|
29
|
+
case 'desktop':
|
|
30
|
+
return 'react-native-desktop';
|
|
31
|
+
case 'reactnative':
|
|
32
|
+
default:
|
|
33
|
+
return 'react-native';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function getModulePath(moduleName) {
|
|
37
|
+
return path.join(process.cwd(), 'node_modules', moduleName);
|
|
38
|
+
}
|
|
39
|
+
function getModule(type) {
|
|
40
|
+
let moduleName = getModuleName(type);
|
|
41
|
+
let modulePath = getModulePath(moduleName);
|
|
42
|
+
if (type === 'desktop' && !fs.existsSync(modulePath)) {
|
|
43
|
+
moduleName = getModuleName('macos');
|
|
44
|
+
modulePath = getModulePath(moduleName);
|
|
45
|
+
}
|
|
46
|
+
return {
|
|
47
|
+
name: moduleName,
|
|
48
|
+
path: modulePath,
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
function injectRN(type, msg) {
|
|
52
|
+
const module = getModule(type);
|
|
53
|
+
const fn = type === 'revert' ? injectServer.revert : injectServer.inject;
|
|
54
|
+
const pass = fn(module.path, options, module.name);
|
|
55
|
+
log(pass, msg +
|
|
56
|
+
(pass
|
|
57
|
+
? '.'
|
|
58
|
+
: ', the file `' +
|
|
59
|
+
path.join(module.name, injectServer.fullPath) +
|
|
60
|
+
'` not found.'));
|
|
61
|
+
process.exit(pass ? 0 : 1);
|
|
62
|
+
}
|
|
63
|
+
if (argv.revert) {
|
|
64
|
+
injectRN(argv.revert, 'Revert injection of ReduxDevTools server from React Native local server');
|
|
65
|
+
}
|
|
66
|
+
if (argv.injectserver) {
|
|
67
|
+
injectRN(argv.injectserver, 'Inject ReduxDevTools server into React Native local server');
|
|
68
|
+
}
|
|
69
|
+
const response = await server(argv);
|
|
70
|
+
if (argv.open && argv.open !== 'false') {
|
|
71
|
+
await response.ready;
|
|
72
|
+
await openApp(argv.open, options);
|
|
73
|
+
}
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { fileURLToPath } from 'url';
|
|
3
|
+
import knex from 'knex';
|
|
4
|
+
// HarmonyOS compatibility: knex's sqlite3 dialect hardcodes require('sqlite3'),
|
|
5
|
+
// but on HarmonyOS the driver is published as '@ohos-ports/sqlite3'. Install a
|
|
6
|
+
// module resolver alias so knex resolves 'sqlite3' to the HarmonyOS driver.
|
|
7
|
+
import { createRequire } from 'module';
|
|
8
|
+
const nodeRequire = createRequire(import.meta.url);
|
|
9
|
+
const nodeModule = nodeRequire('module');
|
|
10
|
+
const originalResolveFilename = nodeModule._resolveFilename;
|
|
11
|
+
nodeModule._resolveFilename = function (request, ...args) {
|
|
12
|
+
if (request === 'sqlite3') {
|
|
13
|
+
try {
|
|
14
|
+
request = nodeRequire.resolve('@ohos-ports/sqlite3');
|
|
15
|
+
}
|
|
16
|
+
catch {
|
|
17
|
+
// driver unavailable; fall through to the original resolver
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
return originalResolveFilename.call(this, request, ...args);
|
|
21
|
+
};
|
|
22
|
+
export default function connector(options) {
|
|
23
|
+
const dbOptions = options.dbOptions;
|
|
24
|
+
dbOptions.useNullAsDefault = true;
|
|
25
|
+
if (!dbOptions.migrate) {
|
|
26
|
+
return knex(dbOptions);
|
|
27
|
+
}
|
|
28
|
+
dbOptions.migrations = {
|
|
29
|
+
directory: path.join(path.dirname(fileURLToPath(import.meta.url)), 'migrations'),
|
|
30
|
+
};
|
|
31
|
+
dbOptions.seeds = {
|
|
32
|
+
directory: path.join(path.dirname(fileURLToPath(import.meta.url)), 'seeds'),
|
|
33
|
+
};
|
|
34
|
+
const knexInstance = knex(dbOptions);
|
|
35
|
+
/* eslint-disable no-console */
|
|
36
|
+
knexInstance.migrate
|
|
37
|
+
.latest({ loadExtensions: ['.js'] })
|
|
38
|
+
.then(function () {
|
|
39
|
+
return knexInstance.seed.run({ loadExtensions: ['.js'] });
|
|
40
|
+
})
|
|
41
|
+
.then(function () {
|
|
42
|
+
console.log(' \x1b[0;32m[Done]\x1b[0m Migrations are finished\n');
|
|
43
|
+
})
|
|
44
|
+
.catch(function (error) {
|
|
45
|
+
console.error(error);
|
|
46
|
+
});
|
|
47
|
+
/* eslint-enable no-console */
|
|
48
|
+
return knexInstance;
|
|
49
|
+
}
|