@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/src/routes.ts
ADDED
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import path from 'path';
|
|
2
|
+
import { createRequire } from 'module';
|
|
3
|
+
import { fileURLToPath } from 'url';
|
|
4
|
+
import express from 'express';
|
|
5
|
+
import type { Router } from 'express';
|
|
6
|
+
import morgan from 'morgan';
|
|
7
|
+
import * as http from 'http';
|
|
8
|
+
import bodyParser from 'body-parser';
|
|
9
|
+
import cors from 'cors';
|
|
10
|
+
import { AGServer } from 'socketcluster-server';
|
|
11
|
+
import { ApolloServer } from '@apollo/server';
|
|
12
|
+
import { expressMiddleware } from '@as-integrations/express5';
|
|
13
|
+
import type { AddData, ReportBaseFields, Store } from './store.js';
|
|
14
|
+
import { resolvers, schema } from './api/schema.js';
|
|
15
|
+
|
|
16
|
+
const app = express.Router();
|
|
17
|
+
|
|
18
|
+
const require = createRequire(import.meta.url);
|
|
19
|
+
|
|
20
|
+
function serveUmdModule(name: string) {
|
|
21
|
+
app.use(
|
|
22
|
+
express.static(
|
|
23
|
+
path.dirname(require.resolve(name + '/package.json')) + '/umd',
|
|
24
|
+
),
|
|
25
|
+
);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
interface Context {
|
|
29
|
+
store?: Store;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
function routes(
|
|
33
|
+
options: AGServer.AGServerOptions,
|
|
34
|
+
store: Store,
|
|
35
|
+
scServer: AGServer,
|
|
36
|
+
): Router {
|
|
37
|
+
const limit = options.maxRequestBody;
|
|
38
|
+
const logHTTPRequests = options.logHTTPRequests;
|
|
39
|
+
|
|
40
|
+
if (logHTTPRequests) {
|
|
41
|
+
if (typeof logHTTPRequests === 'object')
|
|
42
|
+
app.use(
|
|
43
|
+
morgan(
|
|
44
|
+
'combined',
|
|
45
|
+
logHTTPRequests as morgan.Options<
|
|
46
|
+
http.IncomingMessage,
|
|
47
|
+
http.ServerResponse
|
|
48
|
+
>,
|
|
49
|
+
),
|
|
50
|
+
);
|
|
51
|
+
else app.use(morgan('combined'));
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
const server = new ApolloServer<Context>({
|
|
55
|
+
typeDefs: schema,
|
|
56
|
+
resolvers,
|
|
57
|
+
});
|
|
58
|
+
server
|
|
59
|
+
.start()
|
|
60
|
+
.then(() => {
|
|
61
|
+
app.use(
|
|
62
|
+
'/graphql',
|
|
63
|
+
cors<cors.CorsRequest>(),
|
|
64
|
+
bodyParser.json(),
|
|
65
|
+
expressMiddleware(server, {
|
|
66
|
+
context: () => Promise.resolve({ store }),
|
|
67
|
+
}),
|
|
68
|
+
);
|
|
69
|
+
})
|
|
70
|
+
.catch((error) => {
|
|
71
|
+
console.error(error);
|
|
72
|
+
});
|
|
73
|
+
|
|
74
|
+
serveUmdModule('react');
|
|
75
|
+
serveUmdModule('react-dom');
|
|
76
|
+
serveUmdModule('@redux-devtools/app');
|
|
77
|
+
|
|
78
|
+
app.get('/port.js', function (req, res) {
|
|
79
|
+
res.send(`reduxDevToolsPort = ${options.port}`);
|
|
80
|
+
});
|
|
81
|
+
app.get('/{*splat}', function (req, res) {
|
|
82
|
+
res.sendFile(
|
|
83
|
+
path.join(
|
|
84
|
+
path.dirname(fileURLToPath(import.meta.url)),
|
|
85
|
+
'../app/index.html',
|
|
86
|
+
),
|
|
87
|
+
);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
app.use(cors({ methods: 'POST' }));
|
|
91
|
+
app.use(bodyParser.json({ limit: limit }));
|
|
92
|
+
app.use(bodyParser.urlencoded({ limit: limit, extended: false }));
|
|
93
|
+
|
|
94
|
+
app.post('/', function (req, res) {
|
|
95
|
+
if (!req.body) {
|
|
96
|
+
res.status(404).end();
|
|
97
|
+
return;
|
|
98
|
+
}
|
|
99
|
+
switch (req.body.op) {
|
|
100
|
+
case 'get':
|
|
101
|
+
store
|
|
102
|
+
.get(req.body.id as string)
|
|
103
|
+
.then(function (r) {
|
|
104
|
+
res.send(r || {});
|
|
105
|
+
})
|
|
106
|
+
.catch(function (error) {
|
|
107
|
+
console.error(error);
|
|
108
|
+
res.sendStatus(500);
|
|
109
|
+
});
|
|
110
|
+
break;
|
|
111
|
+
case 'list':
|
|
112
|
+
store
|
|
113
|
+
.list(req.body.query as string, req.body.fields as string[])
|
|
114
|
+
.then(function (r) {
|
|
115
|
+
res.send(r);
|
|
116
|
+
})
|
|
117
|
+
.catch(function (error) {
|
|
118
|
+
console.error(error);
|
|
119
|
+
res.sendStatus(500);
|
|
120
|
+
});
|
|
121
|
+
break;
|
|
122
|
+
default:
|
|
123
|
+
store
|
|
124
|
+
.add(req.body as AddData)
|
|
125
|
+
.then(function (r) {
|
|
126
|
+
res.send({
|
|
127
|
+
id: (r as ReportBaseFields).id,
|
|
128
|
+
error: (r as { error: string }).error,
|
|
129
|
+
});
|
|
130
|
+
void scServer.exchange.transmitPublish('report', {
|
|
131
|
+
type: 'add',
|
|
132
|
+
data: r,
|
|
133
|
+
});
|
|
134
|
+
})
|
|
135
|
+
.catch(function (error) {
|
|
136
|
+
console.error(error);
|
|
137
|
+
res.status(500).send({});
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
});
|
|
141
|
+
return app;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export default routes;
|
package/src/store.ts
ADDED
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
import { v4 as uuidV4 } from 'uuid';
|
|
2
|
+
import { pick } from 'lodash-es';
|
|
3
|
+
import { AGServer } from 'socketcluster-server';
|
|
4
|
+
import { Knex } from 'knex';
|
|
5
|
+
import connector from './db/connector.js';
|
|
6
|
+
|
|
7
|
+
const reports = 'remotedev_reports';
|
|
8
|
+
// var payloads = 'remotedev_payloads';
|
|
9
|
+
let knex: Knex;
|
|
10
|
+
|
|
11
|
+
const baseFields = ['id', 'title', 'added'];
|
|
12
|
+
|
|
13
|
+
function error(msg: string): Promise<{ error: string }> {
|
|
14
|
+
return new Promise(function (resolve) {
|
|
15
|
+
return resolve({ error: msg });
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
type ReportType = 'STATE' | 'ACTION' | 'STATES' | 'ACTIONS';
|
|
20
|
+
|
|
21
|
+
export interface Report {
|
|
22
|
+
id: string;
|
|
23
|
+
type: ReportType | null;
|
|
24
|
+
title: string | null;
|
|
25
|
+
description: string | null;
|
|
26
|
+
action: string | null;
|
|
27
|
+
payload: string;
|
|
28
|
+
preloadedState: string | null;
|
|
29
|
+
screenshot: string | null;
|
|
30
|
+
userAgent: string | null;
|
|
31
|
+
version: string | null;
|
|
32
|
+
userId: string | null;
|
|
33
|
+
user: string | null;
|
|
34
|
+
meta: string | null;
|
|
35
|
+
exception: string | null;
|
|
36
|
+
instanceId: string | null;
|
|
37
|
+
added: string | null;
|
|
38
|
+
appId?: string | null;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export interface ReportBaseFields {
|
|
42
|
+
id: string;
|
|
43
|
+
title: string | null;
|
|
44
|
+
added: string | null;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function list(query?: string, fields?: string[]): Promise<ReportBaseFields[]> {
|
|
48
|
+
const r = knex.select(fields || baseFields).from(reports);
|
|
49
|
+
if (query) return r.where(query);
|
|
50
|
+
return r;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
function listAll(query?: string): Promise<Report[]> {
|
|
54
|
+
const r = knex.select().from(reports);
|
|
55
|
+
if (query) return r.where(query);
|
|
56
|
+
return r;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function get(id: string): Promise<Report | { error: string }> {
|
|
60
|
+
if (!id) return error('No id specified.');
|
|
61
|
+
|
|
62
|
+
return knex(reports).where('id', id).first();
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
export interface AddData {
|
|
66
|
+
type: ReportType | null;
|
|
67
|
+
title: string | null;
|
|
68
|
+
description: string | null;
|
|
69
|
+
action: string | null;
|
|
70
|
+
payload: string;
|
|
71
|
+
preloadedState: string | null;
|
|
72
|
+
screenshot: string | null;
|
|
73
|
+
version: string | null;
|
|
74
|
+
userAgent: string | null;
|
|
75
|
+
userId: string | null;
|
|
76
|
+
user: { id: string } | string | null;
|
|
77
|
+
instanceId: string | null;
|
|
78
|
+
meta: string | null;
|
|
79
|
+
exception?: Error;
|
|
80
|
+
appId?: string | null;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function add(data: AddData): Promise<ReportBaseFields | { error: string }> {
|
|
84
|
+
if (!data.type || !data.payload) {
|
|
85
|
+
return error("Required parameters aren't specified.");
|
|
86
|
+
}
|
|
87
|
+
if (data.type !== 'ACTIONS' && data.type !== 'STATE') {
|
|
88
|
+
return error('Type ' + data.type + ' is not supported yet.');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const reportId = uuidV4();
|
|
92
|
+
const report: Report = {
|
|
93
|
+
id: reportId,
|
|
94
|
+
type: data.type,
|
|
95
|
+
title:
|
|
96
|
+
data.title || (data.exception && data.exception.message) || data.action,
|
|
97
|
+
description: data.description,
|
|
98
|
+
action: data.action,
|
|
99
|
+
payload: data.payload,
|
|
100
|
+
preloadedState: data.preloadedState,
|
|
101
|
+
screenshot: data.screenshot,
|
|
102
|
+
version: data.version,
|
|
103
|
+
userAgent: data.userAgent,
|
|
104
|
+
user: data.user as string,
|
|
105
|
+
userId:
|
|
106
|
+
typeof data.user === 'object'
|
|
107
|
+
? (data.user as { id: string }).id
|
|
108
|
+
: data.user,
|
|
109
|
+
instanceId: data.instanceId,
|
|
110
|
+
meta: data.meta,
|
|
111
|
+
exception: composeException(data.exception),
|
|
112
|
+
added: new Date().toISOString(),
|
|
113
|
+
};
|
|
114
|
+
if (data.appId) report.appId = data.appId; // TODO check if the id exists and we have access to link it
|
|
115
|
+
/*
|
|
116
|
+
var payload = {
|
|
117
|
+
id: uuid.v4(),
|
|
118
|
+
reportId: reportId,
|
|
119
|
+
state: data.payload
|
|
120
|
+
};
|
|
121
|
+
*/
|
|
122
|
+
|
|
123
|
+
return knex
|
|
124
|
+
.insert(report)
|
|
125
|
+
.into(reports)
|
|
126
|
+
.then(function () {
|
|
127
|
+
return byBaseFields(report);
|
|
128
|
+
});
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
function byBaseFields(data: Report): ReportBaseFields {
|
|
132
|
+
return pick(data, baseFields) as ReportBaseFields;
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export interface Store {
|
|
136
|
+
list: (query?: string, fields?: string[]) => Promise<ReportBaseFields[]>;
|
|
137
|
+
listAll: (query?: string) => Promise<Report[]>;
|
|
138
|
+
get: (id: string) => Promise<Report | { error: string }>;
|
|
139
|
+
add: (data: AddData) => Promise<ReportBaseFields | { error: string }>;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
function createStore(options: AGServer.AGServerOptions): Store {
|
|
143
|
+
knex = connector(options);
|
|
144
|
+
|
|
145
|
+
return {
|
|
146
|
+
list: list,
|
|
147
|
+
listAll: listAll,
|
|
148
|
+
get: get,
|
|
149
|
+
add: add,
|
|
150
|
+
};
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function composeException(exception: Error | undefined) {
|
|
154
|
+
let message = '';
|
|
155
|
+
|
|
156
|
+
if (exception) {
|
|
157
|
+
message = 'Exception thrown: ';
|
|
158
|
+
if (exception.message) message += exception.message;
|
|
159
|
+
if (exception.stack) message += '\n' + exception.stack;
|
|
160
|
+
}
|
|
161
|
+
return message;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
export default createStore;
|