coolhand-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.
Files changed (83) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +119 -0
  3. package/dist/auth/callback-server.d.ts +13 -0
  4. package/dist/auth/callback-server.d.ts.map +1 -0
  5. package/dist/auth/callback-server.js +133 -0
  6. package/dist/auth/callback-server.js.map +1 -0
  7. package/dist/auth/open-browser.d.ts +8 -0
  8. package/dist/auth/open-browser.d.ts.map +1 -0
  9. package/dist/auth/open-browser.js +31 -0
  10. package/dist/auth/open-browser.js.map +1 -0
  11. package/dist/auth/state.d.ts +3 -0
  12. package/dist/auth/state.d.ts.map +1 -0
  13. package/dist/auth/state.js +16 -0
  14. package/dist/auth/state.js.map +1 -0
  15. package/dist/auth/success-page.d.ts +3 -0
  16. package/dist/auth/success-page.d.ts.map +1 -0
  17. package/dist/auth/success-page.js +176 -0
  18. package/dist/auth/success-page.js.map +1 -0
  19. package/dist/bin.d.ts +3 -0
  20. package/dist/bin.d.ts.map +1 -0
  21. package/dist/bin.js +14 -0
  22. package/dist/bin.js.map +1 -0
  23. package/dist/cli.d.ts +9 -0
  24. package/dist/cli.d.ts.map +1 -0
  25. package/dist/cli.js +187 -0
  26. package/dist/cli.js.map +1 -0
  27. package/dist/commands/accounts.d.ts +3 -0
  28. package/dist/commands/accounts.d.ts.map +1 -0
  29. package/dist/commands/accounts.js +59 -0
  30. package/dist/commands/accounts.js.map +1 -0
  31. package/dist/commands/clients.d.ts +3 -0
  32. package/dist/commands/clients.d.ts.map +1 -0
  33. package/dist/commands/clients.js +59 -0
  34. package/dist/commands/clients.js.map +1 -0
  35. package/dist/commands/login.d.ts +3 -0
  36. package/dist/commands/login.d.ts.map +1 -0
  37. package/dist/commands/login.js +119 -0
  38. package/dist/commands/login.js.map +1 -0
  39. package/dist/commands/logout.d.ts +3 -0
  40. package/dist/commands/logout.d.ts.map +1 -0
  41. package/dist/commands/logout.js +39 -0
  42. package/dist/commands/logout.js.map +1 -0
  43. package/dist/commands/status.d.ts +5 -0
  44. package/dist/commands/status.d.ts.map +1 -0
  45. package/dist/commands/status.js +37 -0
  46. package/dist/commands/status.js.map +1 -0
  47. package/dist/commands/whoami.d.ts +3 -0
  48. package/dist/commands/whoami.d.ts.map +1 -0
  49. package/dist/commands/whoami.js +20 -0
  50. package/dist/commands/whoami.js.map +1 -0
  51. package/dist/config.d.ts +11 -0
  52. package/dist/config.d.ts.map +1 -0
  53. package/dist/config.js +127 -0
  54. package/dist/config.js.map +1 -0
  55. package/dist/env-file.d.ts +12 -0
  56. package/dist/env-file.d.ts.map +1 -0
  57. package/dist/env-file.js +62 -0
  58. package/dist/env-file.js.map +1 -0
  59. package/dist/errors.d.ts +13 -0
  60. package/dist/errors.d.ts.map +1 -0
  61. package/dist/errors.js +16 -0
  62. package/dist/errors.js.map +1 -0
  63. package/dist/index.d.ts +7 -0
  64. package/dist/index.d.ts.map +1 -0
  65. package/dist/index.js +6 -0
  66. package/dist/index.js.map +1 -0
  67. package/dist/logger.d.ts +8 -0
  68. package/dist/logger.d.ts.map +1 -0
  69. package/dist/logger.js +29 -0
  70. package/dist/logger.js.map +1 -0
  71. package/dist/mask.d.ts +7 -0
  72. package/dist/mask.d.ts.map +1 -0
  73. package/dist/mask.js +12 -0
  74. package/dist/mask.js.map +1 -0
  75. package/dist/types.d.ts +52 -0
  76. package/dist/types.d.ts.map +1 -0
  77. package/dist/types.js +3 -0
  78. package/dist/types.js.map +1 -0
  79. package/dist/version.d.ts +11 -0
  80. package/dist/version.d.ts.map +1 -0
  81. package/dist/version.js +11 -0
  82. package/dist/version.js.map +1 -0
  83. package/package.json +74 -0
@@ -0,0 +1,119 @@
1
+ import { CliError, ExitCode } from '../errors.js';
2
+ import { logger, redact } from '../logger.js';
3
+ import { maskToken } from '../mask.js';
4
+ import { upsertClient, configPath } from '../config.js';
5
+ import { writeEnvKey } from '../env-file.js';
6
+ import { startCallbackServer } from '../auth/callback-server.js';
7
+ import { openBrowser } from '../auth/open-browser.js';
8
+ import { generateState } from '../auth/state.js';
9
+ import { DEFAULT_BASE_URL, DEFAULT_TIMEOUT_MS } from '../types.js';
10
+ function parseBaseUrl(input) {
11
+ const raw = input ?? DEFAULT_BASE_URL;
12
+ let parsed;
13
+ try {
14
+ parsed = new URL(raw);
15
+ }
16
+ catch {
17
+ throw new CliError('INVALID_BASE_URL', `Invalid --base-url: ${raw}`);
18
+ }
19
+ if (parsed.protocol !== 'http:' && parsed.protocol !== 'https:') {
20
+ throw new CliError('INVALID_BASE_URL', `--base-url must be http or https, got: ${parsed.protocol}`);
21
+ }
22
+ return parsed;
23
+ }
24
+ function reportError(err, json) {
25
+ if (json) {
26
+ logger.json({ ok: false, error: err.code, message: redact(err.message) });
27
+ }
28
+ else {
29
+ logger.info(`Error: ${redact(err.message)} [${err.code}]`);
30
+ }
31
+ }
32
+ export async function run(opts) {
33
+ let baseUrl;
34
+ try {
35
+ baseUrl = parseBaseUrl(opts.baseUrl);
36
+ }
37
+ catch (err) {
38
+ if (err instanceof CliError) {
39
+ reportError(err, opts.json);
40
+ return err.exitCode;
41
+ }
42
+ throw err;
43
+ }
44
+ const state = generateState();
45
+ const timeoutMs = opts.timeoutMs ?? DEFAULT_TIMEOUT_MS;
46
+ const handle = await startCallbackServer({ expectedState: state, timeoutMs });
47
+ const redirectUri = `http://127.0.0.1:${handle.port}/callback`;
48
+ const authUrl = new URL('/cli/auth', baseUrl);
49
+ authUrl.searchParams.set('redirect_uri', redirectUri);
50
+ authUrl.searchParams.set('state', state);
51
+ if (opts.clientId) {
52
+ authUrl.searchParams.set('client_id', opts.clientId);
53
+ }
54
+ const onSignal = (sig) => {
55
+ logger.info(`\nAborted (${sig}).`);
56
+ handle.close().finally(() => {
57
+ process.exit(ExitCode.ABORTED);
58
+ });
59
+ };
60
+ process.once('SIGINT', onSignal);
61
+ process.once('SIGTERM', onSignal);
62
+ const signalCleanup = () => {
63
+ process.removeListener('SIGINT', onSignal);
64
+ process.removeListener('SIGTERM', onSignal);
65
+ };
66
+ try {
67
+ logger.info(`Opening browser to ${authUrl.toString()}`);
68
+ logger.info('If your browser does not open, paste the URL above into it manually.');
69
+ logger.info(`Waiting for browser authentication... (Ctrl+C to cancel; ${Math.round(timeoutMs / 1000)}s timeout)`);
70
+ await openBrowser(authUrl.toString());
71
+ const callback = await handle.result;
72
+ const entry = {
73
+ client_id: callback.clientId,
74
+ client_name: callback.clientName,
75
+ api_key: callback.token,
76
+ base_url: baseUrl.origin,
77
+ saved_at: new Date().toISOString(),
78
+ };
79
+ await upsertClient(entry, true);
80
+ let envResult;
81
+ if (opts.writeEnv) {
82
+ envResult = await writeEnvKey(opts.writeEnv, 'COOLHAND_API_KEY', callback.token);
83
+ }
84
+ if (opts.json) {
85
+ logger.json({
86
+ ok: true,
87
+ masked_token: maskToken(callback.token),
88
+ client_id: callback.clientId,
89
+ client_name: callback.clientName,
90
+ base_url: baseUrl.origin,
91
+ config_path: configPath(),
92
+ env_file: envResult
93
+ ? { path: envResult.path, created: envResult.created, replaced: envResult.replaced }
94
+ : null,
95
+ });
96
+ }
97
+ else {
98
+ logger.info(`Logged in as "${callback.clientName}" (${callback.clientId}).`);
99
+ logger.info(`Saved to ${configPath()}.`);
100
+ if (envResult) {
101
+ const action = envResult.created ? 'created' : envResult.replaced ? 'updated' : 'appended to';
102
+ logger.info(`COOLHAND_API_KEY ${action} ${envResult.path}.`);
103
+ }
104
+ }
105
+ return ExitCode.OK;
106
+ }
107
+ catch (err) {
108
+ if (err instanceof CliError) {
109
+ reportError(err, opts.json);
110
+ return err.exitCode;
111
+ }
112
+ throw err;
113
+ }
114
+ finally {
115
+ signalCleanup();
116
+ await handle.close().catch(() => undefined);
117
+ }
118
+ }
119
+ //# sourceMappingURL=login.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login.js","sourceRoot":"","sources":["../../src/commands/login.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { LogoutOptions } from '../types.js';
2
+ export declare function run(opts: LogoutOptions): Promise<number>;
3
+ //# sourceMappingURL=logout.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.d.ts","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,wBAAsB,GAAG,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAkC9D"}
@@ -0,0 +1,39 @@
1
+ import { ExitCode } from '../errors.js';
2
+ import { logger } from '../logger.js';
3
+ import { deleteConfig, loadConfig, removeClient } from '../config.js';
4
+ export async function run(opts) {
5
+ if (opts.all) {
6
+ await deleteConfig();
7
+ if (opts.json) {
8
+ logger.json({ ok: true, removed: 'all' });
9
+ }
10
+ else {
11
+ logger.info('Removed all stored Coolhand clients.');
12
+ }
13
+ return ExitCode.OK;
14
+ }
15
+ const cfg = await loadConfig();
16
+ const targetId = opts.clientId ?? cfg.default_client_id;
17
+ if (!targetId) {
18
+ if (opts.json) {
19
+ logger.json({ ok: true, removed: null, message: 'No clients to remove.' });
20
+ }
21
+ else {
22
+ logger.info('No clients are configured.');
23
+ }
24
+ return ExitCode.OK;
25
+ }
26
+ const existed = Boolean(cfg.clients[targetId]);
27
+ await removeClient(targetId);
28
+ if (opts.json) {
29
+ logger.json({ ok: true, removed: existed ? targetId : null });
30
+ }
31
+ else if (existed) {
32
+ logger.info(`Removed client "${targetId}".`);
33
+ }
34
+ else {
35
+ logger.info(`No client "${targetId}" was configured.`);
36
+ }
37
+ return ExitCode.OK;
38
+ }
39
+ //# sourceMappingURL=logout.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logout.js","sourceRoot":"","sources":["../../src/commands/logout.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,YAAY,EAAE,UAAU,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAGtE,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,IAAmB;IAC3C,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;QACb,MAAM,YAAY,EAAE,CAAC;QACrB,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,KAAK,EAAE,CAAC,CAAC;QAC5C,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,sCAAsC,CAAC,CAAC;QACtD,CAAC;QACD,OAAO,QAAQ,CAAC,EAAE,CAAC;IACrB,CAAC;IAED,MAAM,GAAG,GAAG,MAAM,UAAU,EAAE,CAAC;IAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,GAAG,CAAC,iBAAiB,CAAC;IAExD,IAAI,CAAC,QAAQ,EAAE,CAAC;QACd,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;YACd,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,uBAAuB,EAAE,CAAC,CAAC;QAC7E,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,4BAA4B,CAAC,CAAC;QAC5C,CAAC;QACD,OAAO,QAAQ,CAAC,EAAE,CAAC;IACrB,CAAC;IAED,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;IAC/C,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAC;IAE7B,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;IAChE,CAAC;SAAM,IAAI,OAAO,EAAE,CAAC;QACnB,MAAM,CAAC,IAAI,CAAC,mBAAmB,QAAQ,IAAI,CAAC,CAAC;IAC/C,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,IAAI,CAAC,cAAc,QAAQ,mBAAmB,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,QAAQ,CAAC,EAAE,CAAC;AACrB,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { loadConfig } from '../config.js';
2
+ import type { StatusOptions, StatusOutput } from '../types.js';
3
+ export declare function buildStatusOutput(cfg: Awaited<ReturnType<typeof loadConfig>>): StatusOutput;
4
+ export declare function run(opts: StatusOptions): Promise<number>;
5
+ //# sourceMappingURL=status.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.d.ts","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAEA,OAAO,EAAa,UAAU,EAAE,MAAM,cAAc,CAAC;AAErD,OAAO,KAAK,EAAE,aAAa,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAE/D,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,CAAC,UAAU,CAAC,OAAO,UAAU,CAAC,CAAC,GAAG,YAAY,CAY3F;AAED,wBAAsB,GAAG,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAiB9D"}
@@ -0,0 +1,37 @@
1
+ import { ExitCode } from '../errors.js';
2
+ import { logger } from '../logger.js';
3
+ import { getClient, loadConfig } from '../config.js';
4
+ import { maskToken } from '../mask.js';
5
+ export function buildStatusOutput(cfg) {
6
+ const clients = Object.values(cfg.clients).map((entry) => ({
7
+ client_id: entry.client_id,
8
+ client_name: entry.client_name,
9
+ masked_token: maskToken(entry.api_key),
10
+ base_url: entry.base_url,
11
+ }));
12
+ return {
13
+ configured: clients.length > 0,
14
+ clients,
15
+ default_client_id: cfg.default_client_id,
16
+ };
17
+ }
18
+ export async function run(opts) {
19
+ const cfg = await loadConfig();
20
+ const output = buildStatusOutput(cfg);
21
+ const target = getClient(cfg, opts.clientId);
22
+ const configured = opts.clientId ? Boolean(target) : output.configured;
23
+ if (opts.json) {
24
+ logger.json({ ...output, configured });
25
+ }
26
+ else if (configured && target) {
27
+ logger.info(`Configured: "${target.client_name}" (${target.client_id}) — ${maskToken(target.api_key)}`);
28
+ }
29
+ else if (opts.clientId) {
30
+ logger.info(`No token configured for client "${opts.clientId}".`);
31
+ }
32
+ else {
33
+ logger.info('No Coolhand token is configured. Run `coolhand login` to authenticate.');
34
+ }
35
+ return configured ? ExitCode.OK : ExitCode.USER_ERROR;
36
+ }
37
+ //# sourceMappingURL=status.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"status.js","sourceRoot":"","sources":["../../src/commands/status.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,MAAM,UAAU,iBAAiB,CAAC,GAA2C;IAC3E,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QACzD,SAAS,EAAE,KAAK,CAAC,SAAS;QAC1B,WAAW,EAAE,KAAK,CAAC,WAAW;QAC9B,YAAY,EAAE,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC;QACtC,QAAQ,EAAE,KAAK,CAAC,QAAQ;KACzB,CAAC,CAAC,CAAC;IACJ,OAAO;QACL,UAAU,EAAE,OAAO,CAAC,MAAM,GAAG,CAAC;QAC9B,OAAO;QACP,iBAAiB,EAAE,GAAG,CAAC,iBAAiB;KACzC,CAAC;AACJ,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,IAAmB;IAC3C,MAAM,GAAG,GAAG,MAAM,UAAU,EAAE,CAAC;IAC/B,MAAM,MAAM,GAAG,iBAAiB,CAAC,GAAG,CAAC,CAAC;IACtC,MAAM,MAAM,GAAG,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,UAAU,GAAG,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC;IAEvE,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,CAAC,IAAI,CAAC,EAAE,GAAG,MAAM,EAAE,UAAU,EAAE,CAAC,CAAC;IACzC,CAAC;SAAM,IAAI,UAAU,IAAI,MAAM,EAAE,CAAC;QAChC,MAAM,CAAC,IAAI,CAAC,gBAAgB,MAAM,CAAC,WAAW,MAAM,MAAM,CAAC,SAAS,OAAO,SAAS,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;IAC1G,CAAC;SAAM,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QACzB,MAAM,CAAC,IAAI,CAAC,mCAAmC,IAAI,CAAC,QAAQ,IAAI,CAAC,CAAC;IACpE,CAAC;SAAM,CAAC;QACN,MAAM,CAAC,IAAI,CAAC,wEAAwE,CAAC,CAAC;IACxF,CAAC;IAED,OAAO,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,UAAU,CAAC;AACxD,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { WhoamiOptions } from '../types.js';
2
+ export declare function run(opts: WhoamiOptions): Promise<number>;
3
+ //# sourceMappingURL=whoami.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whoami.d.ts","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAEjD,wBAAsB,GAAG,CAAC,IAAI,EAAE,aAAa,GAAG,OAAO,CAAC,MAAM,CAAC,CAiB9D"}
@@ -0,0 +1,20 @@
1
+ import { ExitCode } from '../errors.js';
2
+ import { logger } from '../logger.js';
3
+ import { getClient, loadConfig } from '../config.js';
4
+ import { maskToken } from '../mask.js';
5
+ export async function run(opts) {
6
+ const cfg = await loadConfig();
7
+ const entry = getClient(cfg, opts.clientId);
8
+ if (!entry) {
9
+ if (opts.clientId) {
10
+ logger.info(`No client "${opts.clientId}" is configured.`);
11
+ }
12
+ else {
13
+ logger.info('Not logged in. Run `coolhand login` to authenticate.');
14
+ }
15
+ return ExitCode.USER_ERROR;
16
+ }
17
+ logger.info(`Logged in as "${entry.client_name}" (id: ${entry.client_id}) via ${entry.base_url} — ${maskToken(entry.api_key)}`);
18
+ return ExitCode.OK;
19
+ }
20
+ //# sourceMappingURL=whoami.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"whoami.js","sourceRoot":"","sources":["../../src/commands/whoami.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,SAAS,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,OAAO,EAAE,SAAS,EAAE,MAAM,YAAY,CAAC;AAGvC,MAAM,CAAC,KAAK,UAAU,GAAG,CAAC,IAAmB;IAC3C,MAAM,GAAG,GAAG,MAAM,UAAU,EAAE,CAAC;IAC/B,MAAM,KAAK,GAAG,SAAS,CAAC,GAAG,EAAE,IAAI,CAAC,QAAQ,CAAC,CAAC;IAE5C,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;YAClB,MAAM,CAAC,IAAI,CAAC,cAAc,IAAI,CAAC,QAAQ,kBAAkB,CAAC,CAAC;QAC7D,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,IAAI,CAAC,sDAAsD,CAAC,CAAC;QACtE,CAAC;QACD,OAAO,QAAQ,CAAC,UAAU,CAAC;IAC7B,CAAC;IAED,MAAM,CAAC,IAAI,CACT,iBAAiB,KAAK,CAAC,WAAW,UAAU,KAAK,CAAC,SAAS,SAAS,KAAK,CAAC,QAAQ,MAAM,SAAS,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CACnH,CAAC;IACF,OAAO,QAAQ,CAAC,EAAE,CAAC;AACrB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { ClientEntry, ConfigFile } from './types.js';
2
+ export declare function configDir(): string;
3
+ export declare function configPath(): string;
4
+ export declare function loadConfig(): Promise<ConfigFile>;
5
+ export declare function saveConfig(cfg: ConfigFile): Promise<void>;
6
+ export declare function deleteConfig(): Promise<void>;
7
+ export declare function getClient(cfg: ConfigFile, clientId?: string): ClientEntry | undefined;
8
+ export declare function upsertClient(entry: ClientEntry, makeDefault?: boolean): Promise<ConfigFile>;
9
+ export declare function removeClient(clientId: string): Promise<ConfigFile | null>;
10
+ export declare function setDefault(clientId: string): Promise<ConfigFile>;
11
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAKA,OAAO,KAAK,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAM1D,wBAAgB,SAAS,IAAI,MAAM,CAMlC;AAED,wBAAgB,UAAU,IAAI,MAAM,CAEnC;AAMD,wBAAsB,UAAU,IAAI,OAAO,CAAC,UAAU,CAAC,CAyBtD;AAWD,wBAAsB,UAAU,CAAC,GAAG,EAAE,UAAU,GAAG,OAAO,CAAC,IAAI,CAAC,CAmB/D;AAED,wBAAsB,YAAY,IAAI,OAAO,CAAC,IAAI,CAAC,CAMlD;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,UAAU,EAAE,QAAQ,CAAC,EAAE,MAAM,GAAG,WAAW,GAAG,SAAS,CAMrF;AAED,wBAAsB,YAAY,CAAC,KAAK,EAAE,WAAW,EAAE,WAAW,UAAO,GAAG,OAAO,CAAC,UAAU,CAAC,CAQ9F;AAED,wBAAsB,YAAY,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAgB/E;AAED,wBAAsB,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC,CAQtE"}
package/dist/config.js ADDED
@@ -0,0 +1,127 @@
1
+ import { promises as fs } from 'fs';
2
+ import * as os from 'os';
3
+ import * as path from 'path';
4
+ import { randomBytes } from 'crypto';
5
+ import { CliError } from './errors.js';
6
+ const CONFIG_FILENAME = 'config.json';
7
+ const DIR_MODE = 0o700;
8
+ const FILE_MODE = 0o600;
9
+ export function configDir() {
10
+ const override = process.env.COOLHAND_CONFIG_DIR;
11
+ if (override) {
12
+ return override;
13
+ }
14
+ return path.join(os.homedir(), '.coolhand');
15
+ }
16
+ export function configPath() {
17
+ return path.join(configDir(), CONFIG_FILENAME);
18
+ }
19
+ function emptyConfig() {
20
+ return { version: 1, default_client_id: null, clients: {} };
21
+ }
22
+ export async function loadConfig() {
23
+ const filePath = configPath();
24
+ let raw;
25
+ try {
26
+ raw = await fs.readFile(filePath, 'utf8');
27
+ }
28
+ catch (err) {
29
+ const e = err;
30
+ if (e.code === 'ENOENT') {
31
+ return emptyConfig();
32
+ }
33
+ throw new CliError('CONFIG_READ_FAILED', `Failed to read ${filePath}: ${e.message}`);
34
+ }
35
+ try {
36
+ const parsed = JSON.parse(raw);
37
+ return {
38
+ version: 1,
39
+ default_client_id: parsed.default_client_id ?? null,
40
+ clients: parsed.clients ?? {},
41
+ };
42
+ }
43
+ catch (err) {
44
+ throw new CliError('CONFIG_READ_FAILED', `Config file at ${filePath} is not valid JSON: ${err.message}`);
45
+ }
46
+ }
47
+ async function ensureDir(dir) {
48
+ await fs.mkdir(dir, { recursive: true, mode: DIR_MODE });
49
+ try {
50
+ await fs.chmod(dir, DIR_MODE);
51
+ }
52
+ catch {
53
+ // POSIX-only — Windows will reject chmod with the mode we passed; ignore.
54
+ }
55
+ }
56
+ export async function saveConfig(cfg) {
57
+ const filePath = configPath();
58
+ const dir = path.dirname(filePath);
59
+ await ensureDir(dir);
60
+ const tmpPath = path.join(dir, `.${path.basename(filePath)}.${randomBytes(6).toString('hex')}.tmp`);
61
+ const data = `${JSON.stringify(cfg, null, 2)}\n`;
62
+ try {
63
+ await fs.writeFile(tmpPath, data, { mode: FILE_MODE });
64
+ await fs.rename(tmpPath, filePath);
65
+ try {
66
+ await fs.chmod(filePath, FILE_MODE);
67
+ }
68
+ catch {
69
+ // ignore on Windows
70
+ }
71
+ }
72
+ catch (err) {
73
+ await fs.rm(tmpPath, { force: true }).catch(() => undefined);
74
+ throw new CliError('CONFIG_WRITE_FAILED', `Failed to write ${filePath}: ${err.message}`);
75
+ }
76
+ }
77
+ export async function deleteConfig() {
78
+ try {
79
+ await fs.rm(configPath(), { force: true });
80
+ }
81
+ catch (err) {
82
+ throw new CliError('CONFIG_WRITE_FAILED', `Failed to delete config: ${err.message}`);
83
+ }
84
+ }
85
+ export function getClient(cfg, clientId) {
86
+ const id = clientId ?? cfg.default_client_id;
87
+ if (!id) {
88
+ return undefined;
89
+ }
90
+ return cfg.clients[id];
91
+ }
92
+ export async function upsertClient(entry, makeDefault = true) {
93
+ const cfg = await loadConfig();
94
+ cfg.clients[entry.client_id] = entry;
95
+ if (makeDefault || !cfg.default_client_id) {
96
+ cfg.default_client_id = entry.client_id;
97
+ }
98
+ await saveConfig(cfg);
99
+ return cfg;
100
+ }
101
+ export async function removeClient(clientId) {
102
+ const cfg = await loadConfig();
103
+ if (!cfg.clients[clientId]) {
104
+ return cfg;
105
+ }
106
+ delete cfg.clients[clientId];
107
+ const remaining = Object.keys(cfg.clients);
108
+ if (remaining.length === 0) {
109
+ await deleteConfig();
110
+ return null;
111
+ }
112
+ if (cfg.default_client_id === clientId) {
113
+ cfg.default_client_id = remaining[0];
114
+ }
115
+ await saveConfig(cfg);
116
+ return cfg;
117
+ }
118
+ export async function setDefault(clientId) {
119
+ const cfg = await loadConfig();
120
+ if (!cfg.clients[clientId]) {
121
+ throw new CliError('CLIENT_NOT_FOUND', `No client with id "${clientId}" is configured.`);
122
+ }
123
+ cfg.default_client_id = clientId;
124
+ await saveConfig(cfg);
125
+ return cfg;
126
+ }
127
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ export interface WriteEnvResult {
2
+ created: boolean;
3
+ replaced: boolean;
4
+ path: string;
5
+ }
6
+ /**
7
+ * Idempotently sets `key=value` in the env file at `envPath`.
8
+ * Creates the file if missing. Replaces an existing line matching
9
+ * `^\s*KEY\s*=` while preserving comments, whitespace, and other variables.
10
+ */
11
+ export declare function writeEnvKey(envPath: string, key: string, value: string): Promise<WriteEnvResult>;
12
+ //# sourceMappingURL=env-file.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-file.d.ts","sourceRoot":"","sources":["../src/env-file.ts"],"names":[],"mappings":"AAKA,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,QAAQ,EAAE,OAAO,CAAC;IAClB,IAAI,EAAE,MAAM,CAAC;CACd;AAED;;;;GAIG;AACH,wBAAsB,WAAW,CAAC,OAAO,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC,CAmDtG"}
@@ -0,0 +1,62 @@
1
+ import { promises as fs } from 'fs';
2
+ import * as path from 'path';
3
+ import { randomBytes } from 'crypto';
4
+ import { CliError } from './errors.js';
5
+ /**
6
+ * Idempotently sets `key=value` in the env file at `envPath`.
7
+ * Creates the file if missing. Replaces an existing line matching
8
+ * `^\s*KEY\s*=` while preserving comments, whitespace, and other variables.
9
+ */
10
+ export async function writeEnvKey(envPath, key, value) {
11
+ if (!/^[A-Z_][A-Z0-9_]*$/i.test(key)) {
12
+ throw new CliError('WRITE_ENV_FAILED', `Invalid env key: ${key}`);
13
+ }
14
+ const resolved = path.resolve(envPath);
15
+ let existing = '';
16
+ let created = false;
17
+ try {
18
+ existing = await fs.readFile(resolved, 'utf8');
19
+ }
20
+ catch (err) {
21
+ const e = err;
22
+ if (e.code !== 'ENOENT') {
23
+ throw new CliError('WRITE_ENV_FAILED', `Cannot read ${resolved}: ${e.message}`);
24
+ }
25
+ created = true;
26
+ }
27
+ const lines = existing === '' ? [] : existing.split(/\r?\n/);
28
+ const matchRegex = new RegExp(`^\\s*${key}\\s*=`);
29
+ let replaced = false;
30
+ const out = [];
31
+ for (const line of lines) {
32
+ if (!replaced && matchRegex.test(line)) {
33
+ out.push(`${key}=${value}`);
34
+ replaced = true;
35
+ }
36
+ else {
37
+ out.push(line);
38
+ }
39
+ }
40
+ if (!replaced) {
41
+ if (out.length > 0 && out[out.length - 1] === '') {
42
+ out.splice(out.length - 1, 0, `${key}=${value}`);
43
+ }
44
+ else {
45
+ out.push(`${key}=${value}`);
46
+ out.push('');
47
+ }
48
+ }
49
+ const next = out.join('\n');
50
+ const dir = path.dirname(resolved);
51
+ const tmpPath = path.join(dir, `.${path.basename(resolved)}.${randomBytes(6).toString('hex')}.tmp`);
52
+ try {
53
+ await fs.writeFile(tmpPath, next, { mode: 0o600 });
54
+ await fs.rename(tmpPath, resolved);
55
+ }
56
+ catch (err) {
57
+ await fs.rm(tmpPath, { force: true }).catch(() => undefined);
58
+ throw new CliError('WRITE_ENV_FAILED', `Failed to write ${resolved}: ${err.message}`);
59
+ }
60
+ return { created, replaced, path: resolved };
61
+ }
62
+ //# sourceMappingURL=env-file.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"env-file.js","sourceRoot":"","sources":["../src/env-file.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,13 @@
1
+ export declare enum ExitCode {
2
+ OK = 0,
3
+ USER_ERROR = 1,
4
+ INTERNAL = 2,
5
+ ABORTED = 130
6
+ }
7
+ export type ErrorCode = 'TIMEOUT' | 'STATE_MISMATCH' | 'INVALID_CALLBACK' | 'BROWSER_FAILED' | 'CONFIG_WRITE_FAILED' | 'CONFIG_READ_FAILED' | 'NOT_CONFIGURED' | 'INVALID_REDIRECT_URI' | 'INVALID_BASE_URL' | 'INVALID_ARGS' | 'WRITE_ENV_FAILED' | 'CLIENT_NOT_FOUND';
8
+ export declare class CliError extends Error {
9
+ readonly code: ErrorCode;
10
+ readonly exitCode: number;
11
+ constructor(code: ErrorCode, message: string, exitCode?: number);
12
+ }
13
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,oBAAY,QAAQ;IAClB,EAAE,IAAI;IACN,UAAU,IAAI;IACd,QAAQ,IAAI;IACZ,OAAO,MAAM;CACd;AAED,MAAM,MAAM,SAAS,GACjB,SAAS,GACT,gBAAgB,GAChB,kBAAkB,GAClB,gBAAgB,GAChB,qBAAqB,GACrB,oBAAoB,GACpB,gBAAgB,GAChB,sBAAsB,GACtB,kBAAkB,GAClB,cAAc,GACd,kBAAkB,GAClB,kBAAkB,CAAC;AAEvB,qBAAa,QAAS,SAAQ,KAAK;IACjC,SAAgB,IAAI,EAAE,SAAS,CAAC;IAChC,SAAgB,QAAQ,EAAE,MAAM,CAAC;gBAErB,IAAI,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,QAAQ,GAAE,MAA4B;CAMrF"}
package/dist/errors.js ADDED
@@ -0,0 +1,16 @@
1
+ export var ExitCode;
2
+ (function (ExitCode) {
3
+ ExitCode[ExitCode["OK"] = 0] = "OK";
4
+ ExitCode[ExitCode["USER_ERROR"] = 1] = "USER_ERROR";
5
+ ExitCode[ExitCode["INTERNAL"] = 2] = "INTERNAL";
6
+ ExitCode[ExitCode["ABORTED"] = 130] = "ABORTED";
7
+ })(ExitCode || (ExitCode = {}));
8
+ export class CliError extends Error {
9
+ constructor(code, message, exitCode = ExitCode.USER_ERROR) {
10
+ super(message);
11
+ this.name = 'CliError';
12
+ this.code = code;
13
+ this.exitCode = exitCode;
14
+ }
15
+ }
16
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA,MAAM,CAAN,IAAY,QAKX;AALD,WAAY,QAAQ;IAClB,mCAAM,CAAA;IACN,mDAAc,CAAA;IACd,+CAAY,CAAA;IACZ,+CAAa,CAAA;AACf,CAAC,EALW,QAAQ,KAAR,QAAQ,QAKnB;AAgBD,MAAM,OAAO,QAAS,SAAQ,KAAK;IAIjC,YAAY,IAAe,EAAE,OAAe,EAAE,WAAmB,QAAQ,CAAC,UAAU;QAClF,KAAK,CAAC,OAAO,CAAC,CAAC;QACf,IAAI,CAAC,IAAI,GAAG,UAAU,CAAC;QACvB,IAAI,CAAC,IAAI,GAAG,IAAI,CAAC;QACjB,IAAI,CAAC,QAAQ,GAAG,QAAQ,CAAC;IAC3B,CAAC;CACF"}
@@ -0,0 +1,7 @@
1
+ export { run, parseArgs } from './cli.js';
2
+ export { loadConfig, saveConfig, deleteConfig, getClient, upsertClient, removeClient, setDefault, configPath, configDir, } from './config.js';
3
+ export { maskToken } from './mask.js';
4
+ export { CliError, ExitCode } from './errors.js';
5
+ export { PACKAGE_VERSION, PACKAGE_NAME } from './version.js';
6
+ export type { ClientEntry, ConfigFile, LoginOptions, LogoutOptions, StatusOptions, WhoamiOptions, ClientsOptions, CallbackResult, StatusOutput, } from './types.js';
7
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EACL,UAAU,EACV,UAAU,EACV,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,UAAU,EACV,SAAS,GACV,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAC7D,YAAY,EACV,WAAW,EACX,UAAU,EACV,YAAY,EACZ,aAAa,EACb,aAAa,EACb,aAAa,EACb,cAAc,EACd,cAAc,EACd,YAAY,GACb,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,6 @@
1
+ export { run, parseArgs } from './cli.js';
2
+ export { loadConfig, saveConfig, deleteConfig, getClient, upsertClient, removeClient, setDefault, configPath, configDir, } from './config.js';
3
+ export { maskToken } from './mask.js';
4
+ export { CliError, ExitCode } from './errors.js';
5
+ export { PACKAGE_VERSION, PACKAGE_NAME } from './version.js';
6
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EACL,UAAU,EACV,UAAU,EACV,YAAY,EACZ,SAAS,EACT,YAAY,EACZ,YAAY,EACZ,UAAU,EACV,UAAU,EACV,SAAS,GACV,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,SAAS,EAAE,MAAM,WAAW,CAAC;AACtC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC"}
@@ -0,0 +1,8 @@
1
+ export declare function redact(text: string): string;
2
+ export interface Logger {
3
+ info(message: string): void;
4
+ warn(message: string): void;
5
+ json(payload: unknown): void;
6
+ }
7
+ export declare const logger: Logger;
8
+ //# sourceMappingURL=logger.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.d.ts","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAYA,wBAAgB,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED,MAAM,WAAW,MAAM;IACrB,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,IAAI,CAAC,OAAO,EAAE,OAAO,GAAG,IAAI,CAAC;CAC9B;AAcD,eAAO,MAAM,MAAM,EAAE,MAIpB,CAAC"}
package/dist/logger.js ADDED
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Strips anything that looks like a Coolhand API key from a string, so we never
3
+ * inadvertently log a raw token through an error message. Real tokens are raw
4
+ * 64-char hex strings; this pattern also catches longer hex (forwards-compat)
5
+ * and the legacy `ch_pub_…` form, with low false-positive risk (redacting an
6
+ * unrelated 40+ hex SHA in an error message is harmless).
7
+ */
8
+ const TOKEN_PATTERNS = [
9
+ /\b[a-f0-9]{40,}\b/gi,
10
+ /ch_pub_[A-Za-z0-9_-]{8,}/g,
11
+ ];
12
+ export function redact(text) {
13
+ return TOKEN_PATTERNS.reduce((acc, pattern) => acc.replace(pattern, 'REDACTED'), text);
14
+ }
15
+ function defaultInfo(message) {
16
+ process.stderr.write(`${redact(message)}\n`);
17
+ }
18
+ function defaultWarn(message) {
19
+ process.stderr.write(`${redact(message)}\n`);
20
+ }
21
+ function defaultJson(payload) {
22
+ process.stdout.write(`${JSON.stringify(payload)}\n`);
23
+ }
24
+ export const logger = {
25
+ info: defaultInfo,
26
+ warn: defaultWarn,
27
+ json: defaultJson,
28
+ };
29
+ //# sourceMappingURL=logger.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"logger.js","sourceRoot":"","sources":["../src/logger.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,MAAM,cAAc,GAA0B;IAC5C,qBAAqB;IACrB,2BAA2B;CAC5B,CAAC;AAEF,MAAM,UAAU,MAAM,CAAC,IAAY;IACjC,OAAO,cAAc,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,OAAO,EAAE,EAAE,CAAC,GAAG,CAAC,OAAO,CAAC,OAAO,EAAE,UAAU,CAAC,EAAE,IAAI,CAAC,CAAC;AACzF,CAAC;AAQD,SAAS,WAAW,CAAC,OAAe;IAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,WAAW,CAAC,OAAe;IAClC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,WAAW,CAAC,OAAgB;IACnC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAW;IAC5B,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,WAAW;IACjB,IAAI,EAAE,WAAW;CAClB,CAAC"}
package/dist/mask.d.ts ADDED
@@ -0,0 +1,7 @@
1
+ /**
2
+ * Returns a non-secret representation of an API token suitable for display.
3
+ * For tokens longer than 16 characters, returns the first 8 and last 4
4
+ * separated by an ellipsis. Shorter values are fully masked.
5
+ */
6
+ export declare function maskToken(token: string): string;
7
+ //# sourceMappingURL=mask.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"mask.d.ts","sourceRoot":"","sources":["../src/mask.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,wBAAgB,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,CAK/C"}