@myop/cli 0.1.4 β 0.1.5
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/dist/myop-cli.js
ADDED
|
@@ -0,0 +1,780 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import he from "ora";
|
|
3
|
+
import { Separator as ye, select as ve } from "@inquirer/prompts";
|
|
4
|
+
import { Command as we, Option as V } from "commander";
|
|
5
|
+
import Q from "path";
|
|
6
|
+
import ne from "fs";
|
|
7
|
+
const Se = `
|
|
8
|
+
Usage: myop [OPTIONS] COMMAND [ARGS]...
|
|
9
|
+
|
|
10
|
+
A powerful command-line interface for managing your Myop projects.
|
|
11
|
+
|
|
12
|
+
Options:
|
|
13
|
+
-h, --help Show this help message and exit.
|
|
14
|
+
-v, --version Show the version of the CLI.
|
|
15
|
+
--config FILE Specify a configuration file. (default: config.yaml)
|
|
16
|
+
|
|
17
|
+
Commands:
|
|
18
|
+
init Initialize a new project.
|
|
19
|
+
start Start the project server.
|
|
20
|
+
build Build the project for production.
|
|
21
|
+
test Run tests on the project.
|
|
22
|
+
deploy Deploy the project to the server.
|
|
23
|
+
logs View logs of the project.
|
|
24
|
+
help Show help for a specific command.
|
|
25
|
+
|
|
26
|
+
For more information, visit the documentation site:
|
|
27
|
+
https://docs.mycli.dev
|
|
28
|
+
|
|
29
|
+
GitHub Repository:
|
|
30
|
+
https://github.com/username/mycli
|
|
31
|
+
|
|
32
|
+
Version: 1.0.0
|
|
33
|
+
|
|
34
|
+
Examples:
|
|
35
|
+
mycli init
|
|
36
|
+
mycli start --config custom_config.yaml
|
|
37
|
+
mycli deploy
|
|
38
|
+
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
`, a = {
|
|
42
|
+
program: null,
|
|
43
|
+
executionPath: "",
|
|
44
|
+
options: {
|
|
45
|
+
configPath: "",
|
|
46
|
+
verbose: !1
|
|
47
|
+
},
|
|
48
|
+
myopConfig: null
|
|
49
|
+
}, se = {
|
|
50
|
+
name: "π₯ Install Myop generated dependencies",
|
|
51
|
+
value: "myopInstall",
|
|
52
|
+
description: "Fetch and generates Myop dependencies. flows including components, refs and props.",
|
|
53
|
+
action: async () => {
|
|
54
|
+
console.info("installing... ");
|
|
55
|
+
for (const s of a.myopConfig.flows) {
|
|
56
|
+
const t = Q.join(a.executionPath, "/node_modules/@myop/flow-types/");
|
|
57
|
+
console.info(`Generate flow at ${t}`), console.info(`Generated flow at ${t}`);
|
|
58
|
+
}
|
|
59
|
+
process.exit();
|
|
60
|
+
}
|
|
61
|
+
}, Ce = (s) => {
|
|
62
|
+
const t = Q.join(a.executionPath, s);
|
|
63
|
+
console.info(`reading config file from: ${t}`);
|
|
64
|
+
const m = ne.readFileSync(t, "utf8"), l = JSON.parse(m);
|
|
65
|
+
return console.info("config file loaded, ", l), l;
|
|
66
|
+
}, Z = (s, t) => {
|
|
67
|
+
const m = Q.join(a.executionPath, s);
|
|
68
|
+
console.info(`writing config file to: ${m}`);
|
|
69
|
+
try {
|
|
70
|
+
const l = JSON.stringify(t, null, 2);
|
|
71
|
+
ne.writeFileSync(m, l), console.info(`config file updated ${l}`);
|
|
72
|
+
} catch (l) {
|
|
73
|
+
throw console.info(`error ${l} while writing to ${m}, JSON: ${t}`), console.log(`
|
|
74
|
+
β οΈ Failed write config file to ${m}, for more info use verbose flag`), l;
|
|
75
|
+
}
|
|
76
|
+
}, ie = {
|
|
77
|
+
name: "π Add flow definition to your project",
|
|
78
|
+
value: "addFlow",
|
|
79
|
+
description: "Adds flow to yours myop.config.json",
|
|
80
|
+
_action: (s) => {
|
|
81
|
+
a.myopConfig.flows.includes(s) || a.myopConfig.flows.push(s), Z(a.options.configPath, a.myopConfig);
|
|
82
|
+
},
|
|
83
|
+
action: async () => {
|
|
84
|
+
}
|
|
85
|
+
}, ae = {
|
|
86
|
+
name: "π« Remove flow definition from your project",
|
|
87
|
+
value: "removeFlow",
|
|
88
|
+
description: "Removes flow to yours myop.config.json",
|
|
89
|
+
_action: (s) => {
|
|
90
|
+
a.myopConfig.flows = a.myopConfig.flows.filter((t) => t !== s), Z(a.options.configPath, a.myopConfig);
|
|
91
|
+
},
|
|
92
|
+
action: () => {
|
|
93
|
+
}
|
|
94
|
+
}, Oe = {
|
|
95
|
+
name: "π Quit",
|
|
96
|
+
value: "quit",
|
|
97
|
+
description: "Quit and continue coding.",
|
|
98
|
+
action: () => {
|
|
99
|
+
process.exit();
|
|
100
|
+
}
|
|
101
|
+
}, $e = {
|
|
102
|
+
name: "π’ Create new component",
|
|
103
|
+
value: "-",
|
|
104
|
+
disabled: "(not available yet)"
|
|
105
|
+
}, be = {
|
|
106
|
+
name: "π΅ Create new experience",
|
|
107
|
+
value: "-",
|
|
108
|
+
disabled: "(not available yet)"
|
|
109
|
+
}, Te = {
|
|
110
|
+
name: "π‘ Create new skin",
|
|
111
|
+
value: "-",
|
|
112
|
+
disabled: "(not available yet)"
|
|
113
|
+
}, xe = {
|
|
114
|
+
name: "π΄ Create new flow",
|
|
115
|
+
value: "-",
|
|
116
|
+
disabled: "(not available yet)"
|
|
117
|
+
}, Pe = {
|
|
118
|
+
name: "π Define new custom Myop message",
|
|
119
|
+
value: "generateMyopMessage",
|
|
120
|
+
description: "οΈHelp you creates the right structure for a new Myop message, including types and handlers.",
|
|
121
|
+
disabled: "(not available yet)"
|
|
122
|
+
}, Ne = [Pe, $e, be, Te, xe];
|
|
123
|
+
function Ie(s, t, m, l) {
|
|
124
|
+
return `<!DOCTYPE html>
|
|
125
|
+
<html lang="en">
|
|
126
|
+
<head>
|
|
127
|
+
<meta charset="UTF-8">
|
|
128
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
129
|
+
<title>Myop DevTools - localhost:${s}</title>
|
|
130
|
+
<style>
|
|
131
|
+
${m}
|
|
132
|
+
</style>
|
|
133
|
+
</head>
|
|
134
|
+
<body>
|
|
135
|
+
<div class="devtools-container">
|
|
136
|
+
<div class="toolbar">
|
|
137
|
+
<div class="toolbar-title">Myop DevTools</div>
|
|
138
|
+
<div class="toolbar-info">
|
|
139
|
+
<span><div class="status-dot"></div> localhost:${s}</span>
|
|
140
|
+
<span>Management: ${t}</span>
|
|
141
|
+
</div>
|
|
142
|
+
</div>
|
|
143
|
+
|
|
144
|
+
<div class="tabs">
|
|
145
|
+
<div class="tab active">Network Architecture</div>
|
|
146
|
+
<div class="tab">Performance</div>
|
|
147
|
+
<div class="tab">Console</div>
|
|
148
|
+
</div>
|
|
149
|
+
|
|
150
|
+
<div class="main-content">
|
|
151
|
+
<div class="panel-left">
|
|
152
|
+
<div class="visualization-area">
|
|
153
|
+
<div class="zoom-controls">
|
|
154
|
+
<button class="zoom-btn" id="zoom-in" title="Zoom In">+</button>
|
|
155
|
+
<div class="zoom-level" id="zoom-level">100%</div>
|
|
156
|
+
<button class="zoom-btn" id="zoom-out" title="Zoom Out">β</button>
|
|
157
|
+
<button class="zoom-btn" id="zoom-reset" title="Reset">β²</button>
|
|
158
|
+
</div>
|
|
159
|
+
<svg id="architecture-svg"></svg>
|
|
160
|
+
</div>
|
|
161
|
+
|
|
162
|
+
<div class="section-header">
|
|
163
|
+
<span>β‘</span> METRICS
|
|
164
|
+
</div>
|
|
165
|
+
<div class="stats-grid">
|
|
166
|
+
<div class="stat-item">
|
|
167
|
+
<div class="stat-value" id="total-requests">0</div>
|
|
168
|
+
<div class="stat-label">Total Requests</div>
|
|
169
|
+
</div>
|
|
170
|
+
<div class="stat-item">
|
|
171
|
+
<div class="stat-value" id="local-requests">0</div>
|
|
172
|
+
<div class="stat-label">Served Local</div>
|
|
173
|
+
</div>
|
|
174
|
+
<div class="stat-item">
|
|
175
|
+
<div class="stat-value" id="proxied-requests">0</div>
|
|
176
|
+
<div class="stat-label">Proxied</div>
|
|
177
|
+
</div>
|
|
178
|
+
<div class="stat-item">
|
|
179
|
+
<div class="stat-value" id="origins-count">0</div>
|
|
180
|
+
<div class="stat-label">Origins</div>
|
|
181
|
+
</div>
|
|
182
|
+
</div>
|
|
183
|
+
</div>
|
|
184
|
+
|
|
185
|
+
<div class="panel-right">
|
|
186
|
+
<div class="section-header">
|
|
187
|
+
<span>π¦</span> REGISTERED COMPONENTS
|
|
188
|
+
</div>
|
|
189
|
+
<ul class="component-list" id="components">
|
|
190
|
+
<!-- Populated by JavaScript -->
|
|
191
|
+
</ul>
|
|
192
|
+
|
|
193
|
+
<div class="section-header">
|
|
194
|
+
<span>π</span> ACTIVITY LOG
|
|
195
|
+
</div>
|
|
196
|
+
<div class="console-log" id="activity-log">
|
|
197
|
+
<!-- Populated by JavaScript -->
|
|
198
|
+
</div>
|
|
199
|
+
</div>
|
|
200
|
+
</div>
|
|
201
|
+
</div>
|
|
202
|
+
|
|
203
|
+
<script>
|
|
204
|
+
// Inject PORT as a global variable for the app to use
|
|
205
|
+
window.PORT = ${s};
|
|
206
|
+
|
|
207
|
+
${l}
|
|
208
|
+
<\/script>
|
|
209
|
+
</body>
|
|
210
|
+
</html>`;
|
|
211
|
+
}
|
|
212
|
+
async function Ae() {
|
|
213
|
+
const s = await import("fs"), t = await import("path"), { exec: m } = await import("child_process"), l = await import("http");
|
|
214
|
+
let N;
|
|
215
|
+
if (import.meta.url.startsWith("file://")) {
|
|
216
|
+
const o = import.meta.url.slice(7);
|
|
217
|
+
N = t.default.dirname(o);
|
|
218
|
+
} else
|
|
219
|
+
N = t.default.dirname(import.meta.url);
|
|
220
|
+
const I = t.default.join(N, "commands", "dev", "management-website"), E = s.default.readFileSync(t.default.join(I, "styles.css"), "utf-8"), D = s.default.readFileSync(t.default.join(I, "app.js"), "utf-8"), v = 9292, S = 9293, b = "./dist";
|
|
221
|
+
let w = !1, H = !1;
|
|
222
|
+
const B = /* @__PURE__ */ new Map(), le = a.program.getOptionValue("config") || "./myop.config.json";
|
|
223
|
+
let u, T;
|
|
224
|
+
try {
|
|
225
|
+
const o = s.default.readFileSync(le, "utf-8"), e = JSON.parse(o);
|
|
226
|
+
u = e.componentId, T = e.componentName || null, u || (console.error("β Error: componentId not found in myop.config.json"), process.exit(1));
|
|
227
|
+
} catch (o) {
|
|
228
|
+
console.error("β Error reading myop.config.json:", o.message), process.exit(1);
|
|
229
|
+
}
|
|
230
|
+
const R = process.cwd(), de = (o) => {
|
|
231
|
+
const e = t.default.extname(o).toLowerCase();
|
|
232
|
+
return {
|
|
233
|
+
".html": "text/html",
|
|
234
|
+
".js": "text/javascript",
|
|
235
|
+
".css": "text/css",
|
|
236
|
+
".json": "application/json",
|
|
237
|
+
".png": "image/png",
|
|
238
|
+
".jpg": "image/jpeg",
|
|
239
|
+
".gif": "image/gif",
|
|
240
|
+
".svg": "image/svg+xml",
|
|
241
|
+
".ico": "image/x-icon"
|
|
242
|
+
}[e] || "application/octet-stream";
|
|
243
|
+
}, g = /* @__PURE__ */ new Map(), L = [], pe = 50, x = [], A = /* @__PURE__ */ new Map(), Y = l.default.createServer((o, e) => {
|
|
244
|
+
if (e.setHeader("Content-Type", "application/json"), o.method === "POST" && o.url === "/_register") {
|
|
245
|
+
let i = "";
|
|
246
|
+
o.on("data", (n) => i += n), o.on("end", () => {
|
|
247
|
+
try {
|
|
248
|
+
const { componentId: n, distPath: r, componentName: c } = JSON.parse(i);
|
|
249
|
+
g.set(n, { path: r, name: c || null });
|
|
250
|
+
const p = c ? ` (${c})` : "";
|
|
251
|
+
console.log(`β
Registered: ${n}${p} -> ${r}`), e.writeHead(200), e.end(JSON.stringify({ success: !0, registered: Array.from(g.keys()) }));
|
|
252
|
+
const h = Array.from(g.entries()).map(([C, J]) => ({
|
|
253
|
+
id: C,
|
|
254
|
+
path: J.path,
|
|
255
|
+
name: J.name
|
|
256
|
+
}));
|
|
257
|
+
x.forEach((C) => {
|
|
258
|
+
try {
|
|
259
|
+
C.write(`data: ${JSON.stringify({
|
|
260
|
+
type: "components",
|
|
261
|
+
components: h
|
|
262
|
+
})}
|
|
263
|
+
|
|
264
|
+
`);
|
|
265
|
+
} catch {
|
|
266
|
+
}
|
|
267
|
+
});
|
|
268
|
+
} catch (n) {
|
|
269
|
+
e.writeHead(400), e.end(JSON.stringify({ error: n.message }));
|
|
270
|
+
}
|
|
271
|
+
});
|
|
272
|
+
} else if (o.method === "POST" && o.url === "/_unregister") {
|
|
273
|
+
let i = "";
|
|
274
|
+
o.on("data", (n) => i += n), o.on("end", () => {
|
|
275
|
+
try {
|
|
276
|
+
const { componentId: n } = JSON.parse(i);
|
|
277
|
+
g.delete(n), console.log(`β Unregistered: ${n}`), e.writeHead(200), e.end(JSON.stringify({ success: !0 }));
|
|
278
|
+
const r = Array.from(g.entries()).map(([c, p]) => ({
|
|
279
|
+
id: c,
|
|
280
|
+
path: p.path,
|
|
281
|
+
name: p.name
|
|
282
|
+
}));
|
|
283
|
+
x.forEach((c) => {
|
|
284
|
+
try {
|
|
285
|
+
c.write(`data: ${JSON.stringify({
|
|
286
|
+
type: "components",
|
|
287
|
+
components: r
|
|
288
|
+
})}
|
|
289
|
+
|
|
290
|
+
`);
|
|
291
|
+
} catch {
|
|
292
|
+
}
|
|
293
|
+
});
|
|
294
|
+
} catch (n) {
|
|
295
|
+
e.writeHead(400), e.end(JSON.stringify({ error: n.message }));
|
|
296
|
+
}
|
|
297
|
+
});
|
|
298
|
+
} else o.method === "GET" && o.url === "/_list" ? (e.writeHead(200), e.end(JSON.stringify({ components: Array.from(g.entries()) }))) : (e.writeHead(404), e.end(JSON.stringify({ error: "Not found" })));
|
|
299
|
+
}), _ = l.default.createServer((o, e) => {
|
|
300
|
+
if (o.url.includes("..")) {
|
|
301
|
+
e.writeHead(403, { "Content-Type": "text/plain" }), e.end("Forbidden");
|
|
302
|
+
return;
|
|
303
|
+
}
|
|
304
|
+
const i = new URL(o.url, `http://localhost:${v}`), n = i.pathname, r = n.split("/").filter((y) => y);
|
|
305
|
+
if (n.startsWith("/consume")) {
|
|
306
|
+
const y = i.searchParams.get("id");
|
|
307
|
+
if (!y) {
|
|
308
|
+
e.writeHead(400, { "Content-Type": "application/json" }), e.end(JSON.stringify({ error: "Component ID required. Use /consume?id=<componentId>" }));
|
|
309
|
+
return;
|
|
310
|
+
}
|
|
311
|
+
const $ = g.get(y), P = $ ? $.path : null, te = (M) => {
|
|
312
|
+
let d = "Unknown", O = "Unknown";
|
|
313
|
+
if (o.headers.referer || o.headers.referrer) {
|
|
314
|
+
const f = o.headers.referer || o.headers.referrer;
|
|
315
|
+
try {
|
|
316
|
+
const j = new URL(f);
|
|
317
|
+
d = j.origin, O = j.hostname || j.origin;
|
|
318
|
+
} catch {
|
|
319
|
+
d = f, O = f;
|
|
320
|
+
}
|
|
321
|
+
} else if (o.headers.origin)
|
|
322
|
+
try {
|
|
323
|
+
const f = new URL(o.headers.origin);
|
|
324
|
+
d = f.origin, O = f.hostname || f.origin;
|
|
325
|
+
} catch {
|
|
326
|
+
d = o.headers.origin, O = o.headers.origin;
|
|
327
|
+
}
|
|
328
|
+
else if (o.socket.remoteAddress) {
|
|
329
|
+
const f = o.socket.remoteAddress;
|
|
330
|
+
f === "::1" || f === "::ffff:127.0.0.1" ? (d = "localhost", O = "localhost (direct)") : (d = f, O = f.replace("::ffff:", ""));
|
|
331
|
+
}
|
|
332
|
+
const W = o.headers.referer || o.headers.referrer || d, G = {
|
|
333
|
+
type: "request",
|
|
334
|
+
componentId: y,
|
|
335
|
+
timestamp: Date.now(),
|
|
336
|
+
servedLocally: M,
|
|
337
|
+
referrer: W,
|
|
338
|
+
origin: d,
|
|
339
|
+
originLabel: O
|
|
340
|
+
};
|
|
341
|
+
A.has(d) || (A.set(d, {
|
|
342
|
+
url: d,
|
|
343
|
+
label: O,
|
|
344
|
+
firstSeen: Date.now(),
|
|
345
|
+
requestCount: 0
|
|
346
|
+
}), x.forEach((f) => {
|
|
347
|
+
try {
|
|
348
|
+
f.write(`data: ${JSON.stringify({
|
|
349
|
+
type: "origins",
|
|
350
|
+
origins: Array.from(A.values())
|
|
351
|
+
})}
|
|
352
|
+
|
|
353
|
+
`);
|
|
354
|
+
} catch {
|
|
355
|
+
}
|
|
356
|
+
}));
|
|
357
|
+
const ue = A.get(d);
|
|
358
|
+
ue.requestCount++, x.forEach((f) => {
|
|
359
|
+
try {
|
|
360
|
+
f.write(`data: ${JSON.stringify({
|
|
361
|
+
type: "origins",
|
|
362
|
+
origins: Array.from(A.values())
|
|
363
|
+
})}
|
|
364
|
+
|
|
365
|
+
`);
|
|
366
|
+
} catch {
|
|
367
|
+
}
|
|
368
|
+
}), L.push(G), L.length > pe && L.shift(), x.forEach((f) => {
|
|
369
|
+
try {
|
|
370
|
+
f.write(`data: ${JSON.stringify(G)}
|
|
371
|
+
|
|
372
|
+
`);
|
|
373
|
+
} catch {
|
|
374
|
+
}
|
|
375
|
+
});
|
|
376
|
+
};
|
|
377
|
+
if (P) {
|
|
378
|
+
const M = t.default.join(P, "index.html");
|
|
379
|
+
s.default.readFile(M, "utf-8", (d, O) => {
|
|
380
|
+
if (d) {
|
|
381
|
+
console.log(`β File not found: ${M}`), e.writeHead(404, { "Content-Type": "application/json" }), e.end(JSON.stringify({ error: "index.html not found" }));
|
|
382
|
+
return;
|
|
383
|
+
}
|
|
384
|
+
const W = `dev-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, G = {
|
|
385
|
+
item: {
|
|
386
|
+
name: y,
|
|
387
|
+
id: y,
|
|
388
|
+
consume_variant: [
|
|
389
|
+
{
|
|
390
|
+
id: W,
|
|
391
|
+
name: "dev version",
|
|
392
|
+
loader: {
|
|
393
|
+
type: "HTMLLoader",
|
|
394
|
+
shadowRootMode: "localFrame",
|
|
395
|
+
HTML: O
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
]
|
|
399
|
+
}
|
|
400
|
+
};
|
|
401
|
+
console.log(`β
Serving consume JSON for: ${y}`), te(!0), e.writeHead(200, {
|
|
402
|
+
"Content-Type": "application/json",
|
|
403
|
+
"Access-Control-Allow-Origin": "*"
|
|
404
|
+
}), e.end(JSON.stringify(G, null, 2));
|
|
405
|
+
});
|
|
406
|
+
} else {
|
|
407
|
+
console.log(`π‘ Proxying consume request to cloud.myop.dev for: ${y}`);
|
|
408
|
+
const M = `https://cloud.myop.dev/consume${i.search}`;
|
|
409
|
+
te(!1), fetch(M).then((d) => d.text()).then((d) => {
|
|
410
|
+
e.writeHead(200, {
|
|
411
|
+
"Content-Type": "application/json",
|
|
412
|
+
"Access-Control-Allow-Origin": "*"
|
|
413
|
+
}), e.end(d);
|
|
414
|
+
}).catch((d) => {
|
|
415
|
+
console.error(`β Proxy error: ${d.message}`), e.writeHead(502, { "Content-Type": "application/json" }), e.end(JSON.stringify({ error: "Failed to fetch from cloud.myop.dev" }));
|
|
416
|
+
});
|
|
417
|
+
}
|
|
418
|
+
return;
|
|
419
|
+
}
|
|
420
|
+
if (n === "/events") {
|
|
421
|
+
e.writeHead(200, {
|
|
422
|
+
"Content-Type": "text/event-stream",
|
|
423
|
+
"Cache-Control": "no-cache",
|
|
424
|
+
Connection: "keep-alive",
|
|
425
|
+
"Access-Control-Allow-Origin": "*"
|
|
426
|
+
}), x.push(e);
|
|
427
|
+
const y = Array.from(g.entries()).map(([$, P]) => ({
|
|
428
|
+
id: $,
|
|
429
|
+
path: P.path,
|
|
430
|
+
name: P.name
|
|
431
|
+
}));
|
|
432
|
+
e.write(`data: ${JSON.stringify({
|
|
433
|
+
type: "components",
|
|
434
|
+
components: y
|
|
435
|
+
})}
|
|
436
|
+
|
|
437
|
+
`), e.write(`data: ${JSON.stringify({
|
|
438
|
+
type: "origins",
|
|
439
|
+
origins: Array.from(A.values())
|
|
440
|
+
})}
|
|
441
|
+
|
|
442
|
+
`), e.write(`data: ${JSON.stringify({
|
|
443
|
+
type: "requestLog",
|
|
444
|
+
log: L
|
|
445
|
+
})}
|
|
446
|
+
|
|
447
|
+
`), o.on("close", () => {
|
|
448
|
+
const $ = x.indexOf(e);
|
|
449
|
+
$ !== -1 && x.splice($, 1);
|
|
450
|
+
});
|
|
451
|
+
return;
|
|
452
|
+
}
|
|
453
|
+
if (r.length === 0) {
|
|
454
|
+
e.writeHead(200, { "Content-Type": "text/html" }), e.end(Ie(v, S, E, D));
|
|
455
|
+
return;
|
|
456
|
+
}
|
|
457
|
+
if (r[0] !== "view") {
|
|
458
|
+
e.writeHead(404, { "Content-Type": "text/plain" }), e.end("Not found. Use /view/<componentId>/ to access components.");
|
|
459
|
+
return;
|
|
460
|
+
}
|
|
461
|
+
if (r.length < 2) {
|
|
462
|
+
e.writeHead(400, { "Content-Type": "text/plain" }), e.end("Component ID required. Use /view/<componentId>/");
|
|
463
|
+
return;
|
|
464
|
+
}
|
|
465
|
+
const c = r[1], p = g.get(c);
|
|
466
|
+
if (!p) {
|
|
467
|
+
e.writeHead(404, { "Content-Type": "text/plain" }), e.end(`Component not found: ${c}`);
|
|
468
|
+
return;
|
|
469
|
+
}
|
|
470
|
+
const h = p.path, C = r.slice(2), J = C.length === 0 ? "index.html" : C.join("/"), F = t.default.join(h, J);
|
|
471
|
+
console.log(`π₯ Request: ${o.url} -> ${F}`), s.default.readFile(F, (y, $) => {
|
|
472
|
+
if (y) {
|
|
473
|
+
console.log(`β File not found: ${F}`), e.writeHead(404, { "Content-Type": "text/plain" }), e.end("Not Found");
|
|
474
|
+
return;
|
|
475
|
+
}
|
|
476
|
+
const P = de(F);
|
|
477
|
+
console.log(`β
Serving: ${F} (${P})`), e.writeHead(200, {
|
|
478
|
+
"Content-Type": P,
|
|
479
|
+
"Access-Control-Allow-Origin": "*"
|
|
480
|
+
}), e.end($);
|
|
481
|
+
});
|
|
482
|
+
}), X = () => new Promise((o, e) => {
|
|
483
|
+
const i = JSON.stringify({
|
|
484
|
+
componentId: u,
|
|
485
|
+
distPath: t.default.resolve(R, b),
|
|
486
|
+
componentName: T
|
|
487
|
+
}), n = {
|
|
488
|
+
hostname: "localhost",
|
|
489
|
+
port: S,
|
|
490
|
+
path: "/_register",
|
|
491
|
+
method: "POST",
|
|
492
|
+
headers: {
|
|
493
|
+
"Content-Type": "application/json",
|
|
494
|
+
"Content-Length": Buffer.byteLength(i)
|
|
495
|
+
}
|
|
496
|
+
}, r = l.default.request(n, (c) => {
|
|
497
|
+
let p = "";
|
|
498
|
+
c.on("data", (h) => p += h), c.on("end", () => {
|
|
499
|
+
c.statusCode === 200 ? o(JSON.parse(p)) : e(new Error(`Registration failed: ${c.statusCode}`));
|
|
500
|
+
});
|
|
501
|
+
});
|
|
502
|
+
r.on("error", e), r.write(i), r.end();
|
|
503
|
+
}), me = () => new Promise((o, e) => {
|
|
504
|
+
const i = JSON.stringify({ componentId: u }), n = {
|
|
505
|
+
hostname: "localhost",
|
|
506
|
+
port: S,
|
|
507
|
+
path: "/_unregister",
|
|
508
|
+
method: "POST",
|
|
509
|
+
headers: {
|
|
510
|
+
"Content-Type": "application/json",
|
|
511
|
+
"Content-Length": Buffer.byteLength(i)
|
|
512
|
+
}
|
|
513
|
+
}, r = l.default.request(n, (c) => {
|
|
514
|
+
o();
|
|
515
|
+
});
|
|
516
|
+
r.on("error", () => o()), r.write(i), r.end();
|
|
517
|
+
}), U = () => {
|
|
518
|
+
if (w) {
|
|
519
|
+
H = !0;
|
|
520
|
+
return;
|
|
521
|
+
}
|
|
522
|
+
w = !0, console.log(`
|
|
523
|
+
π¨ Building...`), m("npm run build", (o, e, i) => {
|
|
524
|
+
w = !1, o ? (console.error("β Build failed:", o.message), i && console.error(i)) : (console.log("β
Build completed"), e && console.log(e)), H && (H = !1, U());
|
|
525
|
+
});
|
|
526
|
+
}, K = (o) => {
|
|
527
|
+
s.default.readdir(o, { withFileTypes: !0 }, (e, i) => {
|
|
528
|
+
e || i.forEach((n) => {
|
|
529
|
+
const r = t.default.join(o, n.name);
|
|
530
|
+
if (n.isDirectory())
|
|
531
|
+
n.name !== "node_modules" && n.name !== "dist" && !n.name.startsWith(".") && K(r);
|
|
532
|
+
else if (n.isFile()) {
|
|
533
|
+
const c = t.default.extname(n.name);
|
|
534
|
+
if (c === ".js" || c === ".css") {
|
|
535
|
+
try {
|
|
536
|
+
const p = s.default.readFileSync(r, "utf-8");
|
|
537
|
+
B.set(r, p);
|
|
538
|
+
} catch {
|
|
539
|
+
}
|
|
540
|
+
s.default.watch(r, (p) => {
|
|
541
|
+
if (p === "change")
|
|
542
|
+
try {
|
|
543
|
+
const h = s.default.readFileSync(r, "utf-8"), C = B.get(r);
|
|
544
|
+
h !== C && (B.set(r, h), console.log(`π File changed: ${r}`), U());
|
|
545
|
+
} catch {
|
|
546
|
+
console.log(`π File changed: ${r}`), U();
|
|
547
|
+
}
|
|
548
|
+
});
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
});
|
|
552
|
+
});
|
|
553
|
+
}, q = () => {
|
|
554
|
+
console.log(`
|
|
555
|
+
π¨ Component: ${u}`), U(), K(R), console.log("π Watching .js and .css files for changes..."), console.log(`Press Ctrl+C to stop
|
|
556
|
+
`);
|
|
557
|
+
}, fe = () => new Promise((o) => {
|
|
558
|
+
const e = {
|
|
559
|
+
hostname: "localhost",
|
|
560
|
+
port: S,
|
|
561
|
+
path: "/_list",
|
|
562
|
+
method: "GET",
|
|
563
|
+
timeout: 1e3
|
|
564
|
+
}, i = l.default.request(e, (n) => {
|
|
565
|
+
o(!0);
|
|
566
|
+
});
|
|
567
|
+
i.on("error", () => o(!1)), i.on("timeout", () => {
|
|
568
|
+
i.destroy(), o(!1);
|
|
569
|
+
}), i.end();
|
|
570
|
+
}), ge = () => new Promise((o) => {
|
|
571
|
+
const e = l.default.createServer((i, n) => {
|
|
572
|
+
if (n.setHeader("Content-Type", "application/json"), i.method === "POST" && i.url === "/_register") {
|
|
573
|
+
let r = "";
|
|
574
|
+
i.on("data", (c) => r += c), i.on("end", () => {
|
|
575
|
+
try {
|
|
576
|
+
const { componentId: c, distPath: p, componentName: h } = JSON.parse(r);
|
|
577
|
+
g.set(c, { path: p, name: h || null });
|
|
578
|
+
const C = h ? ` (${h})` : "";
|
|
579
|
+
console.log(`β
Registered: ${c}${C} -> ${p}`), n.writeHead(200), n.end(JSON.stringify({ success: !0, registered: Array.from(g.keys()) }));
|
|
580
|
+
} catch (c) {
|
|
581
|
+
n.writeHead(400), n.end(JSON.stringify({ error: c.message }));
|
|
582
|
+
}
|
|
583
|
+
});
|
|
584
|
+
} else if (i.method === "POST" && i.url === "/_unregister") {
|
|
585
|
+
let r = "";
|
|
586
|
+
i.on("data", (c) => r += c), i.on("end", () => {
|
|
587
|
+
try {
|
|
588
|
+
const { componentId: c } = JSON.parse(r);
|
|
589
|
+
g.delete(c), console.log(`β Unregistered: ${c}`), n.writeHead(200), n.end(JSON.stringify({ success: !0 }));
|
|
590
|
+
} catch (c) {
|
|
591
|
+
n.writeHead(400), n.end(JSON.stringify({ error: c.message }));
|
|
592
|
+
}
|
|
593
|
+
});
|
|
594
|
+
} else i.method === "GET" && i.url === "/_list" ? (n.writeHead(200), n.end(JSON.stringify({ components: Array.from(g.entries()) }))) : (n.writeHead(404), n.end(JSON.stringify({ error: "Not found" })));
|
|
595
|
+
});
|
|
596
|
+
e.on("error", () => {
|
|
597
|
+
o(!1);
|
|
598
|
+
}), e.listen(S, () => {
|
|
599
|
+
console.log(`
|
|
600
|
+
π Taking over as server...`), console.log(`π‘ Management server on port ${S}`), _.on("error", () => {
|
|
601
|
+
e.close(), o(!1);
|
|
602
|
+
}), _.listen(v, () => {
|
|
603
|
+
console.log(`π‘ Main server running at http://localhost:${v}`), g.set(u, {
|
|
604
|
+
path: t.default.resolve(R, b),
|
|
605
|
+
name: T
|
|
606
|
+
});
|
|
607
|
+
const i = T ? ` (${T})` : "";
|
|
608
|
+
console.log(`β
Registered component: ${u}${i}`), console.log(`π‘ Access at: http://localhost:${v}/view/${u}/`), o(!0);
|
|
609
|
+
});
|
|
610
|
+
});
|
|
611
|
+
});
|
|
612
|
+
let k;
|
|
613
|
+
const ee = () => {
|
|
614
|
+
k = setInterval(async () => {
|
|
615
|
+
await fe() || (clearInterval(k), console.log(`
|
|
616
|
+
β οΈ Server appears to be down, attempting to take over...`), await ge() ? console.log("β
Successfully took over as server") : (console.log("βΉοΈ Another instance took over, re-registering..."), setTimeout(async () => {
|
|
617
|
+
try {
|
|
618
|
+
await X(), console.log(`β
Re-registered component: ${u}`), ee();
|
|
619
|
+
} catch (i) {
|
|
620
|
+
console.error("β Failed to re-register:", i.message);
|
|
621
|
+
}
|
|
622
|
+
}, 2e3)));
|
|
623
|
+
}, 3e3);
|
|
624
|
+
}, oe = async () => {
|
|
625
|
+
console.log(`
|
|
626
|
+
|
|
627
|
+
π Shutting down...`), k && clearInterval(k), await me(), process.exit(0);
|
|
628
|
+
};
|
|
629
|
+
process.on("SIGINT", oe), process.on("SIGTERM", oe), Y.on("error", async (o) => {
|
|
630
|
+
if (o.code === "EADDRINUSE") {
|
|
631
|
+
console.log(`
|
|
632
|
+
π Connecting to existing dev server...`);
|
|
633
|
+
try {
|
|
634
|
+
const e = await X();
|
|
635
|
+
console.log(`β
Registered component: ${u}`), console.log(`π‘ Access at: http://localhost:${v}/view/${u}/`), console.log(`π All registered components: ${e.registered.join(", ")}`), q(), ee();
|
|
636
|
+
} catch (e) {
|
|
637
|
+
console.error("β Failed to register component:", e.message), process.exit(1);
|
|
638
|
+
}
|
|
639
|
+
} else
|
|
640
|
+
console.error("β Management server error:", o.message), process.exit(1);
|
|
641
|
+
}), Y.listen(S, async () => {
|
|
642
|
+
console.log(`
|
|
643
|
+
π Starting shared dev server...`), console.log(`π‘ Management server on port ${S}`), _.on("error", (o) => {
|
|
644
|
+
console.error("β Main server error:", o.message), process.exit(1);
|
|
645
|
+
}), _.listen(v, async () => {
|
|
646
|
+
console.log(`π‘ Main server running at http://localhost:${v}`), g.set(u, {
|
|
647
|
+
path: t.default.resolve(R, b),
|
|
648
|
+
name: T
|
|
649
|
+
});
|
|
650
|
+
const o = T ? ` (${T})` : "";
|
|
651
|
+
console.log(`β
Registered component: ${u}${o}`), console.log(`π‘ Access at: http://localhost:${v}/view/${u}/`), q();
|
|
652
|
+
});
|
|
653
|
+
});
|
|
654
|
+
}
|
|
655
|
+
const Me = (s) => new Promise((t) => setTimeout(t, s));
|
|
656
|
+
a.executionPath = process.cwd();
|
|
657
|
+
const z = (s = !1) => {
|
|
658
|
+
const t = a.program.getOptionValue("verbose");
|
|
659
|
+
t || (console.info = () => {
|
|
660
|
+
}), console.info("π verbose mode on"), a.options = {
|
|
661
|
+
configPath: a.program.getOptionValue("config"),
|
|
662
|
+
verbose: t
|
|
663
|
+
};
|
|
664
|
+
try {
|
|
665
|
+
a.myopConfig = Ce(a.options.configPath);
|
|
666
|
+
} catch (m) {
|
|
667
|
+
if (s) {
|
|
668
|
+
console.info(`
|
|
669
|
+
β οΈ failed read config file from ${a.options.configPath}, trying to create new one`);
|
|
670
|
+
try {
|
|
671
|
+
const l = {
|
|
672
|
+
author: "@myop-cli",
|
|
673
|
+
flows: []
|
|
674
|
+
};
|
|
675
|
+
Z(a.options.configPath, l), a.myopConfig = l;
|
|
676
|
+
} catch {
|
|
677
|
+
console.log(`
|
|
678
|
+
β οΈ failed read config file from ${a.options.configPath}, for more details use verbose flag`), console.info("Error details :", m), process.exit();
|
|
679
|
+
}
|
|
680
|
+
} else
|
|
681
|
+
console.log(`
|
|
682
|
+
β οΈ failed read config file from ${a.options.configPath}, for more details use verbose flag`), console.info("Error details :", m), process.exit();
|
|
683
|
+
}
|
|
684
|
+
}, re = [
|
|
685
|
+
se,
|
|
686
|
+
ie,
|
|
687
|
+
ae,
|
|
688
|
+
Oe,
|
|
689
|
+
new ye(),
|
|
690
|
+
...Ne
|
|
691
|
+
], je = async () => ve({
|
|
692
|
+
message: "Select an operation",
|
|
693
|
+
choices: re
|
|
694
|
+
}), ce = async () => {
|
|
695
|
+
const s = await je(), t = re.find((m) => m.value === s);
|
|
696
|
+
t ? t.action ? await t.action() : console.log(`β οΈ Operation ${s} has no action`) : console.log(`β οΈ Operation ${s} not found`), await ce();
|
|
697
|
+
};
|
|
698
|
+
a.program = new we();
|
|
699
|
+
a.program.name("@myop/cli").description("Myop CLI - Remote UI Made Easy").version("0.0.55");
|
|
700
|
+
a.program.addOption(new V("-c, --config <value>", "myop.config.json file location").default("./myop.config.json", "./myop.config.json"));
|
|
701
|
+
a.program.addOption(new V("-h, --help", "Show helpful information"));
|
|
702
|
+
a.program.addOption(new V("-v, --verbose", "Enables verbose output mode for the command-line interface (CLI)."));
|
|
703
|
+
a.program.command("add").description("Install Myop assets").addArgument("type").addArgument("id").action((s, t) => {
|
|
704
|
+
z(!0), console.info("adding ", s, t, a.options.configPath), s === "flow" && ie._action(t), process.exit();
|
|
705
|
+
});
|
|
706
|
+
a.program.command("remove").description("Remove Myop asset").argument("<type>", "Myop asset type").argument("<id>", "Asset id").action((s, t) => {
|
|
707
|
+
z(), console.info("removing ", s, t, a.options.configPath), s === "flow" && ae._action(t), process.exit();
|
|
708
|
+
});
|
|
709
|
+
a.program.command("install").description("Install Myop assets").action(async () => {
|
|
710
|
+
z(), await se.action();
|
|
711
|
+
});
|
|
712
|
+
a.program.command("sync").description("Sync Myop configuration").action(async () => {
|
|
713
|
+
const s = a.program.getOptionValue("config") || "./myop.config.json", t = await import("fs"), { execSync: m } = await import("child_process"), l = await import("http");
|
|
714
|
+
if (t.existsSync(s)) {
|
|
715
|
+
console.log("yes");
|
|
716
|
+
try {
|
|
717
|
+
const N = t.readFileSync(s, "utf-8"), I = JSON.parse(N);
|
|
718
|
+
I.componentId && console.log(I.componentId), console.log("Running npm run build..."), m("npm run build", { stdio: "inherit" });
|
|
719
|
+
const E = "./dist/index.html";
|
|
720
|
+
if (t.existsSync(E)) {
|
|
721
|
+
const D = t.readFileSync(E, "utf-8");
|
|
722
|
+
console.log(`
|
|
723
|
+
Content of ./dist/index.html:`), console.log(D);
|
|
724
|
+
const v = 3302, S = l.default.createServer((b, w) => {
|
|
725
|
+
if (b.method === "OPTIONS") {
|
|
726
|
+
w.writeHead(200, {
|
|
727
|
+
"Access-Control-Allow-Origin": "*",
|
|
728
|
+
"Access-Control-Allow-Methods": "GET, OPTIONS",
|
|
729
|
+
"Access-Control-Allow-Headers": "Content-Type"
|
|
730
|
+
}), w.end();
|
|
731
|
+
return;
|
|
732
|
+
}
|
|
733
|
+
w.writeHead(200, {
|
|
734
|
+
"Content-Type": "text/plain",
|
|
735
|
+
"Access-Control-Allow-Origin": "*",
|
|
736
|
+
"Access-Control-Allow-Methods": "GET, OPTIONS",
|
|
737
|
+
"Access-Control-Allow-Headers": "Content-Type"
|
|
738
|
+
}), w.end(D), console.log(`
|
|
739
|
+
Content served successfully, closing server...`), setTimeout(() => {
|
|
740
|
+
S.close(() => {
|
|
741
|
+
console.log("Server closed. Sync process completed.");
|
|
742
|
+
}), setTimeout(() => {
|
|
743
|
+
process.exit(0);
|
|
744
|
+
}, 100);
|
|
745
|
+
}, 100);
|
|
746
|
+
});
|
|
747
|
+
S.listen(v, () => {
|
|
748
|
+
const b = `http://localhost:${v}`;
|
|
749
|
+
console.log(`
|
|
750
|
+
Server running at ${b}`), console.log("Waiting for request...");
|
|
751
|
+
const w = `http://localhost:9200/dashboard/2.0/component/${I.componentId}?upload=${encodeURIComponent(b)}`;
|
|
752
|
+
console.log(`
|
|
753
|
+
Opening Chrome with: ${w}`);
|
|
754
|
+
try {
|
|
755
|
+
m(`open -a "Google Chrome" "${w}"`, { stdio: "inherit" });
|
|
756
|
+
} catch (H) {
|
|
757
|
+
console.error("Error opening Chrome:", H.message), console.log(`Please open this URL manually: ${w}`);
|
|
758
|
+
}
|
|
759
|
+
});
|
|
760
|
+
return;
|
|
761
|
+
} else
|
|
762
|
+
console.error("Error: ./dist/index.html not found");
|
|
763
|
+
} catch (N) {
|
|
764
|
+
console.error("Error:", N.message);
|
|
765
|
+
}
|
|
766
|
+
} else
|
|
767
|
+
console.log("no");
|
|
768
|
+
process.exit();
|
|
769
|
+
});
|
|
770
|
+
a.program.command("dev").description("Start development server with file watching").action(Ae);
|
|
771
|
+
a.program.command("default", { isDefault: !0 }).action(async () => {
|
|
772
|
+
a.program.getOptionValue("help") && (console.log(Se), process.exit());
|
|
773
|
+
let t = he({
|
|
774
|
+
text: "Loading Myop CLI...",
|
|
775
|
+
color: "green"
|
|
776
|
+
}).start();
|
|
777
|
+
z(), await Me(1e3), t.succeed("Myop CLI Loaded"), await ce();
|
|
778
|
+
});
|
|
779
|
+
a.program.parse(process.argv);
|
|
780
|
+
a.program.opts();
|