@token-dashboard/typeless-usage-uploader 0.1.0 → 0.1.1

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 (3) hide show
  1. package/README.md +10 -0
  2. package/dist/cli.js +58 -1
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -15,6 +15,16 @@ typeless-usage-uploader status
15
15
  typeless-usage-uploader logs
16
16
  ```
17
17
 
18
+ `init` 默认会询问是否登录后自动启动;也可以用参数显式控制:
19
+
20
+ ```bash
21
+ typeless-usage-uploader init --backend-url http://localhost:8086 --auto-start
22
+ typeless-usage-uploader init --backend-url http://localhost:8086 --no-auto-start
23
+ ```
24
+
25
+ 如果之前开启了登录自动启动,重新执行 `init --no-auto-start` 会保存配置、移除
26
+ `~/Library/LaunchAgents` 下的自启动 plist,并重启当前后台服务。
27
+
18
28
  开发环境:
19
29
 
20
30
  ```bash
package/dist/cli.js CHANGED
@@ -1,5 +1,7 @@
1
1
  import fs from 'node:fs';
2
2
  import path from 'node:path';
3
+ import readline from 'node:readline/promises';
4
+ import { stdin as input, stdout as output } from 'node:process';
3
5
  import { fileURLToPath } from 'node:url';
4
6
  import { TypelessUsageUploader } from './collector.js';
5
7
  import {
@@ -15,7 +17,7 @@ import { StateDb } from './state-db.js';
15
17
  const HELP_TEXT = `${PRODUCT_NAME}
16
18
 
17
19
  Usage:
18
- ${CLI_NAME} init [--backend-url <url>] [--interval 300] [--yes]
20
+ ${CLI_NAME} init [--backend-url <url>] [--interval 300] [--yes] [--auto-start|--no-auto-start]
19
21
  ${CLI_NAME} clear [--yes]
20
22
  ${CLI_NAME} start
21
23
  ${CLI_NAME} stop
@@ -31,6 +33,8 @@ Common options:
31
33
  --typeless-db <path> Typeless typeless.db path
32
34
  --typeless-storage <path> Typeless app-storage.json path
33
35
  --state-db <path> Local SQLite state DB path
36
+ --auto-start Start automatically when you log in
37
+ --no-auto-start Do not start automatically when you log in
34
38
  --yes Skip interactive prompts
35
39
  --lines <n> Number of log lines for service logs
36
40
  -h, --help Show help
@@ -44,6 +48,7 @@ class CliOperationalError extends Error {
44
48
  }
45
49
 
46
50
  export const cliDeps = {
51
+ promptConfirm,
47
52
  createUploader(runtime) {
48
53
  return new TypelessUsageUploader({
49
54
  stateDbPath: runtime.stateDbPath,
@@ -82,6 +87,14 @@ export function parseCliArgs(argv) {
82
87
  options.yes = true;
83
88
  continue;
84
89
  }
90
+ if (token === '--auto-start') {
91
+ options.autoStartOnLogin = true;
92
+ continue;
93
+ }
94
+ if (token === '--no-auto-start') {
95
+ options.autoStartOnLogin = false;
96
+ continue;
97
+ }
85
98
 
86
99
  const [key, inlineValue] = token.split('=', 2);
87
100
  const takesValue = new Set([
@@ -152,6 +165,9 @@ function runtimeOverrides(options) {
152
165
  overrides.typelessStoragePath = options.typelessStoragePath;
153
166
  }
154
167
  if (options.stateDbPath !== undefined) overrides.stateDbPath = options.stateDbPath;
168
+ if (options.autoStartOnLogin !== undefined) {
169
+ overrides.autoStartOnLogin = options.autoStartOnLogin;
170
+ }
155
171
  return overrides;
156
172
  }
157
173
 
@@ -159,7 +175,42 @@ function printHelp() {
159
175
  console.log(HELP_TEXT);
160
176
  }
161
177
 
178
+ async function promptValue(label, defaultValue) {
179
+ const rl = readline.createInterface({ input, output });
180
+ try {
181
+ const suffix = defaultValue ? ` [${defaultValue}]` : '';
182
+ const answer = (await rl.question(`${label}${suffix}: `)).trim();
183
+ return answer || defaultValue || null;
184
+ } finally {
185
+ rl.close();
186
+ }
187
+ }
188
+
189
+ async function promptConfirm(label, defaultYes = false) {
190
+ const defaultValue = defaultYes ? 'y' : 'n';
191
+ const answer = await promptValue(
192
+ `${label} (${defaultYes ? 'Y/n' : 'y/N'})`,
193
+ defaultValue,
194
+ );
195
+ return /^(y|yes)$/i.test(String(answer ?? '').trim());
196
+ }
197
+
198
+ async function resolveAutoStartOnLogin(runtime, options) {
199
+ if (options.autoStartOnLogin !== undefined) {
200
+ return options.autoStartOnLogin;
201
+ }
202
+ if (options.yes) {
203
+ return runtime.autoStartOnLogin;
204
+ }
205
+ return cliDeps.promptConfirm(
206
+ 'Start automatically when you log in on this Mac?',
207
+ runtime.autoStartOnLogin,
208
+ );
209
+ }
210
+
162
211
  function currentEntryFile() {
212
+ const distBin = fileURLToPath(new URL('./bin/typeless-usage-uploader.js', import.meta.url));
213
+ if (fs.existsSync(distBin)) return distBin;
163
214
  return fileURLToPath(new URL('../bin/typeless-usage-uploader.js', import.meta.url));
164
215
  }
165
216
 
@@ -168,6 +219,7 @@ async function runInit(options) {
168
219
  if (!overrides.backendUrl) overrides.backendUrl = DEFAULT_BACKEND_URL;
169
220
  let runtime = mergeRuntimeConfig(options.configFile, overrides);
170
221
  runtime.entryFile = currentEntryFile();
222
+ runtime.autoStartOnLogin = await resolveAutoStartOnLogin(runtime, options);
171
223
  runtime = saveRuntimeConfig(runtime);
172
224
 
173
225
  const uploader = cliDeps.createUploader(runtime);
@@ -179,6 +231,11 @@ async function runInit(options) {
179
231
  try {
180
232
  manager.start();
181
233
  console.log(`${PRODUCT_NAME} initialized and started.`);
234
+ console.log(
235
+ runtime.autoStartOnLogin
236
+ ? 'Login auto-start is enabled.'
237
+ : 'Login auto-start is disabled for future logins.',
238
+ );
182
239
  } catch (error) {
183
240
  console.log(`${PRODUCT_NAME} initialized. Service start skipped: ${error instanceof Error ? error.message : String(error)}`);
184
241
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@token-dashboard/typeless-usage-uploader",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "description": "Typeless 去内容化用量上报 CLI",
5
5
  "type": "module",
6
6
  "bin": {