@myop/cli 0.1.10 β 0.1.12
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 +1369 -456
- package/package.json +2 -1
package/dist/myop-cli.js
CHANGED
|
@@ -1,10 +1,16 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
import
|
|
3
|
-
import {
|
|
4
|
-
import { Command as
|
|
5
|
-
import
|
|
6
|
-
import
|
|
7
|
-
|
|
2
|
+
import A from "ora";
|
|
3
|
+
import { select as Me, Separator as pe } from "@inquirer/prompts";
|
|
4
|
+
import { Command as Be, Option as ie } from "commander";
|
|
5
|
+
import { execSync as ne } from "child_process";
|
|
6
|
+
import Z from "path";
|
|
7
|
+
import E from "fs";
|
|
8
|
+
import ue from "crypto";
|
|
9
|
+
import We from "http";
|
|
10
|
+
import { URL as Oe, URLSearchParams as je } from "url";
|
|
11
|
+
import Ye from "open";
|
|
12
|
+
import Ge from "os";
|
|
13
|
+
const Ve = `
|
|
8
14
|
Usage: myop [OPTIONS] COMMAND [ARGS]...
|
|
9
15
|
|
|
10
16
|
A powerful command-line interface for managing your Myop projects.
|
|
@@ -38,7 +44,7 @@ Examples:
|
|
|
38
44
|
|
|
39
45
|
|
|
40
46
|
|
|
41
|
-
`,
|
|
47
|
+
`, l = {
|
|
42
48
|
program: null,
|
|
43
49
|
executionPath: "",
|
|
44
50
|
options: {
|
|
@@ -46,89 +52,89 @@ Examples:
|
|
|
46
52
|
verbose: !1
|
|
47
53
|
},
|
|
48
54
|
myopConfig: null
|
|
49
|
-
},
|
|
55
|
+
}, Ie = {
|
|
50
56
|
name: "π₯ Install Myop generated dependencies",
|
|
51
57
|
value: "myopInstall",
|
|
52
58
|
description: "Fetch and generates Myop dependencies. flows including components, refs and props.",
|
|
53
59
|
action: async () => {
|
|
54
60
|
console.info("installing... ");
|
|
55
|
-
for (const
|
|
56
|
-
const
|
|
57
|
-
console.info(`Generate flow at ${
|
|
61
|
+
for (const e of l.myopConfig.flows) {
|
|
62
|
+
const o = Z.join(l.executionPath, "/node_modules/@myop/flow-types/");
|
|
63
|
+
console.info(`Generate flow at ${o}`), console.info(`Generated flow at ${o}`);
|
|
58
64
|
}
|
|
59
65
|
process.exit();
|
|
60
66
|
}
|
|
61
|
-
},
|
|
62
|
-
const
|
|
63
|
-
console.info(`reading config file from: ${
|
|
64
|
-
const
|
|
65
|
-
return console.info("config file loaded, ",
|
|
66
|
-
},
|
|
67
|
-
const
|
|
68
|
-
console.info(`writing config file to: ${
|
|
67
|
+
}, Ke = (e) => {
|
|
68
|
+
const o = Z.join(l.executionPath, e);
|
|
69
|
+
console.info(`reading config file from: ${o}`);
|
|
70
|
+
const n = E.readFileSync(o, "utf8"), a = JSON.parse(n);
|
|
71
|
+
return console.info("config file loaded, ", a), a;
|
|
72
|
+
}, fe = (e, o) => {
|
|
73
|
+
const n = Z.join(l.executionPath, e);
|
|
74
|
+
console.info(`writing config file to: ${n}`);
|
|
69
75
|
try {
|
|
70
|
-
const
|
|
71
|
-
|
|
72
|
-
} catch (
|
|
73
|
-
throw console.info(`error ${
|
|
74
|
-
β οΈ Failed write config file to ${
|
|
76
|
+
const a = JSON.stringify(o, null, 2);
|
|
77
|
+
E.writeFileSync(n, a), console.info(`config file updated ${a}`);
|
|
78
|
+
} catch (a) {
|
|
79
|
+
throw console.info(`error ${a} while writing to ${n}, JSON: ${o}`), console.log(`
|
|
80
|
+
β οΈ Failed write config file to ${n}, for more info use verbose flag`), a;
|
|
75
81
|
}
|
|
76
|
-
},
|
|
82
|
+
}, ke = {
|
|
77
83
|
name: "π Add flow definition to your project",
|
|
78
84
|
value: "addFlow",
|
|
79
85
|
description: "Adds flow to yours myop.config.json",
|
|
80
|
-
_action: (
|
|
81
|
-
|
|
86
|
+
_action: (e) => {
|
|
87
|
+
l.myopConfig.flows.includes(e) || l.myopConfig.flows.push(e), fe(l.options.configPath, l.myopConfig);
|
|
82
88
|
},
|
|
83
89
|
action: async () => {
|
|
84
90
|
}
|
|
85
|
-
},
|
|
91
|
+
}, Pe = {
|
|
86
92
|
name: "π« Remove flow definition from your project",
|
|
87
93
|
value: "removeFlow",
|
|
88
94
|
description: "Removes flow to yours myop.config.json",
|
|
89
|
-
_action: (
|
|
90
|
-
|
|
95
|
+
_action: (e) => {
|
|
96
|
+
l.myopConfig.flows = l.myopConfig.flows.filter((o) => o !== e), fe(l.options.configPath, l.myopConfig);
|
|
91
97
|
},
|
|
92
98
|
action: () => {
|
|
93
99
|
}
|
|
94
|
-
},
|
|
100
|
+
}, Xe = {
|
|
95
101
|
name: "π Quit",
|
|
96
102
|
value: "quit",
|
|
97
103
|
description: "Quit and continue coding.",
|
|
98
104
|
action: () => {
|
|
99
105
|
process.exit();
|
|
100
106
|
}
|
|
101
|
-
},
|
|
107
|
+
}, Qe = {
|
|
102
108
|
name: "π’ Create new component",
|
|
103
109
|
value: "-",
|
|
104
110
|
disabled: "(not available yet)"
|
|
105
|
-
},
|
|
111
|
+
}, Ze = {
|
|
106
112
|
name: "π΅ Create new experience",
|
|
107
113
|
value: "-",
|
|
108
114
|
disabled: "(not available yet)"
|
|
109
|
-
},
|
|
115
|
+
}, qe = {
|
|
110
116
|
name: "π‘ Create new skin",
|
|
111
117
|
value: "-",
|
|
112
118
|
disabled: "(not available yet)"
|
|
113
|
-
},
|
|
119
|
+
}, et = {
|
|
114
120
|
name: "π΄ Create new flow",
|
|
115
121
|
value: "-",
|
|
116
122
|
disabled: "(not available yet)"
|
|
117
|
-
},
|
|
123
|
+
}, tt = {
|
|
118
124
|
name: "π Define new custom Myop message",
|
|
119
125
|
value: "generateMyopMessage",
|
|
120
126
|
description: "οΈHelp you creates the right structure for a new Myop message, including types and handlers.",
|
|
121
127
|
disabled: "(not available yet)"
|
|
122
|
-
},
|
|
123
|
-
function
|
|
128
|
+
}, ot = [tt, Qe, Ze, qe, et];
|
|
129
|
+
function nt(e, o, n, a) {
|
|
124
130
|
return `<!DOCTYPE html>
|
|
125
131
|
<html lang="en">
|
|
126
132
|
<head>
|
|
127
133
|
<meta charset="UTF-8">
|
|
128
134
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
129
|
-
<title>Myop DevTools - localhost:${
|
|
135
|
+
<title>Myop DevTools - localhost:${e}</title>
|
|
130
136
|
<style>
|
|
131
|
-
${
|
|
137
|
+
${n}
|
|
132
138
|
</style>
|
|
133
139
|
</head>
|
|
134
140
|
<body>
|
|
@@ -136,8 +142,8 @@ ${m}
|
|
|
136
142
|
<div class="toolbar">
|
|
137
143
|
<div class="toolbar-title">Myop DevTools</div>
|
|
138
144
|
<div class="toolbar-info">
|
|
139
|
-
<span><div class="status-dot"></div> localhost:${
|
|
140
|
-
<span>Management: ${
|
|
145
|
+
<span><div class="status-dot"></div> localhost:${e}</span>
|
|
146
|
+
<span>Management: ${o}</span>
|
|
141
147
|
</div>
|
|
142
148
|
</div>
|
|
143
149
|
|
|
@@ -203,33 +209,33 @@ ${m}
|
|
|
203
209
|
|
|
204
210
|
<script>
|
|
205
211
|
// Inject PORT as a global variable for the app to use
|
|
206
|
-
window.PORT = ${
|
|
212
|
+
window.PORT = ${e};
|
|
207
213
|
|
|
208
|
-
${
|
|
214
|
+
${a}
|
|
209
215
|
<\/script>
|
|
210
216
|
</body>
|
|
211
217
|
</html>`;
|
|
212
218
|
}
|
|
213
|
-
async function
|
|
214
|
-
const
|
|
215
|
-
let
|
|
219
|
+
async function _e() {
|
|
220
|
+
const e = await import("fs"), o = await import("path"), { exec: n } = await import("child_process"), a = await import("http"), { createHash: m } = await import("node:crypto");
|
|
221
|
+
let c;
|
|
216
222
|
if (import.meta.url.startsWith("file://")) {
|
|
217
|
-
const
|
|
218
|
-
|
|
223
|
+
const s = import.meta.url.slice(7);
|
|
224
|
+
c = o.default.dirname(s);
|
|
219
225
|
} else
|
|
220
|
-
|
|
221
|
-
const
|
|
222
|
-
let
|
|
223
|
-
const
|
|
224
|
-
let
|
|
226
|
+
c = o.default.dirname(import.meta.url);
|
|
227
|
+
const p = o.default.join(c, "commands", "dev", "management-website"), v = e.default.readFileSync(o.default.join(p, "styles.css"), "utf-8"), S = e.default.readFileSync(o.default.join(p, "app.js"), "utf-8"), f = 9292, w = 9293, y = "./dist";
|
|
228
|
+
let j = !1, $ = !1;
|
|
229
|
+
const _ = /* @__PURE__ */ new Map(), z = l.program.getOptionValue("config") || "./myop.config.json";
|
|
230
|
+
let x, P, g = !1;
|
|
225
231
|
try {
|
|
226
|
-
const
|
|
227
|
-
|
|
228
|
-
} catch (
|
|
229
|
-
console.error("β Error reading myop.config.json:",
|
|
232
|
+
const s = e.default.readFileSync(z, "utf-8"), t = JSON.parse(s);
|
|
233
|
+
x = t.componentId, P = t.componentName || null, g = t.HMR === !0, x || (console.error("β Error: componentId not found in myop.config.json"), process.exit(1)), g && console.log("π₯ HMR enabled");
|
|
234
|
+
} catch (s) {
|
|
235
|
+
console.error("β Error reading myop.config.json:", s.message), process.exit(1);
|
|
230
236
|
}
|
|
231
|
-
const
|
|
232
|
-
const
|
|
237
|
+
const b = process.cwd(), H = (s) => {
|
|
238
|
+
const t = o.default.extname(s).toLowerCase();
|
|
233
239
|
return {
|
|
234
240
|
".html": "text/html",
|
|
235
241
|
".js": "text/javascript",
|
|
@@ -240,314 +246,314 @@ async function Ee() {
|
|
|
240
246
|
".gif": "image/gif",
|
|
241
247
|
".svg": "image/svg+xml",
|
|
242
248
|
".ico": "image/x-icon"
|
|
243
|
-
}[
|
|
244
|
-
},
|
|
245
|
-
if (
|
|
246
|
-
const
|
|
247
|
-
|
|
249
|
+
}[t] || "application/octet-stream";
|
|
250
|
+
}, M = /* @__PURE__ */ new Map(), F = [], Ne = 50, J = [], B = /* @__PURE__ */ new Map(), D = /* @__PURE__ */ new Map(), Ae = (s, t, r) => {
|
|
251
|
+
if (s.url.startsWith("/_hmr/")) {
|
|
252
|
+
const i = s.url.split("/_hmr/")[1], u = s.headers["sec-websocket-key"], d = m("sha1").update(u + "258EAFA5-E914-47DA-95CA-C5AB0DC85B11").digest("base64");
|
|
253
|
+
t.write(
|
|
248
254
|
`HTTP/1.1 101 Switching Protocols\r
|
|
249
255
|
Upgrade: websocket\r
|
|
250
256
|
Connection: Upgrade\r
|
|
251
|
-
Sec-WebSocket-Accept: ${
|
|
257
|
+
Sec-WebSocket-Accept: ${d}\r
|
|
252
258
|
\r
|
|
253
259
|
`
|
|
254
|
-
),
|
|
255
|
-
const
|
|
256
|
-
|
|
257
|
-
}),
|
|
258
|
-
const
|
|
259
|
-
|
|
260
|
+
), D.has(i) || D.set(i, /* @__PURE__ */ new Set()), D.get(i).add(t), console.log(`π HMR client connected: ${i}`), t.on("close", () => {
|
|
261
|
+
const h = D.get(i);
|
|
262
|
+
h && (h.delete(t), h.size === 0 && D.delete(i)), console.log(`π HMR client disconnected: ${i}`);
|
|
263
|
+
}), t.on("error", () => {
|
|
264
|
+
const h = D.get(i);
|
|
265
|
+
h && h.delete(t);
|
|
260
266
|
});
|
|
261
267
|
}
|
|
262
|
-
},
|
|
263
|
-
if (
|
|
264
|
-
let
|
|
265
|
-
|
|
268
|
+
}, ce = a.default.createServer((s, t) => {
|
|
269
|
+
if (t.setHeader("Content-Type", "application/json"), s.method === "POST" && s.url === "/_register") {
|
|
270
|
+
let r = "";
|
|
271
|
+
s.on("data", (i) => r += i), s.on("end", () => {
|
|
266
272
|
try {
|
|
267
|
-
const { componentId:
|
|
268
|
-
|
|
269
|
-
const
|
|
270
|
-
console.log(`β
Registered: ${
|
|
271
|
-
const
|
|
272
|
-
id:
|
|
273
|
-
path:
|
|
274
|
-
name:
|
|
273
|
+
const { componentId: i, distPath: u, componentName: d } = JSON.parse(r);
|
|
274
|
+
M.set(i, { path: u, name: d || null });
|
|
275
|
+
const h = d ? ` (${d})` : "";
|
|
276
|
+
console.log(`β
Registered: ${i}${h} -> ${u}`), t.writeHead(200), t.end(JSON.stringify({ success: !0, registered: Array.from(M.keys()) }));
|
|
277
|
+
const I = Array.from(M.entries()).map(([T, V]) => ({
|
|
278
|
+
id: T,
|
|
279
|
+
path: V.path,
|
|
280
|
+
name: V.name
|
|
275
281
|
}));
|
|
276
|
-
|
|
282
|
+
J.forEach((T) => {
|
|
277
283
|
try {
|
|
278
|
-
|
|
284
|
+
T.write(`data: ${JSON.stringify({
|
|
279
285
|
type: "components",
|
|
280
|
-
components:
|
|
286
|
+
components: I
|
|
281
287
|
})}
|
|
282
288
|
|
|
283
289
|
`);
|
|
284
290
|
} catch {
|
|
285
291
|
}
|
|
286
292
|
});
|
|
287
|
-
} catch (
|
|
288
|
-
|
|
293
|
+
} catch (i) {
|
|
294
|
+
t.writeHead(400), t.end(JSON.stringify({ error: i.message }));
|
|
289
295
|
}
|
|
290
296
|
});
|
|
291
|
-
} else if (
|
|
292
|
-
let
|
|
293
|
-
|
|
297
|
+
} else if (s.method === "POST" && s.url === "/_unregister") {
|
|
298
|
+
let r = "";
|
|
299
|
+
s.on("data", (i) => r += i), s.on("end", () => {
|
|
294
300
|
try {
|
|
295
|
-
const { componentId:
|
|
296
|
-
|
|
297
|
-
const
|
|
298
|
-
id:
|
|
299
|
-
path:
|
|
300
|
-
name:
|
|
301
|
+
const { componentId: i } = JSON.parse(r);
|
|
302
|
+
M.delete(i), console.log(`β Unregistered: ${i}`), t.writeHead(200), t.end(JSON.stringify({ success: !0 }));
|
|
303
|
+
const u = Array.from(M.entries()).map(([d, h]) => ({
|
|
304
|
+
id: d,
|
|
305
|
+
path: h.path,
|
|
306
|
+
name: h.name
|
|
301
307
|
}));
|
|
302
|
-
|
|
308
|
+
J.forEach((d) => {
|
|
303
309
|
try {
|
|
304
|
-
|
|
310
|
+
d.write(`data: ${JSON.stringify({
|
|
305
311
|
type: "components",
|
|
306
|
-
components:
|
|
312
|
+
components: u
|
|
307
313
|
})}
|
|
308
314
|
|
|
309
315
|
`);
|
|
310
316
|
} catch {
|
|
311
317
|
}
|
|
312
318
|
});
|
|
313
|
-
} catch (
|
|
314
|
-
|
|
319
|
+
} catch (i) {
|
|
320
|
+
t.writeHead(400), t.end(JSON.stringify({ error: i.message }));
|
|
315
321
|
}
|
|
316
322
|
});
|
|
317
|
-
} else
|
|
318
|
-
}),
|
|
319
|
-
if (
|
|
320
|
-
|
|
323
|
+
} else s.method === "GET" && s.url === "/_list" ? (t.writeHead(200), t.end(JSON.stringify({ components: Array.from(M.entries()) }))) : (t.writeHead(404), t.end(JSON.stringify({ error: "Not found" })));
|
|
324
|
+
}), q = a.default.createServer((s, t) => {
|
|
325
|
+
if (s.url.includes("..")) {
|
|
326
|
+
t.writeHead(403, { "Content-Type": "text/plain" }), t.end("Forbidden");
|
|
321
327
|
return;
|
|
322
328
|
}
|
|
323
|
-
const
|
|
324
|
-
if (
|
|
325
|
-
const
|
|
326
|
-
if (!
|
|
327
|
-
|
|
329
|
+
const r = new URL(s.url, `http://localhost:${f}`), i = r.pathname, u = i.split("/").filter((k) => k);
|
|
330
|
+
if (i.startsWith("/consume")) {
|
|
331
|
+
const k = r.searchParams.get("id");
|
|
332
|
+
if (!k) {
|
|
333
|
+
t.writeHead(400, { "Content-Type": "application/json" }), t.end(JSON.stringify({ error: "Component ID required. Use /consume?id=<componentId>" }));
|
|
328
334
|
return;
|
|
329
335
|
}
|
|
330
|
-
const
|
|
331
|
-
let
|
|
332
|
-
if (
|
|
333
|
-
const
|
|
336
|
+
const N = M.get(k), L = N ? N.path : null, $e = (W) => {
|
|
337
|
+
let C = "Unknown", R = "Unknown";
|
|
338
|
+
if (s.headers.referer || s.headers.referrer) {
|
|
339
|
+
const O = s.headers.referer || s.headers.referrer;
|
|
334
340
|
try {
|
|
335
|
-
const
|
|
336
|
-
|
|
341
|
+
const Y = new URL(O);
|
|
342
|
+
C = Y.origin, R = Y.hostname || Y.origin;
|
|
337
343
|
} catch {
|
|
338
|
-
|
|
344
|
+
C = O, R = O;
|
|
339
345
|
}
|
|
340
|
-
} else if (
|
|
346
|
+
} else if (s.headers.origin)
|
|
341
347
|
try {
|
|
342
|
-
const
|
|
343
|
-
|
|
348
|
+
const O = new URL(s.headers.origin);
|
|
349
|
+
C = O.origin, R = O.hostname || O.origin;
|
|
344
350
|
} catch {
|
|
345
|
-
|
|
351
|
+
C = s.headers.origin, R = s.headers.origin;
|
|
346
352
|
}
|
|
347
|
-
else if (
|
|
348
|
-
const
|
|
349
|
-
|
|
353
|
+
else if (s.socket.remoteAddress) {
|
|
354
|
+
const O = s.socket.remoteAddress;
|
|
355
|
+
O === "::1" || O === "::ffff:127.0.0.1" ? (C = "localhost", R = "localhost (direct)") : (C = O, R = O.replace("::ffff:", ""));
|
|
350
356
|
}
|
|
351
|
-
const
|
|
357
|
+
const de = s.headers.referer || s.headers.referrer || C, te = {
|
|
352
358
|
type: "request",
|
|
353
|
-
componentId:
|
|
359
|
+
componentId: k,
|
|
354
360
|
timestamp: Date.now(),
|
|
355
|
-
servedLocally:
|
|
356
|
-
referrer:
|
|
357
|
-
origin:
|
|
358
|
-
originLabel:
|
|
361
|
+
servedLocally: W,
|
|
362
|
+
referrer: de,
|
|
363
|
+
origin: C,
|
|
364
|
+
originLabel: R
|
|
359
365
|
};
|
|
360
|
-
|
|
361
|
-
url:
|
|
362
|
-
label:
|
|
366
|
+
B.has(C) || (B.set(C, {
|
|
367
|
+
url: C,
|
|
368
|
+
label: R,
|
|
363
369
|
firstSeen: Date.now(),
|
|
364
370
|
requestCount: 0
|
|
365
|
-
}),
|
|
371
|
+
}), J.forEach((O) => {
|
|
366
372
|
try {
|
|
367
|
-
|
|
373
|
+
O.write(`data: ${JSON.stringify({
|
|
368
374
|
type: "origins",
|
|
369
|
-
origins: Array.from(
|
|
375
|
+
origins: Array.from(B.values())
|
|
370
376
|
})}
|
|
371
377
|
|
|
372
378
|
`);
|
|
373
379
|
} catch {
|
|
374
380
|
}
|
|
375
381
|
}));
|
|
376
|
-
const
|
|
377
|
-
|
|
382
|
+
const ze = B.get(C);
|
|
383
|
+
ze.requestCount++, J.forEach((O) => {
|
|
378
384
|
try {
|
|
379
|
-
|
|
385
|
+
O.write(`data: ${JSON.stringify({
|
|
380
386
|
type: "origins",
|
|
381
|
-
origins: Array.from(
|
|
387
|
+
origins: Array.from(B.values())
|
|
382
388
|
})}
|
|
383
389
|
|
|
384
390
|
`);
|
|
385
391
|
} catch {
|
|
386
392
|
}
|
|
387
|
-
}),
|
|
393
|
+
}), F.push(te), F.length > Ne && F.shift(), J.forEach((O) => {
|
|
388
394
|
try {
|
|
389
|
-
|
|
395
|
+
O.write(`data: ${JSON.stringify(te)}
|
|
390
396
|
|
|
391
397
|
`);
|
|
392
398
|
} catch {
|
|
393
399
|
}
|
|
394
400
|
});
|
|
395
401
|
};
|
|
396
|
-
if (
|
|
397
|
-
const
|
|
398
|
-
|
|
399
|
-
if (
|
|
400
|
-
console.log(`β File not found: ${
|
|
402
|
+
if (L) {
|
|
403
|
+
const W = o.default.join(L, "index.html");
|
|
404
|
+
e.default.readFile(W, "utf-8", (C, R) => {
|
|
405
|
+
if (C) {
|
|
406
|
+
console.log(`β File not found: ${W}`), t.writeHead(404, { "Content-Type": "application/json" }), t.end(JSON.stringify({ error: "index.html not found" }));
|
|
401
407
|
return;
|
|
402
408
|
}
|
|
403
|
-
const
|
|
409
|
+
const de = `dev-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`, te = {
|
|
404
410
|
item: {
|
|
405
|
-
name:
|
|
406
|
-
id:
|
|
411
|
+
name: k,
|
|
412
|
+
id: k,
|
|
407
413
|
consume_variant: [
|
|
408
414
|
{
|
|
409
|
-
id:
|
|
415
|
+
id: de,
|
|
410
416
|
name: "dev version",
|
|
411
417
|
loader: {
|
|
412
418
|
type: "HTMLLoader",
|
|
413
419
|
shadowRootMode: "localFrame",
|
|
414
|
-
HTML:
|
|
420
|
+
HTML: R
|
|
415
421
|
}
|
|
416
422
|
}
|
|
417
423
|
]
|
|
418
424
|
}
|
|
419
425
|
};
|
|
420
|
-
console.log(`β
Serving consume JSON for: ${
|
|
426
|
+
console.log(`β
Serving consume JSON for: ${k}`), $e(!0), t.writeHead(200, {
|
|
421
427
|
"Content-Type": "application/json",
|
|
422
428
|
"Access-Control-Allow-Origin": "*"
|
|
423
|
-
}),
|
|
429
|
+
}), t.end(JSON.stringify(te, null, 2));
|
|
424
430
|
});
|
|
425
431
|
} else {
|
|
426
|
-
console.log(`π‘ Proxying consume request to cloud.myop.dev for: ${
|
|
427
|
-
const
|
|
428
|
-
|
|
429
|
-
|
|
432
|
+
console.log(`π‘ Proxying consume request to cloud.myop.dev for: ${k}`);
|
|
433
|
+
const W = `https://cloud.myop.dev/consume${r.search}`;
|
|
434
|
+
$e(!1), fetch(W).then((C) => C.text()).then((C) => {
|
|
435
|
+
t.writeHead(200, {
|
|
430
436
|
"Content-Type": "application/json",
|
|
431
437
|
"Access-Control-Allow-Origin": "*"
|
|
432
|
-
}),
|
|
433
|
-
}).catch((
|
|
434
|
-
console.error(`β Proxy error: ${
|
|
438
|
+
}), t.end(C);
|
|
439
|
+
}).catch((C) => {
|
|
440
|
+
console.error(`β Proxy error: ${C.message}`), t.writeHead(502, { "Content-Type": "application/json" }), t.end(JSON.stringify({ error: "Failed to fetch from cloud.myop.dev" }));
|
|
435
441
|
});
|
|
436
442
|
}
|
|
437
443
|
return;
|
|
438
444
|
}
|
|
439
|
-
if (
|
|
440
|
-
|
|
445
|
+
if (i === "/events") {
|
|
446
|
+
t.writeHead(200, {
|
|
441
447
|
"Content-Type": "text/event-stream",
|
|
442
448
|
"Cache-Control": "no-cache",
|
|
443
449
|
Connection: "keep-alive",
|
|
444
450
|
"Access-Control-Allow-Origin": "*"
|
|
445
|
-
}),
|
|
446
|
-
const
|
|
447
|
-
id:
|
|
448
|
-
path:
|
|
449
|
-
name:
|
|
451
|
+
}), J.push(t);
|
|
452
|
+
const k = Array.from(M.entries()).map(([N, L]) => ({
|
|
453
|
+
id: N,
|
|
454
|
+
path: L.path,
|
|
455
|
+
name: L.name
|
|
450
456
|
}));
|
|
451
|
-
|
|
457
|
+
t.write(`data: ${JSON.stringify({
|
|
452
458
|
type: "components",
|
|
453
|
-
components:
|
|
459
|
+
components: k
|
|
454
460
|
})}
|
|
455
461
|
|
|
456
|
-
`),
|
|
462
|
+
`), t.write(`data: ${JSON.stringify({
|
|
457
463
|
type: "origins",
|
|
458
|
-
origins: Array.from(
|
|
464
|
+
origins: Array.from(B.values())
|
|
459
465
|
})}
|
|
460
466
|
|
|
461
|
-
`),
|
|
467
|
+
`), t.write(`data: ${JSON.stringify({
|
|
462
468
|
type: "requestLog",
|
|
463
|
-
log:
|
|
469
|
+
log: F
|
|
464
470
|
})}
|
|
465
471
|
|
|
466
|
-
`),
|
|
467
|
-
const
|
|
468
|
-
|
|
472
|
+
`), s.on("close", () => {
|
|
473
|
+
const N = J.indexOf(t);
|
|
474
|
+
N !== -1 && J.splice(N, 1);
|
|
469
475
|
});
|
|
470
476
|
return;
|
|
471
477
|
}
|
|
472
|
-
if (
|
|
473
|
-
|
|
478
|
+
if (u.length === 0) {
|
|
479
|
+
t.writeHead(200, { "Content-Type": "text/html" }), t.end(nt(f, w, v, S));
|
|
474
480
|
return;
|
|
475
481
|
}
|
|
476
|
-
if (
|
|
477
|
-
|
|
482
|
+
if (u[0] !== "view") {
|
|
483
|
+
t.writeHead(404, { "Content-Type": "text/plain" }), t.end("Not found. Use /view/<componentId>/ to access components.");
|
|
478
484
|
return;
|
|
479
485
|
}
|
|
480
|
-
if (
|
|
481
|
-
|
|
486
|
+
if (u.length < 2) {
|
|
487
|
+
t.writeHead(400, { "Content-Type": "text/plain" }), t.end("Component ID required. Use /view/<componentId>/");
|
|
482
488
|
return;
|
|
483
489
|
}
|
|
484
|
-
const
|
|
485
|
-
if (!
|
|
486
|
-
|
|
490
|
+
const d = u[1], h = M.get(d);
|
|
491
|
+
if (!h) {
|
|
492
|
+
t.writeHead(404, { "Content-Type": "text/plain" }), t.end(`Component not found: ${d}`);
|
|
487
493
|
return;
|
|
488
494
|
}
|
|
489
|
-
const
|
|
490
|
-
console.log(`π₯ Request: ${
|
|
491
|
-
if (
|
|
492
|
-
console.log(`β File not found: ${
|
|
495
|
+
const I = h.path, T = u.slice(2), V = T.length === 0 ? "index.html" : T.join("/"), K = o.default.join(I, V);
|
|
496
|
+
console.log(`π₯ Request: ${s.url} -> ${K}`), e.default.readFile(K, (k, N) => {
|
|
497
|
+
if (k) {
|
|
498
|
+
console.log(`β File not found: ${K}`), t.writeHead(404, { "Content-Type": "text/plain" }), t.end("Not Found");
|
|
493
499
|
return;
|
|
494
500
|
}
|
|
495
|
-
const
|
|
496
|
-
console.log(`β
Serving: ${
|
|
497
|
-
"Content-Type":
|
|
501
|
+
const L = H(K);
|
|
502
|
+
console.log(`β
Serving: ${K} (${L})`), t.writeHead(200, {
|
|
503
|
+
"Content-Type": L,
|
|
498
504
|
"Access-Control-Allow-Origin": "*"
|
|
499
|
-
}),
|
|
505
|
+
}), t.end(N);
|
|
500
506
|
});
|
|
501
|
-
}),
|
|
502
|
-
const
|
|
503
|
-
componentId:
|
|
504
|
-
distPath:
|
|
505
|
-
componentName:
|
|
506
|
-
}),
|
|
507
|
+
}), we = () => new Promise((s, t) => {
|
|
508
|
+
const r = JSON.stringify({
|
|
509
|
+
componentId: x,
|
|
510
|
+
distPath: o.default.resolve(b, y),
|
|
511
|
+
componentName: P
|
|
512
|
+
}), i = {
|
|
507
513
|
hostname: "localhost",
|
|
508
|
-
port:
|
|
514
|
+
port: w,
|
|
509
515
|
path: "/_register",
|
|
510
516
|
method: "POST",
|
|
511
517
|
headers: {
|
|
512
518
|
"Content-Type": "application/json",
|
|
513
|
-
"Content-Length": Buffer.byteLength(
|
|
519
|
+
"Content-Length": Buffer.byteLength(r)
|
|
514
520
|
}
|
|
515
|
-
},
|
|
516
|
-
let
|
|
517
|
-
|
|
518
|
-
|
|
521
|
+
}, u = a.default.request(i, (d) => {
|
|
522
|
+
let h = "";
|
|
523
|
+
d.on("data", (I) => h += I), d.on("end", () => {
|
|
524
|
+
d.statusCode === 200 ? s(JSON.parse(h)) : t(new Error(`Registration failed: ${d.statusCode}`));
|
|
519
525
|
});
|
|
520
526
|
});
|
|
521
|
-
|
|
522
|
-
}),
|
|
523
|
-
const
|
|
527
|
+
u.on("error", t), u.write(r), u.end();
|
|
528
|
+
}), Ee = () => new Promise((s, t) => {
|
|
529
|
+
const r = JSON.stringify({ componentId: x }), i = {
|
|
524
530
|
hostname: "localhost",
|
|
525
|
-
port:
|
|
531
|
+
port: w,
|
|
526
532
|
path: "/_unregister",
|
|
527
533
|
method: "POST",
|
|
528
534
|
headers: {
|
|
529
535
|
"Content-Type": "application/json",
|
|
530
|
-
"Content-Length": Buffer.byteLength(
|
|
536
|
+
"Content-Length": Buffer.byteLength(r)
|
|
531
537
|
}
|
|
532
|
-
},
|
|
533
|
-
|
|
538
|
+
}, u = a.default.request(i, (d) => {
|
|
539
|
+
s();
|
|
534
540
|
});
|
|
535
|
-
|
|
536
|
-
}),
|
|
537
|
-
if (!
|
|
538
|
-
const
|
|
541
|
+
u.on("error", () => s()), u.write(r), u.end();
|
|
542
|
+
}), He = () => {
|
|
543
|
+
if (!g) return;
|
|
544
|
+
const s = o.default.join(y, "index.html");
|
|
539
545
|
try {
|
|
540
|
-
let
|
|
541
|
-
if (
|
|
542
|
-
const
|
|
543
|
-
|
|
546
|
+
let t = e.default.readFileSync(s, "utf-8");
|
|
547
|
+
if (t.includes("<!-- MYOP HMR -->")) {
|
|
548
|
+
const i = t.indexOf("<!-- MYOP HMR -->"), u = t.indexOf("<\/script>", i) + 9;
|
|
549
|
+
t = t.slice(0, i) + t.slice(u);
|
|
544
550
|
}
|
|
545
|
-
const
|
|
551
|
+
const r = `
|
|
546
552
|
<!-- MYOP HMR -->
|
|
547
553
|
<script>
|
|
548
554
|
(function() {
|
|
549
|
-
const componentId = '${
|
|
550
|
-
const wsUrl = 'ws://localhost:${
|
|
555
|
+
const componentId = '${x}';
|
|
556
|
+
const wsUrl = 'ws://localhost:${w}/_hmr/' + componentId;
|
|
551
557
|
let ws;
|
|
552
558
|
let reconnectAttempts = 0;
|
|
553
559
|
const maxReconnectAttempts = 10;
|
|
@@ -648,318 +654,1225 @@ Sec-WebSocket-Accept: ${r}\r
|
|
|
648
654
|
})();
|
|
649
655
|
<\/script>
|
|
650
656
|
`;
|
|
651
|
-
|
|
652
|
-
} catch (
|
|
653
|
-
console.error("β Failed to inject HMR script:",
|
|
657
|
+
t.includes("</body>") ? t = t.replace("</body>", `${r}</body>`) : t.includes("</html>") ? t = t.replace("</html>", `${r}</html>`) : t += r, e.default.writeFileSync(s, t, "utf-8"), console.log("π₯ HMR script injected");
|
|
658
|
+
} catch (t) {
|
|
659
|
+
console.error("β Failed to inject HMR script:", t.message);
|
|
654
660
|
}
|
|
655
|
-
},
|
|
656
|
-
const
|
|
657
|
-
let
|
|
658
|
-
return
|
|
659
|
-
Buffer.from([129,
|
|
661
|
+
}, Je = (s) => {
|
|
662
|
+
const t = Buffer.from(s), r = t.length;
|
|
663
|
+
let i;
|
|
664
|
+
return r < 126 ? i = Buffer.concat([
|
|
665
|
+
Buffer.from([129, r]),
|
|
660
666
|
// FIN + text frame, length
|
|
661
|
-
|
|
662
|
-
]) :
|
|
667
|
+
t
|
|
668
|
+
]) : r < 65536 ? i = Buffer.concat([
|
|
663
669
|
Buffer.from([129, 126]),
|
|
664
670
|
// FIN + text frame, extended length
|
|
665
|
-
Buffer.from([
|
|
671
|
+
Buffer.from([r >> 8, r & 255]),
|
|
666
672
|
// 16-bit length
|
|
667
|
-
|
|
668
|
-
]) :
|
|
673
|
+
t
|
|
674
|
+
]) : i = Buffer.concat([
|
|
669
675
|
Buffer.from([129, 127]),
|
|
670
676
|
// FIN + text frame, extended length
|
|
671
|
-
Buffer.from([0, 0, 0, 0,
|
|
677
|
+
Buffer.from([0, 0, 0, 0, r >> 24, r >> 16 & 255, r >> 8 & 255, r & 255]),
|
|
672
678
|
// 64-bit length
|
|
673
|
-
|
|
674
|
-
]),
|
|
675
|
-
},
|
|
676
|
-
if (!
|
|
677
|
-
const
|
|
678
|
-
if (!
|
|
679
|
+
t
|
|
680
|
+
]), i;
|
|
681
|
+
}, Le = () => {
|
|
682
|
+
if (!g) return;
|
|
683
|
+
const s = D.get(x);
|
|
684
|
+
if (!s || s.size === 0)
|
|
679
685
|
return;
|
|
680
|
-
console.log(`π₯ Notifying ${
|
|
681
|
-
const
|
|
686
|
+
console.log(`π₯ Notifying ${s.size} HMR client(s)`);
|
|
687
|
+
const t = o.default.join(y, "index.html");
|
|
682
688
|
try {
|
|
683
|
-
let
|
|
684
|
-
if (
|
|
685
|
-
const
|
|
686
|
-
|
|
689
|
+
let r = e.default.readFileSync(t, "utf-8");
|
|
690
|
+
if (r.includes("<!-- MYOP HMR -->")) {
|
|
691
|
+
const d = r.indexOf("<!-- MYOP HMR -->"), h = r.indexOf("<\/script>", d) + 9;
|
|
692
|
+
r = r.slice(0, d) + r.slice(h);
|
|
687
693
|
}
|
|
688
|
-
const
|
|
694
|
+
const i = JSON.stringify({
|
|
689
695
|
type: "update",
|
|
690
|
-
html:
|
|
691
|
-
}),
|
|
692
|
-
|
|
696
|
+
html: r
|
|
697
|
+
}), u = Je(i);
|
|
698
|
+
s.forEach((d) => {
|
|
693
699
|
try {
|
|
694
|
-
|
|
700
|
+
d.write(u);
|
|
695
701
|
} catch {
|
|
696
|
-
|
|
702
|
+
s.delete(d);
|
|
697
703
|
}
|
|
698
704
|
});
|
|
699
|
-
} catch (
|
|
700
|
-
console.error("β Failed to read HTML for HMR:",
|
|
705
|
+
} catch (r) {
|
|
706
|
+
console.error("β Failed to read HTML for HMR:", r.message);
|
|
701
707
|
}
|
|
702
|
-
},
|
|
703
|
-
if (
|
|
704
|
-
|
|
708
|
+
}, le = () => {
|
|
709
|
+
if (j) {
|
|
710
|
+
$ = !0;
|
|
705
711
|
return;
|
|
706
712
|
}
|
|
707
|
-
|
|
708
|
-
π¨ Building...`),
|
|
709
|
-
|
|
713
|
+
j = !0, console.log(`
|
|
714
|
+
π¨ Building...`), n("npm run build", (s, t, r) => {
|
|
715
|
+
j = !1, s ? (console.error("β Build failed:", s.message), r && console.error(r)) : (console.log("β
Build completed"), t && console.log(t), He(), Le()), $ && ($ = !1, le());
|
|
710
716
|
});
|
|
711
|
-
},
|
|
712
|
-
|
|
713
|
-
|
|
714
|
-
const
|
|
715
|
-
if (
|
|
716
|
-
|
|
717
|
-
else if (
|
|
718
|
-
const
|
|
719
|
-
if (
|
|
717
|
+
}, ve = /* @__PURE__ */ new Set(), Se = (s) => {
|
|
718
|
+
e.default.readdir(s, { withFileTypes: !0 }, (t, r) => {
|
|
719
|
+
t || (r.forEach((i) => {
|
|
720
|
+
const u = o.default.join(s, i.name);
|
|
721
|
+
if (i.isDirectory())
|
|
722
|
+
i.name !== "node_modules" && i.name !== "dist" && !i.name.startsWith(".") && Se(u);
|
|
723
|
+
else if (i.isFile()) {
|
|
724
|
+
const d = o.default.extname(i.name);
|
|
725
|
+
if (d === ".js" || d === ".css" || d === ".html")
|
|
720
726
|
try {
|
|
721
|
-
const
|
|
722
|
-
|
|
727
|
+
const h = e.default.readFileSync(u, "utf-8");
|
|
728
|
+
_.set(u, h);
|
|
723
729
|
} catch {
|
|
724
730
|
}
|
|
725
|
-
i.default.watch(c, (l) => {
|
|
726
|
-
if (l === "change")
|
|
727
|
-
try {
|
|
728
|
-
const w = i.default.readFileSync(c, "utf-8"), C = V.get(c);
|
|
729
|
-
w !== C && (V.set(c, w), console.log(`π File changed: ${c}`), B());
|
|
730
|
-
} catch {
|
|
731
|
-
console.log(`π File changed: ${c}`), B();
|
|
732
|
-
}
|
|
733
|
-
});
|
|
734
|
-
}
|
|
735
731
|
}
|
|
736
|
-
})
|
|
732
|
+
}), ve.has(s) || (ve.add(s), e.default.watch(s, (i, u) => {
|
|
733
|
+
if (!u) return;
|
|
734
|
+
const d = o.default.extname(u);
|
|
735
|
+
if (d !== ".js" && d !== ".css" && d !== ".html") return;
|
|
736
|
+
const h = o.default.join(s, u);
|
|
737
|
+
setTimeout(() => {
|
|
738
|
+
try {
|
|
739
|
+
const I = e.default.readFileSync(h, "utf-8"), T = _.get(h);
|
|
740
|
+
I !== T && (_.set(h, I), console.log(`π File changed: ${h}`), le());
|
|
741
|
+
} catch {
|
|
742
|
+
}
|
|
743
|
+
}, 50);
|
|
744
|
+
})));
|
|
737
745
|
});
|
|
738
|
-
},
|
|
746
|
+
}, xe = () => {
|
|
739
747
|
console.log(`
|
|
740
|
-
π¨ Component: ${
|
|
748
|
+
π¨ Component: ${x}`), le(), Se(b), console.log("π Watching .js, .css, and .html files for changes..."), console.log(`Press Ctrl+C to stop
|
|
741
749
|
`);
|
|
742
|
-
},
|
|
743
|
-
const
|
|
750
|
+
}, De = () => new Promise((s) => {
|
|
751
|
+
const t = {
|
|
744
752
|
hostname: "localhost",
|
|
745
|
-
port:
|
|
753
|
+
port: w,
|
|
746
754
|
path: "/_list",
|
|
747
755
|
method: "GET",
|
|
748
756
|
timeout: 1e3
|
|
749
|
-
},
|
|
750
|
-
|
|
757
|
+
}, r = a.default.request(t, (i) => {
|
|
758
|
+
s(!0);
|
|
751
759
|
});
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
}),
|
|
755
|
-
}),
|
|
756
|
-
const
|
|
757
|
-
if (
|
|
758
|
-
let
|
|
759
|
-
|
|
760
|
+
r.on("error", () => s(!1)), r.on("timeout", () => {
|
|
761
|
+
r.destroy(), s(!1);
|
|
762
|
+
}), r.end();
|
|
763
|
+
}), Ue = () => new Promise((s) => {
|
|
764
|
+
const t = a.default.createServer((r, i) => {
|
|
765
|
+
if (i.setHeader("Content-Type", "application/json"), r.method === "POST" && r.url === "/_register") {
|
|
766
|
+
let u = "";
|
|
767
|
+
r.on("data", (d) => u += d), r.on("end", () => {
|
|
760
768
|
try {
|
|
761
|
-
const { componentId:
|
|
762
|
-
|
|
763
|
-
const
|
|
764
|
-
console.log(`β
Registered: ${
|
|
765
|
-
} catch (
|
|
766
|
-
|
|
769
|
+
const { componentId: d, distPath: h, componentName: I } = JSON.parse(u);
|
|
770
|
+
M.set(d, { path: h, name: I || null });
|
|
771
|
+
const T = I ? ` (${I})` : "";
|
|
772
|
+
console.log(`β
Registered: ${d}${T} -> ${h}`), i.writeHead(200), i.end(JSON.stringify({ success: !0, registered: Array.from(M.keys()) }));
|
|
773
|
+
} catch (d) {
|
|
774
|
+
i.writeHead(400), i.end(JSON.stringify({ error: d.message }));
|
|
767
775
|
}
|
|
768
776
|
});
|
|
769
|
-
} else if (
|
|
770
|
-
let
|
|
771
|
-
|
|
777
|
+
} else if (r.method === "POST" && r.url === "/_unregister") {
|
|
778
|
+
let u = "";
|
|
779
|
+
r.on("data", (d) => u += d), r.on("end", () => {
|
|
772
780
|
try {
|
|
773
|
-
const { componentId:
|
|
774
|
-
|
|
775
|
-
} catch (
|
|
776
|
-
|
|
781
|
+
const { componentId: d } = JSON.parse(u);
|
|
782
|
+
M.delete(d), console.log(`β Unregistered: ${d}`), i.writeHead(200), i.end(JSON.stringify({ success: !0 }));
|
|
783
|
+
} catch (d) {
|
|
784
|
+
i.writeHead(400), i.end(JSON.stringify({ error: d.message }));
|
|
777
785
|
}
|
|
778
786
|
});
|
|
779
|
-
} else
|
|
787
|
+
} else r.method === "GET" && r.url === "/_list" ? (i.writeHead(200), i.end(JSON.stringify({ components: Array.from(M.entries()) }))) : (i.writeHead(404), i.end(JSON.stringify({ error: "Not found" })));
|
|
780
788
|
});
|
|
781
|
-
|
|
782
|
-
|
|
783
|
-
}),
|
|
789
|
+
t.on("error", () => {
|
|
790
|
+
s(!1);
|
|
791
|
+
}), t.listen(w, () => {
|
|
784
792
|
console.log(`
|
|
785
|
-
π Taking over as server...`), console.log(`π‘ Management server on port ${
|
|
786
|
-
|
|
787
|
-
}),
|
|
788
|
-
console.log(`π‘ Main server running at http://localhost:${
|
|
789
|
-
path:
|
|
790
|
-
name:
|
|
793
|
+
π Taking over as server...`), console.log(`π‘ Management server on port ${w}`), q.on("error", () => {
|
|
794
|
+
t.close(), s(!1);
|
|
795
|
+
}), q.listen(f, () => {
|
|
796
|
+
console.log(`π‘ Main server running at http://localhost:${f}`), M.set(x, {
|
|
797
|
+
path: o.default.resolve(b, y),
|
|
798
|
+
name: P
|
|
791
799
|
});
|
|
792
|
-
const
|
|
793
|
-
console.log(`β
Registered component: ${
|
|
800
|
+
const r = P ? ` (${P})` : "";
|
|
801
|
+
console.log(`β
Registered component: ${x}${r}`), console.log(`π‘ Access at: http://localhost:${f}/view/${x}/`), s(!0);
|
|
794
802
|
});
|
|
795
803
|
});
|
|
796
804
|
});
|
|
797
|
-
let
|
|
798
|
-
const
|
|
799
|
-
|
|
800
|
-
await
|
|
801
|
-
β οΈ Server appears to be down, attempting to take over...`), await
|
|
805
|
+
let ee;
|
|
806
|
+
const be = () => {
|
|
807
|
+
ee = setInterval(async () => {
|
|
808
|
+
await De() || (clearInterval(ee), console.log(`
|
|
809
|
+
β οΈ Server appears to be down, attempting to take over...`), await Ue() ? console.log("β
Successfully took over as server") : (console.log("βΉοΈ Another instance took over, re-registering..."), setTimeout(async () => {
|
|
802
810
|
try {
|
|
803
|
-
await
|
|
804
|
-
} catch (
|
|
805
|
-
console.error("β Failed to re-register:",
|
|
811
|
+
await we(), console.log(`β
Re-registered component: ${x}`), be();
|
|
812
|
+
} catch (r) {
|
|
813
|
+
console.error("β Failed to re-register:", r.message);
|
|
806
814
|
}
|
|
807
815
|
}, 2e3)));
|
|
808
816
|
}, 3e3);
|
|
809
|
-
},
|
|
817
|
+
}, Ce = async () => {
|
|
810
818
|
console.log(`
|
|
811
819
|
|
|
812
|
-
π Shutting down...`),
|
|
820
|
+
π Shutting down...`), ee && clearInterval(ee), await Ee(), process.exit(0);
|
|
813
821
|
};
|
|
814
|
-
process.on("SIGINT",
|
|
815
|
-
if (
|
|
822
|
+
process.on("SIGINT", Ce), process.on("SIGTERM", Ce), ce.on("error", async (s) => {
|
|
823
|
+
if (s.code === "EADDRINUSE") {
|
|
816
824
|
console.log(`
|
|
817
825
|
π Connecting to existing dev server...`);
|
|
818
826
|
try {
|
|
819
|
-
const
|
|
820
|
-
console.log(`β
Registered component: ${
|
|
821
|
-
} catch (
|
|
822
|
-
console.error("β Failed to register component:",
|
|
827
|
+
const t = await we();
|
|
828
|
+
console.log(`β
Registered component: ${x}`), console.log(`π‘ Access at: http://localhost:${f}/view/${x}/`), console.log(`π All registered components: ${t.registered.join(", ")}`), xe(), be();
|
|
829
|
+
} catch (t) {
|
|
830
|
+
console.error("β Failed to register component:", t.message), process.exit(1);
|
|
823
831
|
}
|
|
824
832
|
} else
|
|
825
|
-
console.error("β Management server error:",
|
|
826
|
-
}),
|
|
833
|
+
console.error("β Management server error:", s.message), process.exit(1);
|
|
834
|
+
}), ce.on("upgrade", Ae), ce.listen(w, async () => {
|
|
827
835
|
console.log(`
|
|
828
|
-
π Starting shared dev server...`), console.log(`π‘ Management server on port ${
|
|
829
|
-
console.error("β Main server error:",
|
|
830
|
-
}),
|
|
831
|
-
console.log(`π‘ Main server running at http://localhost:${
|
|
832
|
-
path:
|
|
833
|
-
name:
|
|
836
|
+
π Starting shared dev server...`), console.log(`π‘ Management server on port ${w}`), q.on("error", (s) => {
|
|
837
|
+
console.error("β Main server error:", s.message), process.exit(1);
|
|
838
|
+
}), q.listen(f, async () => {
|
|
839
|
+
console.log(`π‘ Main server running at http://localhost:${f}`), M.set(x, {
|
|
840
|
+
path: o.default.resolve(b, y),
|
|
841
|
+
name: P
|
|
834
842
|
});
|
|
835
|
-
const
|
|
836
|
-
console.log(`β
Registered component: ${
|
|
843
|
+
const s = P ? ` (${P})` : "";
|
|
844
|
+
console.log(`β
Registered component: ${x}${s}`), console.log(`π‘ Access at: http://localhost:${f}/view/${x}/`), xe();
|
|
845
|
+
});
|
|
846
|
+
});
|
|
847
|
+
}
|
|
848
|
+
const me = Z.join(Ge.homedir(), ".myop"), Q = Z.join(me, "credentials.json");
|
|
849
|
+
function st() {
|
|
850
|
+
E.existsSync(me) || E.mkdirSync(me, { recursive: !0, mode: 448 });
|
|
851
|
+
}
|
|
852
|
+
function ge() {
|
|
853
|
+
try {
|
|
854
|
+
if (!E.existsSync(Q))
|
|
855
|
+
return null;
|
|
856
|
+
const e = E.readFileSync(Q, "utf8");
|
|
857
|
+
return JSON.parse(e);
|
|
858
|
+
} catch (e) {
|
|
859
|
+
return console.info("Failed to read credentials:", e.message), null;
|
|
860
|
+
}
|
|
861
|
+
}
|
|
862
|
+
function Te(e) {
|
|
863
|
+
st();
|
|
864
|
+
const o = {
|
|
865
|
+
...e,
|
|
866
|
+
savedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
867
|
+
};
|
|
868
|
+
E.writeFileSync(Q, JSON.stringify(o, null, 2), {
|
|
869
|
+
mode: 384
|
|
870
|
+
// Read/write for owner only
|
|
871
|
+
});
|
|
872
|
+
}
|
|
873
|
+
function Re() {
|
|
874
|
+
try {
|
|
875
|
+
return E.existsSync(Q) && E.unlinkSync(Q), !0;
|
|
876
|
+
} catch (e) {
|
|
877
|
+
return console.error("Failed to clear credentials:", e.message), !1;
|
|
878
|
+
}
|
|
879
|
+
}
|
|
880
|
+
function rt(e) {
|
|
881
|
+
if (!e || !e.expiresAt)
|
|
882
|
+
return !0;
|
|
883
|
+
const o = 5 * 60 * 1e3, n = new Date(e.expiresAt).getTime();
|
|
884
|
+
return Date.now() > n - o;
|
|
885
|
+
}
|
|
886
|
+
function he() {
|
|
887
|
+
const e = ge();
|
|
888
|
+
return e ? {
|
|
889
|
+
email: e.userEmail,
|
|
890
|
+
userId: e.userId
|
|
891
|
+
} : null;
|
|
892
|
+
}
|
|
893
|
+
const G = process.env.MYOP_MCP_URL || "https://mcp.myop.dev", se = 19284, ye = `http://localhost:${se}/callback`, it = "myop-cli";
|
|
894
|
+
function at() {
|
|
895
|
+
return ue.randomBytes(32).toString("base64url");
|
|
896
|
+
}
|
|
897
|
+
function ct(e) {
|
|
898
|
+
return ue.createHash("sha256").update(e).digest("base64url");
|
|
899
|
+
}
|
|
900
|
+
async function lt() {
|
|
901
|
+
const e = await fetch(`${G}/oauth/register`, {
|
|
902
|
+
method: "POST",
|
|
903
|
+
headers: { "Content-Type": "application/json" },
|
|
904
|
+
body: JSON.stringify({
|
|
905
|
+
client_name: it,
|
|
906
|
+
redirect_uris: [ye],
|
|
907
|
+
grant_types: ["authorization_code", "refresh_token"],
|
|
908
|
+
response_types: ["code"]
|
|
909
|
+
})
|
|
910
|
+
});
|
|
911
|
+
if (!e.ok) {
|
|
912
|
+
const o = await e.text();
|
|
913
|
+
throw new Error(`Failed to register client: ${o}`);
|
|
914
|
+
}
|
|
915
|
+
return e.json();
|
|
916
|
+
}
|
|
917
|
+
function oe(e, o, n, a = null) {
|
|
918
|
+
const m = {
|
|
919
|
+
success: `<svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="#4ade80" stroke-width="2">
|
|
920
|
+
<circle cx="12" cy="12" r="10"/>
|
|
921
|
+
<path d="M8 12l2.5 2.5L16 9"/>
|
|
922
|
+
</svg>`,
|
|
923
|
+
error: `<svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="#f87171" stroke-width="2">
|
|
924
|
+
<circle cx="12" cy="12" r="10"/>
|
|
925
|
+
<path d="M15 9l-6 6M9 9l6 6"/>
|
|
926
|
+
</svg>`,
|
|
927
|
+
warning: `<svg width="64" height="64" viewBox="0 0 24 24" fill="none" stroke="#fbbf24" stroke-width="2">
|
|
928
|
+
<path d="M12 2L2 22h20L12 2z"/>
|
|
929
|
+
<path d="M12 9v4M12 17h.01"/>
|
|
930
|
+
</svg>`
|
|
931
|
+
}, c = {
|
|
932
|
+
success: { accent: "#4ade80", glow: "rgba(74, 222, 128, 0.1)" },
|
|
933
|
+
error: { accent: "#f87171", glow: "rgba(248, 113, 113, 0.1)" },
|
|
934
|
+
warning: { accent: "#fbbf24", glow: "rgba(251, 191, 36, 0.1)" }
|
|
935
|
+
}, { accent: p, glow: v } = c[e] || c.error;
|
|
936
|
+
return `<!DOCTYPE html>
|
|
937
|
+
<html lang="en">
|
|
938
|
+
<head>
|
|
939
|
+
<meta charset="UTF-8">
|
|
940
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
941
|
+
<title>myop-cli | ${o}</title>
|
|
942
|
+
<style>
|
|
943
|
+
* {
|
|
944
|
+
margin: 0;
|
|
945
|
+
padding: 0;
|
|
946
|
+
box-sizing: border-box;
|
|
947
|
+
}
|
|
948
|
+
|
|
949
|
+
body {
|
|
950
|
+
font-family: 'SF Mono', 'Monaco', 'Inconsolata', 'Roboto Mono', 'Consolas', monospace;
|
|
951
|
+
background: #1e1e1e;
|
|
952
|
+
color: #e8eaed;
|
|
953
|
+
min-height: 100vh;
|
|
954
|
+
display: flex;
|
|
955
|
+
align-items: center;
|
|
956
|
+
justify-content: center;
|
|
957
|
+
padding: 20px;
|
|
958
|
+
}
|
|
959
|
+
|
|
960
|
+
.container {
|
|
961
|
+
background: #292a2d;
|
|
962
|
+
border: 1px solid #3c4043;
|
|
963
|
+
border-radius: 8px;
|
|
964
|
+
padding: 48px;
|
|
965
|
+
max-width: 480px;
|
|
966
|
+
width: 100%;
|
|
967
|
+
text-align: center;
|
|
968
|
+
box-shadow: 0 8px 32px rgba(0, 0, 0, 0.4);
|
|
969
|
+
animation: slideUp 0.3s ease-out;
|
|
970
|
+
}
|
|
971
|
+
|
|
972
|
+
@keyframes slideUp {
|
|
973
|
+
from {
|
|
974
|
+
opacity: 0;
|
|
975
|
+
transform: translateY(20px);
|
|
976
|
+
}
|
|
977
|
+
to {
|
|
978
|
+
opacity: 1;
|
|
979
|
+
transform: translateY(0);
|
|
980
|
+
}
|
|
981
|
+
}
|
|
982
|
+
|
|
983
|
+
.icon {
|
|
984
|
+
margin-bottom: 24px;
|
|
985
|
+
animation: pulse 2s ease-in-out infinite;
|
|
986
|
+
}
|
|
987
|
+
|
|
988
|
+
@keyframes pulse {
|
|
989
|
+
0%, 100% { opacity: 1; }
|
|
990
|
+
50% { opacity: 0.7; }
|
|
991
|
+
}
|
|
992
|
+
|
|
993
|
+
h1 {
|
|
994
|
+
font-size: 20px;
|
|
995
|
+
font-weight: 500;
|
|
996
|
+
color: ${p};
|
|
997
|
+
margin-bottom: 12px;
|
|
998
|
+
letter-spacing: -0.5px;
|
|
999
|
+
}
|
|
1000
|
+
|
|
1001
|
+
.message {
|
|
1002
|
+
color: #9aa0a6;
|
|
1003
|
+
font-size: 14px;
|
|
1004
|
+
line-height: 1.6;
|
|
1005
|
+
margin-bottom: 24px;
|
|
1006
|
+
}
|
|
1007
|
+
|
|
1008
|
+
.details {
|
|
1009
|
+
background: #1e1e1e;
|
|
1010
|
+
border: 1px solid #3c4043;
|
|
1011
|
+
border-radius: 4px;
|
|
1012
|
+
padding: 12px 16px;
|
|
1013
|
+
font-size: 12px;
|
|
1014
|
+
color: #f87171;
|
|
1015
|
+
text-align: left;
|
|
1016
|
+
margin-bottom: 24px;
|
|
1017
|
+
word-break: break-all;
|
|
1018
|
+
}
|
|
1019
|
+
|
|
1020
|
+
.details code {
|
|
1021
|
+
color: #fbbf24;
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
.hint {
|
|
1025
|
+
display: inline-flex;
|
|
1026
|
+
align-items: center;
|
|
1027
|
+
gap: 8px;
|
|
1028
|
+
background: ${v};
|
|
1029
|
+
border: 1px solid ${p}33;
|
|
1030
|
+
border-radius: 4px;
|
|
1031
|
+
padding: 10px 16px;
|
|
1032
|
+
font-size: 12px;
|
|
1033
|
+
color: #9aa0a6;
|
|
1034
|
+
}
|
|
1035
|
+
|
|
1036
|
+
.hint kbd {
|
|
1037
|
+
background: #3c4043;
|
|
1038
|
+
border: 1px solid #5f6368;
|
|
1039
|
+
border-radius: 3px;
|
|
1040
|
+
padding: 2px 6px;
|
|
1041
|
+
font-size: 11px;
|
|
1042
|
+
color: #e8eaed;
|
|
1043
|
+
}
|
|
1044
|
+
|
|
1045
|
+
.logo {
|
|
1046
|
+
margin-top: 32px;
|
|
1047
|
+
padding-top: 24px;
|
|
1048
|
+
border-top: 1px solid #3c4043;
|
|
1049
|
+
}
|
|
1050
|
+
|
|
1051
|
+
.logo span {
|
|
1052
|
+
font-size: 12px;
|
|
1053
|
+
color: #5f6368;
|
|
1054
|
+
letter-spacing: 1px;
|
|
1055
|
+
}
|
|
1056
|
+
|
|
1057
|
+
.logo .brand {
|
|
1058
|
+
color: #8ab4f8;
|
|
1059
|
+
font-weight: 600;
|
|
1060
|
+
}
|
|
1061
|
+
</style>
|
|
1062
|
+
</head>
|
|
1063
|
+
<body>
|
|
1064
|
+
<div class="container">
|
|
1065
|
+
<div class="icon">
|
|
1066
|
+
${m[e] || m.error}
|
|
1067
|
+
</div>
|
|
1068
|
+
<h1>${o}</h1>
|
|
1069
|
+
<p class="message">${n}</p>
|
|
1070
|
+
${a ? `<div class="details"><code>Error:</code> ${a}</div>` : ""}
|
|
1071
|
+
<div class="hint">
|
|
1072
|
+
<span>Press</span>
|
|
1073
|
+
<kbd>β</kbd><kbd>W</kbd>
|
|
1074
|
+
<span>to close this window</span>
|
|
1075
|
+
</div>
|
|
1076
|
+
<div class="logo">
|
|
1077
|
+
<span><span class="brand">myop</span>-cli</span>
|
|
1078
|
+
</div>
|
|
1079
|
+
</div>
|
|
1080
|
+
</body>
|
|
1081
|
+
</html>`;
|
|
1082
|
+
}
|
|
1083
|
+
function dt(e) {
|
|
1084
|
+
return new Promise((o, n) => {
|
|
1085
|
+
const a = We.createServer((m, c) => {
|
|
1086
|
+
const p = new Oe(m.url, `http://localhost:${se}`);
|
|
1087
|
+
if (p.pathname === "/callback") {
|
|
1088
|
+
const v = p.searchParams.get("code"), S = p.searchParams.get("state"), f = p.searchParams.get("error");
|
|
1089
|
+
if (f) {
|
|
1090
|
+
c.writeHead(200, { "Content-Type": "text/html" }), c.end(oe(
|
|
1091
|
+
"error",
|
|
1092
|
+
"Authentication Failed",
|
|
1093
|
+
"Unable to complete the authentication process.",
|
|
1094
|
+
f
|
|
1095
|
+
)), a.close(), n(new Error(`OAuth error: ${f}`));
|
|
1096
|
+
return;
|
|
1097
|
+
}
|
|
1098
|
+
if (S !== e) {
|
|
1099
|
+
c.writeHead(400, { "Content-Type": "text/html" }), c.end(oe(
|
|
1100
|
+
"warning",
|
|
1101
|
+
"Security Error",
|
|
1102
|
+
"State mismatch detected. This could indicate a CSRF attack. Please try authenticating again.",
|
|
1103
|
+
"state_mismatch"
|
|
1104
|
+
)), a.close(), n(new Error("State mismatch"));
|
|
1105
|
+
return;
|
|
1106
|
+
}
|
|
1107
|
+
if (!v) {
|
|
1108
|
+
c.writeHead(400, { "Content-Type": "text/html" }), c.end(oe(
|
|
1109
|
+
"error",
|
|
1110
|
+
"Missing Authorization Code",
|
|
1111
|
+
"No authorization code was received from the server.",
|
|
1112
|
+
"missing_code"
|
|
1113
|
+
)), a.close(), n(new Error("No authorization code"));
|
|
1114
|
+
return;
|
|
1115
|
+
}
|
|
1116
|
+
c.writeHead(200, { "Content-Type": "text/html" }), c.end(oe(
|
|
1117
|
+
"success",
|
|
1118
|
+
"Authentication Successful",
|
|
1119
|
+
"You have been authenticated successfully. Return to the terminal to continue."
|
|
1120
|
+
)), a.close(), o(v);
|
|
1121
|
+
} else
|
|
1122
|
+
c.writeHead(404), c.end("Not found");
|
|
837
1123
|
});
|
|
1124
|
+
a.listen(se, () => {
|
|
1125
|
+
console.info(`OAuth callback server listening on port ${se}`);
|
|
1126
|
+
}), setTimeout(() => {
|
|
1127
|
+
a.close(), n(new Error("Authentication timed out"));
|
|
1128
|
+
}, 5 * 60 * 1e3);
|
|
1129
|
+
});
|
|
1130
|
+
}
|
|
1131
|
+
async function pt(e, o, n) {
|
|
1132
|
+
const a = await fetch(`${G}/oauth/token`, {
|
|
1133
|
+
method: "POST",
|
|
1134
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
1135
|
+
body: new je({
|
|
1136
|
+
grant_type: "authorization_code",
|
|
1137
|
+
code: e,
|
|
1138
|
+
client_id: o,
|
|
1139
|
+
redirect_uri: ye,
|
|
1140
|
+
code_verifier: n
|
|
1141
|
+
})
|
|
1142
|
+
});
|
|
1143
|
+
if (!a.ok) {
|
|
1144
|
+
const m = await a.json();
|
|
1145
|
+
throw new Error(m.error_description || m.error || "Token exchange failed");
|
|
1146
|
+
}
|
|
1147
|
+
return a.json();
|
|
1148
|
+
}
|
|
1149
|
+
async function mt(e, o) {
|
|
1150
|
+
const n = await fetch(`${G}/oauth/token`, {
|
|
1151
|
+
method: "POST",
|
|
1152
|
+
headers: { "Content-Type": "application/x-www-form-urlencoded" },
|
|
1153
|
+
body: new je({
|
|
1154
|
+
grant_type: "refresh_token",
|
|
1155
|
+
refresh_token: e,
|
|
1156
|
+
client_id: o
|
|
1157
|
+
})
|
|
1158
|
+
});
|
|
1159
|
+
if (!n.ok) {
|
|
1160
|
+
const a = await n.json();
|
|
1161
|
+
throw new Error(a.error_description || a.error || "Token refresh failed");
|
|
1162
|
+
}
|
|
1163
|
+
return n.json();
|
|
1164
|
+
}
|
|
1165
|
+
async function ut(e) {
|
|
1166
|
+
var m, c, p;
|
|
1167
|
+
const o = await fetch(`${G}/mcp`, {
|
|
1168
|
+
method: "POST",
|
|
1169
|
+
headers: {
|
|
1170
|
+
"Content-Type": "application/json",
|
|
1171
|
+
Authorization: `Bearer ${e}`
|
|
1172
|
+
},
|
|
1173
|
+
body: JSON.stringify({
|
|
1174
|
+
jsonrpc: "2.0",
|
|
1175
|
+
id: 1,
|
|
1176
|
+
method: "tools/call",
|
|
1177
|
+
params: {
|
|
1178
|
+
name: "whoami",
|
|
1179
|
+
arguments: {}
|
|
1180
|
+
}
|
|
1181
|
+
})
|
|
838
1182
|
});
|
|
1183
|
+
if (!o.ok)
|
|
1184
|
+
throw new Error("Failed to get user info");
|
|
1185
|
+
const n = await o.json();
|
|
1186
|
+
if (n.error)
|
|
1187
|
+
throw new Error(n.error.message);
|
|
1188
|
+
const a = (p = (c = (m = n.result) == null ? void 0 : m.content) == null ? void 0 : c[0]) == null ? void 0 : p.text;
|
|
1189
|
+
if (a)
|
|
1190
|
+
return JSON.parse(a);
|
|
1191
|
+
throw new Error("Invalid response from whoami");
|
|
1192
|
+
}
|
|
1193
|
+
async function X() {
|
|
1194
|
+
const e = A("Starting authentication...").start();
|
|
1195
|
+
try {
|
|
1196
|
+
e.text = "Registering OAuth client...";
|
|
1197
|
+
const n = (await lt()).client_id, a = at(), m = ct(a), c = ue.randomBytes(16).toString("hex");
|
|
1198
|
+
e.text = "Waiting for authorization...";
|
|
1199
|
+
const p = dt(c), v = new Oe(`${G}/oauth/authorize`);
|
|
1200
|
+
v.searchParams.set("response_type", "code"), v.searchParams.set("client_id", n), v.searchParams.set("redirect_uri", ye), v.searchParams.set("code_challenge", m), v.searchParams.set("code_challenge_method", "S256"), v.searchParams.set("state", c), e.stop(), console.log(`
|
|
1201
|
+
π Opening browser for authentication...`), console.log("If the browser does not open, visit:"), console.log(` ${v.toString()}
|
|
1202
|
+
`), await Ye(v.toString());
|
|
1203
|
+
const S = await p;
|
|
1204
|
+
e.start("Exchanging authorization code...");
|
|
1205
|
+
const f = await pt(S, n, a);
|
|
1206
|
+
e.text = "Getting user info...";
|
|
1207
|
+
const w = await ut(f.access_token), y = {
|
|
1208
|
+
accessToken: f.access_token,
|
|
1209
|
+
refreshToken: f.refresh_token,
|
|
1210
|
+
expiresAt: new Date(Date.now() + f.expires_in * 1e3).toISOString(),
|
|
1211
|
+
clientId: n,
|
|
1212
|
+
userId: w.userId,
|
|
1213
|
+
userEmail: w.email
|
|
1214
|
+
};
|
|
1215
|
+
return Te(y), e.succeed(`Authenticated as ${w.email}`), y;
|
|
1216
|
+
} catch (o) {
|
|
1217
|
+
throw e.fail(`Authentication failed: ${o.message}`), o;
|
|
1218
|
+
}
|
|
839
1219
|
}
|
|
840
|
-
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
}
|
|
846
|
-
|
|
847
|
-
|
|
1220
|
+
async function Fe() {
|
|
1221
|
+
const e = ge();
|
|
1222
|
+
if (!e) {
|
|
1223
|
+
console.log("Not currently logged in.");
|
|
1224
|
+
return;
|
|
1225
|
+
}
|
|
1226
|
+
Re(), console.log(`β
Logged out (was: ${e.userEmail})`);
|
|
1227
|
+
}
|
|
1228
|
+
async function ft() {
|
|
1229
|
+
let e = ge();
|
|
1230
|
+
if (!e)
|
|
1231
|
+
return console.log(`Not logged in. Starting authentication...
|
|
1232
|
+
`), await X();
|
|
1233
|
+
if (!rt(e))
|
|
1234
|
+
return e;
|
|
1235
|
+
if (e.refreshToken) {
|
|
1236
|
+
const o = A("Refreshing access token...").start();
|
|
1237
|
+
try {
|
|
1238
|
+
const n = await mt(
|
|
1239
|
+
e.refreshToken,
|
|
1240
|
+
e.clientId
|
|
1241
|
+
);
|
|
1242
|
+
return e = {
|
|
1243
|
+
...e,
|
|
1244
|
+
accessToken: n.access_token,
|
|
1245
|
+
refreshToken: n.refresh_token,
|
|
1246
|
+
expiresAt: new Date(Date.now() + n.expires_in * 1e3).toISOString()
|
|
1247
|
+
}, Te(e), o.succeed("Token refreshed"), e;
|
|
1248
|
+
} catch {
|
|
1249
|
+
return o.warn("Token refresh failed, please log in again"), Re(), await X();
|
|
1250
|
+
}
|
|
1251
|
+
}
|
|
1252
|
+
return console.log(`Session expired. Please log in again.
|
|
1253
|
+
`), await X();
|
|
1254
|
+
}
|
|
1255
|
+
function gt() {
|
|
1256
|
+
return G;
|
|
1257
|
+
}
|
|
1258
|
+
const re = "@myop/cli";
|
|
1259
|
+
async function ht() {
|
|
1260
|
+
try {
|
|
1261
|
+
const e = await fetch(`https://registry.npmjs.org/${re}/latest`);
|
|
1262
|
+
return e.ok ? (await e.json()).version : null;
|
|
1263
|
+
} catch {
|
|
1264
|
+
return null;
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
function yt(e, o) {
|
|
1268
|
+
const n = e.split(".").map(Number), a = o.split(".").map(Number);
|
|
1269
|
+
for (let m = 0; m < Math.max(n.length, a.length); m++) {
|
|
1270
|
+
const c = n[m] || 0, p = a[m] || 0;
|
|
1271
|
+
if (c > p) return 1;
|
|
1272
|
+
if (c < p) return -1;
|
|
1273
|
+
}
|
|
1274
|
+
return 0;
|
|
1275
|
+
}
|
|
1276
|
+
async function wt(e) {
|
|
1277
|
+
const o = A({
|
|
1278
|
+
text: "Checking for updates...",
|
|
1279
|
+
color: "cyan"
|
|
1280
|
+
}).start(), n = await ht();
|
|
1281
|
+
if (o.stop(), !n || yt(n, e) <= 0)
|
|
1282
|
+
return !1;
|
|
1283
|
+
if (console.log(`
|
|
1284
|
+
π¦ New version available: ${e} β ${n}
|
|
1285
|
+
`), await Me({
|
|
1286
|
+
message: "Would you like to update now?",
|
|
1287
|
+
choices: [
|
|
1288
|
+
{ name: "Yes, update now", value: !0 },
|
|
1289
|
+
{ name: "No, continue with current version", value: !1 }
|
|
1290
|
+
]
|
|
1291
|
+
})) {
|
|
1292
|
+
const m = A({
|
|
1293
|
+
text: `Updating ${re} to v${n}...`,
|
|
1294
|
+
color: "green"
|
|
1295
|
+
}).start();
|
|
1296
|
+
try {
|
|
1297
|
+
ne(`npm install -g ${re}@latest`, { stdio: "pipe" }), m.succeed(`Updated to v${n}`), console.log(`
|
|
1298
|
+
Please restart the CLI to use the new version.
|
|
1299
|
+
`), process.exit(0);
|
|
1300
|
+
} catch {
|
|
1301
|
+
return m.fail("Update failed"), console.log(`
|
|
1302
|
+
You can manually update by running: npm install -g ${re}@latest
|
|
1303
|
+
`), !1;
|
|
1304
|
+
}
|
|
1305
|
+
}
|
|
1306
|
+
return !1;
|
|
1307
|
+
}
|
|
1308
|
+
const vt = (e) => new Promise((o) => setTimeout(o, e));
|
|
1309
|
+
l.executionPath = process.cwd();
|
|
1310
|
+
const ae = (e = !1) => {
|
|
1311
|
+
const o = l.program.getOptionValue("verbose");
|
|
1312
|
+
o || (console.info = () => {
|
|
1313
|
+
}), console.info("π verbose mode on"), l.options = {
|
|
1314
|
+
configPath: l.program.getOptionValue("config"),
|
|
1315
|
+
verbose: o
|
|
848
1316
|
};
|
|
849
1317
|
try {
|
|
850
|
-
|
|
851
|
-
} catch (
|
|
852
|
-
if (
|
|
1318
|
+
return l.myopConfig = Ke(l.options.configPath), { configFound: !0 };
|
|
1319
|
+
} catch (n) {
|
|
1320
|
+
if (e) {
|
|
853
1321
|
console.info(`
|
|
854
|
-
β οΈ failed read config file from ${
|
|
1322
|
+
β οΈ failed read config file from ${l.options.configPath}, trying to create new one`);
|
|
855
1323
|
try {
|
|
856
|
-
const
|
|
1324
|
+
const a = {
|
|
857
1325
|
author: "@myop-cli",
|
|
858
1326
|
flows: []
|
|
859
1327
|
};
|
|
860
|
-
|
|
1328
|
+
return fe(l.options.configPath, a), l.myopConfig = a, { configFound: !0 };
|
|
861
1329
|
} catch {
|
|
862
|
-
console.
|
|
863
|
-
β οΈ failed read config file from ${a.options.configPath}, for more details use verbose flag`), console.info("Error details :", m), process.exit();
|
|
1330
|
+
return console.info("Error details :", n), { configFound: !1, error: n };
|
|
864
1331
|
}
|
|
865
1332
|
} else
|
|
866
|
-
console.
|
|
867
|
-
β οΈ failed read config file from ${a.options.configPath}, for more details use verbose flag`), console.info("Error details :", m), process.exit();
|
|
1333
|
+
return console.info("Error details :", n), { configFound: !1, error: n };
|
|
868
1334
|
}
|
|
869
|
-
}, de = [
|
|
870
|
-
ae,
|
|
871
|
-
ce,
|
|
872
|
-
le,
|
|
873
|
-
Te,
|
|
874
|
-
new xe(),
|
|
875
|
-
...je
|
|
876
|
-
], De = async () => $e({
|
|
877
|
-
message: "Select an operation",
|
|
878
|
-
choices: de
|
|
879
|
-
}), pe = async () => {
|
|
880
|
-
const i = await De(), s = de.find((m) => m.value === i);
|
|
881
|
-
s ? s.action ? await s.action() : console.log(`β οΈ Operation ${i} has no action`) : console.log(`β οΈ Operation ${i} not found`), await pe();
|
|
882
1335
|
};
|
|
883
|
-
|
|
884
|
-
|
|
885
|
-
|
|
886
|
-
|
|
887
|
-
|
|
888
|
-
|
|
889
|
-
|
|
1336
|
+
[
|
|
1337
|
+
new pe(),
|
|
1338
|
+
...ot
|
|
1339
|
+
];
|
|
1340
|
+
l.program = new Be();
|
|
1341
|
+
l.program.name("@myop/cli").description("Myop CLI - Remote UI Made Easy").version("0.1.10");
|
|
1342
|
+
l.program.addOption(new ie("-c, --config <value>", "myop.config.json file location").default("./myop.config.json", "./myop.config.json"));
|
|
1343
|
+
l.program.addOption(new ie("-h, --help", "Show helpful information"));
|
|
1344
|
+
l.program.addOption(new ie("-v, --verbose", "Enables verbose output mode for the command-line interface (CLI)."));
|
|
1345
|
+
l.program.addOption(new ie("--ci", "CI mode: print status info (version, config, auth) as JSON and exit without prompts"));
|
|
1346
|
+
l.program.command("add").description("Install Myop assets").addArgument("type").addArgument("id").action((e, o) => {
|
|
1347
|
+
ae(!0), console.info("adding ", e, o, l.options.configPath), e === "flow" && ke._action(o), process.exit();
|
|
1348
|
+
});
|
|
1349
|
+
l.program.command("remove").description("Remove Myop asset").argument("<type>", "Myop asset type").argument("<id>", "Asset id").action((e, o) => {
|
|
1350
|
+
ae(), console.info("removing ", e, o, l.options.configPath), e === "flow" && Pe._action(o), process.exit();
|
|
1351
|
+
});
|
|
1352
|
+
l.program.command("install").description("Install Myop assets").action(async () => {
|
|
1353
|
+
ae(), await Ie.action();
|
|
1354
|
+
});
|
|
1355
|
+
l.program.command("login").description("Authenticate with Myop platform").action(async () => {
|
|
1356
|
+
try {
|
|
1357
|
+
await X();
|
|
1358
|
+
} catch (e) {
|
|
1359
|
+
console.error("Login failed:", e.message), process.exit(1);
|
|
1360
|
+
}
|
|
1361
|
+
process.exit(0);
|
|
890
1362
|
});
|
|
891
|
-
|
|
892
|
-
|
|
1363
|
+
l.program.command("logout").description("Clear stored credentials").action(async () => {
|
|
1364
|
+
await Fe(), process.exit(0);
|
|
893
1365
|
});
|
|
894
|
-
|
|
895
|
-
|
|
1366
|
+
l.program.command("whoami").description("Show current authenticated user").action(async () => {
|
|
1367
|
+
const e = he();
|
|
1368
|
+
e && e.email ? console.log(`Logged in as: ${e.email}`) : console.log("Not logged in. Run `myop login` to authenticate."), process.exit(0);
|
|
896
1369
|
});
|
|
897
|
-
|
|
898
|
-
|
|
899
|
-
|
|
900
|
-
|
|
1370
|
+
l.program.command("sync").description("Build and upload component to Myop platform").option("--skip-build", "Skip the build step").action(async (e) => {
|
|
1371
|
+
var j, $, _, z, x, P;
|
|
1372
|
+
const o = l.program.getOptionValue("config") || "./myop.config.json", n = await import("fs"), { execSync: a } = await import("child_process"), m = await import("path");
|
|
1373
|
+
let c = {};
|
|
1374
|
+
if (n.existsSync(o))
|
|
901
1375
|
try {
|
|
902
|
-
const
|
|
903
|
-
|
|
904
|
-
const
|
|
905
|
-
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
|
|
913
|
-
|
|
914
|
-
|
|
915
|
-
|
|
916
|
-
|
|
1376
|
+
const g = n.readFileSync(o, "utf-8");
|
|
1377
|
+
c = JSON.parse(g);
|
|
1378
|
+
const b = c.name || c.componentName;
|
|
1379
|
+
console.log(`π Found config: ${b || "Unnamed component"}`), c.componentId && console.log(` Component ID: ${c.componentId}`);
|
|
1380
|
+
} catch (g) {
|
|
1381
|
+
console.error(`β οΈ Failed to parse ${o}:`, g.message);
|
|
1382
|
+
}
|
|
1383
|
+
else
|
|
1384
|
+
console.log("β οΈ No myop.config.json found. A new component will be created.");
|
|
1385
|
+
if (!e.skipBuild) {
|
|
1386
|
+
const g = A("Building project...").start();
|
|
1387
|
+
try {
|
|
1388
|
+
a("npm run build", { stdio: "pipe" }), g.succeed("Build completed");
|
|
1389
|
+
} catch (b) {
|
|
1390
|
+
g.fail("Build failed"), console.error(b.message), process.exit(1);
|
|
1391
|
+
}
|
|
1392
|
+
}
|
|
1393
|
+
const p = "./dist/index.html";
|
|
1394
|
+
n.existsSync(p) || (console.error("β Error: ./dist/index.html not found"), console.log(" Make sure your build outputs to ./dist/index.html"), process.exit(1));
|
|
1395
|
+
let v;
|
|
1396
|
+
try {
|
|
1397
|
+
v = await ft();
|
|
1398
|
+
} catch (g) {
|
|
1399
|
+
console.error("β Authentication failed:", g.message), process.exit(1);
|
|
1400
|
+
}
|
|
1401
|
+
const S = gt();
|
|
1402
|
+
let f = A("Requesting upload URL...").start(), w;
|
|
1403
|
+
try {
|
|
1404
|
+
const g = await fetch(`${S}/mcp`, {
|
|
1405
|
+
method: "POST",
|
|
1406
|
+
headers: {
|
|
1407
|
+
"Content-Type": "application/json",
|
|
1408
|
+
Authorization: `Bearer ${v.accessToken}`
|
|
1409
|
+
},
|
|
1410
|
+
body: JSON.stringify({
|
|
1411
|
+
jsonrpc: "2.0",
|
|
1412
|
+
id: 1,
|
|
1413
|
+
method: "tools/call",
|
|
1414
|
+
params: {
|
|
1415
|
+
name: "upload_component",
|
|
1416
|
+
arguments: {
|
|
1417
|
+
name: c.name || c.componentName || m.default.basename(process.cwd()),
|
|
1418
|
+
componentId: c.componentId || void 0,
|
|
1419
|
+
organization: c.organization || void 0
|
|
917
1420
|
}
|
|
918
|
-
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
|
|
922
|
-
|
|
923
|
-
|
|
924
|
-
|
|
925
|
-
|
|
926
|
-
|
|
927
|
-
|
|
928
|
-
|
|
929
|
-
|
|
930
|
-
|
|
931
|
-
|
|
932
|
-
|
|
933
|
-
|
|
934
|
-
|
|
935
|
-
|
|
936
|
-
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
1421
|
+
}
|
|
1422
|
+
})
|
|
1423
|
+
});
|
|
1424
|
+
if (!g.ok)
|
|
1425
|
+
throw new Error(`Server returned ${g.status}`);
|
|
1426
|
+
const b = await g.json();
|
|
1427
|
+
if (b.error)
|
|
1428
|
+
throw new Error(b.error.message);
|
|
1429
|
+
const H = (_ = ($ = (j = b.result) == null ? void 0 : j.content) == null ? void 0 : $[0]) == null ? void 0 : _.text;
|
|
1430
|
+
if (w = JSON.parse(H), !w.success)
|
|
1431
|
+
throw new Error(w.error);
|
|
1432
|
+
f.succeed("Upload URL obtained");
|
|
1433
|
+
} catch (g) {
|
|
1434
|
+
f.fail("Failed to get upload URL"), console.error(" ", g.message), process.exit(1);
|
|
1435
|
+
}
|
|
1436
|
+
f = A("Uploading component...").start();
|
|
1437
|
+
try {
|
|
1438
|
+
const g = n.readFileSync(p, "utf-8");
|
|
1439
|
+
let b;
|
|
1440
|
+
const H = w.curlCommand.match(/(?:"|\\")([^"\\]+(?:\\.[^"\\]*)*)(?:"|\\")$/);
|
|
1441
|
+
if (H)
|
|
1442
|
+
b = H[1];
|
|
1443
|
+
else {
|
|
1444
|
+
const F = w.curlCommand.match(/(https:\/\/[^\s"\\]+)/);
|
|
1445
|
+
if (F)
|
|
1446
|
+
b = F[1];
|
|
1447
|
+
else
|
|
1448
|
+
throw new Error("Could not parse presigned URL from: " + w.curlCommand);
|
|
1449
|
+
}
|
|
1450
|
+
console.info("Uploading to:", b.substring(0, 100) + "...");
|
|
1451
|
+
const M = await fetch(b, {
|
|
1452
|
+
method: "PUT",
|
|
1453
|
+
headers: {
|
|
1454
|
+
"Content-Type": "text/html"
|
|
1455
|
+
},
|
|
1456
|
+
body: g
|
|
1457
|
+
});
|
|
1458
|
+
if (!M.ok) {
|
|
1459
|
+
const F = await M.text();
|
|
1460
|
+
throw new Error(`Upload failed with status ${M.status}: ${F}`);
|
|
1461
|
+
}
|
|
1462
|
+
f.succeed("Component uploaded");
|
|
1463
|
+
} catch (g) {
|
|
1464
|
+
f.fail("Upload failed"), console.error(" ", g.message), g.cause && console.error(" Cause:", g.cause), process.exit(1);
|
|
1465
|
+
}
|
|
1466
|
+
f = A("Confirming upload...").start();
|
|
1467
|
+
let y;
|
|
1468
|
+
try {
|
|
1469
|
+
const g = await fetch(`${S}/mcp`, {
|
|
1470
|
+
method: "POST",
|
|
1471
|
+
headers: {
|
|
1472
|
+
"Content-Type": "application/json",
|
|
1473
|
+
Authorization: `Bearer ${v.accessToken}`
|
|
1474
|
+
},
|
|
1475
|
+
body: JSON.stringify({
|
|
1476
|
+
jsonrpc: "2.0",
|
|
1477
|
+
id: 2,
|
|
1478
|
+
method: "tools/call",
|
|
1479
|
+
params: {
|
|
1480
|
+
name: "confirm_upload",
|
|
1481
|
+
arguments: {
|
|
1482
|
+
uploadId: w.uploadId
|
|
943
1483
|
}
|
|
944
|
-
}
|
|
945
|
-
|
|
946
|
-
|
|
947
|
-
|
|
948
|
-
|
|
949
|
-
|
|
1484
|
+
}
|
|
1485
|
+
})
|
|
1486
|
+
});
|
|
1487
|
+
if (!g.ok)
|
|
1488
|
+
throw new Error(`Server returned ${g.status}`);
|
|
1489
|
+
const b = await g.json();
|
|
1490
|
+
if (b.error)
|
|
1491
|
+
throw new Error(b.error.message);
|
|
1492
|
+
const H = (P = (x = (z = b.result) == null ? void 0 : z.content) == null ? void 0 : x[0]) == null ? void 0 : P.text;
|
|
1493
|
+
if (y = JSON.parse(H), !y.success)
|
|
1494
|
+
throw new Error(y.error);
|
|
1495
|
+
f.succeed("Upload confirmed");
|
|
1496
|
+
} catch (g) {
|
|
1497
|
+
f.fail("Confirmation failed"), console.error(" ", g.message), process.exit(1);
|
|
1498
|
+
}
|
|
1499
|
+
if (y.isNewComponent || !c.componentId) {
|
|
1500
|
+
c.componentId = y.componentId, c.organization = y.orgId, c.name || (c.name = y.componentName);
|
|
1501
|
+
try {
|
|
1502
|
+
n.writeFileSync(o, JSON.stringify(c, null, 2)), console.log(`
|
|
1503
|
+
π Updated ${o} with componentId`);
|
|
1504
|
+
} catch (g) {
|
|
1505
|
+
console.log(`
|
|
1506
|
+
β οΈ Could not update ${o}: ${g.message}`), console.log(` Please add componentId: "${y.componentId}" manually`);
|
|
950
1507
|
}
|
|
951
|
-
}
|
|
952
|
-
|
|
953
|
-
|
|
1508
|
+
}
|
|
1509
|
+
console.log(`
|
|
1510
|
+
β
Sync completed successfully!`), console.log(` Component: ${y.componentName}`), console.log(` Dashboard: ${y.dashboardUrl}`), process.exit(0);
|
|
954
1511
|
});
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
1512
|
+
l.program.command("dev").description("Start development server with file watching").action(_e);
|
|
1513
|
+
const St = () => {
|
|
1514
|
+
try {
|
|
1515
|
+
ne("git --version", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
1516
|
+
} catch {
|
|
1517
|
+
return { gitNotInstalled: !0 };
|
|
1518
|
+
}
|
|
1519
|
+
try {
|
|
1520
|
+
ne("git rev-parse --git-dir", { encoding: "utf-8", stdio: ["pipe", "pipe", "pipe"] });
|
|
1521
|
+
} catch {
|
|
1522
|
+
return { notARepo: !0 };
|
|
1523
|
+
}
|
|
1524
|
+
try {
|
|
1525
|
+
const e = ne("git diff --stat HEAD -- . 2>/dev/null || git diff --stat -- . 2>/dev/null", {
|
|
1526
|
+
encoding: "utf-8",
|
|
1527
|
+
stdio: ["pipe", "pipe", "pipe"]
|
|
1528
|
+
}).trim();
|
|
1529
|
+
if (!e)
|
|
1530
|
+
return {
|
|
1531
|
+
files: 0,
|
|
1532
|
+
insertions: 0,
|
|
1533
|
+
deletions: 0
|
|
1534
|
+
};
|
|
1535
|
+
const o = e.split(`
|
|
1536
|
+
`), n = o[o.length - 1], a = n.match(/(\d+) insertion/), m = n.match(/(\d+) deletion/), c = n.match(/(\d+) file/);
|
|
1537
|
+
return {
|
|
1538
|
+
files: c ? parseInt(c[1]) : 0,
|
|
1539
|
+
insertions: a ? parseInt(a[1]) : 0,
|
|
1540
|
+
deletions: m ? parseInt(m[1]) : 0
|
|
1541
|
+
};
|
|
1542
|
+
} catch {
|
|
1543
|
+
return null;
|
|
1544
|
+
}
|
|
1545
|
+
}, U = async (e = !1, o = !1) => {
|
|
1546
|
+
var w, y, j;
|
|
1547
|
+
const n = he(), a = !!(n != null && n.email), m = ((w = l.myopConfig) == null ? void 0 : w.name) || ((y = l.myopConfig) == null ? void 0 : y.componentName), c = (j = l.myopConfig) == null ? void 0 : j.componentId, p = St();
|
|
1548
|
+
console.log(`
|
|
1549
|
+
βββββββββββββββββββββββββββββββββββββββββββββββββββ`), console.log("β β"), console.log("β Welcome to Myop CLI - Remote UI Made Easy β"), console.log("β β"), console.log(`βββββββββββββββββββββββββββββββββββββββββββββββββββ
|
|
1550
|
+
`), e && m ? (console.log(` Component: ${m}`), c ? (console.log(` ID: ${c}`), console.log(` Dashboard: https://dashboard.myop.dev/dashboard/2.0/component/${c}`)) : console.log(" ID: (not yet pushed)")) : console.log(" Component: No myop.config.json found"), console.log(` User: ${a ? n.email : "Not logged in"}`), p != null && p.gitNotInstalled ? (console.log(" Changes: Git not installed"), console.log(" Install: https://git-scm.com/downloads"), console.log(" Mac: brew install git | Windows: https://gitforwindows.org")) : p != null && p.notARepo ? console.log(" Changes: Not a git repository") : p && (p.insertions > 0 || p.deletions > 0) ? console.log(` Changes: ${p.files} file${p.files !== 1 ? "s" : ""} | \x1B[32m+${p.insertions}\x1B[0m \x1B[31m-${p.deletions}\x1B[0m`) : p && console.log(" Changes: No uncommitted changes"), console.log("");
|
|
1551
|
+
const S = [
|
|
1552
|
+
{
|
|
1553
|
+
emoji: "π",
|
|
1554
|
+
label: "Initialize new component",
|
|
1555
|
+
value: "init",
|
|
1556
|
+
help: "Creates myop.config.json in current directory",
|
|
1557
|
+
disabled: e ? "(config already exists)" : !1
|
|
1558
|
+
},
|
|
1559
|
+
{
|
|
1560
|
+
emoji: "π¦",
|
|
1561
|
+
label: m ? `Push "${m}"` : "Push component",
|
|
1562
|
+
value: "sync",
|
|
1563
|
+
help: "Builds project & uploads dist/index.html to Myop",
|
|
1564
|
+
disabled: e ? a ? !1 : "(login required)" : "(no config file)"
|
|
1565
|
+
},
|
|
1566
|
+
{
|
|
1567
|
+
emoji: "π οΈ ",
|
|
1568
|
+
label: m ? `Start dev mode for "${m}"` : "Start dev mode",
|
|
1569
|
+
value: "dev",
|
|
1570
|
+
help: "Starts dev server with HMR for instant preview of changes",
|
|
1571
|
+
disabled: e ? !1 : "(no config file)"
|
|
1572
|
+
}
|
|
1573
|
+
].map(($) => ({
|
|
1574
|
+
name: o && !$.disabled ? `${$.emoji} ${$.label}
|
|
1575
|
+
${$.help}` : `${$.emoji} ${$.label}`,
|
|
1576
|
+
value: $.value,
|
|
1577
|
+
disabled: $.disabled
|
|
1578
|
+
}));
|
|
1579
|
+
switch (S.push(
|
|
1580
|
+
new pe(),
|
|
1581
|
+
{
|
|
1582
|
+
name: o && a ? `π Logout (${n.email})
|
|
1583
|
+
Clears stored credentials from this machine` : o && !a ? `π Login to Myop
|
|
1584
|
+
Opens browser to authenticate with Myop` : a ? `π Logout (${n.email})` : "π Login to Myop",
|
|
1585
|
+
value: a ? "logout" : "login"
|
|
1586
|
+
},
|
|
1587
|
+
{
|
|
1588
|
+
name: o ? "π Hide help" : "π Show help",
|
|
1589
|
+
value: "help"
|
|
1590
|
+
},
|
|
1591
|
+
new pe(),
|
|
1592
|
+
{
|
|
1593
|
+
name: "π Exit",
|
|
1594
|
+
value: "exit"
|
|
1595
|
+
}
|
|
1596
|
+
), await Me({
|
|
1597
|
+
message: "What would you like to do?",
|
|
1598
|
+
choices: S
|
|
1599
|
+
})) {
|
|
1600
|
+
case "init":
|
|
1601
|
+
await xt();
|
|
1602
|
+
break;
|
|
1603
|
+
case "sync":
|
|
1604
|
+
console.log(`
|
|
1605
|
+
Running sync...
|
|
1606
|
+
`);
|
|
1607
|
+
const { execSync: $ } = await import("child_process");
|
|
1608
|
+
try {
|
|
1609
|
+
$("node " + process.argv[1] + " sync", { stdio: "inherit" });
|
|
1610
|
+
} catch {
|
|
1611
|
+
}
|
|
1612
|
+
await U(!0, o);
|
|
1613
|
+
break;
|
|
1614
|
+
case "dev":
|
|
1615
|
+
await _e();
|
|
1616
|
+
break;
|
|
1617
|
+
case "login":
|
|
1618
|
+
try {
|
|
1619
|
+
await X(), console.log(`
|
|
1620
|
+
`), await U(e, o);
|
|
1621
|
+
} catch (_) {
|
|
1622
|
+
console.error("Login failed:", _.message), await U(e, o);
|
|
1623
|
+
}
|
|
1624
|
+
break;
|
|
1625
|
+
case "logout":
|
|
1626
|
+
await Fe(), console.log(`
|
|
1627
|
+
`), await U(e, o);
|
|
1628
|
+
break;
|
|
1629
|
+
case "help":
|
|
1630
|
+
await U(e, !o);
|
|
1631
|
+
break;
|
|
1632
|
+
case "exit":
|
|
1633
|
+
process.exit(0);
|
|
1634
|
+
}
|
|
1635
|
+
}, xt = async () => {
|
|
1636
|
+
const { input: e, select: o } = await import("@inquirer/prompts"), n = await import("fs"), m = (await import("path")).default.basename(process.cwd()), c = await e({
|
|
1637
|
+
message: "Component name:",
|
|
1638
|
+
default: m
|
|
1639
|
+
}), p = await o({
|
|
1640
|
+
message: "Component type:",
|
|
1641
|
+
choices: [
|
|
1642
|
+
{ name: "π HTML", value: "html", description: "Plain HTML/JS/CSS component" },
|
|
1643
|
+
{ name: "βοΈ React", value: "react", disabled: "(coming soon)" },
|
|
1644
|
+
{ name: "π Vue", value: "vue", disabled: "(coming soon)" },
|
|
1645
|
+
{ name: "π
°οΈ Angular", value: "angular", disabled: "(coming soon)" }
|
|
1646
|
+
]
|
|
1647
|
+
}), v = {
|
|
1648
|
+
name: c,
|
|
1649
|
+
type: p,
|
|
1650
|
+
author: "@myop-cli"
|
|
1651
|
+
}, S = l.program.getOptionValue("config") || "./myop.config.json";
|
|
1652
|
+
try {
|
|
1653
|
+
n.writeFileSync(S, JSON.stringify(v, null, 2)), console.log(`
|
|
1654
|
+
β
Created ${S}`);
|
|
1655
|
+
const f = {
|
|
1656
|
+
name: c.toLowerCase().replace(/\s+/g, "-"),
|
|
1657
|
+
version: "1.0.0",
|
|
1658
|
+
type: "module",
|
|
1659
|
+
scripts: {
|
|
1660
|
+
build: "node build.js",
|
|
1661
|
+
dev: "myop dev"
|
|
1662
|
+
},
|
|
1663
|
+
devDependencies: {
|
|
1664
|
+
esbuild: "^0.24.0"
|
|
1665
|
+
}
|
|
1666
|
+
};
|
|
1667
|
+
n.writeFileSync("package.json", JSON.stringify(f, null, 2)), console.log("β
Created package.json"), n.mkdirSync("src/modules", { recursive: !0 }), n.mkdirSync("src/styles", { recursive: !0 }), n.writeFileSync("build.js", `import * as esbuild from 'esbuild';
|
|
1668
|
+
import fs from 'fs';
|
|
1669
|
+
import path from 'path';
|
|
1670
|
+
|
|
1671
|
+
// Auto-discover all JS modules and CSS files
|
|
1672
|
+
const getAllFiles = (dir, ext) => {
|
|
1673
|
+
const files = [];
|
|
1674
|
+
const items = fs.readdirSync(dir, { withFileTypes: true });
|
|
1675
|
+
for (const item of items) {
|
|
1676
|
+
const fullPath = path.join(dir, item.name);
|
|
1677
|
+
if (item.isDirectory()) {
|
|
1678
|
+
files.push(...getAllFiles(fullPath, ext));
|
|
1679
|
+
} else if (item.name.endsWith(ext)) {
|
|
1680
|
+
files.push(fullPath);
|
|
1681
|
+
}
|
|
1682
|
+
}
|
|
1683
|
+
return files;
|
|
1684
|
+
};
|
|
1685
|
+
|
|
1686
|
+
// Generate temp entry that imports all modules
|
|
1687
|
+
const jsFiles = getAllFiles('src/modules', '.js');
|
|
1688
|
+
const jsImports = jsFiles.map((f, i) => \`import * as mod\${i} from './\${f.replace(/\\\\/g, '/')}';\`).join('\\n');
|
|
1689
|
+
const jsExports = jsFiles.map((_, i) => \`mod\${i}\`).join(', ');
|
|
1690
|
+
const tempJsEntry = \`// Auto-generated entry point
|
|
1691
|
+
\${jsImports}
|
|
1692
|
+
import { init } from './src/modules/app.js';
|
|
1693
|
+
import { setupMyopInterface } from './src/modules/myop.js';
|
|
1694
|
+
export { \${jsExports} };
|
|
1695
|
+
document.addEventListener('DOMContentLoaded', () => { init(); setupMyopInterface(); });
|
|
1696
|
+
\`;
|
|
1697
|
+
fs.writeFileSync('.temp-entry.js', tempJsEntry);
|
|
1698
|
+
|
|
1699
|
+
// Generate temp CSS entry that imports all styles
|
|
1700
|
+
const cssFiles = getAllFiles('src/styles', '.css').filter(f => !f.endsWith('index.css'));
|
|
1701
|
+
const cssImports = cssFiles.map(f => \`@import './\${f.replace(/\\\\/g, '/')}';\`).join('\\n');
|
|
1702
|
+
const tempCssEntry = \`/* Auto-generated - imports all CSS files */\\n\${cssImports}\\n\`;
|
|
1703
|
+
fs.writeFileSync('.temp-styles.css', tempCssEntry);
|
|
1704
|
+
|
|
1705
|
+
// Bundle JS (includes all modules)
|
|
1706
|
+
const jsResult = await esbuild.build({
|
|
1707
|
+
entryPoints: ['.temp-entry.js'],
|
|
1708
|
+
bundle: true,
|
|
1709
|
+
minify: true,
|
|
1710
|
+
write: false,
|
|
1711
|
+
format: 'iife'
|
|
1712
|
+
});
|
|
1713
|
+
|
|
1714
|
+
// Bundle CSS (includes all styles)
|
|
1715
|
+
const cssResult = await esbuild.build({
|
|
1716
|
+
entryPoints: ['.temp-styles.css'],
|
|
1717
|
+
bundle: true,
|
|
1718
|
+
minify: true,
|
|
1719
|
+
write: false
|
|
1720
|
+
});
|
|
1721
|
+
|
|
1722
|
+
// Cleanup temp files
|
|
1723
|
+
fs.unlinkSync('.temp-entry.js');
|
|
1724
|
+
fs.unlinkSync('.temp-styles.css');
|
|
1725
|
+
|
|
1726
|
+
// Read HTML template
|
|
1727
|
+
let html = fs.readFileSync('index.html', 'utf-8');
|
|
1728
|
+
|
|
1729
|
+
// Remove dev script/link tags
|
|
1730
|
+
html = html.replace(/<link rel="stylesheet" href="[^"]*">[\\n\\r]*/g, '');
|
|
1731
|
+
html = html.replace(/<script[^>]*src="[^"]*"[^>]*><\\/script>[\\n\\r]*/g, '');
|
|
1732
|
+
|
|
1733
|
+
// Inline JS and CSS
|
|
1734
|
+
const js = jsResult.outputFiles[0].text;
|
|
1735
|
+
const css = cssResult.outputFiles[0].text;
|
|
1736
|
+
|
|
1737
|
+
html = html.replace('</head>', \`<style>\${css}</style></head>\`);
|
|
1738
|
+
html = html.replace('</body>', \`<script>\${js}<\/script></body>\`);
|
|
1739
|
+
|
|
1740
|
+
// Write to dist
|
|
1741
|
+
fs.mkdirSync('dist', { recursive: true });
|
|
1742
|
+
fs.writeFileSync('dist/index.html', html);
|
|
1743
|
+
|
|
1744
|
+
console.log('β
Built dist/index.html');
|
|
1745
|
+
console.log(\` Bundled \${jsFiles.length} JS modules, \${cssFiles.length} CSS files\`);
|
|
1746
|
+
`), console.log("β
Created build.js");
|
|
1747
|
+
const y = `<!DOCTYPE html>
|
|
1748
|
+
<html lang="en">
|
|
1749
|
+
<head>
|
|
1750
|
+
<meta charset="UTF-8">
|
|
1751
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1752
|
+
<title>${c}</title>
|
|
1753
|
+
<link rel="stylesheet" href="./src/styles/index.css">
|
|
1754
|
+
</head>
|
|
1755
|
+
<body>
|
|
1756
|
+
<div id="app">
|
|
1757
|
+
<h1>${c}</h1>
|
|
1758
|
+
<p>Your Myop component is ready!</p>
|
|
1759
|
+
</div>
|
|
1760
|
+
<script type="module" src="./src/index.js"><\/script>
|
|
1761
|
+
</body>
|
|
1762
|
+
</html>
|
|
1763
|
+
`;
|
|
1764
|
+
n.writeFileSync("index.html", y), console.log("β
Created index.html");
|
|
1765
|
+
const j = `// ${c} - Entry Point
|
|
1766
|
+
import { init } from './modules/app.js';
|
|
1767
|
+
import { setupMyopInterface } from './modules/myop.js';
|
|
1768
|
+
|
|
1769
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
1770
|
+
init();
|
|
1771
|
+
setupMyopInterface();
|
|
1772
|
+
});
|
|
1773
|
+
`;
|
|
1774
|
+
n.writeFileSync("src/index.js", j), console.log("β
Created src/index.js");
|
|
1775
|
+
const $ = `// ${c} - Main Application Logic
|
|
1776
|
+
|
|
1777
|
+
export function init() {
|
|
1778
|
+
console.log('${c} loaded');
|
|
1779
|
+
|
|
1780
|
+
// Your component logic here
|
|
1781
|
+
}
|
|
1782
|
+
`;
|
|
1783
|
+
n.writeFileSync("src/modules/app.js", $), console.log("β
Created src/modules/app.js"), n.writeFileSync("src/modules/myop.js", `// Myop Interface - Communication with host app
|
|
1784
|
+
|
|
1785
|
+
export function setupMyopInterface() {
|
|
1786
|
+
// Called when host app sends data to this component
|
|
1787
|
+
window.myop_init_interface = (data) => {
|
|
1788
|
+
console.log('Received data from host:', data);
|
|
1789
|
+
// Initialize your component with data from the host app
|
|
1790
|
+
};
|
|
1791
|
+
|
|
1792
|
+
// Called to set up CTA (Call-to-Action) handler
|
|
1793
|
+
window.myop_cta_handler = (callback) => {
|
|
1794
|
+
// Store callback to trigger actions back to host
|
|
1795
|
+
// Example: callback({ action: 'button-click', data: { id: 123 } });
|
|
1796
|
+
};
|
|
1797
|
+
}
|
|
1798
|
+
`), console.log("β
Created src/modules/myop.js");
|
|
1799
|
+
const z = `/* ${c} - Styles Entry Point */
|
|
1800
|
+
/* Add your CSS imports here - they will be auto-bundled */
|
|
1801
|
+
@import './main.css';
|
|
1802
|
+
`;
|
|
1803
|
+
n.writeFileSync("src/styles/index.css", z), console.log("β
Created src/styles/index.css");
|
|
1804
|
+
const x = `/* ${c} - Main Styles */
|
|
1805
|
+
|
|
1806
|
+
* {
|
|
1807
|
+
box-sizing: border-box;
|
|
1808
|
+
margin: 0;
|
|
1809
|
+
padding: 0;
|
|
1810
|
+
}
|
|
1811
|
+
|
|
1812
|
+
body {
|
|
1813
|
+
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
|
1814
|
+
padding: 20px;
|
|
1815
|
+
color: #333;
|
|
1816
|
+
}
|
|
1817
|
+
|
|
1818
|
+
#app {
|
|
1819
|
+
max-width: 600px;
|
|
1820
|
+
margin: 0 auto;
|
|
1821
|
+
}
|
|
1822
|
+
|
|
1823
|
+
h1 {
|
|
1824
|
+
margin-bottom: 16px;
|
|
1825
|
+
color: #1a1a1a;
|
|
1826
|
+
}
|
|
1827
|
+
|
|
1828
|
+
p {
|
|
1829
|
+
color: #666;
|
|
1830
|
+
line-height: 1.5;
|
|
1831
|
+
}
|
|
1832
|
+
`;
|
|
1833
|
+
n.writeFileSync("src/styles/main.css", x), console.log("β
Created src/styles/main.css"), console.log(`
|
|
1834
|
+
π¦ Next steps:`), console.log(" 1. npm install"), console.log(" 2. npm run build"), console.log(` 3. myop sync
|
|
1835
|
+
`), l.myopConfig = v, await U(!0);
|
|
1836
|
+
} catch (f) {
|
|
1837
|
+
console.error(`Failed to initialize component: ${f.message}`), process.exit(1);
|
|
1838
|
+
}
|
|
1839
|
+
};
|
|
1840
|
+
l.program.command("default", { isDefault: !0 }).action(async () => {
|
|
1841
|
+
if (l.program.getOptionValue("help") && (console.log(Ve), process.exit()), l.program.getOptionValue("ci")) {
|
|
1842
|
+
const c = await import("fs"), p = l.program.getOptionValue("config") || "./myop.config.json", v = l.program.version(), S = he();
|
|
1843
|
+
let f = { found: !1 };
|
|
1844
|
+
try {
|
|
1845
|
+
if (c.existsSync(p)) {
|
|
1846
|
+
const y = c.readFileSync(p, "utf-8"), j = JSON.parse(y);
|
|
1847
|
+
f = {
|
|
1848
|
+
found: !0,
|
|
1849
|
+
path: p,
|
|
1850
|
+
name: j.name || j.componentName || null,
|
|
1851
|
+
componentId: j.componentId || null,
|
|
1852
|
+
organization: j.organization || null
|
|
1853
|
+
};
|
|
1854
|
+
}
|
|
1855
|
+
} catch (y) {
|
|
1856
|
+
f = { found: !1, error: y.message };
|
|
1857
|
+
}
|
|
1858
|
+
const w = {
|
|
1859
|
+
version: v,
|
|
1860
|
+
config: f,
|
|
1861
|
+
auth: {
|
|
1862
|
+
loggedIn: !!(S != null && S.email),
|
|
1863
|
+
email: (S == null ? void 0 : S.email) || null
|
|
1864
|
+
}
|
|
1865
|
+
};
|
|
1866
|
+
console.log(JSON.stringify(w, null, 2)), process.exit(0);
|
|
1867
|
+
}
|
|
1868
|
+
let n = A({
|
|
959
1869
|
text: "Loading Myop CLI...",
|
|
960
1870
|
color: "green"
|
|
961
1871
|
}).start();
|
|
962
|
-
|
|
1872
|
+
const a = ae();
|
|
1873
|
+
await vt(500), n.stop();
|
|
1874
|
+
const m = l.program.version();
|
|
1875
|
+
await wt(m), await U(a.configFound);
|
|
963
1876
|
});
|
|
964
|
-
|
|
965
|
-
|
|
1877
|
+
l.program.parse(process.argv);
|
|
1878
|
+
l.program.opts();
|