@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
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
export function up(knex) {
|
|
2
|
+
return Promise.all([
|
|
3
|
+
knex.schema.createTable('remotedev_reports', function (table) {
|
|
4
|
+
table.uuid('id').primary();
|
|
5
|
+
table.string('type');
|
|
6
|
+
table.string('title');
|
|
7
|
+
table.string('description');
|
|
8
|
+
table.string('action');
|
|
9
|
+
table.text('payload', 'longtext');
|
|
10
|
+
table.text('preloadedState', 'longtext');
|
|
11
|
+
table.text('screenshot', 'longtext');
|
|
12
|
+
table.string('userAgent');
|
|
13
|
+
table.string('version');
|
|
14
|
+
table.string('user');
|
|
15
|
+
table.string('userId');
|
|
16
|
+
table.string('instanceId');
|
|
17
|
+
table.string('meta');
|
|
18
|
+
table.string('exception');
|
|
19
|
+
table.timestamp('added').defaultTo(knex.fn.now());
|
|
20
|
+
table
|
|
21
|
+
.uuid('appId')
|
|
22
|
+
.references('id')
|
|
23
|
+
.inTable('remotedev_apps')
|
|
24
|
+
.onDelete('CASCADE')
|
|
25
|
+
.onUpdate('CASCADE')
|
|
26
|
+
.defaultTo('78626c31-e16b-4528-b8e5-f81301b627f4');
|
|
27
|
+
}),
|
|
28
|
+
knex.schema.createTable('remotedev_payloads', function (table) {
|
|
29
|
+
table.uuid('id').primary();
|
|
30
|
+
table.text('state');
|
|
31
|
+
table.text('action');
|
|
32
|
+
table.timestamp('added').defaultTo(knex.fn.now());
|
|
33
|
+
table
|
|
34
|
+
.uuid('reportId')
|
|
35
|
+
.references('id')
|
|
36
|
+
.inTable('remotedev_reports')
|
|
37
|
+
.onDelete('CASCADE')
|
|
38
|
+
.onUpdate('CASCADE');
|
|
39
|
+
}),
|
|
40
|
+
knex.schema.createTable('remotedev_apps', function (table) {
|
|
41
|
+
table.uuid('id').primary();
|
|
42
|
+
table.string('title');
|
|
43
|
+
table.string('description');
|
|
44
|
+
table.string('url');
|
|
45
|
+
table.timestamps(false, true);
|
|
46
|
+
}),
|
|
47
|
+
knex.schema.createTable('remotedev_users', function (table) {
|
|
48
|
+
table.uuid('id').primary();
|
|
49
|
+
table.string('name');
|
|
50
|
+
table.string('login');
|
|
51
|
+
table.string('email');
|
|
52
|
+
table.string('avatarUrl');
|
|
53
|
+
table.string('profileUrl');
|
|
54
|
+
table.string('oauthId');
|
|
55
|
+
table.string('oauthType');
|
|
56
|
+
table.string('token');
|
|
57
|
+
table.timestamps(false, true);
|
|
58
|
+
}),
|
|
59
|
+
knex.schema.createTable('remotedev_users_apps', function (table) {
|
|
60
|
+
table.boolean('readOnly').defaultTo(false);
|
|
61
|
+
table.uuid('userId');
|
|
62
|
+
table.uuid('appId');
|
|
63
|
+
table.primary(['userId', 'appId']);
|
|
64
|
+
table
|
|
65
|
+
.foreign('userId')
|
|
66
|
+
.references('id')
|
|
67
|
+
.inTable('remotedev_users')
|
|
68
|
+
.onDelete('CASCADE')
|
|
69
|
+
.onUpdate('CASCADE');
|
|
70
|
+
table
|
|
71
|
+
.foreign('appId')
|
|
72
|
+
.references('id')
|
|
73
|
+
.inTable('remotedev_apps')
|
|
74
|
+
.onDelete('CASCADE')
|
|
75
|
+
.onUpdate('CASCADE');
|
|
76
|
+
}),
|
|
77
|
+
]);
|
|
78
|
+
}
|
|
79
|
+
export function down(knex) {
|
|
80
|
+
return Promise.all([
|
|
81
|
+
knex.schema.dropTable('remotedev_reports'),
|
|
82
|
+
knex.schema.dropTable('remotedev_apps'),
|
|
83
|
+
]);
|
|
84
|
+
}
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
import express from 'express';
|
|
2
|
+
import http from 'http';
|
|
3
|
+
import getPort from 'get-port';
|
|
4
|
+
import socketClusterServer from 'socketcluster-server';
|
|
5
|
+
import getOptions from './options.js';
|
|
6
|
+
import routes from './routes.js';
|
|
7
|
+
import createStore from './store.js';
|
|
8
|
+
// const LOG_LEVEL_NONE = 0;
|
|
9
|
+
// const LOG_LEVEL_ERROR = 1;
|
|
10
|
+
const LOG_LEVEL_WARN = 2;
|
|
11
|
+
const LOG_LEVEL_INFO = 3;
|
|
12
|
+
export default async function (argv) {
|
|
13
|
+
const options = Object.assign(getOptions(argv), {
|
|
14
|
+
allowClientPublish: false,
|
|
15
|
+
});
|
|
16
|
+
const port = options.port;
|
|
17
|
+
const logLevel = options.logLevel === undefined ? LOG_LEVEL_INFO : options.logLevel;
|
|
18
|
+
// Check port already used
|
|
19
|
+
const p = await getPort({ port });
|
|
20
|
+
if (port !== p) {
|
|
21
|
+
if (logLevel >= LOG_LEVEL_WARN) {
|
|
22
|
+
console.log(`[ReduxDevTools] Server port ${port} is already used.`);
|
|
23
|
+
}
|
|
24
|
+
return {
|
|
25
|
+
portAlreadyUsed: true,
|
|
26
|
+
ready: Promise.resolve(),
|
|
27
|
+
};
|
|
28
|
+
}
|
|
29
|
+
if (logLevel >= LOG_LEVEL_INFO) {
|
|
30
|
+
console.log('[ReduxDevTools] Start server...');
|
|
31
|
+
console.log('-'.repeat(80) + '\n');
|
|
32
|
+
}
|
|
33
|
+
const httpServer = http.createServer();
|
|
34
|
+
const agServer = socketClusterServer.attach(httpServer, options);
|
|
35
|
+
const app = express();
|
|
36
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
37
|
+
httpServer.on('request', app);
|
|
38
|
+
const store = createStore(options);
|
|
39
|
+
app.use(routes(options, store, agServer));
|
|
40
|
+
agServer.setMiddleware(agServer.MIDDLEWARE_INBOUND,
|
|
41
|
+
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
|
42
|
+
async (middlewareStream) => {
|
|
43
|
+
for await (const action of middlewareStream) {
|
|
44
|
+
if (action.type === action.TRANSMIT) {
|
|
45
|
+
const channel = action.receiver;
|
|
46
|
+
const data = action.data;
|
|
47
|
+
if (channel.substring(0, 3) === 'sc-' ||
|
|
48
|
+
channel === 'respond' ||
|
|
49
|
+
channel === 'log') {
|
|
50
|
+
void agServer.exchange.transmitPublish(channel, data);
|
|
51
|
+
}
|
|
52
|
+
else if (channel === 'log-noid') {
|
|
53
|
+
void agServer.exchange.transmitPublish('log', {
|
|
54
|
+
id: action.socket.id,
|
|
55
|
+
data: data,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
else if (action.type === action.SUBSCRIBE) {
|
|
60
|
+
if (action.channel === 'report') {
|
|
61
|
+
store
|
|
62
|
+
.list()
|
|
63
|
+
.then(function (data) {
|
|
64
|
+
void agServer.exchange.transmitPublish('report', {
|
|
65
|
+
type: 'list',
|
|
66
|
+
data: data,
|
|
67
|
+
});
|
|
68
|
+
})
|
|
69
|
+
.catch(function (error) {
|
|
70
|
+
console.error(error);
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
action.allow();
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
void (async () => {
|
|
78
|
+
for await (const { socket } of agServer.listener('connection')) {
|
|
79
|
+
let channelToWatch, channelToEmit;
|
|
80
|
+
void (async () => {
|
|
81
|
+
for await (const request of socket.procedure('login')) {
|
|
82
|
+
const credentials = request.data;
|
|
83
|
+
if (credentials === 'master') {
|
|
84
|
+
channelToWatch = 'respond';
|
|
85
|
+
channelToEmit = 'log';
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
channelToWatch = 'log';
|
|
89
|
+
channelToEmit = 'respond';
|
|
90
|
+
}
|
|
91
|
+
request.end(channelToWatch);
|
|
92
|
+
}
|
|
93
|
+
})();
|
|
94
|
+
void (async () => {
|
|
95
|
+
for await (const request of socket.procedure('getReport')) {
|
|
96
|
+
const id = request.data;
|
|
97
|
+
store
|
|
98
|
+
.get(id)
|
|
99
|
+
.then(function (data) {
|
|
100
|
+
request.end(data);
|
|
101
|
+
})
|
|
102
|
+
.catch(function (error) {
|
|
103
|
+
console.error(error);
|
|
104
|
+
});
|
|
105
|
+
}
|
|
106
|
+
})();
|
|
107
|
+
void (async () => {
|
|
108
|
+
for await (const data of socket.listener('disconnect')) {
|
|
109
|
+
const channel = agServer.exchange.channel('sc-' + socket.id);
|
|
110
|
+
channel.unsubscribe();
|
|
111
|
+
void agServer.exchange.transmitPublish(channelToEmit, {
|
|
112
|
+
id: socket.id,
|
|
113
|
+
type: 'DISCONNECTED',
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
})();
|
|
117
|
+
}
|
|
118
|
+
})();
|
|
119
|
+
httpServer.listen(options.port);
|
|
120
|
+
return {
|
|
121
|
+
ready: (async () => {
|
|
122
|
+
await agServer.listener('ready').once();
|
|
123
|
+
})(),
|
|
124
|
+
};
|
|
125
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
interface ProtocolOptions {
|
|
2
|
+
key: string | undefined;
|
|
3
|
+
cert: string | undefined;
|
|
4
|
+
passphrase: string | undefined;
|
|
5
|
+
}
|
|
6
|
+
interface DbOptions {
|
|
7
|
+
client: string;
|
|
8
|
+
connection: {
|
|
9
|
+
filename: string;
|
|
10
|
+
};
|
|
11
|
+
useNullAsDefault: boolean;
|
|
12
|
+
debug: boolean;
|
|
13
|
+
migrate: boolean;
|
|
14
|
+
}
|
|
15
|
+
export interface Options {
|
|
16
|
+
host: string | undefined;
|
|
17
|
+
port: number;
|
|
18
|
+
protocol: 'http' | 'https';
|
|
19
|
+
protocolOptions: ProtocolOptions | undefined;
|
|
20
|
+
dbOptions: DbOptions;
|
|
21
|
+
maxRequestBody: string;
|
|
22
|
+
logHTTPRequests?: boolean;
|
|
23
|
+
logLevel: 0 | 1 | 3 | 2;
|
|
24
|
+
wsEngine: string;
|
|
25
|
+
}
|
|
26
|
+
export default function getOptions(argv: {
|
|
27
|
+
[arg: string]: any;
|
|
28
|
+
}): Options;
|
|
29
|
+
export {};
|
package/dist/options.js
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
export default function getOptions(argv) {
|
|
3
|
+
let dbOptions = argv.dbOptions;
|
|
4
|
+
if (typeof dbOptions === 'string') {
|
|
5
|
+
dbOptions = JSON.parse(fs.readFileSync(dbOptions, 'utf8'));
|
|
6
|
+
}
|
|
7
|
+
else if (typeof dbOptions === 'undefined') {
|
|
8
|
+
dbOptions = JSON.parse(fs.readFileSync(new URL('../defaultDbOptions.json', import.meta.url), 'utf8'));
|
|
9
|
+
}
|
|
10
|
+
return {
|
|
11
|
+
host: argv.hostname || process.env.npm_package_remotedev_hostname || undefined,
|
|
12
|
+
port: Number(argv.port || process.env.npm_package_remotedev_port) || 8000,
|
|
13
|
+
protocol: argv.protocol || process.env.npm_package_remotedev_protocol || 'http',
|
|
14
|
+
protocolOptions: !(argv.protocol === 'https')
|
|
15
|
+
? undefined
|
|
16
|
+
: {
|
|
17
|
+
key: argv.key || process.env.npm_package_remotedev_key || undefined,
|
|
18
|
+
cert: argv.cert || process.env.npm_package_remotedev_cert || undefined,
|
|
19
|
+
passphrase: argv.passphrase ||
|
|
20
|
+
process.env.npm_package_remotedev_passphrase ||
|
|
21
|
+
undefined,
|
|
22
|
+
},
|
|
23
|
+
dbOptions: dbOptions,
|
|
24
|
+
maxRequestBody: argv.passphrase || '16mb',
|
|
25
|
+
logHTTPRequests: argv.logHTTPRequests,
|
|
26
|
+
logLevel: argv.logLevel || 3,
|
|
27
|
+
wsEngine: argv.wsEngine || process.env.npm_package_remotedev_wsengine || 'ws',
|
|
28
|
+
};
|
|
29
|
+
}
|
package/dist/routes.d.ts
ADDED
package/dist/routes.js
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import express from 'express';
|
|
5
|
+
import morgan from 'morgan';
|
|
6
|
+
import bodyParser from 'body-parser';
|
|
7
|
+
import cors from 'cors';
|
|
8
|
+
import { ApolloServer } from '@apollo/server';
|
|
9
|
+
import { expressMiddleware } from '@as-integrations/express5';
|
|
10
|
+
import { resolvers, schema } from './api/schema.js';
|
|
11
|
+
const app = express.Router();
|
|
12
|
+
const require = createRequire(import.meta.url);
|
|
13
|
+
function serveUmdModule(name) {
|
|
14
|
+
app.use(express.static(path.dirname(require.resolve(name + '/package.json')) + '/umd'));
|
|
15
|
+
}
|
|
16
|
+
function routes(options, store, scServer) {
|
|
17
|
+
const limit = options.maxRequestBody;
|
|
18
|
+
const logHTTPRequests = options.logHTTPRequests;
|
|
19
|
+
if (logHTTPRequests) {
|
|
20
|
+
if (typeof logHTTPRequests === 'object')
|
|
21
|
+
app.use(morgan('combined', logHTTPRequests));
|
|
22
|
+
else
|
|
23
|
+
app.use(morgan('combined'));
|
|
24
|
+
}
|
|
25
|
+
const server = new ApolloServer({
|
|
26
|
+
typeDefs: schema,
|
|
27
|
+
resolvers,
|
|
28
|
+
});
|
|
29
|
+
server
|
|
30
|
+
.start()
|
|
31
|
+
.then(() => {
|
|
32
|
+
app.use('/graphql', cors(), bodyParser.json(), expressMiddleware(server, {
|
|
33
|
+
context: () => Promise.resolve({ store }),
|
|
34
|
+
}));
|
|
35
|
+
})
|
|
36
|
+
.catch((error) => {
|
|
37
|
+
console.error(error);
|
|
38
|
+
});
|
|
39
|
+
serveUmdModule('react');
|
|
40
|
+
serveUmdModule('react-dom');
|
|
41
|
+
serveUmdModule('@redux-devtools/app');
|
|
42
|
+
app.get('/port.js', function (req, res) {
|
|
43
|
+
res.send(`reduxDevToolsPort = ${options.port}`);
|
|
44
|
+
});
|
|
45
|
+
app.get('/{*splat}', function (req, res) {
|
|
46
|
+
res.sendFile(path.join(path.dirname(fileURLToPath(import.meta.url)), '../app/index.html'));
|
|
47
|
+
});
|
|
48
|
+
app.use(cors({ methods: 'POST' }));
|
|
49
|
+
app.use(bodyParser.json({ limit: limit }));
|
|
50
|
+
app.use(bodyParser.urlencoded({ limit: limit, extended: false }));
|
|
51
|
+
app.post('/', function (req, res) {
|
|
52
|
+
if (!req.body) {
|
|
53
|
+
res.status(404).end();
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
switch (req.body.op) {
|
|
57
|
+
case 'get':
|
|
58
|
+
store
|
|
59
|
+
.get(req.body.id)
|
|
60
|
+
.then(function (r) {
|
|
61
|
+
res.send(r || {});
|
|
62
|
+
})
|
|
63
|
+
.catch(function (error) {
|
|
64
|
+
console.error(error);
|
|
65
|
+
res.sendStatus(500);
|
|
66
|
+
});
|
|
67
|
+
break;
|
|
68
|
+
case 'list':
|
|
69
|
+
store
|
|
70
|
+
.list(req.body.query, req.body.fields)
|
|
71
|
+
.then(function (r) {
|
|
72
|
+
res.send(r);
|
|
73
|
+
})
|
|
74
|
+
.catch(function (error) {
|
|
75
|
+
console.error(error);
|
|
76
|
+
res.sendStatus(500);
|
|
77
|
+
});
|
|
78
|
+
break;
|
|
79
|
+
default:
|
|
80
|
+
store
|
|
81
|
+
.add(req.body)
|
|
82
|
+
.then(function (r) {
|
|
83
|
+
res.send({
|
|
84
|
+
id: r.id,
|
|
85
|
+
error: r.error,
|
|
86
|
+
});
|
|
87
|
+
void scServer.exchange.transmitPublish('report', {
|
|
88
|
+
type: 'add',
|
|
89
|
+
data: r,
|
|
90
|
+
});
|
|
91
|
+
})
|
|
92
|
+
.catch(function (error) {
|
|
93
|
+
console.error(error);
|
|
94
|
+
res.status(500).send({});
|
|
95
|
+
});
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
return app;
|
|
99
|
+
}
|
|
100
|
+
export default routes;
|
package/dist/store.d.ts
ADDED
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { AGServer } from 'socketcluster-server';
|
|
2
|
+
type ReportType = 'STATE' | 'ACTION' | 'STATES' | 'ACTIONS';
|
|
3
|
+
export interface Report {
|
|
4
|
+
id: string;
|
|
5
|
+
type: ReportType | null;
|
|
6
|
+
title: string | null;
|
|
7
|
+
description: string | null;
|
|
8
|
+
action: string | null;
|
|
9
|
+
payload: string;
|
|
10
|
+
preloadedState: string | null;
|
|
11
|
+
screenshot: string | null;
|
|
12
|
+
userAgent: string | null;
|
|
13
|
+
version: string | null;
|
|
14
|
+
userId: string | null;
|
|
15
|
+
user: string | null;
|
|
16
|
+
meta: string | null;
|
|
17
|
+
exception: string | null;
|
|
18
|
+
instanceId: string | null;
|
|
19
|
+
added: string | null;
|
|
20
|
+
appId?: string | null;
|
|
21
|
+
}
|
|
22
|
+
export interface ReportBaseFields {
|
|
23
|
+
id: string;
|
|
24
|
+
title: string | null;
|
|
25
|
+
added: string | null;
|
|
26
|
+
}
|
|
27
|
+
export interface AddData {
|
|
28
|
+
type: ReportType | null;
|
|
29
|
+
title: string | null;
|
|
30
|
+
description: string | null;
|
|
31
|
+
action: string | null;
|
|
32
|
+
payload: string;
|
|
33
|
+
preloadedState: string | null;
|
|
34
|
+
screenshot: string | null;
|
|
35
|
+
version: string | null;
|
|
36
|
+
userAgent: string | null;
|
|
37
|
+
userId: string | null;
|
|
38
|
+
user: {
|
|
39
|
+
id: string;
|
|
40
|
+
} | string | null;
|
|
41
|
+
instanceId: string | null;
|
|
42
|
+
meta: string | null;
|
|
43
|
+
exception?: Error;
|
|
44
|
+
appId?: string | null;
|
|
45
|
+
}
|
|
46
|
+
export interface Store {
|
|
47
|
+
list: (query?: string, fields?: string[]) => Promise<ReportBaseFields[]>;
|
|
48
|
+
listAll: (query?: string) => Promise<Report[]>;
|
|
49
|
+
get: (id: string) => Promise<Report | {
|
|
50
|
+
error: string;
|
|
51
|
+
}>;
|
|
52
|
+
add: (data: AddData) => Promise<ReportBaseFields | {
|
|
53
|
+
error: string;
|
|
54
|
+
}>;
|
|
55
|
+
}
|
|
56
|
+
declare function createStore(options: AGServer.AGServerOptions): Store;
|
|
57
|
+
export default createStore;
|
package/dist/store.js
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { v4 as uuidV4 } from 'uuid';
|
|
2
|
+
import { pick } from 'lodash-es';
|
|
3
|
+
import connector from './db/connector.js';
|
|
4
|
+
const reports = 'remotedev_reports';
|
|
5
|
+
// var payloads = 'remotedev_payloads';
|
|
6
|
+
let knex;
|
|
7
|
+
const baseFields = ['id', 'title', 'added'];
|
|
8
|
+
function error(msg) {
|
|
9
|
+
return new Promise(function (resolve) {
|
|
10
|
+
return resolve({ error: msg });
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
function list(query, fields) {
|
|
14
|
+
const r = knex.select(fields || baseFields).from(reports);
|
|
15
|
+
if (query)
|
|
16
|
+
return r.where(query);
|
|
17
|
+
return r;
|
|
18
|
+
}
|
|
19
|
+
function listAll(query) {
|
|
20
|
+
const r = knex.select().from(reports);
|
|
21
|
+
if (query)
|
|
22
|
+
return r.where(query);
|
|
23
|
+
return r;
|
|
24
|
+
}
|
|
25
|
+
function get(id) {
|
|
26
|
+
if (!id)
|
|
27
|
+
return error('No id specified.');
|
|
28
|
+
return knex(reports).where('id', id).first();
|
|
29
|
+
}
|
|
30
|
+
function add(data) {
|
|
31
|
+
if (!data.type || !data.payload) {
|
|
32
|
+
return error("Required parameters aren't specified.");
|
|
33
|
+
}
|
|
34
|
+
if (data.type !== 'ACTIONS' && data.type !== 'STATE') {
|
|
35
|
+
return error('Type ' + data.type + ' is not supported yet.');
|
|
36
|
+
}
|
|
37
|
+
const reportId = uuidV4();
|
|
38
|
+
const report = {
|
|
39
|
+
id: reportId,
|
|
40
|
+
type: data.type,
|
|
41
|
+
title: data.title || (data.exception && data.exception.message) || data.action,
|
|
42
|
+
description: data.description,
|
|
43
|
+
action: data.action,
|
|
44
|
+
payload: data.payload,
|
|
45
|
+
preloadedState: data.preloadedState,
|
|
46
|
+
screenshot: data.screenshot,
|
|
47
|
+
version: data.version,
|
|
48
|
+
userAgent: data.userAgent,
|
|
49
|
+
user: data.user,
|
|
50
|
+
userId: typeof data.user === 'object'
|
|
51
|
+
? data.user.id
|
|
52
|
+
: data.user,
|
|
53
|
+
instanceId: data.instanceId,
|
|
54
|
+
meta: data.meta,
|
|
55
|
+
exception: composeException(data.exception),
|
|
56
|
+
added: new Date().toISOString(),
|
|
57
|
+
};
|
|
58
|
+
if (data.appId)
|
|
59
|
+
report.appId = data.appId; // TODO check if the id exists and we have access to link it
|
|
60
|
+
/*
|
|
61
|
+
var payload = {
|
|
62
|
+
id: uuid.v4(),
|
|
63
|
+
reportId: reportId,
|
|
64
|
+
state: data.payload
|
|
65
|
+
};
|
|
66
|
+
*/
|
|
67
|
+
return knex
|
|
68
|
+
.insert(report)
|
|
69
|
+
.into(reports)
|
|
70
|
+
.then(function () {
|
|
71
|
+
return byBaseFields(report);
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
function byBaseFields(data) {
|
|
75
|
+
return pick(data, baseFields);
|
|
76
|
+
}
|
|
77
|
+
function createStore(options) {
|
|
78
|
+
knex = connector(options);
|
|
79
|
+
return {
|
|
80
|
+
list: list,
|
|
81
|
+
listAll: listAll,
|
|
82
|
+
get: get,
|
|
83
|
+
add: add,
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
function composeException(exception) {
|
|
87
|
+
let message = '';
|
|
88
|
+
if (exception) {
|
|
89
|
+
message = 'Exception thrown: ';
|
|
90
|
+
if (exception.message)
|
|
91
|
+
message += exception.message;
|
|
92
|
+
if (exception.stack)
|
|
93
|
+
message += '\n' + exception.stack;
|
|
94
|
+
}
|
|
95
|
+
return message;
|
|
96
|
+
}
|
|
97
|
+
export default createStore;
|
package/package.json
ADDED
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@ohos-ports/redux-devtools-cli",
|
|
3
|
+
"version": "5.0.0-beta.0",
|
|
4
|
+
"description": "CLI for remote debugging with Redux DevTools.",
|
|
5
|
+
"homepage": "https://github.com/reduxjs/redux-devtools/tree/master/packages/redux-devtools-cli",
|
|
6
|
+
"bugs": {
|
|
7
|
+
"url": "https://github.com/ohos-ports/ohos-ports/issues"
|
|
8
|
+
},
|
|
9
|
+
"license": "MIT",
|
|
10
|
+
"author": "Mihail Diordiev <zalmoxisus@gmail.com> (https://github.com/zalmoxisus)",
|
|
11
|
+
"files": [
|
|
12
|
+
"bin",
|
|
13
|
+
"dist",
|
|
14
|
+
"src",
|
|
15
|
+
"app",
|
|
16
|
+
"index.js",
|
|
17
|
+
"defaultDbOptions.json"
|
|
18
|
+
],
|
|
19
|
+
"type": "module",
|
|
20
|
+
"main": "dist/index.js",
|
|
21
|
+
"types": "dist/index.d.ts",
|
|
22
|
+
"bin": {
|
|
23
|
+
"redux-devtools": "bin/redux-devtools.js"
|
|
24
|
+
},
|
|
25
|
+
"repository": {
|
|
26
|
+
"type": "git",
|
|
27
|
+
"url": "https://github.com/ohos-ports/ohos-ports.git",
|
|
28
|
+
"directory": "ports/redux-devtools-cli/5.0.0"
|
|
29
|
+
},
|
|
30
|
+
"engines": {
|
|
31
|
+
"node": ">=20"
|
|
32
|
+
},
|
|
33
|
+
"dependencies": {
|
|
34
|
+
"@apollo/server": "^5.2.0",
|
|
35
|
+
"@as-integrations/express5": "^1.1.2",
|
|
36
|
+
"@emotion/react": "^11.14.0",
|
|
37
|
+
"@emotion/styled": "^11.14.1",
|
|
38
|
+
"@reduxjs/toolkit": "^2.11.2",
|
|
39
|
+
"@types/react": "^19.2.14",
|
|
40
|
+
"body-parser": "^2.2.2",
|
|
41
|
+
"chalk": "^5.6.2",
|
|
42
|
+
"cors": "^2.8.6",
|
|
43
|
+
"cross-spawn": "^7.0.6",
|
|
44
|
+
"electron": "^31.7.7",
|
|
45
|
+
"express": "^5.2.1",
|
|
46
|
+
"get-port": "^7.1.0",
|
|
47
|
+
"graphql": "^16.13.0",
|
|
48
|
+
"knex": "^3.1.0",
|
|
49
|
+
"lodash-es": "^4.17.23",
|
|
50
|
+
"minimist": "^1.2.8",
|
|
51
|
+
"morgan": "^1.10.1",
|
|
52
|
+
"open": "^11.0.0",
|
|
53
|
+
"react": "^19.2.4",
|
|
54
|
+
"react-dom": "^19.2.4",
|
|
55
|
+
"react-is": "^19.2.4",
|
|
56
|
+
"semver": "^7.7.4",
|
|
57
|
+
"socketcluster-server": "^20.0.0",
|
|
58
|
+
"@ohos-ports/sqlite3": "^5.1.7-beta.0",
|
|
59
|
+
"uuid": "^13.0.0",
|
|
60
|
+
"@redux-devtools/app": "^8.0.0"
|
|
61
|
+
},
|
|
62
|
+
"devDependencies": {
|
|
63
|
+
"@jest/globals": "^30.2.0",
|
|
64
|
+
"@types/body-parser": "^1.19.6",
|
|
65
|
+
"@types/cors": "^2.8.19",
|
|
66
|
+
"@types/cross-spawn": "^6.0.6",
|
|
67
|
+
"@types/express": "^5.0.6",
|
|
68
|
+
"@types/jest": "^30.0.0",
|
|
69
|
+
"@types/lodash-es": "^4.17.12",
|
|
70
|
+
"@types/minimist": "^1.2.5",
|
|
71
|
+
"@types/morgan": "^1.9.10",
|
|
72
|
+
"@types/node": "^24.11.0",
|
|
73
|
+
"@types/semver": "^7.7.1",
|
|
74
|
+
"@types/socketcluster-client": "^20.0.0",
|
|
75
|
+
"@types/socketcluster-server": "^20.0.0",
|
|
76
|
+
"@types/supertest": "^7.2.0",
|
|
77
|
+
"@types/uuid": "^11.0.0",
|
|
78
|
+
"globals": "^17.4.0",
|
|
79
|
+
"jest": "^30.2.0",
|
|
80
|
+
"ncp": "^2.0.0",
|
|
81
|
+
"rimraf": "^6.1.3",
|
|
82
|
+
"socketcluster-client": "^20.0.1",
|
|
83
|
+
"supertest": "^7.2.2",
|
|
84
|
+
"ts-jest": "^29.4.6",
|
|
85
|
+
"typescript": "~5.9.3"
|
|
86
|
+
},
|
|
87
|
+
"scripts": {
|
|
88
|
+
"build": "tsc && ncp ./src/api/schema_def.graphql ./dist/api/schema_def.graphql",
|
|
89
|
+
"start": "node ./bin/redux-devtools.js",
|
|
90
|
+
"start:electron": "node ./bin/redux-devtools.js --open",
|
|
91
|
+
"clean": "rimraf dist",
|
|
92
|
+
"test": "node --experimental-vm-modules node_modules/jest/bin/jest.js",
|
|
93
|
+
"lint": "eslint .",
|
|
94
|
+
"type-check": "tsc --noEmit",
|
|
95
|
+
"prepublish": "pnpm run type-check && pnpm run lint && pnpm run test"
|
|
96
|
+
}
|
|
97
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import type { Store } from '../store.js';
|
|
3
|
+
|
|
4
|
+
export const schema = fs.readFileSync(
|
|
5
|
+
new URL('./schema_def.graphql', import.meta.url),
|
|
6
|
+
'utf8',
|
|
7
|
+
);
|
|
8
|
+
|
|
9
|
+
export const resolvers = {
|
|
10
|
+
Query: {
|
|
11
|
+
reports: function report(
|
|
12
|
+
source: unknown,
|
|
13
|
+
args: unknown,
|
|
14
|
+
context: { store: Store },
|
|
15
|
+
) {
|
|
16
|
+
return context.store.listAll();
|
|
17
|
+
},
|
|
18
|
+
report: function report(
|
|
19
|
+
source: unknown,
|
|
20
|
+
args: { id: string },
|
|
21
|
+
context: { store: Store },
|
|
22
|
+
) {
|
|
23
|
+
return context.store.get(args.id);
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
};
|