@monban-online/cli 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api/client.js +97 -0
- package/dist/api/client.js.map +1 -0
- package/dist/auth/login-flow.js +92 -0
- package/dist/auth/login-flow.js.map +1 -0
- package/dist/auth/token-store.js +35 -0
- package/dist/auth/token-store.js.map +1 -0
- package/dist/commands/create-counter.js +19 -0
- package/dist/commands/create-counter.js.map +1 -0
- package/dist/commands/delete-counter.js +19 -0
- package/dist/commands/delete-counter.js.map +1 -0
- package/dist/commands/init.js +12 -0
- package/dist/commands/init.js.map +1 -0
- package/dist/commands/install-script.js +24 -0
- package/dist/commands/install-script.js.map +1 -0
- package/dist/commands/list-counters.js +18 -0
- package/dist/commands/list-counters.js.map +1 -0
- package/dist/commands/login.js +12 -0
- package/dist/commands/login.js.map +1 -0
- package/dist/commands/logout.js +11 -0
- package/dist/commands/logout.js.map +1 -0
- package/dist/commands/pull-counter.js +16 -0
- package/dist/commands/pull-counter.js.map +1 -0
- package/dist/commands/push-counter.js +16 -0
- package/dist/commands/push-counter.js.map +1 -0
- package/dist/commands/status-inquiry.js +29 -0
- package/dist/commands/status-inquiry.js.map +1 -0
- package/dist/commands/sync-inquiries.js +28 -0
- package/dist/commands/sync-inquiries.js.map +1 -0
- package/dist/commands/whoami.js +13 -0
- package/dist/commands/whoami.js.map +1 -0
- package/dist/config.js +5 -0
- package/dist/config.js.map +1 -0
- package/dist/index.js +37 -0
- package/dist/index.js.map +1 -0
- package/dist/workspace/counter-files.js +22 -0
- package/dist/workspace/counter-files.js.map +1 -0
- package/dist/workspace/inquiry-store.js +124 -0
- package/dist/workspace/inquiry-store.js.map +1 -0
- package/dist/workspace/layout.js +48 -0
- package/dist/workspace/layout.js.map +1 -0
- package/dist/workspace/script-install.js +34 -0
- package/dist/workspace/script-install.js.map +1 -0
- package/package.json +24 -0
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
import { loadAuth, saveAuth } from "../auth/token-store.js";
|
|
2
|
+
export class ApiError extends Error {
|
|
3
|
+
status;
|
|
4
|
+
body;
|
|
5
|
+
constructor(message, status, body) {
|
|
6
|
+
super(message);
|
|
7
|
+
this.status = status;
|
|
8
|
+
this.body = body;
|
|
9
|
+
this.name = "ApiError";
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
export async function fetchAuthConfig(appUrl) {
|
|
13
|
+
return fetchJson(`${appUrl}/api/cli/auth-config`);
|
|
14
|
+
}
|
|
15
|
+
export async function apiGet(path) {
|
|
16
|
+
return apiRequest(path, { method: "GET" });
|
|
17
|
+
}
|
|
18
|
+
export async function apiPost(path, body) {
|
|
19
|
+
return apiRequest(path, {
|
|
20
|
+
method: "POST",
|
|
21
|
+
headers: { "content-type": "application/json" },
|
|
22
|
+
body: JSON.stringify(body),
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
export async function apiPut(path, body) {
|
|
26
|
+
return apiRequest(path, {
|
|
27
|
+
method: "PUT",
|
|
28
|
+
headers: { "content-type": "application/json" },
|
|
29
|
+
body: JSON.stringify(body),
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
export async function apiDelete(path) {
|
|
33
|
+
return apiRequest(path, { method: "DELETE" });
|
|
34
|
+
}
|
|
35
|
+
async function apiRequest(path, init, retry = true) {
|
|
36
|
+
const auth = await loadAuth();
|
|
37
|
+
if (!auth)
|
|
38
|
+
throw new Error("not logged in. Run `monban login` first.");
|
|
39
|
+
const response = await fetch(`${auth.appUrl}${path}`, {
|
|
40
|
+
...init,
|
|
41
|
+
headers: {
|
|
42
|
+
...(init.headers ?? {}),
|
|
43
|
+
authorization: `Bearer ${auth.accessToken}`,
|
|
44
|
+
},
|
|
45
|
+
});
|
|
46
|
+
if (response.status === 401 && retry && auth.refreshToken) {
|
|
47
|
+
const refreshed = await refreshAuth(auth);
|
|
48
|
+
if (refreshed) {
|
|
49
|
+
await saveAuth(refreshed);
|
|
50
|
+
return apiRequest(path, init, false);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
return readJsonResponse(response);
|
|
54
|
+
}
|
|
55
|
+
async function refreshAuth(auth) {
|
|
56
|
+
if (!auth.refreshToken)
|
|
57
|
+
return undefined;
|
|
58
|
+
const body = new URLSearchParams({
|
|
59
|
+
client_id: auth.clientId,
|
|
60
|
+
grant_type: "refresh_token",
|
|
61
|
+
refresh_token: auth.refreshToken,
|
|
62
|
+
});
|
|
63
|
+
const response = await fetch(auth.tokenEndpoint, {
|
|
64
|
+
method: "POST",
|
|
65
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
66
|
+
body,
|
|
67
|
+
});
|
|
68
|
+
if (!response.ok)
|
|
69
|
+
return undefined;
|
|
70
|
+
const token = (await response.json());
|
|
71
|
+
if (!token.access_token)
|
|
72
|
+
return undefined;
|
|
73
|
+
return {
|
|
74
|
+
...auth,
|
|
75
|
+
accessToken: token.access_token,
|
|
76
|
+
refreshToken: token.refresh_token ?? auth.refreshToken,
|
|
77
|
+
expiresAt: token.expires_in
|
|
78
|
+
? new Date(Date.now() + token.expires_in * 1000).toISOString()
|
|
79
|
+
: null,
|
|
80
|
+
};
|
|
81
|
+
}
|
|
82
|
+
async function fetchJson(url) {
|
|
83
|
+
const response = await fetch(url);
|
|
84
|
+
return readJsonResponse(response);
|
|
85
|
+
}
|
|
86
|
+
async function readJsonResponse(response) {
|
|
87
|
+
const text = await response.text();
|
|
88
|
+
const body = text ? JSON.parse(text) : null;
|
|
89
|
+
if (!response.ok) {
|
|
90
|
+
const message = body && typeof body === "object" && "error" in body
|
|
91
|
+
? String(body.error)
|
|
92
|
+
: `request failed with status ${response.status}`;
|
|
93
|
+
throw new ApiError(message, response.status, body);
|
|
94
|
+
}
|
|
95
|
+
return body;
|
|
96
|
+
}
|
|
97
|
+
//# sourceMappingURL=client.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import { spawn } from "node:child_process";
|
|
2
|
+
import { fetchAuthConfig } from "../api/client.js";
|
|
3
|
+
import { normalizeAppUrl } from "../config.js";
|
|
4
|
+
import { saveAuth } from "./token-store.js";
|
|
5
|
+
export async function login(options) {
|
|
6
|
+
const appUrl = normalizeAppUrl(options.appUrl);
|
|
7
|
+
const config = await fetchAuthConfig(appUrl);
|
|
8
|
+
const device = await startDeviceAuthorization(config);
|
|
9
|
+
const verificationUrl = device.verification_uri_complete ?? device.verification_uri;
|
|
10
|
+
console.log("Open this URL to continue WorkOS login:");
|
|
11
|
+
console.log(verificationUrl);
|
|
12
|
+
console.log(`Code: ${device.user_code}`);
|
|
13
|
+
openBrowser(verificationUrl);
|
|
14
|
+
const token = await pollForToken({
|
|
15
|
+
tokenEndpoint: config.tokenEndpoint,
|
|
16
|
+
clientId: config.clientId,
|
|
17
|
+
deviceCode: device.device_code,
|
|
18
|
+
intervalSeconds: device.interval ?? 5,
|
|
19
|
+
expiresInSeconds: device.expires_in,
|
|
20
|
+
});
|
|
21
|
+
if (!token.access_token) {
|
|
22
|
+
throw new Error(token.error_description ?? token.error ?? "login failed");
|
|
23
|
+
}
|
|
24
|
+
await saveAuth({
|
|
25
|
+
appUrl,
|
|
26
|
+
clientId: config.clientId,
|
|
27
|
+
tokenEndpoint: config.tokenEndpoint,
|
|
28
|
+
accessToken: token.access_token,
|
|
29
|
+
refreshToken: token.refresh_token ?? null,
|
|
30
|
+
expiresAt: token.expires_in
|
|
31
|
+
? new Date(Date.now() + token.expires_in * 1000).toISOString()
|
|
32
|
+
: null,
|
|
33
|
+
});
|
|
34
|
+
console.log("Logged in.");
|
|
35
|
+
}
|
|
36
|
+
async function startDeviceAuthorization(config) {
|
|
37
|
+
const response = await fetch(config.deviceAuthorizationEndpoint, {
|
|
38
|
+
method: "POST",
|
|
39
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
40
|
+
body: new URLSearchParams({
|
|
41
|
+
client_id: config.clientId,
|
|
42
|
+
}),
|
|
43
|
+
});
|
|
44
|
+
const body = (await response.json());
|
|
45
|
+
if (!response.ok) {
|
|
46
|
+
throw new Error(body.error_description ?? body.error ?? "login setup failed");
|
|
47
|
+
}
|
|
48
|
+
return body;
|
|
49
|
+
}
|
|
50
|
+
async function pollForToken(args) {
|
|
51
|
+
const deadline = Date.now() + args.expiresInSeconds * 1000;
|
|
52
|
+
let intervalMs = args.intervalSeconds * 1000;
|
|
53
|
+
while (Date.now() < deadline) {
|
|
54
|
+
await sleep(intervalMs);
|
|
55
|
+
const response = await fetch(args.tokenEndpoint, {
|
|
56
|
+
method: "POST",
|
|
57
|
+
headers: { "content-type": "application/x-www-form-urlencoded" },
|
|
58
|
+
body: new URLSearchParams({
|
|
59
|
+
client_id: args.clientId,
|
|
60
|
+
grant_type: "urn:ietf:params:oauth:grant-type:device_code",
|
|
61
|
+
device_code: args.deviceCode,
|
|
62
|
+
}),
|
|
63
|
+
});
|
|
64
|
+
const token = (await response.json());
|
|
65
|
+
if (response.ok)
|
|
66
|
+
return token;
|
|
67
|
+
if (token.error === "authorization_pending")
|
|
68
|
+
continue;
|
|
69
|
+
if (token.error === "slow_down") {
|
|
70
|
+
intervalMs += 5000;
|
|
71
|
+
continue;
|
|
72
|
+
}
|
|
73
|
+
return token;
|
|
74
|
+
}
|
|
75
|
+
throw new Error("login timed out");
|
|
76
|
+
}
|
|
77
|
+
function openBrowser(url) {
|
|
78
|
+
const platform = process.platform;
|
|
79
|
+
const command = platform === "darwin"
|
|
80
|
+
? "open"
|
|
81
|
+
: platform === "win32"
|
|
82
|
+
? "cmd"
|
|
83
|
+
: "xdg-open";
|
|
84
|
+
const args = platform === "win32" ? ["/c", "start", "", url] : [url];
|
|
85
|
+
const child = spawn(command, args, { stdio: "ignore", detached: true });
|
|
86
|
+
child.on("error", () => undefined);
|
|
87
|
+
child.unref();
|
|
88
|
+
}
|
|
89
|
+
function sleep(ms) {
|
|
90
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
91
|
+
}
|
|
92
|
+
//# sourceMappingURL=login-flow.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login-flow.js","sourceRoot":"","sources":["../../src/auth/login-flow.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { mkdir, readFile, rm, writeFile, chmod } from "node:fs/promises";
|
|
2
|
+
import { homedir } from "node:os";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
export function authFilePath() {
|
|
5
|
+
if (process.env.MONBAN_AUTH_PATH)
|
|
6
|
+
return path.resolve(process.env.MONBAN_AUTH_PATH);
|
|
7
|
+
const configDir = process.env.XDG_CONFIG_HOME ?? path.join(homedir(), ".config");
|
|
8
|
+
return path.join(configDir, "monban", "auth.json");
|
|
9
|
+
}
|
|
10
|
+
export async function loadAuth() {
|
|
11
|
+
try {
|
|
12
|
+
const raw = await readFile(authFilePath(), "utf8");
|
|
13
|
+
return JSON.parse(raw);
|
|
14
|
+
}
|
|
15
|
+
catch (e) {
|
|
16
|
+
if (isNotFound(e))
|
|
17
|
+
return undefined;
|
|
18
|
+
throw e;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
export async function saveAuth(auth) {
|
|
22
|
+
const file = authFilePath();
|
|
23
|
+
await mkdir(path.dirname(file), { recursive: true, mode: 0o700 });
|
|
24
|
+
await writeFile(file, `${JSON.stringify(auth, null, 2)}\n`, {
|
|
25
|
+
mode: 0o600,
|
|
26
|
+
});
|
|
27
|
+
await chmod(file, 0o600).catch(() => undefined);
|
|
28
|
+
}
|
|
29
|
+
export async function clearAuth() {
|
|
30
|
+
await rm(authFilePath(), { force: true });
|
|
31
|
+
}
|
|
32
|
+
function isNotFound(e) {
|
|
33
|
+
return Boolean(e && typeof e === "object" && "code" in e && e.code === "ENOENT");
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=token-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"token-store.js","sourceRoot":"","sources":["../../src/auth/token-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,EAAE,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAC;AACzE,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,IAAI,MAAM,WAAW,CAAC;AAW7B,MAAM,UAAU,YAAY;IAC1B,IAAI,OAAO,CAAC,GAAG,CAAC,gBAAgB;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,GAAG,CAAC,gBAAgB,CAAC,CAAC;IACpF,MAAM,SAAS,GACb,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI,IAAI,CAAC,IAAI,CAAC,OAAO,EAAE,EAAE,SAAS,CAAC,CAAC;IACjE,OAAO,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;AACrD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ;IAC5B,IAAI,CAAC;QACH,MAAM,GAAG,GAAG,MAAM,QAAQ,CAAC,YAAY,EAAE,EAAE,MAAM,CAAC,CAAC;QACnD,OAAO,IAAI,CAAC,KAAK,CAAC,GAAG,CAAe,CAAC;IACvC,CAAC;IAAC,OAAO,CAAC,EAAE,CAAC;QACX,IAAI,UAAU,CAAC,CAAC,CAAC;YAAE,OAAO,SAAS,CAAC;QACpC,MAAM,CAAC,CAAC;IACV,CAAC;AACH,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,QAAQ,CAAC,IAAgB;IAC7C,MAAM,IAAI,GAAG,YAAY,EAAE,CAAC;IAC5B,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC;IAClE,MAAM,SAAS,CAAC,IAAI,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;QAC1D,IAAI,EAAE,KAAK;KACZ,CAAC,CAAC;IACH,MAAM,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS;IAC7B,MAAM,EAAE,CAAC,YAAY,EAAE,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC;AAC5C,CAAC;AAED,SAAS,UAAU,CAAC,CAAU;IAC5B,OAAO,OAAO,CAAC,CAAC,IAAI,OAAO,CAAC,KAAK,QAAQ,IAAI,MAAM,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,KAAK,QAAQ,CAAC,CAAC;AACnF,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { apiPost } from "../api/client.js";
|
|
2
|
+
import { readCounterFiles } from "../workspace/counter-files.js";
|
|
3
|
+
export function registerCreateCounterCommand(program) {
|
|
4
|
+
const create = program.command("create").description("Create monban resources.");
|
|
5
|
+
create
|
|
6
|
+
.command("counter")
|
|
7
|
+
.description("Create a counter from local settings.yaml, TRIGGERS.md, and SYSTEM_PROMPT.md.")
|
|
8
|
+
.argument("<counterId>")
|
|
9
|
+
.option("--root <path>", "project root", process.cwd())
|
|
10
|
+
.action(async (counterId, options) => {
|
|
11
|
+
const files = await readCounterFiles(counterId, options.root);
|
|
12
|
+
await apiPost("/api/cli/counters", {
|
|
13
|
+
counterId,
|
|
14
|
+
...files,
|
|
15
|
+
});
|
|
16
|
+
console.log(`Created ${counterId}`);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=create-counter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-counter.js","sourceRoot":"","sources":["../../src/commands/create-counter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,OAAO,EAAE,MAAM,kBAAkB,CAAC;AAC3C,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEjE,MAAM,UAAU,4BAA4B,CAAC,OAAgB;IAC3D,MAAM,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,WAAW,CAAC,0BAA0B,CAAC,CAAC;IACjF,MAAM;SACH,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,+EAA+E,CAAC;SAC5F,QAAQ,CAAC,aAAa,CAAC;SACvB,MAAM,CAAC,eAAe,EAAE,cAAc,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;SACtD,MAAM,CAAC,KAAK,EAAE,SAAiB,EAAE,OAAyB,EAAE,EAAE;QAC7D,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAC9D,MAAM,OAAO,CAAC,mBAAmB,EAAE;YACjC,SAAS;YACT,GAAG,KAAK;SACT,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,WAAW,SAAS,EAAE,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { apiDelete } from "../api/client.js";
|
|
2
|
+
export function registerDeleteCounterCommand(program) {
|
|
3
|
+
const deleteCommand = program
|
|
4
|
+
.command("delete")
|
|
5
|
+
.description("Delete monban resources.");
|
|
6
|
+
deleteCommand
|
|
7
|
+
.command("counter")
|
|
8
|
+
.description("Delete a counter from monban. This does not remove local files.")
|
|
9
|
+
.argument("<counterId>")
|
|
10
|
+
.option("--yes", "confirm deletion")
|
|
11
|
+
.action(async (counterId, options) => {
|
|
12
|
+
if (!options.yes) {
|
|
13
|
+
throw new Error("destructive command requires --yes");
|
|
14
|
+
}
|
|
15
|
+
await apiDelete(`/api/cli/counters/${encodeURIComponent(counterId)}`);
|
|
16
|
+
console.log(`Deleted ${counterId}`);
|
|
17
|
+
});
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=delete-counter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"delete-counter.js","sourceRoot":"","sources":["../../src/commands/delete-counter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAE7C,MAAM,UAAU,4BAA4B,CAAC,OAAgB;IAC3D,MAAM,aAAa,GAAG,OAAO;SAC1B,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,0BAA0B,CAAC,CAAC;IAC3C,aAAa;SACV,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,iEAAiE,CAAC;SAC9E,QAAQ,CAAC,aAAa,CAAC;SACvB,MAAM,CAAC,OAAO,EAAE,kBAAkB,CAAC;SACnC,MAAM,CAAC,KAAK,EAAE,SAAiB,EAAE,OAA0B,EAAE,EAAE;QAC9D,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC;YACjB,MAAM,IAAI,KAAK,CAAC,oCAAoC,CAAC,CAAC;QACxD,CAAC;QACD,MAAM,SAAS,CAAC,qBAAqB,kBAAkB,CAAC,SAAS,CAAC,EAAE,CAAC,CAAC;QACtE,OAAO,CAAC,GAAG,CAAC,WAAW,SAAS,EAAE,CAAC,CAAC;IACtC,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { ensureWorkspace, workspaceRoot } from "../workspace/layout.js";
|
|
2
|
+
export function registerInitCommand(program) {
|
|
3
|
+
program
|
|
4
|
+
.command("init")
|
|
5
|
+
.description("Create the local monban workspace.")
|
|
6
|
+
.option("--root <path>", "project root", process.cwd())
|
|
7
|
+
.action(async (options) => {
|
|
8
|
+
await ensureWorkspace(options.root);
|
|
9
|
+
console.log(`Initialized ${workspaceRoot(options.root)}`);
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=init.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/commands/init.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AAExE,MAAM,UAAU,mBAAmB,CAAC,OAAgB;IAClD,OAAO;SACJ,OAAO,CAAC,MAAM,CAAC;SACf,WAAW,CAAC,oCAAoC,CAAC;SACjD,MAAM,CAAC,eAAe,EAAE,cAAc,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;SACtD,MAAM,CAAC,KAAK,EAAE,OAAyB,EAAE,EAAE;QAC1C,MAAM,eAAe,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,eAAe,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAC5D,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { DEFAULT_APP_URL } from "../config.js";
|
|
2
|
+
import { installScript } from "../workspace/script-install.js";
|
|
3
|
+
export function registerInstallScriptCommand(program) {
|
|
4
|
+
const install = program
|
|
5
|
+
.command("install")
|
|
6
|
+
.description("Install monban assets into the current project.");
|
|
7
|
+
install
|
|
8
|
+
.command("script")
|
|
9
|
+
.description("Write or insert the monban embed script.")
|
|
10
|
+
.argument("<counterId>")
|
|
11
|
+
.option("--file <path>", "file to update")
|
|
12
|
+
.option("--app-url <url>", "monban runtime URL", DEFAULT_APP_URL)
|
|
13
|
+
.option("--root <path>", "project root", process.cwd())
|
|
14
|
+
.action(async (counterId, options) => {
|
|
15
|
+
const result = await installScript({
|
|
16
|
+
counterId,
|
|
17
|
+
file: options.file,
|
|
18
|
+
appUrl: options.appUrl,
|
|
19
|
+
root: options.root,
|
|
20
|
+
});
|
|
21
|
+
console.log(`${result.changed ? "Updated" : "Already installed"} ${result.file}`);
|
|
22
|
+
});
|
|
23
|
+
}
|
|
24
|
+
//# sourceMappingURL=install-script.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"install-script.js","sourceRoot":"","sources":["../../src/commands/install-script.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAC/C,OAAO,EAAE,aAAa,EAAE,MAAM,gCAAgC,CAAC;AAE/D,MAAM,UAAU,4BAA4B,CAAC,OAAgB;IAC3D,MAAM,OAAO,GAAG,OAAO;SACpB,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,iDAAiD,CAAC,CAAC;IAClE,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,0CAA0C,CAAC;SACvD,QAAQ,CAAC,aAAa,CAAC;SACvB,MAAM,CAAC,eAAe,EAAE,gBAAgB,CAAC;SACzC,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,EAAE,eAAe,CAAC;SAChE,MAAM,CAAC,eAAe,EAAE,cAAc,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;SACtD,MAAM,CACL,KAAK,EACH,SAAiB,EACjB,OAAwD,EACxD,EAAE;QACF,MAAM,MAAM,GAAG,MAAM,aAAa,CAAC;YACjC,SAAS;YACT,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,MAAM,EAAE,OAAO,CAAC,MAAM;YACtB,IAAI,EAAE,OAAO,CAAC,IAAI;SACnB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,mBAAmB,IAAI,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;IACpF,CAAC,CACF,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { apiGet } from "../api/client.js";
|
|
2
|
+
export function registerListCountersCommand(program) {
|
|
3
|
+
const list = program.command("list").description("List monban resources.");
|
|
4
|
+
list
|
|
5
|
+
.command("counters")
|
|
6
|
+
.description("List counters owned by the logged-in user.")
|
|
7
|
+
.action(async () => {
|
|
8
|
+
const result = await apiGet("/api/cli/counters");
|
|
9
|
+
if (result.counters.length === 0) {
|
|
10
|
+
console.log("No counters.");
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
for (const counter of result.counters) {
|
|
14
|
+
console.log(`${counter.id}\t${counter.name}\t${counter.model}\t${counter.monthlyTokenUsed}/${counter.monthlyTokenLimit}`);
|
|
15
|
+
}
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
//# sourceMappingURL=list-counters.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"list-counters.js","sourceRoot":"","sources":["../../src/commands/list-counters.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAa1C,MAAM,UAAU,2BAA2B,CAAC,OAAgB;IAC1D,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,wBAAwB,CAAC,CAAC;IAC3E,IAAI;SACD,OAAO,CAAC,UAAU,CAAC;SACnB,WAAW,CAAC,4CAA4C,CAAC;SACzD,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAuB,mBAAmB,CAAC,CAAC;QACvE,IAAI,MAAM,CAAC,QAAQ,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,CAAC;YAC5B,OAAO;QACT,CAAC;QACD,KAAK,MAAM,OAAO,IAAI,MAAM,CAAC,QAAQ,EAAE,CAAC;YACtC,OAAO,CAAC,GAAG,CACT,GAAG,OAAO,CAAC,EAAE,KAAK,OAAO,CAAC,IAAI,KAAK,OAAO,CAAC,KAAK,KAAK,OAAO,CAAC,gBAAgB,IAAI,OAAO,CAAC,iBAAiB,EAAE,CAC7G,CAAC;QACJ,CAAC;IACH,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { login } from "../auth/login-flow.js";
|
|
2
|
+
import { DEFAULT_APP_URL } from "../config.js";
|
|
3
|
+
export function registerLoginCommand(program) {
|
|
4
|
+
program
|
|
5
|
+
.command("login")
|
|
6
|
+
.description("Login to monban with WorkOS.")
|
|
7
|
+
.option("--app-url <url>", "monban runtime URL", DEFAULT_APP_URL)
|
|
8
|
+
.action(async (options) => {
|
|
9
|
+
await login({ appUrl: options.appUrl });
|
|
10
|
+
});
|
|
11
|
+
}
|
|
12
|
+
//# sourceMappingURL=login.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,EAAE,MAAM,uBAAuB,CAAC;AAC9C,OAAO,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAE/C,MAAM,UAAU,oBAAoB,CAAC,OAAgB;IACnD,OAAO;SACJ,OAAO,CAAC,OAAO,CAAC;SAChB,WAAW,CAAC,8BAA8B,CAAC;SAC3C,MAAM,CAAC,iBAAiB,EAAE,oBAAoB,EAAE,eAAe,CAAC;SAChE,MAAM,CAAC,KAAK,EAAE,OAA2B,EAAE,EAAE;QAC5C,MAAM,KAAK,CAAC,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,CAAC,CAAC;IAC1C,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { clearAuth } from "../auth/token-store.js";
|
|
2
|
+
export function registerLogoutCommand(program) {
|
|
3
|
+
program
|
|
4
|
+
.command("logout")
|
|
5
|
+
.description("Remove local monban auth tokens.")
|
|
6
|
+
.action(async () => {
|
|
7
|
+
await clearAuth();
|
|
8
|
+
console.log("Logged out.");
|
|
9
|
+
});
|
|
10
|
+
}
|
|
11
|
+
//# sourceMappingURL=logout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,wBAAwB,CAAC;AAEnD,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,kCAAkC,CAAC;SAC/C,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,SAAS,EAAE,CAAC;QAClB,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC;IAC7B,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { apiGet } from "../api/client.js";
|
|
2
|
+
import { writeCounterFiles } from "../workspace/counter-files.js";
|
|
3
|
+
export function registerPullCounterCommand(program) {
|
|
4
|
+
const pull = program.command("pull").description("Pull data from monban.");
|
|
5
|
+
pull
|
|
6
|
+
.command("counter")
|
|
7
|
+
.description("Pull a counter's three files into the local workspace.")
|
|
8
|
+
.argument("<counterId>")
|
|
9
|
+
.option("--root <path>", "project root", process.cwd())
|
|
10
|
+
.action(async (counterId, options) => {
|
|
11
|
+
const files = await apiGet(`/api/cli/counters/${encodeURIComponent(counterId)}/files`);
|
|
12
|
+
await writeCounterFiles(counterId, files, options.root);
|
|
13
|
+
console.log(`Pulled ${counterId}`);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=pull-counter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"pull-counter.js","sourceRoot":"","sources":["../../src/commands/pull-counter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAA6B,MAAM,kBAAkB,CAAC;AACrE,OAAO,EAAE,iBAAiB,EAAE,MAAM,+BAA+B,CAAC;AAElE,MAAM,UAAU,0BAA0B,CAAC,OAAgB;IACzD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,wBAAwB,CAAC,CAAC;IAC3E,IAAI;SACD,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,wDAAwD,CAAC;SACrE,QAAQ,CAAC,aAAa,CAAC;SACvB,MAAM,CAAC,eAAe,EAAE,cAAc,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;SACtD,MAAM,CAAC,KAAK,EAAE,SAAiB,EAAE,OAAyB,EAAE,EAAE;QAC7D,MAAM,KAAK,GAAG,MAAM,MAAM,CACxB,qBAAqB,kBAAkB,CAAC,SAAS,CAAC,QAAQ,CAC3D,CAAC;QACF,MAAM,iBAAiB,CAAC,SAAS,EAAE,KAAK,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QACxD,OAAO,CAAC,GAAG,CAAC,UAAU,SAAS,EAAE,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { apiPut } from "../api/client.js";
|
|
2
|
+
import { readCounterFiles } from "../workspace/counter-files.js";
|
|
3
|
+
export function registerPushCounterCommand(program) {
|
|
4
|
+
const push = program.command("push").description("Push local data to monban.");
|
|
5
|
+
push
|
|
6
|
+
.command("counter")
|
|
7
|
+
.description("Push a counter's local three files to monban.")
|
|
8
|
+
.argument("<counterId>")
|
|
9
|
+
.option("--root <path>", "project root", process.cwd())
|
|
10
|
+
.action(async (counterId, options) => {
|
|
11
|
+
const files = await readCounterFiles(counterId, options.root);
|
|
12
|
+
await apiPut(`/api/cli/counters/${encodeURIComponent(counterId)}/files`, files);
|
|
13
|
+
console.log(`Pushed ${counterId}`);
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=push-counter.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"push-counter.js","sourceRoot":"","sources":["../../src/commands/push-counter.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,gBAAgB,EAAE,MAAM,+BAA+B,CAAC;AAEjE,MAAM,UAAU,0BAA0B,CAAC,OAAgB;IACzD,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,4BAA4B,CAAC,CAAC;IAC/E,IAAI;SACD,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,+CAA+C,CAAC;SAC5D,QAAQ,CAAC,aAAa,CAAC;SACvB,MAAM,CAAC,eAAe,EAAE,cAAc,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;SACtD,MAAM,CAAC,KAAK,EAAE,SAAiB,EAAE,OAAyB,EAAE,EAAE;QAC7D,MAAM,KAAK,GAAG,MAAM,gBAAgB,CAAC,SAAS,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC;QAC9D,MAAM,MAAM,CAAC,qBAAqB,kBAAkB,CAAC,SAAS,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC;QAChF,OAAO,CAAC,GAAG,CAAC,UAAU,SAAS,EAAE,CAAC,CAAC;IACrC,CAAC,CAAC,CAAC;AACP,CAAC"}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import { updateInquiryStatus, } from "../workspace/inquiry-store.js";
|
|
2
|
+
const STATUSES = ["unhandled", "resolved", "ignored"];
|
|
3
|
+
export function registerStatusInquiryCommand(program) {
|
|
4
|
+
const statusCommand = program
|
|
5
|
+
.command("status")
|
|
6
|
+
.description("Update local monban status.");
|
|
7
|
+
statusCommand
|
|
8
|
+
.command("inquiry")
|
|
9
|
+
.description("Update local inquiry status.json.")
|
|
10
|
+
.argument("<inquiryId>")
|
|
11
|
+
.argument("<status>")
|
|
12
|
+
.option("--counter <counterId>", "counter id when the inquiry is not yet known locally")
|
|
13
|
+
.option("--note <text>", "local note")
|
|
14
|
+
.option("--root <path>", "project root", process.cwd())
|
|
15
|
+
.action(async (inquiryId, status, options) => {
|
|
16
|
+
if (!STATUSES.includes(status)) {
|
|
17
|
+
throw new Error(`status must be one of: ${STATUSES.join(", ")}`);
|
|
18
|
+
}
|
|
19
|
+
const result = await updateInquiryStatus({
|
|
20
|
+
inquiryId,
|
|
21
|
+
status: status,
|
|
22
|
+
note: options.note,
|
|
23
|
+
counterId: options.counter,
|
|
24
|
+
root: options.root,
|
|
25
|
+
});
|
|
26
|
+
console.log(`Updated ${inquiryId} in ${result.counterId}`);
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=status-inquiry.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"status-inquiry.js","sourceRoot":"","sources":["../../src/commands/status-inquiry.ts"],"names":[],"mappings":"AACA,OAAO,EACL,mBAAmB,GAEpB,MAAM,+BAA+B,CAAC;AAEvC,MAAM,QAAQ,GAAG,CAAC,WAAW,EAAE,UAAU,EAAE,SAAS,CAAU,CAAC;AAE/D,MAAM,UAAU,4BAA4B,CAAC,OAAgB;IAC3D,MAAM,aAAa,GAAG,OAAO;SAC1B,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,6BAA6B,CAAC,CAAC;IAC9C,aAAa;SACV,OAAO,CAAC,SAAS,CAAC;SAClB,WAAW,CAAC,mCAAmC,CAAC;SAChD,QAAQ,CAAC,aAAa,CAAC;SACvB,QAAQ,CAAC,UAAU,CAAC;SACpB,MAAM,CAAC,uBAAuB,EAAE,sDAAsD,CAAC;SACvF,MAAM,CAAC,eAAe,EAAE,YAAY,CAAC;SACrC,MAAM,CAAC,eAAe,EAAE,cAAc,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;SACtD,MAAM,CACL,KAAK,EACH,SAAiB,EACjB,MAAc,EACd,OAA0D,EAC1D,EAAE;QACF,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,MAAuB,CAAC,EAAE,CAAC;YAChD,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnE,CAAC;QACD,MAAM,MAAM,GAAG,MAAM,mBAAmB,CAAC;YACvC,SAAS;YACT,MAAM,EAAE,MAAuB;YAC/B,IAAI,EAAE,OAAO,CAAC,IAAI;YAClB,SAAS,EAAE,OAAO,CAAC,OAAO;YAC1B,IAAI,EAAE,OAAO,CAAC,IAAI;SACnB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,WAAW,SAAS,OAAO,MAAM,CAAC,SAAS,EAAE,CAAC,CAAC;IAC7D,CAAC,CACF,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { apiGet } from "../api/client.js";
|
|
2
|
+
import { appendInquiryMessages } from "../workspace/inquiry-store.js";
|
|
3
|
+
import { readWorkspaceState } from "../workspace/layout.js";
|
|
4
|
+
export function registerSyncInquiriesCommand(program) {
|
|
5
|
+
const sync = program.command("sync").description("Sync monban data.");
|
|
6
|
+
sync
|
|
7
|
+
.command("inquiries")
|
|
8
|
+
.description("Sync new AI-mode inquiry messages into messages.jsonl.")
|
|
9
|
+
.argument("<counterId>")
|
|
10
|
+
.option("--root <path>", "project root", process.cwd())
|
|
11
|
+
.option("--limit <number>", "max messages to fetch", "100")
|
|
12
|
+
.action(async (counterId, options) => {
|
|
13
|
+
const state = await readWorkspaceState(options.root);
|
|
14
|
+
const afterMessageId = state.counters?.[counterId]?.afterMessageId ?? undefined;
|
|
15
|
+
const params = new URLSearchParams({ limit: options.limit });
|
|
16
|
+
if (afterMessageId)
|
|
17
|
+
params.set("afterMessageId", afterMessageId);
|
|
18
|
+
const result = await apiGet(`/api/cli/counters/${encodeURIComponent(counterId)}/inquiry-messages?${params}`);
|
|
19
|
+
const saved = await appendInquiryMessages({
|
|
20
|
+
counterId,
|
|
21
|
+
messages: result.messages,
|
|
22
|
+
nextAfterMessageId: result.nextAfterMessageId,
|
|
23
|
+
root: options.root,
|
|
24
|
+
});
|
|
25
|
+
console.log(`Synced ${saved.appended} new messages for ${counterId}`);
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
//# sourceMappingURL=sync-inquiries.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sync-inquiries.js","sourceRoot":"","sources":["../../src/commands/sync-inquiries.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAgC,MAAM,kBAAkB,CAAC;AACxE,OAAO,EAAE,qBAAqB,EAAE,MAAM,+BAA+B,CAAC;AACtE,OAAO,EAAE,kBAAkB,EAAE,MAAM,wBAAwB,CAAC;AAE5D,MAAM,UAAU,4BAA4B,CAAC,OAAgB;IAC3D,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,WAAW,CAAC,mBAAmB,CAAC,CAAC;IACtE,IAAI;SACD,OAAO,CAAC,WAAW,CAAC;SACpB,WAAW,CAAC,wDAAwD,CAAC;SACrE,QAAQ,CAAC,aAAa,CAAC;SACvB,MAAM,CAAC,eAAe,EAAE,cAAc,EAAE,OAAO,CAAC,GAAG,EAAE,CAAC;SACtD,MAAM,CAAC,kBAAkB,EAAE,uBAAuB,EAAE,KAAK,CAAC;SAC1D,MAAM,CACL,KAAK,EACH,SAAiB,EACjB,OAAwC,EACxC,EAAE;QACF,MAAM,KAAK,GAAG,MAAM,kBAAkB,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;QACrD,MAAM,cAAc,GAClB,KAAK,CAAC,QAAQ,EAAE,CAAC,SAAS,CAAC,EAAE,cAAc,IAAI,SAAS,CAAC;QAC3D,MAAM,MAAM,GAAG,IAAI,eAAe,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC,CAAC;QAC7D,IAAI,cAAc;YAAE,MAAM,CAAC,GAAG,CAAC,gBAAgB,EAAE,cAAc,CAAC,CAAC;QAEjE,MAAM,MAAM,GAAG,MAAM,MAAM,CACzB,qBAAqB,kBAAkB,CAAC,SAAS,CAAC,qBAAqB,MAAM,EAAE,CAChF,CAAC;QACF,MAAM,KAAK,GAAG,MAAM,qBAAqB,CAAC;YACxC,SAAS;YACT,QAAQ,EAAE,MAAM,CAAC,QAAQ;YACzB,kBAAkB,EAAE,MAAM,CAAC,kBAAkB;YAC7C,IAAI,EAAE,OAAO,CAAC,IAAI;SACnB,CAAC,CAAC;QACH,OAAO,CAAC,GAAG,CAAC,UAAU,KAAK,CAAC,QAAQ,qBAAqB,SAAS,EAAE,CAAC,CAAC;IACxE,CAAC,CACF,CAAC;AACN,CAAC"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { apiGet } from "../api/client.js";
|
|
2
|
+
export function registerWhoamiCommand(program) {
|
|
3
|
+
program
|
|
4
|
+
.command("whoami")
|
|
5
|
+
.description("Show the authenticated WorkOS user and plan.")
|
|
6
|
+
.action(async () => {
|
|
7
|
+
const result = await apiGet("/api/cli/whoami");
|
|
8
|
+
console.log(`userId: ${result.userId}`);
|
|
9
|
+
console.log(`plan: ${result.plan}`);
|
|
10
|
+
console.log(`counters: ${result.counters.length}`);
|
|
11
|
+
});
|
|
12
|
+
}
|
|
13
|
+
//# sourceMappingURL=whoami.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAuB,MAAM,kBAAkB,CAAC;AAE/D,MAAM,UAAU,qBAAqB,CAAC,OAAgB;IACpD,OAAO;SACJ,OAAO,CAAC,QAAQ,CAAC;SACjB,WAAW,CAAC,8CAA8C,CAAC;SAC3D,MAAM,CAAC,KAAK,IAAI,EAAE;QACjB,MAAM,MAAM,GAAG,MAAM,MAAM,CAAiB,iBAAiB,CAAC,CAAC;QAC/D,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;QACxC,OAAO,CAAC,GAAG,CAAC,SAAS,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC;QACpC,OAAO,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IACrD,CAAC,CAAC,CAAC;AACP,CAAC"}
|
package/dist/config.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA,MAAM,CAAC,MAAM,eAAe,GAAG,2BAA2B,CAAC;AAE3D,MAAM,UAAU,eAAe,CAAC,KAAyB;IACvD,OAAO,CAAC,KAAK,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,IAAI,eAAe,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACtF,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { Command } from "commander";
|
|
3
|
+
import { registerInitCommand } from "./commands/init.js";
|
|
4
|
+
import { registerInstallScriptCommand } from "./commands/install-script.js";
|
|
5
|
+
import { registerListCountersCommand } from "./commands/list-counters.js";
|
|
6
|
+
import { registerLoginCommand } from "./commands/login.js";
|
|
7
|
+
import { registerLogoutCommand } from "./commands/logout.js";
|
|
8
|
+
import { registerCreateCounterCommand } from "./commands/create-counter.js";
|
|
9
|
+
import { registerDeleteCounterCommand } from "./commands/delete-counter.js";
|
|
10
|
+
import { registerPullCounterCommand } from "./commands/pull-counter.js";
|
|
11
|
+
import { registerPushCounterCommand } from "./commands/push-counter.js";
|
|
12
|
+
import { registerStatusInquiryCommand } from "./commands/status-inquiry.js";
|
|
13
|
+
import { registerSyncInquiriesCommand } from "./commands/sync-inquiries.js";
|
|
14
|
+
import { registerWhoamiCommand } from "./commands/whoami.js";
|
|
15
|
+
const program = new Command();
|
|
16
|
+
program
|
|
17
|
+
.name("monban")
|
|
18
|
+
.description("Manage monban counters from a local workspace.")
|
|
19
|
+
.version("0.1.0");
|
|
20
|
+
registerLoginCommand(program);
|
|
21
|
+
registerLogoutCommand(program);
|
|
22
|
+
registerWhoamiCommand(program);
|
|
23
|
+
registerInitCommand(program);
|
|
24
|
+
registerListCountersCommand(program);
|
|
25
|
+
registerCreateCounterCommand(program);
|
|
26
|
+
registerDeleteCounterCommand(program);
|
|
27
|
+
registerPullCounterCommand(program);
|
|
28
|
+
registerPushCounterCommand(program);
|
|
29
|
+
registerSyncInquiriesCommand(program);
|
|
30
|
+
registerStatusInquiryCommand(program);
|
|
31
|
+
registerInstallScriptCommand(program);
|
|
32
|
+
program.parseAsync().catch((e) => {
|
|
33
|
+
const message = e instanceof Error ? e.message : "command failed";
|
|
34
|
+
console.error(`monban: ${message}`);
|
|
35
|
+
process.exitCode = 1;
|
|
36
|
+
});
|
|
37
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAEA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACpC,OAAO,EAAE,mBAAmB,EAAE,MAAM,oBAAoB,CAAC;AACzD,OAAO,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAE,2BAA2B,EAAE,MAAM,6BAA6B,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,MAAM,qBAAqB,CAAC;AAC3D,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,0BAA0B,EAAE,MAAM,4BAA4B,CAAC;AACxE,OAAO,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAE,4BAA4B,EAAE,MAAM,8BAA8B,CAAC;AAC5E,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,MAAM,OAAO,GAAG,IAAI,OAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,QAAQ,CAAC;KACd,WAAW,CAAC,gDAAgD,CAAC;KAC7D,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,oBAAoB,CAAC,OAAO,CAAC,CAAC;AAC9B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,qBAAqB,CAAC,OAAO,CAAC,CAAC;AAC/B,mBAAmB,CAAC,OAAO,CAAC,CAAC;AAC7B,2BAA2B,CAAC,OAAO,CAAC,CAAC;AACrC,4BAA4B,CAAC,OAAO,CAAC,CAAC;AACtC,4BAA4B,CAAC,OAAO,CAAC,CAAC;AACtC,0BAA0B,CAAC,OAAO,CAAC,CAAC;AACpC,0BAA0B,CAAC,OAAO,CAAC,CAAC;AACpC,4BAA4B,CAAC,OAAO,CAAC,CAAC;AACtC,4BAA4B,CAAC,OAAO,CAAC,CAAC;AACtC,4BAA4B,CAAC,OAAO,CAAC,CAAC;AAEtC,OAAO,CAAC,UAAU,EAAE,CAAC,KAAK,CAAC,CAAC,CAAU,EAAE,EAAE;IACxC,MAAM,OAAO,GAAG,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,gBAAgB,CAAC;IAClE,OAAO,CAAC,KAAK,CAAC,WAAW,OAAO,EAAE,CAAC,CAAC;IACpC,OAAO,CAAC,QAAQ,GAAG,CAAC,CAAC;AACvB,CAAC,CAAC,CAAC"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { counterDir } from "./layout.js";
|
|
4
|
+
export async function writeCounterFiles(counterId, files, root = process.cwd()) {
|
|
5
|
+
const dir = counterDir(counterId, root);
|
|
6
|
+
await mkdir(dir, { recursive: true });
|
|
7
|
+
await Promise.all([
|
|
8
|
+
writeFile(path.join(dir, "settings.yaml"), files.settingsYaml),
|
|
9
|
+
writeFile(path.join(dir, "TRIGGERS.md"), files.triggersMd),
|
|
10
|
+
writeFile(path.join(dir, "SYSTEM_PROMPT.md"), files.systemPromptMd),
|
|
11
|
+
]);
|
|
12
|
+
}
|
|
13
|
+
export async function readCounterFiles(counterId, root = process.cwd()) {
|
|
14
|
+
const dir = counterDir(counterId, root);
|
|
15
|
+
const [settingsYaml, triggersMd, systemPromptMd] = await Promise.all([
|
|
16
|
+
readFile(path.join(dir, "settings.yaml"), "utf8"),
|
|
17
|
+
readFile(path.join(dir, "TRIGGERS.md"), "utf8"),
|
|
18
|
+
readFile(path.join(dir, "SYSTEM_PROMPT.md"), "utf8"),
|
|
19
|
+
]);
|
|
20
|
+
return { settingsYaml, triggersMd, systemPromptMd };
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=counter-files.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"counter-files.js","sourceRoot":"","sources":["../../src/workspace/counter-files.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AAQzC,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,SAAiB,EACjB,KAAmB,EACnB,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE;IAEpB,MAAM,GAAG,GAAG,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACxC,MAAM,KAAK,CAAC,GAAG,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IACtC,MAAM,OAAO,CAAC,GAAG,CAAC;QAChB,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,EAAE,KAAK,CAAC,YAAY,CAAC;QAC9D,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,EAAE,KAAK,CAAC,UAAU,CAAC;QAC1D,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,EAAE,KAAK,CAAC,cAAc,CAAC;KACpE,CAAC,CAAC;AACL,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,gBAAgB,CACpC,SAAiB,EACjB,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE;IAEpB,MAAM,GAAG,GAAG,UAAU,CAAC,SAAS,EAAE,IAAI,CAAC,CAAC;IACxC,MAAM,CAAC,YAAY,EAAE,UAAU,EAAE,cAAc,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;QACnE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,eAAe,CAAC,EAAE,MAAM,CAAC;QACjD,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,aAAa,CAAC,EAAE,MAAM,CAAC;QAC/C,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,kBAAkB,CAAC,EAAE,MAAM,CAAC;KACrD,CAAC,CAAC;IACH,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,cAAc,EAAE,CAAC;AACtD,CAAC"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { inquiryDir, isNotFound, readWorkspaceState, writeWorkspaceState, } from "./layout.js";
|
|
4
|
+
export async function appendInquiryMessages(args) {
|
|
5
|
+
const root = args.root ?? process.cwd();
|
|
6
|
+
const dir = inquiryDir(args.counterId, root);
|
|
7
|
+
await mkdir(dir, { recursive: true });
|
|
8
|
+
const messagesFile = path.join(dir, "messages.jsonl");
|
|
9
|
+
const existingIds = await readExistingMessageIds(messagesFile);
|
|
10
|
+
const newMessages = args.messages.filter((m) => !existingIds.has(m.id));
|
|
11
|
+
if (newMessages.length > 0) {
|
|
12
|
+
const lines = newMessages.map((m) => JSON.stringify(m)).join("\n");
|
|
13
|
+
await appendFileText(messagesFile, `${lines}\n`);
|
|
14
|
+
}
|
|
15
|
+
await ensureInquiryStatuses(args.counterId, newMessages, root);
|
|
16
|
+
const state = await readWorkspaceState(root);
|
|
17
|
+
state.counters ??= {};
|
|
18
|
+
state.counters[args.counterId] = {
|
|
19
|
+
...(state.counters[args.counterId] ?? {}),
|
|
20
|
+
afterMessageId: args.nextAfterMessageId,
|
|
21
|
+
};
|
|
22
|
+
await writeWorkspaceState(state, root);
|
|
23
|
+
return { appended: newMessages.length };
|
|
24
|
+
}
|
|
25
|
+
export async function updateInquiryStatus(args) {
|
|
26
|
+
const root = args.root ?? process.cwd();
|
|
27
|
+
const counterIds = args.counterId
|
|
28
|
+
? [args.counterId]
|
|
29
|
+
: await counterIdsWithStatusForInquiry(root, args.inquiryId);
|
|
30
|
+
if (counterIds.length === 0) {
|
|
31
|
+
throw new Error("inquiry is not in local status.json. Run sync first or pass --counter.");
|
|
32
|
+
}
|
|
33
|
+
if (counterIds.length > 1) {
|
|
34
|
+
throw new Error("inquiry exists in multiple counters. Pass --counter.");
|
|
35
|
+
}
|
|
36
|
+
const counterId = counterIds[0];
|
|
37
|
+
const statusFile = path.join(inquiryDir(counterId, root), "status.json");
|
|
38
|
+
const statuses = await readStatuses(statusFile);
|
|
39
|
+
statuses[args.inquiryId] = {
|
|
40
|
+
status: args.status,
|
|
41
|
+
note: args.note ?? statuses[args.inquiryId]?.note ?? "",
|
|
42
|
+
updatedAt: new Date().toISOString(),
|
|
43
|
+
};
|
|
44
|
+
await writeStatuses(statusFile, statuses);
|
|
45
|
+
return { counterId };
|
|
46
|
+
}
|
|
47
|
+
async function ensureInquiryStatuses(counterId, messages, root) {
|
|
48
|
+
const statusFile = path.join(inquiryDir(counterId, root), "status.json");
|
|
49
|
+
const statuses = await readStatuses(statusFile);
|
|
50
|
+
let changed = false;
|
|
51
|
+
for (const message of messages) {
|
|
52
|
+
if (!statuses[message.inquiryId]) {
|
|
53
|
+
statuses[message.inquiryId] = {
|
|
54
|
+
status: "unhandled",
|
|
55
|
+
note: "",
|
|
56
|
+
updatedAt: new Date().toISOString(),
|
|
57
|
+
};
|
|
58
|
+
changed = true;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
if (changed || messages.length === 0)
|
|
62
|
+
await writeStatuses(statusFile, statuses);
|
|
63
|
+
}
|
|
64
|
+
async function readExistingMessageIds(file) {
|
|
65
|
+
try {
|
|
66
|
+
const raw = await readFile(file, "utf8");
|
|
67
|
+
const ids = new Set();
|
|
68
|
+
for (const line of raw.split("\n")) {
|
|
69
|
+
if (!line.trim())
|
|
70
|
+
continue;
|
|
71
|
+
const parsed = JSON.parse(line);
|
|
72
|
+
if (typeof parsed.id === "string")
|
|
73
|
+
ids.add(parsed.id);
|
|
74
|
+
}
|
|
75
|
+
return ids;
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
if (isNotFound(e))
|
|
79
|
+
return new Set();
|
|
80
|
+
throw e;
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
async function readStatuses(file) {
|
|
84
|
+
try {
|
|
85
|
+
return JSON.parse(await readFile(file, "utf8"));
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
if (isNotFound(e))
|
|
89
|
+
return {};
|
|
90
|
+
throw e;
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
async function writeStatuses(file, statuses) {
|
|
94
|
+
await mkdir(path.dirname(file), { recursive: true });
|
|
95
|
+
await writeFile(file, `${JSON.stringify(statuses, null, 2)}\n`);
|
|
96
|
+
}
|
|
97
|
+
async function appendFileText(file, text) {
|
|
98
|
+
const existing = await readFile(file, "utf8").catch((e) => {
|
|
99
|
+
if (isNotFound(e))
|
|
100
|
+
return "";
|
|
101
|
+
throw e;
|
|
102
|
+
});
|
|
103
|
+
const separator = existing.length > 0 && !existing.endsWith("\n") ? "\n" : "";
|
|
104
|
+
await writeFile(file, `${existing}${separator}${text}`);
|
|
105
|
+
}
|
|
106
|
+
async function counterIdsWithStatusForInquiry(root, inquiryId) {
|
|
107
|
+
const inquiriesRoot = path.join(root, "monban", "inquiries");
|
|
108
|
+
const { readdir } = await import("node:fs/promises");
|
|
109
|
+
const entries = await readdir(inquiriesRoot, { withFileTypes: true }).catch((e) => {
|
|
110
|
+
if (isNotFound(e))
|
|
111
|
+
return [];
|
|
112
|
+
throw e;
|
|
113
|
+
});
|
|
114
|
+
const matches = [];
|
|
115
|
+
for (const entry of entries) {
|
|
116
|
+
if (!entry.isDirectory())
|
|
117
|
+
continue;
|
|
118
|
+
const statuses = await readStatuses(path.join(inquiriesRoot, entry.name, "status.json"));
|
|
119
|
+
if (statuses[inquiryId])
|
|
120
|
+
matches.push(entry.name);
|
|
121
|
+
}
|
|
122
|
+
return matches;
|
|
123
|
+
}
|
|
124
|
+
//# sourceMappingURL=inquiry-store.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"inquiry-store.js","sourceRoot":"","sources":["../../src/workspace/inquiry-store.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
export function workspaceRoot(root = process.cwd()) {
|
|
4
|
+
return path.join(path.resolve(root), "monban");
|
|
5
|
+
}
|
|
6
|
+
export function counterDir(counterId, root = process.cwd()) {
|
|
7
|
+
return path.join(workspaceRoot(root), "counters", counterId);
|
|
8
|
+
}
|
|
9
|
+
export function inquiryDir(counterId, root = process.cwd()) {
|
|
10
|
+
return path.join(workspaceRoot(root), "inquiries", counterId);
|
|
11
|
+
}
|
|
12
|
+
export function stateFile(root = process.cwd()) {
|
|
13
|
+
return path.join(workspaceRoot(root), "state.json");
|
|
14
|
+
}
|
|
15
|
+
export async function ensureWorkspace(root = process.cwd()) {
|
|
16
|
+
await mkdir(path.join(workspaceRoot(root), "counters"), { recursive: true });
|
|
17
|
+
await mkdir(path.join(workspaceRoot(root), "inquiries"), { recursive: true });
|
|
18
|
+
await writeJsonIfMissing(stateFile(root), { counters: {} });
|
|
19
|
+
}
|
|
20
|
+
export async function readWorkspaceState(root = process.cwd()) {
|
|
21
|
+
try {
|
|
22
|
+
return JSON.parse(await readFile(stateFile(root), "utf8"));
|
|
23
|
+
}
|
|
24
|
+
catch (e) {
|
|
25
|
+
if (isNotFound(e))
|
|
26
|
+
return { counters: {} };
|
|
27
|
+
throw e;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
export async function writeWorkspaceState(state, root = process.cwd()) {
|
|
31
|
+
await mkdir(path.dirname(stateFile(root)), { recursive: true });
|
|
32
|
+
await writeFile(stateFile(root), `${JSON.stringify(state, null, 2)}\n`);
|
|
33
|
+
}
|
|
34
|
+
async function writeJsonIfMissing(file, value) {
|
|
35
|
+
try {
|
|
36
|
+
await readFile(file, "utf8");
|
|
37
|
+
}
|
|
38
|
+
catch (e) {
|
|
39
|
+
if (!isNotFound(e))
|
|
40
|
+
throw e;
|
|
41
|
+
await mkdir(path.dirname(file), { recursive: true });
|
|
42
|
+
await writeFile(file, `${JSON.stringify(value, null, 2)}\n`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
export function isNotFound(e) {
|
|
46
|
+
return Boolean(e && typeof e === "object" && "code" in e && e.code === "ENOENT");
|
|
47
|
+
}
|
|
48
|
+
//# sourceMappingURL=layout.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"layout.js","sourceRoot":"","sources":["../../src/workspace/layout.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { mkdir, readFile, writeFile } from "node:fs/promises";
|
|
2
|
+
import path from "node:path";
|
|
3
|
+
import { DEFAULT_APP_URL, normalizeAppUrl } from "../config.js";
|
|
4
|
+
import { workspaceRoot } from "./layout.js";
|
|
5
|
+
export function embedSnippet(counterId, appUrl = DEFAULT_APP_URL) {
|
|
6
|
+
const url = normalizeAppUrl(appUrl);
|
|
7
|
+
return `<script src="${url}/embed.js" data-counter-id="${counterId}"></script>`;
|
|
8
|
+
}
|
|
9
|
+
export async function installScript(args) {
|
|
10
|
+
const root = args.root ?? process.cwd();
|
|
11
|
+
const snippet = embedSnippet(args.counterId, args.appUrl);
|
|
12
|
+
if (!args.file) {
|
|
13
|
+
const file = path.join(workspaceRoot(root), "embed-snippet.html");
|
|
14
|
+
await mkdir(path.dirname(file), { recursive: true });
|
|
15
|
+
await writeFile(file, `${snippet}\n`);
|
|
16
|
+
return { file, changed: true };
|
|
17
|
+
}
|
|
18
|
+
const file = path.resolve(root, args.file);
|
|
19
|
+
const original = await readFile(file, "utf8");
|
|
20
|
+
const next = upsertSnippet(original, snippet);
|
|
21
|
+
if (next !== original)
|
|
22
|
+
await writeFile(file, next);
|
|
23
|
+
return { file, changed: next !== original };
|
|
24
|
+
}
|
|
25
|
+
function upsertSnippet(source, snippet) {
|
|
26
|
+
if (source.includes("data-counter-id=") && source.includes("/embed.js")) {
|
|
27
|
+
return source.replace(/<script\s+src=["'][^"']*\/embed\.js["']\s+data-counter-id=["'][^"']+["']\s*><\/script>/, snippet);
|
|
28
|
+
}
|
|
29
|
+
if (/<\/body>/i.test(source)) {
|
|
30
|
+
return source.replace(/<\/body>/i, ` ${snippet}\n</body>`);
|
|
31
|
+
}
|
|
32
|
+
return `${source.replace(/\s*$/, "")}\n${snippet}\n`;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=script-install.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"script-install.js","sourceRoot":"","sources":["../../src/workspace/script-install.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,eAAe,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAChE,OAAO,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAE5C,MAAM,UAAU,YAAY,CAAC,SAAiB,EAAE,MAAM,GAAG,eAAe;IACtE,MAAM,GAAG,GAAG,eAAe,CAAC,MAAM,CAAC,CAAC;IACpC,OAAO,gBAAgB,GAAG,+BAA+B,SAAS,aAAa,CAAC;AAClF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,aAAa,CAAC,IAKnC;IACC,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC;IACxC,MAAM,OAAO,GAAG,YAAY,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IAC1D,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QACf,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,CAAC,aAAa,CAAC,IAAI,CAAC,EAAE,oBAAoB,CAAC,CAAC;QAClE,MAAM,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACrD,MAAM,SAAS,CAAC,IAAI,EAAE,GAAG,OAAO,IAAI,CAAC,CAAC;QACtC,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC;IACjC,CAAC;IAED,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IAC3C,MAAM,QAAQ,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC9C,MAAM,IAAI,GAAG,aAAa,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IAC9C,IAAI,IAAI,KAAK,QAAQ;QAAE,MAAM,SAAS,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;IACnD,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,KAAK,QAAQ,EAAE,CAAC;AAC9C,CAAC;AAED,SAAS,aAAa,CAAC,MAAc,EAAE,OAAe;IACpD,IAAI,MAAM,CAAC,QAAQ,CAAC,kBAAkB,CAAC,IAAI,MAAM,CAAC,QAAQ,CAAC,WAAW,CAAC,EAAE,CAAC;QACxE,OAAO,MAAM,CAAC,OAAO,CACnB,wFAAwF,EACxF,OAAO,CACR,CAAC;IACJ,CAAC;IACD,IAAI,WAAW,CAAC,IAAI,CAAC,MAAM,CAAC,EAAE,CAAC;QAC7B,OAAO,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,KAAK,OAAO,WAAW,CAAC,CAAC;IAC9D,CAAC;IACD,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,KAAK,OAAO,IAAI,CAAC;AACvD,CAAC"}
|
package/package.json
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@monban-online/cli",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"type": "module",
|
|
5
|
+
"bin": {
|
|
6
|
+
"monban": "dist/index.js"
|
|
7
|
+
},
|
|
8
|
+
"files": [
|
|
9
|
+
"dist"
|
|
10
|
+
],
|
|
11
|
+
"scripts": {
|
|
12
|
+
"build": "tsc -p tsconfig.json",
|
|
13
|
+
"typecheck": "tsc -p tsconfig.json --noEmit --pretty false",
|
|
14
|
+
"test": "tsx --test tests/**/*.test.ts"
|
|
15
|
+
},
|
|
16
|
+
"dependencies": {
|
|
17
|
+
"commander": "^14.0.2"
|
|
18
|
+
},
|
|
19
|
+
"devDependencies": {
|
|
20
|
+
"@types/node": "^20",
|
|
21
|
+
"tsx": "^4.21.0",
|
|
22
|
+
"typescript": "^5"
|
|
23
|
+
}
|
|
24
|
+
}
|