@urugus/slack-cli 0.2.9 → 0.2.10

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 (52) hide show
  1. package/.claude/settings.local.json +60 -14
  2. package/README.md +8 -0
  3. package/dist/commands/send.d.ts.map +1 -1
  4. package/dist/commands/send.js +16 -2
  5. package/dist/commands/send.js.map +1 -1
  6. package/dist/index.js +0 -0
  7. package/dist/types/commands.d.ts +2 -0
  8. package/dist/types/commands.d.ts.map +1 -1
  9. package/dist/utils/config.d.ts +10 -0
  10. package/dist/utils/config.d.ts.map +1 -0
  11. package/dist/utils/config.js +94 -0
  12. package/dist/utils/config.js.map +1 -0
  13. package/dist/utils/constants.d.ts +5 -0
  14. package/dist/utils/constants.d.ts.map +1 -1
  15. package/dist/utils/constants.js +5 -0
  16. package/dist/utils/constants.js.map +1 -1
  17. package/dist/utils/formatters/output-formatter.d.ts +7 -0
  18. package/dist/utils/formatters/output-formatter.d.ts.map +1 -0
  19. package/dist/utils/formatters/output-formatter.js +7 -0
  20. package/dist/utils/formatters/output-formatter.js.map +1 -0
  21. package/dist/utils/profile-config-refactored.d.ts +20 -0
  22. package/dist/utils/profile-config-refactored.d.ts.map +1 -0
  23. package/dist/utils/profile-config-refactored.js +174 -0
  24. package/dist/utils/profile-config-refactored.js.map +1 -0
  25. package/dist/utils/schedule-utils.d.ts +3 -0
  26. package/dist/utils/schedule-utils.d.ts.map +1 -0
  27. package/dist/utils/schedule-utils.js +34 -0
  28. package/dist/utils/schedule-utils.js.map +1 -0
  29. package/dist/utils/slack-api-client.d.ts +2 -1
  30. package/dist/utils/slack-api-client.d.ts.map +1 -1
  31. package/dist/utils/slack-api-client.js +3 -0
  32. package/dist/utils/slack-api-client.js.map +1 -1
  33. package/dist/utils/slack-operations/message-operations.d.ts +2 -1
  34. package/dist/utils/slack-operations/message-operations.d.ts.map +1 -1
  35. package/dist/utils/slack-operations/message-operations.js +11 -0
  36. package/dist/utils/slack-operations/message-operations.js.map +1 -1
  37. package/dist/utils/validators.d.ts +4 -0
  38. package/dist/utils/validators.d.ts.map +1 -1
  39. package/dist/utils/validators.js +31 -0
  40. package/dist/utils/validators.js.map +1 -1
  41. package/package.json +2 -2
  42. package/src/commands/send.ts +21 -3
  43. package/src/types/commands.ts +2 -0
  44. package/src/utils/constants.ts +7 -0
  45. package/src/utils/schedule-utils.ts +41 -0
  46. package/src/utils/slack-api-client.ts +10 -1
  47. package/src/utils/slack-operations/message-operations.ts +25 -1
  48. package/src/utils/validators.ts +38 -0
  49. package/tests/commands/send.test.ts +235 -44
  50. package/tests/utils/schedule-utils.test.ts +63 -0
  51. package/tests/utils/slack-api-client.test.ts +18 -1
  52. package/tests/utils/slack-operations/message-operations.test.ts +19 -1
@@ -1,29 +1,75 @@
1
1
  {
2
2
  "permissions": {
3
3
  "allow": [
4
+ "Bash(mkdir:*)",
5
+ "Bash(ls:*)",
6
+ "Bash(npm install)",
7
+ "Bash(npm run test:*)",
4
8
  "Bash(find:*)",
5
- "Bash(npm install:*)",
6
- "Bash(gh issue list:*)",
7
- "Bash(gh pr list:*)",
8
- "Bash(gh pr checkout:*)",
9
9
  "Bash(npm test)",
10
- "Bash(npm run lint)",
11
10
  "Bash(npm run build:*)",
11
+ "Bash(npm run lint)",
12
+ "Bash(npm run format:check:*)",
13
+ "Bash(npm run format:*)",
14
+ "Bash(npm test:*)",
15
+ "Bash(node:*)",
12
16
  "Bash(git add:*)",
13
17
  "Bash(git commit:*)",
18
+ "Bash(grep:*)",
19
+ "Bash(true)",
20
+ "Bash(npx vitest run:*)",
21
+ "Bash(NODE_ENV=test npx vitest run --reporter=tap 2 >& 1)",
22
+ "Bash(npm ls:*)",
23
+ "Bash(/opt/homebrew/bin/slack-cli config:*)",
24
+ "Bash(npm bin:*)",
25
+ "Bash(npm root:*)",
26
+ "Bash(strace:*)",
27
+ "Bash(npx vitest list:*)",
28
+ "Bash(NODE_OPTIONS=\"--trace-warnings\" npx vitest run --no-threads 2 >& 1)",
29
+ "Bash(NODE_ENV=test npx vitest run --reporter=tap tests/commands/config.test.ts 2 >& 1)",
30
+ "Bash(echo:*)",
31
+ "Bash(git reset:*)",
32
+ "Bash(npm uninstall:*)",
33
+ "Bash(pkill:*)",
34
+ "Bash(/opt/homebrew/bin/slack:*)",
35
+ "Bash(brew list:*)",
36
+ "Bash(brew info:*)",
37
+ "Bash(npm link:*)",
38
+ "Bash(slack-cli:*)",
14
39
  "Bash(git push:*)",
15
- "Bash(git config:*)",
16
- "Bash(gh pr view:*)",
40
+ "Bash(gh run list:*)",
17
41
  "Bash(gh run view:*)",
42
+ "Bash(gh run watch:*)",
43
+ "Bash(cat:*)",
44
+ "Bash(mv:*)",
45
+ "Bash(rm:*)",
46
+ "WebFetch(domain:api.slack.com)",
47
+ "Bash(npm run typecheck:*)",
48
+ "Bash(npm run:*)",
49
+ "Bash(npm whoami:*)",
50
+ "Bash(npm unlink:*)",
51
+ "Bash(npm update:*)",
52
+ "Bash(npm install:*)",
53
+ "Bash(npm view:*)",
54
+ "Bash(npm publish:*)",
55
+ "Bash(rg:*)",
56
+ "Bash(npm version:*)",
57
+ "Bash(npx tsx:*)",
58
+ "Bash(gh workflow view:*)",
59
+ "Bash(git tag:*)",
60
+ "Bash(./bin/dev:*)",
18
61
  "Bash(git checkout:*)",
62
+ "Bash(gh pr create:*)",
63
+ "Bash(gh pr checks:*)",
64
+ "Bash(gh pr view:*)",
65
+ "Bash(gh pr merge:*)",
19
66
  "Bash(git pull:*)",
20
- "Bash(git rebase:*)",
21
- "WebFetch(domain:github.com)",
22
- "Bash(rm:*)",
23
- "Bash(gh pr comment:*)",
24
- "Bash(gh pr close:*)",
25
- "Bash(npm publish:*)"
67
+ "Bash(gh api graphql:*)",
68
+ "mcp__slack__slack_list_channels",
69
+ "Bash(curl -X GET 'https://slack.com/api/conversations.members?channel=C02EHQ7TG68&limit=100' -H 'Authorization: Bearer xoxe.xoxp-1-Mi0yLTIxNjQ2MDk0NzItNzY4NTQ0NzAyNTM2MC04NzE0NzA4NDQ1NTcyLTkwODMxMzU5MDAwODItZTNjMDUyZjEwMzZhMDJhYzFlNTU5YjczNmE3MWFkODg0NDAzZDdiYmI5YTBjZDc4MzQ3MjJkZGE4ODFkZDYxMw')",
70
+ "Bash(curl -X GET 'https://slack.com/api/conversations.members?channel=C02EHQ7TG68&limit=100' -H 'Authorization: Bearer xoxb-2164609472-8861111830563-KKbispuxfw36K2YuIbnjgbT2')",
71
+ "Bash(curl -X GET 'https://slack.com/api/users.info?user=U07L5D50RAL' -H 'Authorization: Bearer xoxb-2164609472-8861111830563-KKbispuxfw36K2YuIbnjgbT2')"
26
72
  ],
27
73
  "deny": []
28
74
  }
29
- }
75
+ }
package/README.md CHANGED
@@ -64,6 +64,12 @@ slack-cli send -c channel-name -m "Reply message" --thread 1719207629.000100
64
64
 
65
65
  # Reply to a thread (short option)
66
66
  slack-cli send -c channel-name -m "Reply message" -t 1719207629.000100
67
+
68
+ # Schedule by absolute time (Unix seconds or ISO 8601)
69
+ slack-cli send -c channel-name -m "Scheduled message" --at "2026-03-01T09:00:00Z"
70
+
71
+ # Schedule after N minutes
72
+ slack-cli send -c channel-name -m "Scheduled message" --after 30
67
73
  ```
68
74
 
69
75
  ### List Channels
@@ -167,6 +173,8 @@ slack-cli config set --token NEW_TOKEN
167
173
  | --message | -m | Message to send |
168
174
  | --file | -f | File containing message content |
169
175
  | --thread | -t | Thread timestamp to reply to |
176
+ | --at | | Schedule time (Unix seconds or ISO 8601) |
177
+ | --after | | Schedule message after N minutes |
170
178
 
171
179
  ### channels command
172
180
  | Option | Short | Description |
@@ -1 +1 @@
1
- {"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../../src/commands/send.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAYpC,wBAAgB,gBAAgB,IAAI,OAAO,CAsC1C"}
1
+ {"version":3,"file":"send.d.ts","sourceRoot":"","sources":["../../src/commands/send.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAapC,wBAAgB,gBAAgB,IAAI,OAAO,CAuD1C"}
@@ -46,16 +46,23 @@ const errors_1 = require("../utils/errors");
46
46
  const error_utils_1 = require("../utils/error-utils");
47
47
  const option_parsers_1 = require("../utils/option-parsers");
48
48
  const validators_1 = require("../utils/validators");
49
+ const schedule_utils_1 = require("../utils/schedule-utils");
49
50
  const fs = __importStar(require("fs/promises"));
50
51
  function setupSendCommand() {
51
52
  const sendCommand = new commander_1.Command('send')
52
- .description('Send a message to a Slack channel')
53
+ .description('Send or schedule a message to a Slack channel')
53
54
  .requiredOption('-c, --channel <channel>', 'Target channel name or ID')
54
55
  .option('-m, --message <message>', 'Message to send')
55
56
  .option('-f, --file <file>', 'File containing message content')
56
57
  .option('-t, --thread <thread>', 'Thread timestamp to reply to')
58
+ .option('--at <time>', 'Schedule time (Unix timestamp in seconds or ISO 8601)')
59
+ .option('--after <minutes>', 'Schedule message after N minutes')
57
60
  .option('--profile <profile>', 'Use specific workspace profile')
58
- .hook('preAction', (0, validators_1.createValidationHook)([validators_1.optionValidators.messageOrFile, validators_1.optionValidators.threadTimestamp]))
61
+ .hook('preAction', (0, validators_1.createValidationHook)([
62
+ validators_1.optionValidators.messageOrFile,
63
+ validators_1.optionValidators.threadTimestamp,
64
+ validators_1.optionValidators.scheduleTiming,
65
+ ]))
59
66
  .action((0, command_wrapper_1.wrapCommand)(async (options) => {
60
67
  // Get message content
61
68
  let messageContent;
@@ -70,9 +77,16 @@ function setupSendCommand() {
70
77
  else {
71
78
  messageContent = options.message; // This is safe because of preAction validation
72
79
  }
80
+ const postAt = (0, schedule_utils_1.resolvePostAt)(options.at, options.after);
73
81
  // Send message
74
82
  const profile = (0, option_parsers_1.parseProfile)(options.profile);
75
83
  const client = await (0, client_factory_1.createSlackClient)(profile);
84
+ if (postAt !== null) {
85
+ await client.scheduleMessage(options.channel, messageContent, postAt, options.thread);
86
+ const postAtIso = new Date(postAt * 1000).toISOString();
87
+ console.log(chalk_1.default.green(`✓ ${constants_1.SUCCESS_MESSAGES.MESSAGE_SCHEDULED(options.channel, postAtIso)}`));
88
+ return;
89
+ }
76
90
  await client.sendMessage(options.channel, messageContent, options.thread);
77
91
  console.log(chalk_1.default.green(`✓ ${constants_1.SUCCESS_MESSAGES.MESSAGE_SENT(options.channel)}`));
78
92
  }));
@@ -1 +1 @@
1
- {"version":3,"file":"send.js","sourceRoot":"","sources":["../../src/commands/send.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAYA,4CAsCC;AAlDD,yCAAoC;AACpC,kDAA0B;AAC1B,8DAAuD;AACvD,kDAAsE;AACtE,4DAA4D;AAC5D,4CAA4C;AAE5C,sDAA2D;AAC3D,4DAAuD;AACvD,oDAA6E;AAC7E,gDAAkC;AAElC,SAAgB,gBAAgB;IAC9B,MAAM,WAAW,GAAG,IAAI,mBAAO,CAAC,MAAM,CAAC;SACpC,WAAW,CAAC,mCAAmC,CAAC;SAChD,cAAc,CAAC,yBAAyB,EAAE,2BAA2B,CAAC;SACtE,MAAM,CAAC,yBAAyB,EAAE,iBAAiB,CAAC;SACpD,MAAM,CAAC,mBAAmB,EAAE,iCAAiC,CAAC;SAC9D,MAAM,CAAC,uBAAuB,EAAE,8BAA8B,CAAC;SAC/D,MAAM,CAAC,qBAAqB,EAAE,gCAAgC,CAAC;SAC/D,IAAI,CACH,WAAW,EACX,IAAA,iCAAoB,EAAC,CAAC,6BAAgB,CAAC,aAAa,EAAE,6BAAgB,CAAC,eAAe,CAAC,CAAC,CACzF;SACA,MAAM,CACL,IAAA,6BAAW,EAAC,KAAK,EAAE,OAAoB,EAAE,EAAE;QACzC,sBAAsB;QACtB,IAAI,cAAsB,CAAC;QAC3B,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,IAAI,CAAC;gBACH,cAAc,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC5D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,IAAI,kBAAS,CACjB,0BAAc,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,EAAE,IAAA,iCAAmB,EAAC,KAAK,CAAC,CAAC,CACzE,CAAC;YACJ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,cAAc,GAAG,OAAO,CAAC,OAAQ,CAAC,CAAC,+CAA+C;QACpF,CAAC;QAED,eAAe;QACf,MAAM,OAAO,GAAG,IAAA,6BAAY,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,MAAM,IAAA,kCAAiB,EAAC,OAAO,CAAC,CAAC;QAChD,MAAM,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAE1E,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,KAAK,4BAAgB,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;IAClF,CAAC,CAAC,CACH,CAAC;IAEJ,OAAO,WAAW,CAAC;AACrB,CAAC"}
1
+ {"version":3,"file":"send.js","sourceRoot":"","sources":["../../src/commands/send.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAaA,4CAuDC;AApED,yCAAoC;AACpC,kDAA0B;AAC1B,8DAAuD;AACvD,kDAAsE;AACtE,4DAA4D;AAC5D,4CAA4C;AAE5C,sDAA2D;AAC3D,4DAAuD;AACvD,oDAA6E;AAC7E,4DAAwD;AACxD,gDAAkC;AAElC,SAAgB,gBAAgB;IAC9B,MAAM,WAAW,GAAG,IAAI,mBAAO,CAAC,MAAM,CAAC;SACpC,WAAW,CAAC,+CAA+C,CAAC;SAC5D,cAAc,CAAC,yBAAyB,EAAE,2BAA2B,CAAC;SACtE,MAAM,CAAC,yBAAyB,EAAE,iBAAiB,CAAC;SACpD,MAAM,CAAC,mBAAmB,EAAE,iCAAiC,CAAC;SAC9D,MAAM,CAAC,uBAAuB,EAAE,8BAA8B,CAAC;SAC/D,MAAM,CAAC,aAAa,EAAE,uDAAuD,CAAC;SAC9E,MAAM,CAAC,mBAAmB,EAAE,kCAAkC,CAAC;SAC/D,MAAM,CAAC,qBAAqB,EAAE,gCAAgC,CAAC;SAC/D,IAAI,CACH,WAAW,EACX,IAAA,iCAAoB,EAAC;QACnB,6BAAgB,CAAC,aAAa;QAC9B,6BAAgB,CAAC,eAAe;QAChC,6BAAgB,CAAC,cAAc;KAChC,CAAC,CACH;SACA,MAAM,CACL,IAAA,6BAAW,EAAC,KAAK,EAAE,OAAoB,EAAE,EAAE;QACzC,sBAAsB;QACtB,IAAI,cAAsB,CAAC;QAC3B,IAAI,OAAO,CAAC,IAAI,EAAE,CAAC;YACjB,IAAI,CAAC;gBACH,cAAc,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,OAAO,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;YAC5D,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,IAAI,kBAAS,CACjB,0BAAc,CAAC,eAAe,CAAC,OAAO,CAAC,IAAI,EAAE,IAAA,iCAAmB,EAAC,KAAK,CAAC,CAAC,CACzE,CAAC;YACJ,CAAC;QACH,CAAC;aAAM,CAAC;YACN,cAAc,GAAG,OAAO,CAAC,OAAQ,CAAC,CAAC,+CAA+C;QACpF,CAAC;QAED,MAAM,MAAM,GAAG,IAAA,8BAAa,EAAC,OAAO,CAAC,EAAE,EAAE,OAAO,CAAC,KAAK,CAAC,CAAC;QAExD,eAAe;QACf,MAAM,OAAO,GAAG,IAAA,6BAAY,EAAC,OAAO,CAAC,OAAO,CAAC,CAAC;QAC9C,MAAM,MAAM,GAAG,MAAM,IAAA,kCAAiB,EAAC,OAAO,CAAC,CAAC;QAEhD,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;YACpB,MAAM,MAAM,CAAC,eAAe,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;YACtF,MAAM,SAAS,GAAG,IAAI,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YACxD,OAAO,CAAC,GAAG,CACT,eAAK,CAAC,KAAK,CAAC,KAAK,4BAAgB,CAAC,iBAAiB,CAAC,OAAO,CAAC,OAAO,EAAE,SAAS,CAAC,EAAE,CAAC,CACnF,CAAC;YACF,OAAO;QACT,CAAC;QAED,MAAM,MAAM,CAAC,WAAW,CAAC,OAAO,CAAC,OAAO,EAAE,cAAc,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC;QAC1E,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,KAAK,4BAAgB,CAAC,YAAY,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC;IAClF,CAAC,CAAC,CACH,CAAC;IAEJ,OAAO,WAAW,CAAC;AACrB,CAAC"}
package/dist/index.js CHANGED
File without changes
@@ -16,6 +16,8 @@ export interface SendOptions {
16
16
  message?: string;
17
17
  file?: string;
18
18
  thread?: string;
19
+ at?: string;
20
+ after?: string;
19
21
  profile?: string;
20
22
  }
21
23
  export interface ChannelsOptions {
@@ -1 +1 @@
1
- {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/types/commands.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,KAAK,CAAC;IACnD,eAAe,EAAE,OAAO,CAAC;IACzB,MAAM,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
1
+ {"version":3,"file":"commands.d.ts","sourceRoot":"","sources":["../../src/types/commands.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,gBAAgB;IAC/B,OAAO,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,kBAAkB;IACjC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,WAAW;IAC1B,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,QAAQ,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,KAAK,CAAC;IACnD,eAAe,EAAE,OAAO,CAAC;IACzB,MAAM,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IACpC,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,cAAc;IAC7B,OAAO,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,aAAa;IAC5B,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,MAAM,CAAC,EAAE,OAAO,GAAG,QAAQ,GAAG,MAAM,CAAC;IACrC,SAAS,CAAC,EAAE,OAAO,CAAC;IACpB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB"}
@@ -0,0 +1,10 @@
1
+ import type { Config, ConfigOptions } from '../types/config';
2
+ export declare class ConfigManager {
3
+ private configPath;
4
+ constructor(options?: ConfigOptions);
5
+ setToken(token: string): Promise<void>;
6
+ getConfig(): Promise<Config | null>;
7
+ clearConfig(): Promise<void>;
8
+ maskToken(token: string): string;
9
+ }
10
+ //# sourceMappingURL=config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAE7D,qBAAa,aAAa;IACxB,OAAO,CAAC,UAAU,CAAS;gBAEf,OAAO,GAAE,aAAkB;IAKjC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAatC,SAAS,IAAI,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAqBnC,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC;IAUlC,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;CAUjC"}
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.ConfigManager = void 0;
37
+ const fs = __importStar(require("fs/promises"));
38
+ const path = __importStar(require("path"));
39
+ const os = __importStar(require("os"));
40
+ class ConfigManager {
41
+ constructor(options = {}) {
42
+ const configDir = options.configDir || path.join(os.homedir(), '.slack-cli');
43
+ this.configPath = path.join(configDir, 'config.json');
44
+ }
45
+ async setToken(token) {
46
+ const config = {
47
+ token,
48
+ updatedAt: new Date().toISOString(),
49
+ };
50
+ const configDir = path.dirname(this.configPath);
51
+ await fs.mkdir(configDir, { recursive: true });
52
+ await fs.writeFile(this.configPath, JSON.stringify(config, null, 2));
53
+ await fs.chmod(this.configPath, 0o600);
54
+ }
55
+ async getConfig() {
56
+ try {
57
+ const data = await fs.readFile(this.configPath, 'utf-8');
58
+ const config = JSON.parse(data);
59
+ if (!config.token || !config.updatedAt) {
60
+ throw new Error('Invalid config file format');
61
+ }
62
+ return config;
63
+ }
64
+ catch (error) {
65
+ if (error && typeof error === 'object' && 'code' in error && error.code === 'ENOENT') {
66
+ return null;
67
+ }
68
+ if (error instanceof SyntaxError) {
69
+ throw new Error('Invalid config file format');
70
+ }
71
+ throw error;
72
+ }
73
+ }
74
+ async clearConfig() {
75
+ try {
76
+ await fs.unlink(this.configPath);
77
+ }
78
+ catch (error) {
79
+ if (error && typeof error === 'object' && 'code' in error && error.code !== 'ENOENT') {
80
+ throw error;
81
+ }
82
+ }
83
+ }
84
+ maskToken(token) {
85
+ if (token.length <= 9) {
86
+ return '****';
87
+ }
88
+ const prefix = token.substring(0, 4);
89
+ const suffix = token.substring(token.length - 4);
90
+ return `${prefix}-****-****-${suffix}`;
91
+ }
92
+ }
93
+ exports.ConfigManager = ConfigManager;
94
+ //# sourceMappingURL=config.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config.js","sourceRoot":"","sources":["../../src/utils/config.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,gDAAkC;AAClC,2CAA6B;AAC7B,uCAAyB;AAGzB,MAAa,aAAa;IAGxB,YAAY,UAAyB,EAAE;QACrC,MAAM,SAAS,GAAG,OAAO,CAAC,SAAS,IAAI,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,OAAO,EAAE,EAAE,YAAY,CAAC,CAAC;QAC7E,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC;IACxD,CAAC;IAED,KAAK,CAAC,QAAQ,CAAC,KAAa;QAC1B,MAAM,MAAM,GAAW;YACrB,KAAK;YACL,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAC;QAEF,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAChD,MAAM,EAAE,CAAC,KAAK,CAAC,SAAS,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAE/C,MAAM,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;QACrE,MAAM,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;IACzC,CAAC;IAED,KAAK,CAAC,SAAS;QACb,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,IAAI,CAAC,UAAU,EAAE,OAAO,CAAC,CAAC;YACzD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAEhC,IAAI,CAAC,MAAM,CAAC,KAAK,IAAI,CAAC,MAAM,CAAC,SAAS,EAAE,CAAC;gBACvC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;YAChD,CAAC;YAED,OAAO,MAAgB,CAAC;QAC1B,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACrF,OAAO,IAAI,CAAC;YACd,CAAC;YACD,IAAI,KAAK,YAAY,WAAW,EAAE,CAAC;gBACjC,MAAM,IAAI,KAAK,CAAC,4BAA4B,CAAC,CAAC;YAChD,CAAC;YACD,MAAM,KAAK,CAAC;QACd,CAAC;IACH,CAAC;IAED,KAAK,CAAC,WAAW;QACf,IAAI,CAAC;YACH,MAAM,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QACnC,CAAC;QAAC,OAAO,KAAc,EAAE,CAAC;YACxB,IAAI,KAAK,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,MAAM,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ,EAAE,CAAC;gBACrF,MAAM,KAAK,CAAC;YACd,CAAC;QACH,CAAC;IACH,CAAC;IAED,SAAS,CAAC,KAAa;QACrB,IAAI,KAAK,CAAC,MAAM,IAAI,CAAC,EAAE,CAAC;YACtB,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QACrC,MAAM,MAAM,GAAG,KAAK,CAAC,SAAS,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAEjD,OAAO,GAAG,MAAM,cAAc,MAAM,EAAE,CAAC;IACzC,CAAC;CACF;AA9DD,sCA8DC"}
@@ -9,6 +9,10 @@ export declare const ERROR_MESSAGES: {
9
9
  readonly NO_MESSAGE_OR_FILE: "You must specify either --message or --file";
10
10
  readonly BOTH_MESSAGE_AND_FILE: "Cannot use both --message and --file";
11
11
  readonly INVALID_THREAD_TIMESTAMP: "Invalid thread timestamp format";
12
+ readonly INVALID_SCHEDULE_AT: "Invalid schedule time format. Use Unix timestamp (seconds) or ISO 8601 date-time";
13
+ readonly INVALID_SCHEDULE_AFTER: "--after must be a positive integer (minutes)";
14
+ readonly BOTH_SCHEDULE_OPTIONS: "Cannot use both --at and --after";
15
+ readonly SCHEDULE_TIME_IN_PAST: "Schedule time must be in the future";
12
16
  readonly API_ERROR: (error: string) => string;
13
17
  readonly CHANNEL_NOT_FOUND: (channel: string) => string;
14
18
  readonly FILE_READ_ERROR: (file: string, error: string) => string;
@@ -21,6 +25,7 @@ export declare const SUCCESS_MESSAGES: {
21
25
  readonly PROFILE_SWITCHED: (profileName: string) => string;
22
26
  readonly PROFILE_CLEARED: (profileName: string) => string;
23
27
  readonly MESSAGE_SENT: (channel: string) => string;
28
+ readonly MESSAGE_SCHEDULED: (channel: string, postAtIso: string) => string;
24
29
  };
25
30
  export declare const FILE_PERMISSIONS: {
26
31
  CONFIG_FILE: number;
@@ -1 +1 @@
1
- {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,IAAI,CAAC;AACnC,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAClC,eAAO,MAAM,oBAAoB,YAAY,CAAC;AAE9C,eAAO,MAAM,cAAc;sCAEA,MAAM;8CAEE,MAAM;;;;;;gCAUpB,MAAM;0CACI,MAAM;qCAGX,MAAM,SAAS,MAAM;oCACtB,MAAM;;6CAIG,MAAM;CAC9B,CAAC;AAEX,eAAO,MAAM,gBAAgB;wCACA,MAAM;6CACD,MAAM;4CACP,MAAM;qCACb,MAAM;CACtB,CAAC;AAGX,eAAO,MAAM,gBAAgB;;CAE5B,CAAC;AAGF,eAAO,MAAM,UAAU;;;;CAItB,CAAC;AAGF,eAAO,MAAM,UAAU;;;;;;;;;;CAUtB,CAAC;AAGF,eAAO,MAAM,QAAQ;;;;CAIpB,CAAC;AAGF,eAAO,MAAM,WAAW,wBAAwB,CAAC"}
1
+ {"version":3,"file":"constants.d.ts","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,iBAAiB,IAAI,CAAC;AACnC,eAAO,MAAM,gBAAgB,IAAI,CAAC;AAClC,eAAO,MAAM,oBAAoB,YAAY,CAAC;AAE9C,eAAO,MAAM,cAAc;sCAEA,MAAM;8CAEE,MAAM;;;;;;;;;;gCAepB,MAAM;0CACI,MAAM;qCAGX,MAAM,SAAS,MAAM;oCACtB,MAAM;;6CAIG,MAAM;CAC9B,CAAC;AAEX,eAAO,MAAM,gBAAgB;wCACA,MAAM;6CACD,MAAM;4CACP,MAAM;qCACb,MAAM;0CACD,MAAM,aAAa,MAAM;CAE9C,CAAC;AAGX,eAAO,MAAM,gBAAgB;;CAE5B,CAAC;AAGF,eAAO,MAAM,UAAU;;;;CAItB,CAAC;AAGF,eAAO,MAAM,UAAU;;;;;;;;;;CAUtB,CAAC;AAGF,eAAO,MAAM,QAAQ;;;;CAIpB,CAAC;AAGF,eAAO,MAAM,WAAW,wBAAwB,CAAC"}
@@ -14,6 +14,10 @@ exports.ERROR_MESSAGES = {
14
14
  NO_MESSAGE_OR_FILE: 'You must specify either --message or --file',
15
15
  BOTH_MESSAGE_AND_FILE: 'Cannot use both --message and --file',
16
16
  INVALID_THREAD_TIMESTAMP: 'Invalid thread timestamp format',
17
+ INVALID_SCHEDULE_AT: 'Invalid schedule time format. Use Unix timestamp (seconds) or ISO 8601 date-time',
18
+ INVALID_SCHEDULE_AFTER: '--after must be a positive integer (minutes)',
19
+ BOTH_SCHEDULE_OPTIONS: 'Cannot use both --at and --after',
20
+ SCHEDULE_TIME_IN_PAST: 'Schedule time must be in the future',
17
21
  // API errors
18
22
  API_ERROR: (error) => `API Error: ${error}`,
19
23
  CHANNEL_NOT_FOUND: (channel) => `Channel not found: ${channel}`,
@@ -29,6 +33,7 @@ exports.SUCCESS_MESSAGES = {
29
33
  PROFILE_SWITCHED: (profileName) => `Switched to profile "${profileName}"`,
30
34
  PROFILE_CLEARED: (profileName) => `Profile "${profileName}" cleared successfully`,
31
35
  MESSAGE_SENT: (channel) => `Message sent successfully to #${channel}`,
36
+ MESSAGE_SCHEDULED: (channel, postAtIso) => `Message scheduled to #${channel} at ${postAtIso}`,
32
37
  };
33
38
  // File and system constants
34
39
  exports.FILE_PERMISSIONS = {
@@ -1 +1 @@
1
- {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,iBAAiB,GAAG,CAAC,CAAC;AACtB,QAAA,gBAAgB,GAAG,CAAC,CAAC;AACrB,QAAA,oBAAoB,GAAG,SAAS,CAAC;AAEjC,QAAA,cAAc,GAAG;IAC5B,uBAAuB;IACvB,SAAS,EAAE,CAAC,WAAmB,EAAE,EAAE,CACjC,uCAAuC,WAAW,0DAA0D,WAAW,cAAc;IACvI,iBAAiB,EAAE,CAAC,WAAmB,EAAE,EAAE,CAAC,YAAY,WAAW,aAAa;IAChF,iBAAiB,EAAE,8EAA8E;IACjG,qBAAqB,EAAE,4BAA4B;IAEnD,oBAAoB;IACpB,kBAAkB,EAAE,6CAA6C;IACjE,qBAAqB,EAAE,sCAAsC;IAC7D,wBAAwB,EAAE,iCAAiC;IAE3D,aAAa;IACb,SAAS,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,cAAc,KAAK,EAAE;IACnD,iBAAiB,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,sBAAsB,OAAO,EAAE;IAEvE,cAAc;IACd,eAAe,EAAE,CAAC,IAAY,EAAE,KAAa,EAAE,EAAE,CAAC,sBAAsB,IAAI,KAAK,KAAK,EAAE;IACxF,cAAc,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,mBAAmB,IAAI,EAAE;IAE3D,0BAA0B;IAC1B,iBAAiB,EAAE,mBAAmB;IACtC,sBAAsB,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,2BAA2B,KAAK,EAAE;CACrE,CAAC;AAEE,QAAA,gBAAgB,GAAG;IAC9B,WAAW,EAAE,CAAC,WAAmB,EAAE,EAAE,CAAC,yCAAyC,WAAW,GAAG;IAC7F,gBAAgB,EAAE,CAAC,WAAmB,EAAE,EAAE,CAAC,wBAAwB,WAAW,GAAG;IACjF,eAAe,EAAE,CAAC,WAAmB,EAAE,EAAE,CAAC,YAAY,WAAW,wBAAwB;IACzF,YAAY,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,iCAAiC,OAAO,EAAE;CACrE,CAAC;AAEX,4BAA4B;AACf,QAAA,gBAAgB,GAAG;IAC9B,WAAW,EAAE,KAAK,EAAE,4BAA4B;CACjD,CAAC;AAEF,aAAa;AACA,QAAA,UAAU,GAAG;IACxB,iBAAiB,EAAE,IAAI;IACvB,iBAAiB,EAAE,CAAC;IACpB,qBAAqB,EAAE,EAAE;CAC1B,CAAC;AAEF,kCAAkC;AACrB,QAAA,UAAU,GAAG;IACxB,mBAAmB,EAAE,CAAC;IACtB,UAAU,EAAE,EAAE;IACd,cAAc,EAAE,IAAI;IACpB,YAAY,EAAE;QACZ,OAAO,EAAE,CAAC;QACV,MAAM,EAAE,CAAC;QACT,UAAU,EAAE,IAAI;QAChB,UAAU,EAAE,KAAK;KAClB;CACF,CAAC;AAEF,iBAAiB;AACJ,QAAA,QAAQ,GAAG;IACtB,aAAa,EAAE,EAAE;IACjB,cAAc,EAAE,IAAI;IACpB,oBAAoB,EAAE,EAAE;CACzB,CAAC;AAEF,eAAe;AACF,QAAA,WAAW,GAAG,qBAAqB,CAAC"}
1
+ {"version":3,"file":"constants.js","sourceRoot":"","sources":["../../src/utils/constants.ts"],"names":[],"mappings":";;;AAAa,QAAA,iBAAiB,GAAG,CAAC,CAAC;AACtB,QAAA,gBAAgB,GAAG,CAAC,CAAC;AACrB,QAAA,oBAAoB,GAAG,SAAS,CAAC;AAEjC,QAAA,cAAc,GAAG;IAC5B,uBAAuB;IACvB,SAAS,EAAE,CAAC,WAAmB,EAAE,EAAE,CACjC,uCAAuC,WAAW,0DAA0D,WAAW,cAAc;IACvI,iBAAiB,EAAE,CAAC,WAAmB,EAAE,EAAE,CAAC,YAAY,WAAW,aAAa;IAChF,iBAAiB,EAAE,8EAA8E;IACjG,qBAAqB,EAAE,4BAA4B;IAEnD,oBAAoB;IACpB,kBAAkB,EAAE,6CAA6C;IACjE,qBAAqB,EAAE,sCAAsC;IAC7D,wBAAwB,EAAE,iCAAiC;IAC3D,mBAAmB,EACjB,kFAAkF;IACpF,sBAAsB,EAAE,8CAA8C;IACtE,qBAAqB,EAAE,kCAAkC;IACzD,qBAAqB,EAAE,qCAAqC;IAE5D,aAAa;IACb,SAAS,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,cAAc,KAAK,EAAE;IACnD,iBAAiB,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,sBAAsB,OAAO,EAAE;IAEvE,cAAc;IACd,eAAe,EAAE,CAAC,IAAY,EAAE,KAAa,EAAE,EAAE,CAAC,sBAAsB,IAAI,KAAK,KAAK,EAAE;IACxF,cAAc,EAAE,CAAC,IAAY,EAAE,EAAE,CAAC,mBAAmB,IAAI,EAAE;IAE3D,0BAA0B;IAC1B,iBAAiB,EAAE,mBAAmB;IACtC,sBAAsB,EAAE,CAAC,KAAa,EAAE,EAAE,CAAC,2BAA2B,KAAK,EAAE;CACrE,CAAC;AAEE,QAAA,gBAAgB,GAAG;IAC9B,WAAW,EAAE,CAAC,WAAmB,EAAE,EAAE,CAAC,yCAAyC,WAAW,GAAG;IAC7F,gBAAgB,EAAE,CAAC,WAAmB,EAAE,EAAE,CAAC,wBAAwB,WAAW,GAAG;IACjF,eAAe,EAAE,CAAC,WAAmB,EAAE,EAAE,CAAC,YAAY,WAAW,wBAAwB;IACzF,YAAY,EAAE,CAAC,OAAe,EAAE,EAAE,CAAC,iCAAiC,OAAO,EAAE;IAC7E,iBAAiB,EAAE,CAAC,OAAe,EAAE,SAAiB,EAAE,EAAE,CACxD,yBAAyB,OAAO,OAAO,SAAS,EAAE;CAC5C,CAAC;AAEX,4BAA4B;AACf,QAAA,gBAAgB,GAAG;IAC9B,WAAW,EAAE,KAAK,EAAE,4BAA4B;CACjD,CAAC;AAEF,aAAa;AACA,QAAA,UAAU,GAAG;IACxB,iBAAiB,EAAE,IAAI;IACvB,iBAAiB,EAAE,CAAC;IACpB,qBAAqB,EAAE,EAAE;CAC1B,CAAC;AAEF,kCAAkC;AACrB,QAAA,UAAU,GAAG;IACxB,mBAAmB,EAAE,CAAC;IACtB,UAAU,EAAE,EAAE;IACd,cAAc,EAAE,IAAI;IACpB,YAAY,EAAE;QACZ,OAAO,EAAE,CAAC;QACV,MAAM,EAAE,CAAC;QACT,UAAU,EAAE,IAAI;QAChB,UAAU,EAAE,KAAK;KAClB;CACF,CAAC;AAEF,iBAAiB;AACJ,QAAA,QAAQ,GAAG;IACtB,aAAa,EAAE,EAAE;IACjB,cAAc,EAAE,IAAI;IACpB,oBAAoB,EAAE,EAAE;CACzB,CAAC;AAEF,eAAe;AACF,QAAA,WAAW,GAAG,qBAAqB,CAAC"}
@@ -0,0 +1,7 @@
1
+ export interface OutputFormatter<T> {
2
+ format(data: T[]): void;
3
+ }
4
+ export declare abstract class BaseFormatter<T> implements OutputFormatter<T> {
5
+ abstract format(data: T[]): void;
6
+ }
7
+ //# sourceMappingURL=output-formatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-formatter.d.ts","sourceRoot":"","sources":["../../../src/utils/formatters/output-formatter.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,eAAe,CAAC,CAAC;IAChC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,IAAI,CAAC;CACzB;AAED,8BAAsB,aAAa,CAAC,CAAC,CAAE,YAAW,eAAe,CAAC,CAAC,CAAC;IAClE,QAAQ,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,EAAE,GAAG,IAAI;CACjC"}
@@ -0,0 +1,7 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BaseFormatter = void 0;
4
+ class BaseFormatter {
5
+ }
6
+ exports.BaseFormatter = BaseFormatter;
7
+ //# sourceMappingURL=output-formatter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"output-formatter.js","sourceRoot":"","sources":["../../../src/utils/formatters/output-formatter.ts"],"names":[],"mappings":";;;AAIA,MAAsB,aAAa;CAElC;AAFD,sCAEC"}
@@ -0,0 +1,20 @@
1
+ import type { Config, ConfigOptions, Profile } from '../types/config';
2
+ export declare class ProfileConfigManager {
3
+ private fileManager;
4
+ private cryptoService;
5
+ private profileManager;
6
+ constructor(_options?: ConfigOptions);
7
+ setToken(token: string, profile?: string): Promise<void>;
8
+ getConfig(profile?: string): Promise<Config | null>;
9
+ listProfiles(): Promise<Profile[]>;
10
+ useProfile(profile: string): Promise<void>;
11
+ getCurrentProfile(): Promise<string>;
12
+ clearConfig(profile?: string): Promise<void>;
13
+ maskToken(token: string): string;
14
+ migrateIfNeeded(): Promise<void>;
15
+ }
16
+ export declare const profileConfig: {
17
+ getCurrentProfile: () => string;
18
+ getToken: (_profile?: string) => string | undefined;
19
+ };
20
+ //# sourceMappingURL=profile-config-refactored.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-config-refactored.d.ts","sourceRoot":"","sources":["../../src/utils/profile-config-refactored.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAC;AAOtE,qBAAa,oBAAoB;IAC/B,OAAO,CAAC,WAAW,CAAoB;IACvC,OAAO,CAAC,aAAa,CAAqB;IAC1C,OAAO,CAAC,cAAc,CAAiB;gBAE3B,QAAQ,GAAE,aAAkB;IAQlC,QAAQ,CAAC,KAAK,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgBxD,SAAS,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAcnD,YAAY,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAiBlC,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAS1C,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAIpC,WAAW,CAAC,OAAO,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAgClD,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM;IAY1B,eAAe,IAAI,OAAO,CAAC,IAAI,CAAC;CAwBvC;AAGD,eAAO,MAAM,aAAa;6BACD,MAAM;0BAGP,MAAM,KAAG,MAAM,GAAG,SAAS;CAKlD,CAAC"}
@@ -0,0 +1,174 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.profileConfig = exports.ProfileConfigManager = void 0;
37
+ const constants_1 = require("./constants");
38
+ const config_file_manager_1 = require("./config/config-file-manager");
39
+ const token_crypto_service_1 = require("./config/token-crypto-service");
40
+ const profile_manager_1 = require("./config/profile-manager");
41
+ const fs = __importStar(require("fs/promises"));
42
+ class ProfileConfigManager {
43
+ constructor(_options = {}) {
44
+ // Note: ConfigFileManager currently doesn't support custom configDir
45
+ // This would need to be added if required
46
+ this.fileManager = new config_file_manager_1.ConfigFileManager();
47
+ this.cryptoService = new token_crypto_service_1.TokenCryptoService();
48
+ this.profileManager = new profile_manager_1.ProfileManager(this.fileManager, this.cryptoService);
49
+ }
50
+ async setToken(token, profile) {
51
+ const profileName = profile || (await this.profileManager.getCurrentProfile());
52
+ const config = {
53
+ token,
54
+ updatedAt: new Date().toISOString(),
55
+ };
56
+ await this.profileManager.setProfile(profileName, config);
57
+ // Set as default profile if it's the first one or explicitly setting default
58
+ const profiles = await this.profileManager.listProfiles();
59
+ if (profiles.length === 1 || profileName === constants_1.DEFAULT_PROFILE_NAME) {
60
+ await this.profileManager.setCurrentProfile(profileName);
61
+ }
62
+ }
63
+ async getConfig(profile) {
64
+ const profileName = profile || (await this.profileManager.getCurrentProfile());
65
+ try {
66
+ return await this.profileManager.getProfile(profileName);
67
+ }
68
+ catch (error) {
69
+ // Return null if profile not found
70
+ if (error instanceof Error && error.message.includes('not found')) {
71
+ return null;
72
+ }
73
+ throw error;
74
+ }
75
+ }
76
+ async listProfiles() {
77
+ const profileNames = await this.profileManager.listProfiles();
78
+ const currentProfile = await this.profileManager.getCurrentProfile();
79
+ const profiles = [];
80
+ for (const name of profileNames) {
81
+ const config = await this.profileManager.getProfile(name);
82
+ profiles.push({
83
+ name,
84
+ config,
85
+ isDefault: name === currentProfile,
86
+ });
87
+ }
88
+ return profiles;
89
+ }
90
+ async useProfile(profile) {
91
+ const exists = await this.profileManager.profileExists(profile);
92
+ if (!exists) {
93
+ throw new Error(`Profile "${profile}" does not exist`);
94
+ }
95
+ await this.profileManager.setCurrentProfile(profile);
96
+ }
97
+ async getCurrentProfile() {
98
+ return await this.profileManager.getCurrentProfile();
99
+ }
100
+ async clearConfig(profile) {
101
+ const profileName = profile || (await this.profileManager.getCurrentProfile());
102
+ try {
103
+ await this.profileManager.deleteProfile(profileName);
104
+ }
105
+ catch (error) {
106
+ // If profile doesn't exist, do nothing
107
+ if (error instanceof Error && error.message.includes('not found')) {
108
+ return;
109
+ }
110
+ throw error;
111
+ }
112
+ // If we deleted the current profile, set a new default
113
+ const currentProfile = await this.profileManager.getCurrentProfile();
114
+ if (currentProfile === profileName) {
115
+ const remainingProfiles = await this.profileManager.listProfiles();
116
+ if (remainingProfiles.length > 0) {
117
+ await this.profileManager.setCurrentProfile(remainingProfiles[0]);
118
+ }
119
+ else {
120
+ // No profiles left, delete the config file
121
+ try {
122
+ await fs.unlink(this.fileManager.getConfigPath());
123
+ }
124
+ catch (error) {
125
+ if (error && typeof error === 'object' && 'code' in error && error.code !== 'ENOENT') {
126
+ throw error;
127
+ }
128
+ }
129
+ }
130
+ }
131
+ }
132
+ maskToken(token) {
133
+ if (token.length <= constants_1.TOKEN_MIN_LENGTH) {
134
+ return '****';
135
+ }
136
+ const prefix = token.substring(0, constants_1.TOKEN_MASK_LENGTH);
137
+ const suffix = token.substring(token.length - constants_1.TOKEN_MASK_LENGTH);
138
+ return `${prefix}-****-****-${suffix}`;
139
+ }
140
+ // Migration support - to be called separately if needed
141
+ async migrateIfNeeded() {
142
+ const data = await this.fileManager.read();
143
+ // Check if migration is needed (old format detection)
144
+ const anyData = data;
145
+ if (anyData.token && !anyData.profiles) {
146
+ // Old format detected, migrate
147
+ const oldConfig = {
148
+ token: anyData.token,
149
+ updatedAt: anyData.updatedAt || new Date().toISOString(),
150
+ };
151
+ // Create new format
152
+ const newData = {
153
+ profiles: { [constants_1.DEFAULT_PROFILE_NAME]: oldConfig },
154
+ currentProfile: constants_1.DEFAULT_PROFILE_NAME,
155
+ };
156
+ await this.fileManager.write(newData);
157
+ // Re-encrypt token using new service
158
+ await this.setToken(oldConfig.token, constants_1.DEFAULT_PROFILE_NAME);
159
+ }
160
+ }
161
+ }
162
+ exports.ProfileConfigManager = ProfileConfigManager;
163
+ // Export a simplified version for backward compatibility
164
+ exports.profileConfig = {
165
+ getCurrentProfile: () => {
166
+ return constants_1.DEFAULT_PROFILE_NAME;
167
+ },
168
+ getToken: (_profile) => {
169
+ // This is a simplified version for testing
170
+ // In real usage, it would need to be async
171
+ return undefined;
172
+ },
173
+ };
174
+ //# sourceMappingURL=profile-config-refactored.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-config-refactored.js","sourceRoot":"","sources":["../../src/utils/profile-config-refactored.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ export declare function parseScheduledTimestamp(value: string): number | null;
2
+ export declare function resolvePostAt(at: string | undefined, afterMinutes: string | undefined, nowMs?: number): number | null;
3
+ //# sourceMappingURL=schedule-utils.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"schedule-utils.d.ts","sourceRoot":"","sources":["../../src/utils/schedule-utils.ts"],"names":[],"mappings":"AAAA,wBAAgB,uBAAuB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAcpE;AAED,wBAAgB,aAAa,CAC3B,EAAE,EAAE,MAAM,GAAG,SAAS,EACtB,YAAY,EAAE,MAAM,GAAG,SAAS,EAChC,KAAK,SAAa,GACjB,MAAM,GAAG,IAAI,CAoBf"}