@nulab/bee 0.0.0 → 1.0.0-rc.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.
Files changed (135) hide show
  1. package/README.md +36 -0
  2. package/bin/cli.mjs +2 -0
  3. package/dist/chunks/activities.mjs +90 -0
  4. package/dist/chunks/activities2.mjs +91 -0
  5. package/dist/chunks/activities3.mjs +91 -0
  6. package/dist/chunks/add-user.mjs +42 -0
  7. package/dist/chunks/add.mjs +62 -0
  8. package/dist/chunks/add2.mjs +40 -0
  9. package/dist/chunks/api.mjs +138 -0
  10. package/dist/chunks/attachments.mjs +48 -0
  11. package/dist/chunks/attachments2.mjs +48 -0
  12. package/dist/chunks/attachments3.mjs +49 -0
  13. package/dist/chunks/browse.mjs +270 -0
  14. package/dist/chunks/clone.mjs +61 -0
  15. package/dist/chunks/close.mjs +51 -0
  16. package/dist/chunks/comment.mjs +124 -0
  17. package/dist/chunks/comment2.mjs +112 -0
  18. package/dist/chunks/comments.mjs +58 -0
  19. package/dist/chunks/completion.mjs +118 -0
  20. package/dist/chunks/count.mjs +74 -0
  21. package/dist/chunks/count2.mjs +70 -0
  22. package/dist/chunks/count3.mjs +60 -0
  23. package/dist/chunks/count4.mjs +35 -0
  24. package/dist/chunks/count5.mjs +53 -0
  25. package/dist/chunks/create.mjs +61 -0
  26. package/dist/chunks/create2.mjs +83 -0
  27. package/dist/chunks/create3.mjs +65 -0
  28. package/dist/chunks/create4.mjs +74 -0
  29. package/dist/chunks/create5.mjs +57 -0
  30. package/dist/chunks/create6.mjs +38 -0
  31. package/dist/chunks/create7.mjs +46 -0
  32. package/dist/chunks/create8.mjs +50 -0
  33. package/dist/chunks/create9.mjs +50 -0
  34. package/dist/chunks/dashboard.mjs +85 -0
  35. package/dist/chunks/delete.mjs +48 -0
  36. package/dist/chunks/delete2.mjs +47 -0
  37. package/dist/chunks/delete3.mjs +47 -0
  38. package/dist/chunks/delete4.mjs +47 -0
  39. package/dist/chunks/delete5.mjs +48 -0
  40. package/dist/chunks/delete6.mjs +48 -0
  41. package/dist/chunks/delete7.mjs +55 -0
  42. package/dist/chunks/delete8.mjs +54 -0
  43. package/dist/chunks/delete9.mjs +49 -0
  44. package/dist/chunks/edit.mjs +56 -0
  45. package/dist/chunks/edit2.mjs +73 -0
  46. package/dist/chunks/edit3.mjs +65 -0
  47. package/dist/chunks/edit4.mjs +52 -0
  48. package/dist/chunks/edit5.mjs +38 -0
  49. package/dist/chunks/edit6.mjs +51 -0
  50. package/dist/chunks/edit7.mjs +47 -0
  51. package/dist/chunks/edit8.mjs +47 -0
  52. package/dist/chunks/history.mjs +57 -0
  53. package/dist/chunks/index.mjs +15 -0
  54. package/dist/chunks/index10.mjs +18 -0
  55. package/dist/chunks/index11.mjs +13 -0
  56. package/dist/chunks/index12.mjs +13 -0
  57. package/dist/chunks/index13.mjs +13 -0
  58. package/dist/chunks/index14.mjs +8 -0
  59. package/dist/chunks/index15.mjs +13 -0
  60. package/dist/chunks/index16.mjs +13 -0
  61. package/dist/chunks/index17.mjs +14 -0
  62. package/dist/chunks/index2.mjs +18 -0
  63. package/dist/chunks/index3.mjs +20 -0
  64. package/dist/chunks/index4.mjs +15 -0
  65. package/dist/chunks/index5.mjs +13 -0
  66. package/dist/chunks/index6.mjs +17 -0
  67. package/dist/chunks/index7.mjs +8 -0
  68. package/dist/chunks/index8.mjs +8 -0
  69. package/dist/chunks/index9.mjs +13 -0
  70. package/dist/chunks/list.mjs +53 -0
  71. package/dist/chunks/list10.mjs +44 -0
  72. package/dist/chunks/list11.mjs +49 -0
  73. package/dist/chunks/list12.mjs +45 -0
  74. package/dist/chunks/list13.mjs +45 -0
  75. package/dist/chunks/list14.mjs +55 -0
  76. package/dist/chunks/list15.mjs +47 -0
  77. package/dist/chunks/list2.mjs +95 -0
  78. package/dist/chunks/list3.mjs +86 -0
  79. package/dist/chunks/list4.mjs +80 -0
  80. package/dist/chunks/list5.mjs +78 -0
  81. package/dist/chunks/list6.mjs +45 -0
  82. package/dist/chunks/list7.mjs +49 -0
  83. package/dist/chunks/list8.mjs +47 -0
  84. package/dist/chunks/list9.mjs +53 -0
  85. package/dist/chunks/login.mjs +206 -0
  86. package/dist/chunks/logout.mjs +57 -0
  87. package/dist/chunks/me.mjs +49 -0
  88. package/dist/chunks/read-all.mjs +30 -0
  89. package/dist/chunks/read.mjs +30 -0
  90. package/dist/chunks/read2.mjs +28 -0
  91. package/dist/chunks/refresh.mjs +77 -0
  92. package/dist/chunks/remove-user.mjs +42 -0
  93. package/dist/chunks/remove.mjs +28 -0
  94. package/dist/chunks/reopen.mjs +43 -0
  95. package/dist/chunks/status.mjs +62 -0
  96. package/dist/chunks/status2.mjs +62 -0
  97. package/dist/chunks/status3.mjs +67 -0
  98. package/dist/chunks/switch.mjs +52 -0
  99. package/dist/chunks/tags.mjs +41 -0
  100. package/dist/chunks/token.mjs +39 -0
  101. package/dist/chunks/tree.mjs +61 -0
  102. package/dist/chunks/users.mjs +48 -0
  103. package/dist/chunks/view.mjs +58 -0
  104. package/dist/chunks/view2.mjs +95 -0
  105. package/dist/chunks/view3.mjs +69 -0
  106. package/dist/chunks/view4.mjs +71 -0
  107. package/dist/chunks/view5.mjs +62 -0
  108. package/dist/chunks/view6.mjs +53 -0
  109. package/dist/chunks/view7.mjs +49 -0
  110. package/dist/chunks/view8.mjs +62 -0
  111. package/dist/chunks/view9.mjs +49 -0
  112. package/dist/index.mjs +152 -0
  113. package/dist/shared/bee.-8tk76YJ.mjs +42 -0
  114. package/dist/shared/bee.BTBGpv4K.mjs +34 -0
  115. package/dist/shared/bee.BXiuAfjJ.mjs +10 -0
  116. package/dist/shared/bee.BeQSH2t0.mjs +25 -0
  117. package/dist/shared/bee.Btmq3TXs.mjs +19 -0
  118. package/dist/shared/bee.C--ZWPxf.mjs +14 -0
  119. package/dist/shared/bee.CCNmDHVv.mjs +33 -0
  120. package/dist/shared/bee.CQ3kBgas.mjs +58 -0
  121. package/dist/shared/bee.CThuQMit.mjs +124 -0
  122. package/dist/shared/bee.ChBdZ0cH.mjs +9 -0
  123. package/dist/shared/bee.CktwmH8R.mjs +25 -0
  124. package/dist/shared/bee.CzKcWSES.mjs +42 -0
  125. package/dist/shared/bee.D6yQ6Pqf.mjs +18 -0
  126. package/dist/shared/bee.DHTPkjMh.mjs +48 -0
  127. package/dist/shared/bee.DVTuFf-T.mjs +276 -0
  128. package/dist/shared/bee.DoTvz3uW.mjs +13 -0
  129. package/dist/shared/bee.Ds2l-nTJ.mjs +308 -0
  130. package/dist/shared/bee.IM3QELRf.mjs +32 -0
  131. package/dist/shared/bee.XxOB1Her.mjs +8 -0
  132. package/dist/shared/bee.n5MYN4a6.mjs +12 -0
  133. package/dist/shared/bee.sHWg0IFT.mjs +22 -0
  134. package/package.json +50 -2
  135. package/.github/workflows/initial-release.yml +0 -23
@@ -0,0 +1,53 @@
1
+ import consola from 'consola';
2
+ import { g as getClient } from '../shared/bee.CThuQMit.mjs';
3
+ import 'backlog-js';
4
+ import 'node:http';
5
+ import 'open';
6
+ import 'node:child_process';
7
+ import { o as outputResult } from '../shared/bee.BTBGpv4K.mjs';
8
+ import 'node:stream/consumers';
9
+ import 'valibot';
10
+ import { p as printTable } from '../shared/bee.IM3QELRf.mjs';
11
+ import { B as BeeCommand, E as ENV_AUTH, a as ENV_PROJECT } from '../shared/bee.CQ3kBgas.mjs';
12
+ import { k as keyword, j as json, s as space } from '../shared/bee.DHTPkjMh.mjs';
13
+ import '../shared/bee.XxOB1Her.mjs';
14
+ import '../shared/bee.CktwmH8R.mjs';
15
+ import '../shared/bee.DVTuFf-T.mjs';
16
+ import 'node:fs';
17
+ import 'node:path';
18
+ import 'node:os';
19
+ import '../shared/bee.BeQSH2t0.mjs';
20
+ import '../shared/bee.-8tk76YJ.mjs';
21
+ import '../shared/bee.Ds2l-nTJ.mjs';
22
+ import 'commander';
23
+ import 'consola/utils';
24
+
25
+ const list = new BeeCommand("list").summary("List wiki pages").description(`Use \`--keyword\` to filter pages by name or content.`).argument("<project>", "Project ID or project key").addOption(keyword()).addOption(json()).addOption(space()).envVars([...ENV_AUTH, ENV_PROJECT]).examples([
26
+ { description: "List all wiki pages in a project", command: "bee wiki list PROJECT" },
27
+ {
28
+ description: "Search wiki pages by keyword",
29
+ command: 'bee wiki list PROJECT --keyword "setup"'
30
+ },
31
+ { description: "Output as JSON", command: "bee wiki list PROJECT --json" }
32
+ ]).action(async (project, opts) => {
33
+ const { client } = await getClient(opts.space);
34
+ const wikis = await client.getWikis({
35
+ projectIdOrKey: project,
36
+ keyword: opts.keyword
37
+ });
38
+ const json = opts.json === true ? "" : opts.json;
39
+ outputResult(wikis, { json }, (data) => {
40
+ if (data.length === 0) {
41
+ consola.info("No wiki pages found.");
42
+ return;
43
+ }
44
+ const rows = data.map((wiki) => [
45
+ { header: "ID", value: String(wiki.id) },
46
+ { header: "NAME", value: wiki.name },
47
+ { header: "UPDATED", value: wiki.updated.slice(0, 10) }
48
+ ]);
49
+ printTable(rows);
50
+ });
51
+ });
52
+
53
+ export { list as default };
@@ -0,0 +1,206 @@
1
+ import consola from 'consola';
2
+ import { p as promptRequired, u as updateConfig } from '../shared/bee.DVTuFf-T.mjs';
3
+ import { r as readStdin } from '../shared/bee.C--ZWPxf.mjs';
4
+ import 'valibot';
5
+ import { U as UserError } from '../shared/bee.XxOB1Her.mjs';
6
+ import { Backlog, OAuth2 } from 'backlog-js';
7
+ import { e as exchangeAuthorizationCode } from '../shared/bee.CktwmH8R.mjs';
8
+ import { createServer } from 'node:http';
9
+ import { e as openUrl } from '../shared/bee.CzKcWSES.mjs';
10
+ import 'node:child_process';
11
+ import { B as BeeCommand } from '../shared/bee.CQ3kBgas.mjs';
12
+ import 'node:stream/consumers';
13
+ import 'node:fs';
14
+ import 'node:path';
15
+ import 'node:os';
16
+ import '../shared/bee.BeQSH2t0.mjs';
17
+ import 'open';
18
+ import 'commander';
19
+ import 'consola/utils';
20
+
21
+ const CALLBACK_TIMEOUT_MS = 3e5;
22
+ const CALLBACK_PORT = 5033;
23
+ const SUCCESS_HTML = `<!DOCTYPE html>
24
+ <html><head><meta charset="utf-8"><title>Authentication Successful</title></head>
25
+ <body style="font-family:system-ui;text-align:center;padding:2em">
26
+ <h1>Authentication Successful</h1>
27
+ <p>You can close this window and return to the terminal.</p>
28
+ </body></html>`;
29
+ const ERROR_HTML = `<!DOCTYPE html>
30
+ <html><head><meta charset="utf-8"><title>Authentication Failed</title></head>
31
+ <body style="font-family:system-ui;text-align:center;padding:2em">
32
+ <h1>Authentication Failed</h1>
33
+ <p>Something went wrong. Please try again.</p>
34
+ </body></html>`;
35
+ const respondHtml = (res, html, statusCode = 200) => {
36
+ res.writeHead(statusCode, { "Content-Type": "text/html" });
37
+ res.end(html);
38
+ };
39
+ const startCallbackServer = () => {
40
+ let resolveCode = null;
41
+ let rejectCode = null;
42
+ const server = createServer((req, res) => {
43
+ const url = new URL(req.url ?? "/", `http://localhost:${CALLBACK_PORT}`);
44
+ if (url.pathname !== "/callback") {
45
+ res.writeHead(404);
46
+ res.end("Not Found");
47
+ return;
48
+ }
49
+ const code = url.searchParams.get("code");
50
+ const state = url.searchParams.get("state");
51
+ const error = url.searchParams.get("error");
52
+ if (error) {
53
+ rejectCode?.(new Error(`OAuth error: ${error}`));
54
+ respondHtml(res, ERROR_HTML);
55
+ return;
56
+ }
57
+ if (!code || !state) {
58
+ rejectCode?.(new Error("Missing code or state parameter"));
59
+ respondHtml(res, ERROR_HTML);
60
+ return;
61
+ }
62
+ resolveCode?.({ code, state });
63
+ respondHtml(res, SUCCESS_HTML);
64
+ });
65
+ server.listen(CALLBACK_PORT);
66
+ return {
67
+ port: CALLBACK_PORT,
68
+ waitForCallback(expectedState) {
69
+ return new Promise((resolve, reject) => {
70
+ const timeout = setTimeout(() => {
71
+ reject(new Error("OAuth callback timed out after 5 minutes"));
72
+ server.close();
73
+ }, CALLBACK_TIMEOUT_MS);
74
+ resolveCode = (result) => {
75
+ clearTimeout(timeout);
76
+ if (result.state === expectedState) {
77
+ resolve(result.code);
78
+ } else {
79
+ reject(new Error("OAuth state mismatch \u2014 possible CSRF attack"));
80
+ }
81
+ };
82
+ rejectCode = (error) => {
83
+ clearTimeout(timeout);
84
+ reject(error);
85
+ };
86
+ });
87
+ },
88
+ stop() {
89
+ server.close();
90
+ }
91
+ };
92
+ };
93
+
94
+ const login = new BeeCommand("login").summary("Authenticate with a Backlog space").description(
95
+ `The default mode is API key with interactive prompts.
96
+
97
+ Use \`--with-token\` to pass an API key on standard input.
98
+ Use \`--method oauth\` for OAuth authentication via the browser.`
99
+ ).option("-m, --method <method>", "The authentication method to use", "api-key").option("--with-token", "Read token from standard input").option("--client-id <id>", "The OAuth Client ID to use when authenticating with Backlog").option(
100
+ "--client-secret <secret>",
101
+ "The OAuth Client Secret to use when authenticating with Backlog"
102
+ ).envVars([
103
+ ["BACKLOG_SPACE", "Default space hostname"],
104
+ ["BACKLOG_OAUTH_CLIENT_ID", "OAuth Client ID"],
105
+ ["BACKLOG_OAUTH_CLIENT_SECRET", "OAuth Client Secret"]
106
+ ]).examples([
107
+ { description: "Start interactive setup", command: "bee auth login" },
108
+ {
109
+ description: "Login with API key from stdin",
110
+ command: "echo 'your-api-key' | bee auth login --with-token"
111
+ },
112
+ { description: "Login with OAuth", command: "bee auth login -m oauth" }
113
+ ]).action(async (opts) => {
114
+ const { method } = opts;
115
+ if (method !== "api-key" && method !== "oauth") {
116
+ throw new UserError('Invalid auth method. Use "api-key" or "oauth".');
117
+ }
118
+ const hostname = await promptRequired("Backlog space hostname:", process.env.BACKLOG_SPACE, {
119
+ placeholder: "xxx.backlog.com"
120
+ });
121
+ await (method === "api-key" ? loginWithApiKey(hostname, opts) : loginWithOAuth(hostname, opts));
122
+ });
123
+ const loginWithApiKey = async (hostname, opts) => {
124
+ if (!opts.withToken) {
125
+ consola.info(`Tip: you can generate an API key at https://${hostname}/EditApiSettings.action`);
126
+ }
127
+ const apiKey = opts.withToken ? await readStdin() : await promptRequired("API key:");
128
+ consola.start(`Authenticating with ${hostname}...`);
129
+ let user;
130
+ try {
131
+ const client = new Backlog({ host: hostname, apiKey });
132
+ user = await client.getMyself();
133
+ } catch {
134
+ throw new UserError(
135
+ `Authentication failed. Could not connect to ${hostname} with the provided API key.`
136
+ );
137
+ }
138
+ saveSpace(hostname, { method: "api-key", apiKey });
139
+ consola.success(`Logged in to ${hostname} as ${user.name} (${user.userId})`);
140
+ };
141
+ const loginWithOAuth = async (hostname, opts) => {
142
+ const clientId = await promptRequired(
143
+ "OAuth Client ID:",
144
+ opts.clientId ?? process.env.BACKLOG_OAUTH_CLIENT_ID
145
+ );
146
+ const clientSecret = await promptRequired(
147
+ "OAuth Client Secret:",
148
+ opts.clientSecret ?? process.env.BACKLOG_OAUTH_CLIENT_SECRET
149
+ );
150
+ const callbackServer = startCallbackServer();
151
+ const redirectUri = `http://localhost:${callbackServer.port}/callback`;
152
+ const state = crypto.randomUUID();
153
+ const oauth2 = new OAuth2({ clientId, clientSecret });
154
+ const authUrl = oauth2.getAuthorizationURL({ host: hostname, redirectUri, state });
155
+ consola.info("Opening browser for authorization...");
156
+ consola.info(`If the browser doesn't open, visit: ${authUrl}`);
157
+ await openUrl(authUrl);
158
+ let code;
159
+ try {
160
+ code = await callbackServer.waitForCallback(state);
161
+ } catch (error) {
162
+ callbackServer.stop();
163
+ throw new UserError(
164
+ `OAuth authorization failed: ${error instanceof Error ? error.message : String(error)}`
165
+ );
166
+ } finally {
167
+ callbackServer.stop();
168
+ }
169
+ consola.start("Exchanging authorization code for tokens...");
170
+ let tokenResponse;
171
+ try {
172
+ tokenResponse = await exchangeAuthorizationCode(hostname, {
173
+ code,
174
+ clientId,
175
+ clientSecret,
176
+ redirectUri
177
+ });
178
+ } catch {
179
+ throw new UserError("Failed to exchange authorization code for tokens.");
180
+ }
181
+ let user;
182
+ try {
183
+ const client = new Backlog({ host: hostname, accessToken: tokenResponse.access_token });
184
+ user = await client.getMyself();
185
+ } catch {
186
+ throw new UserError("Authentication verification failed.");
187
+ }
188
+ saveSpace(hostname, {
189
+ method: "oauth",
190
+ accessToken: tokenResponse.access_token,
191
+ refreshToken: tokenResponse.refresh_token,
192
+ clientId,
193
+ clientSecret
194
+ });
195
+ consola.success(`Logged in to ${hostname} as ${user.name} (${user.userId})`);
196
+ };
197
+ const saveSpace = (hostname, auth) => {
198
+ updateConfig((config) => {
199
+ const index = config.spaces.findIndex((s) => s.host === hostname);
200
+ const spaces = index === -1 ? [...config.spaces, { host: hostname, auth }] : config.spaces.with(index, { ...config.spaces[index], auth });
201
+ const defaultSpace = config.defaultSpace ?? hostname;
202
+ return { ...config, spaces, defaultSpace };
203
+ });
204
+ };
205
+
206
+ export { login as default };
@@ -0,0 +1,57 @@
1
+ import consola from 'consola';
2
+ import { U as UserError } from '../shared/bee.XxOB1Her.mjs';
3
+ import 'node:stream/consumers';
4
+ import 'valibot';
5
+ import { l as loadConfig } from '../shared/bee.DVTuFf-T.mjs';
6
+ import { r as removeSpace } from '../shared/bee.-8tk76YJ.mjs';
7
+ import { B as BeeCommand } from '../shared/bee.CQ3kBgas.mjs';
8
+ import { s as space } from '../shared/bee.DHTPkjMh.mjs';
9
+ import 'node:fs';
10
+ import 'node:path';
11
+ import 'node:os';
12
+ import '../shared/bee.BeQSH2t0.mjs';
13
+ import 'commander';
14
+ import 'consola/utils';
15
+
16
+ const logout = new BeeCommand("logout").summary("Remove authentication for a Backlog space").description(
17
+ `Removes stored credentials locally. Does not revoke API keys or OAuth tokens on the server.`
18
+ ).addOption(space()).examples([
19
+ { description: "Select space via prompt", command: "bee auth logout" },
20
+ {
21
+ description: "Log out of a specific space",
22
+ command: "bee auth logout -s xxx.backlog.com"
23
+ }
24
+ ]).action(async (opts) => {
25
+ const config = loadConfig();
26
+ let hostname = opts.space;
27
+ if (!hostname) {
28
+ if (config.spaces.length === 0) {
29
+ consola.info("No spaces are currently authenticated.");
30
+ return;
31
+ }
32
+ const [firstSpace] = config.spaces;
33
+ if (config.spaces.length === 1) {
34
+ hostname = firstSpace.host;
35
+ } else if (process.stdin.isTTY) {
36
+ hostname = await consola.prompt("Select a space to log out from:", {
37
+ type: "select",
38
+ options: config.spaces.map((s) => s.host)
39
+ });
40
+ if (typeof hostname !== "string" || !hostname) {
41
+ throw new UserError("No space selected.");
42
+ }
43
+ } else {
44
+ throw new UserError(
45
+ "Hostname is required. Use --space to provide it in non-interactive mode."
46
+ );
47
+ }
48
+ }
49
+ try {
50
+ removeSpace(hostname);
51
+ } catch {
52
+ throw new UserError(`Space "${hostname}" is not configured.`);
53
+ }
54
+ consola.success(`Logged out of ${hostname}.`);
55
+ });
56
+
57
+ export { logout as default };
@@ -0,0 +1,49 @@
1
+ import consola from 'consola';
2
+ import { R as ROLE_LABELS } from '../shared/bee.BXiuAfjJ.mjs';
3
+ import { g as getClient } from '../shared/bee.CThuQMit.mjs';
4
+ import 'backlog-js';
5
+ import 'node:http';
6
+ import 'open';
7
+ import 'node:child_process';
8
+ import { o as outputResult } from '../shared/bee.BTBGpv4K.mjs';
9
+ import 'node:stream/consumers';
10
+ import 'valibot';
11
+ import { f as formatDate } from '../shared/bee.n5MYN4a6.mjs';
12
+ import { p as printDefinitionList } from '../shared/bee.D6yQ6Pqf.mjs';
13
+ import { B as BeeCommand, E as ENV_AUTH } from '../shared/bee.CQ3kBgas.mjs';
14
+ import { j as json, s as space } from '../shared/bee.DHTPkjMh.mjs';
15
+ import '../shared/bee.XxOB1Her.mjs';
16
+ import '../shared/bee.CktwmH8R.mjs';
17
+ import '../shared/bee.DVTuFf-T.mjs';
18
+ import 'node:fs';
19
+ import 'node:path';
20
+ import 'node:os';
21
+ import '../shared/bee.BeQSH2t0.mjs';
22
+ import '../shared/bee.-8tk76YJ.mjs';
23
+ import '../shared/bee.Ds2l-nTJ.mjs';
24
+ import 'commander';
25
+ import 'consola/utils';
26
+
27
+ const me = new BeeCommand("me").summary("View the authenticated user").description(`Shortcut for \`bee user view\` using the currently authenticated user.`).addOption(json()).addOption(space()).envVars([...ENV_AUTH]).examples([
28
+ { description: "View your own profile", command: "bee user me" },
29
+ { description: "Output as JSON", command: "bee user me --json" }
30
+ ]).action(async (opts) => {
31
+ const { client } = await getClient(opts.space);
32
+ const myself = await client.getMyself();
33
+ outputResult(myself, opts, (data) => {
34
+ consola.log("");
35
+ consola.log(` ${data.name}`);
36
+ consola.log("");
37
+ printDefinitionList([
38
+ ["ID", String(data.id)],
39
+ ["User ID", data.userId],
40
+ ["Email", data.mailAddress],
41
+ ["Role", ROLE_LABELS[data.roleType] ?? `Unknown (${data.roleType})`],
42
+ ["Language", data.lang],
43
+ ["Last Login", data.lastLoginTime ? formatDate(data.lastLoginTime) : void 0]
44
+ ]);
45
+ consola.log("");
46
+ });
47
+ });
48
+
49
+ export { me as default };
@@ -0,0 +1,30 @@
1
+ import consola from 'consola';
2
+ import { g as getClient } from '../shared/bee.CThuQMit.mjs';
3
+ import 'backlog-js';
4
+ import 'node:http';
5
+ import 'open';
6
+ import 'node:child_process';
7
+ import { B as BeeCommand, E as ENV_AUTH } from '../shared/bee.CQ3kBgas.mjs';
8
+ import { s as space } from '../shared/bee.DHTPkjMh.mjs';
9
+ import '../shared/bee.XxOB1Her.mjs';
10
+ import 'node:stream/consumers';
11
+ import 'valibot';
12
+ import '../shared/bee.CktwmH8R.mjs';
13
+ import '../shared/bee.DVTuFf-T.mjs';
14
+ import 'node:fs';
15
+ import 'node:path';
16
+ import 'node:os';
17
+ import '../shared/bee.BeQSH2t0.mjs';
18
+ import '../shared/bee.-8tk76YJ.mjs';
19
+ import 'commander';
20
+ import 'consola/utils';
21
+
22
+ const readAll = new BeeCommand("read-all").summary("Mark all notifications as read").description(`Resets the unread notification count to zero.`).addOption(space()).envVars([...ENV_AUTH]).examples([
23
+ { description: "Mark all notifications as read", command: "bee notification read-all" }
24
+ ]).action(async (opts) => {
25
+ const { client } = await getClient(opts.space);
26
+ await client.resetNotificationsMarkAsRead();
27
+ consola.success("Marked all notifications as read.");
28
+ });
29
+
30
+ export { readAll as default };
@@ -0,0 +1,30 @@
1
+ import consola from 'consola';
2
+ import { g as getClient } from '../shared/bee.CThuQMit.mjs';
3
+ import 'backlog-js';
4
+ import 'node:http';
5
+ import 'open';
6
+ import 'node:child_process';
7
+ import { B as BeeCommand, E as ENV_AUTH } from '../shared/bee.CQ3kBgas.mjs';
8
+ import { s as space } from '../shared/bee.DHTPkjMh.mjs';
9
+ import '../shared/bee.XxOB1Her.mjs';
10
+ import 'node:stream/consumers';
11
+ import 'valibot';
12
+ import '../shared/bee.CktwmH8R.mjs';
13
+ import '../shared/bee.DVTuFf-T.mjs';
14
+ import 'node:fs';
15
+ import 'node:path';
16
+ import 'node:os';
17
+ import '../shared/bee.BeQSH2t0.mjs';
18
+ import '../shared/bee.-8tk76YJ.mjs';
19
+ import 'commander';
20
+ import 'consola/utils';
21
+
22
+ const read = new BeeCommand("read").summary("Mark a notification as read").description(`Use \`bee notification list\` to find notification IDs.`).argument("<id>", "Notification ID").addOption(space()).envVars([...ENV_AUTH]).examples([
23
+ { description: "Mark a notification as read", command: "bee notification read 12345" }
24
+ ]).action(async (id, opts) => {
25
+ const { client } = await getClient(opts.space);
26
+ await client.markAsReadNotification(Number(id));
27
+ consola.success(`Marked notification ${id} as read.`);
28
+ });
29
+
30
+ export { read as default };
@@ -0,0 +1,28 @@
1
+ import consola from 'consola';
2
+ import { g as getClient } from '../shared/bee.CThuQMit.mjs';
3
+ import 'backlog-js';
4
+ import 'node:http';
5
+ import 'open';
6
+ import 'node:child_process';
7
+ import { B as BeeCommand, E as ENV_AUTH } from '../shared/bee.CQ3kBgas.mjs';
8
+ import { s as space } from '../shared/bee.DHTPkjMh.mjs';
9
+ import '../shared/bee.XxOB1Her.mjs';
10
+ import 'node:stream/consumers';
11
+ import 'valibot';
12
+ import '../shared/bee.CktwmH8R.mjs';
13
+ import '../shared/bee.DVTuFf-T.mjs';
14
+ import 'node:fs';
15
+ import 'node:path';
16
+ import 'node:os';
17
+ import '../shared/bee.BeQSH2t0.mjs';
18
+ import '../shared/bee.-8tk76YJ.mjs';
19
+ import 'commander';
20
+ import 'consola/utils';
21
+
22
+ const read = new BeeCommand("read").summary("Mark a watching item as read").description(`Use \`bee watching list\` to find watching IDs.`).argument("<watching>", "Watching ID").addOption(space()).envVars([...ENV_AUTH]).examples([{ description: "Mark a watching item as read", command: "bee watching read 12345" }]).action(async (watching, opts) => {
23
+ const { client } = await getClient(opts.space);
24
+ await client.resetWatchingListItemAsRead(Number(watching));
25
+ consola.success(`Marked watching ${watching} as read.`);
26
+ });
27
+
28
+ export { read as default };
@@ -0,0 +1,77 @@
1
+ import consola from 'consola';
2
+ import { U as UserError } from '../shared/bee.XxOB1Her.mjs';
3
+ import 'node:stream/consumers';
4
+ import 'valibot';
5
+ import { Backlog } from 'backlog-js';
6
+ import { r as refreshAccessToken } from '../shared/bee.CktwmH8R.mjs';
7
+ import { l as loadConfig } from '../shared/bee.DVTuFf-T.mjs';
8
+ import { f as findSpace, u as updateSpaceAuth } from '../shared/bee.-8tk76YJ.mjs';
9
+ import 'node:http';
10
+ import 'open';
11
+ import 'node:child_process';
12
+ import { B as BeeCommand } from '../shared/bee.CQ3kBgas.mjs';
13
+ import { s as space } from '../shared/bee.DHTPkjMh.mjs';
14
+ import 'node:fs';
15
+ import 'node:path';
16
+ import 'node:os';
17
+ import '../shared/bee.BeQSH2t0.mjs';
18
+ import 'commander';
19
+ import 'consola/utils';
20
+
21
+ const refresh = new BeeCommand("refresh").summary("Refresh OAuth token").description(
22
+ `Only available for spaces authenticated with OAuth. If the refresh token is expired, re-authenticate with \`bee auth login -m oauth\`.`
23
+ ).addOption(space()).examples([
24
+ { description: "Refresh token for default space", command: "bee auth refresh" },
25
+ {
26
+ description: "Refresh token for specific space",
27
+ command: "bee auth refresh -s xxx.backlog.com"
28
+ }
29
+ ]).action(async (opts) => {
30
+ const config = loadConfig();
31
+ const host = opts.space ?? config.defaultSpace;
32
+ const space = host ? findSpace(config.spaces, host) : null;
33
+ if (!space) {
34
+ throw new UserError("No space configured. Run `bee auth login` to authenticate.");
35
+ }
36
+ if (space.auth.method !== "oauth") {
37
+ throw new UserError(
38
+ "Token refresh is only available for OAuth authentication. Current space uses API key."
39
+ );
40
+ }
41
+ const { clientId, clientSecret } = space.auth;
42
+ if (!clientId || !clientSecret) {
43
+ throw new UserError(
44
+ "Client ID and Client Secret are missing from the stored OAuth configuration. Please re-authenticate with `bee auth login -m oauth`."
45
+ );
46
+ }
47
+ consola.start(`Refreshing OAuth token for ${space.host}...`);
48
+ let tokenResponse;
49
+ try {
50
+ tokenResponse = await refreshAccessToken(space.host, {
51
+ clientId,
52
+ clientSecret,
53
+ refreshToken: space.auth.refreshToken
54
+ });
55
+ } catch {
56
+ throw new UserError(
57
+ "Failed to refresh OAuth token. Please re-authenticate with `bee auth login -m oauth`."
58
+ );
59
+ }
60
+ let user;
61
+ try {
62
+ const client = new Backlog({ host: space.host, accessToken: tokenResponse.access_token });
63
+ user = await client.getMyself();
64
+ } catch {
65
+ throw new UserError("Token verification failed after refresh.");
66
+ }
67
+ updateSpaceAuth(space.host, {
68
+ method: "oauth",
69
+ accessToken: tokenResponse.access_token,
70
+ refreshToken: tokenResponse.refresh_token,
71
+ clientId,
72
+ clientSecret
73
+ });
74
+ consola.success(`Token refreshed for ${space.host} (${user.name})`);
75
+ });
76
+
77
+ export { refresh as default };
@@ -0,0 +1,42 @@
1
+ import consola from 'consola';
2
+ import { g as getClient } from '../shared/bee.CThuQMit.mjs';
3
+ import 'backlog-js';
4
+ import 'node:http';
5
+ import 'open';
6
+ import 'node:child_process';
7
+ import { o as outputResult } from '../shared/bee.BTBGpv4K.mjs';
8
+ import { U as UserError } from '../shared/bee.XxOB1Her.mjs';
9
+ import 'node:stream/consumers';
10
+ import 'valibot';
11
+ import { B as BeeCommand, E as ENV_AUTH, a as ENV_PROJECT } from '../shared/bee.CQ3kBgas.mjs';
12
+ import { p as project, R as RequiredOption, j as json, s as space, r as resolveOptions } from '../shared/bee.DHTPkjMh.mjs';
13
+ import '../shared/bee.CktwmH8R.mjs';
14
+ import '../shared/bee.DVTuFf-T.mjs';
15
+ import 'node:fs';
16
+ import 'node:path';
17
+ import 'node:os';
18
+ import '../shared/bee.BeQSH2t0.mjs';
19
+ import '../shared/bee.-8tk76YJ.mjs';
20
+ import 'commander';
21
+ import 'consola/utils';
22
+
23
+ const removeUser = new BeeCommand("remove-user").summary("Remove a user from a project").description(`Use \`bee project users\` to look up user IDs.`).addOption(project()).addOption(new RequiredOption("--user-id <id>", "User ID")).addOption(json()).addOption(space()).envVars([...ENV_AUTH, ENV_PROJECT]).examples([
24
+ {
25
+ description: "Remove a user from a project",
26
+ command: "bee project remove-user -p PROJECT_KEY --user-id 12345"
27
+ }
28
+ ]).action(async (opts, cmd) => {
29
+ await resolveOptions(cmd);
30
+ const userId = Number(opts.userId);
31
+ if (Number.isNaN(userId)) {
32
+ throw new UserError("User ID must be a number.");
33
+ }
34
+ const { client } = await getClient(opts.space);
35
+ const user = await client.deleteProjectUsers(opts.project, { userId });
36
+ const jsonArg = opts.json === true ? "" : opts.json;
37
+ outputResult(user, { ...opts, json: jsonArg }, (data) => {
38
+ consola.success(`Removed user ${data.name} from project ${opts.project}.`);
39
+ });
40
+ });
41
+
42
+ export { removeUser as default };
@@ -0,0 +1,28 @@
1
+ import consola from 'consola';
2
+ import { g as getClient } from '../shared/bee.CThuQMit.mjs';
3
+ import 'backlog-js';
4
+ import 'node:http';
5
+ import 'open';
6
+ import 'node:child_process';
7
+ import { B as BeeCommand, E as ENV_AUTH } from '../shared/bee.CQ3kBgas.mjs';
8
+ import { s as space } from '../shared/bee.DHTPkjMh.mjs';
9
+ import '../shared/bee.XxOB1Her.mjs';
10
+ import 'node:stream/consumers';
11
+ import 'valibot';
12
+ import '../shared/bee.CktwmH8R.mjs';
13
+ import '../shared/bee.DVTuFf-T.mjs';
14
+ import 'node:fs';
15
+ import 'node:path';
16
+ import 'node:os';
17
+ import '../shared/bee.BeQSH2t0.mjs';
18
+ import '../shared/bee.-8tk76YJ.mjs';
19
+ import 'commander';
20
+ import 'consola/utils';
21
+
22
+ const remove = new BeeCommand("remove").summary("Remove a star").description(`Use \`bee star list\` to find star IDs.`).argument("<star>", "Star ID").addOption(space()).envVars([...ENV_AUTH]).examples([{ description: "Remove a star", command: "bee star remove 12345" }]).action(async (star, opts) => {
23
+ const { client } = await getClient(opts.space);
24
+ await client.removeStar(Number(star));
25
+ consola.success(`Removed star ${star}.`);
26
+ });
27
+
28
+ export { remove as default };
@@ -0,0 +1,43 @@
1
+ import consola from 'consola';
2
+ import { I as IssueStatusId } from '../shared/bee.Btmq3TXs.mjs';
3
+ import { g as getClient } from '../shared/bee.CThuQMit.mjs';
4
+ import 'backlog-js';
5
+ import 'node:http';
6
+ import 'open';
7
+ import 'node:child_process';
8
+ import { o as outputResult } from '../shared/bee.BTBGpv4K.mjs';
9
+ import 'node:stream/consumers';
10
+ import 'valibot';
11
+ import { B as BeeCommand, E as ENV_AUTH } from '../shared/bee.CQ3kBgas.mjs';
12
+ import { g as notify, j as json, s as space } from '../shared/bee.DHTPkjMh.mjs';
13
+ import '../shared/bee.XxOB1Her.mjs';
14
+ import '../shared/bee.CktwmH8R.mjs';
15
+ import '../shared/bee.DVTuFf-T.mjs';
16
+ import 'node:fs';
17
+ import 'node:path';
18
+ import 'node:os';
19
+ import '../shared/bee.BeQSH2t0.mjs';
20
+ import '../shared/bee.-8tk76YJ.mjs';
21
+ import 'commander';
22
+ import 'consola/utils';
23
+
24
+ const reopen = new BeeCommand("reopen").summary("Reopen an issue").description(`Sets the status back to Open.`).argument("<issue>", "Issue ID or issue key").option("-c, --comment <text>", "Comment to add when reopening").addOption(notify()).addOption(json()).addOption(space()).envVars([...ENV_AUTH]).examples([
25
+ { description: "Reopen an issue", command: "bee issue reopen PROJECT-123" },
26
+ {
27
+ description: "Reopen with a comment",
28
+ command: 'bee issue reopen PROJECT-123 -c "Reopening due to regression"'
29
+ }
30
+ ]).action(async (issue, opts) => {
31
+ const { client } = await getClient(opts.space);
32
+ const notifiedUserId = opts.notify ?? [];
33
+ const issueData = await client.patchIssue(issue, {
34
+ statusId: IssueStatusId.Open,
35
+ comment: opts.comment,
36
+ notifiedUserId
37
+ });
38
+ outputResult(issueData, opts, (data) => {
39
+ consola.success(`Reopened issue ${data.issueKey}: ${data.summary}`);
40
+ });
41
+ });
42
+
43
+ export { reopen as default };