@2amtech/hai 0.0.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 (239) hide show
  1. package/README.md +212 -0
  2. package/dist/ai/agent-info.d.ts +1 -0
  3. package/dist/ai/agent-info.js +42 -0
  4. package/dist/ai/agent-info.js.map +1 -0
  5. package/dist/ai/agents/architect.d.ts +3 -0
  6. package/dist/ai/agents/architect.js +107 -0
  7. package/dist/ai/agents/architect.js.map +1 -0
  8. package/dist/ai/agents/backend-dev.d.ts +3 -0
  9. package/dist/ai/agents/backend-dev.js +33 -0
  10. package/dist/ai/agents/backend-dev.js.map +1 -0
  11. package/dist/ai/agents/frontend-dev.d.ts +3 -0
  12. package/dist/ai/agents/frontend-dev.js +31 -0
  13. package/dist/ai/agents/frontend-dev.js.map +1 -0
  14. package/dist/ai/agents/index.d.ts +3 -0
  15. package/dist/ai/agents/index.js +17 -0
  16. package/dist/ai/agents/index.js.map +1 -0
  17. package/dist/ai/agents/refactorer.d.ts +3 -0
  18. package/dist/ai/agents/refactorer.js +38 -0
  19. package/dist/ai/agents/refactorer.js.map +1 -0
  20. package/dist/ai/agents/researcher.d.ts +3 -0
  21. package/dist/ai/agents/researcher.js +28 -0
  22. package/dist/ai/agents/researcher.js.map +1 -0
  23. package/dist/ai/agents/security-reviewer.d.ts +3 -0
  24. package/dist/ai/agents/security-reviewer.js +99 -0
  25. package/dist/ai/agents/security-reviewer.js.map +1 -0
  26. package/dist/ai/agents/types.d.ts +6 -0
  27. package/dist/ai/agents/types.js +2 -0
  28. package/dist/ai/agents/types.js.map +1 -0
  29. package/dist/ai/agents/verifier.d.ts +3 -0
  30. package/dist/ai/agents/verifier.js +28 -0
  31. package/dist/ai/agents/verifier.js.map +1 -0
  32. package/dist/ai/prompts/document.d.ts +3 -0
  33. package/dist/ai/prompts/document.js +57 -0
  34. package/dist/ai/prompts/document.js.map +1 -0
  35. package/dist/ai/prompts/implement.d.ts +3 -0
  36. package/dist/ai/prompts/implement.js +128 -0
  37. package/dist/ai/prompts/implement.js.map +1 -0
  38. package/dist/ai/prompts/index.d.ts +3 -0
  39. package/dist/ai/prompts/index.js +17 -0
  40. package/dist/ai/prompts/index.js.map +1 -0
  41. package/dist/ai/prompts/optimize-ai.d.ts +3 -0
  42. package/dist/ai/prompts/optimize-ai.js +104 -0
  43. package/dist/ai/prompts/optimize-ai.js.map +1 -0
  44. package/dist/ai/prompts/pull-specs.d.ts +3 -0
  45. package/dist/ai/prompts/pull-specs.js +10 -0
  46. package/dist/ai/prompts/pull-specs.js.map +1 -0
  47. package/dist/ai/prompts/pull-tickets.d.ts +3 -0
  48. package/dist/ai/prompts/pull-tickets.js +11 -0
  49. package/dist/ai/prompts/pull-tickets.js.map +1 -0
  50. package/dist/ai/prompts/pull.d.ts +3 -0
  51. package/dist/ai/prompts/pull.js +9 -0
  52. package/dist/ai/prompts/pull.js.map +1 -0
  53. package/dist/ai/prompts/review-changes.d.ts +3 -0
  54. package/dist/ai/prompts/review-changes.js +88 -0
  55. package/dist/ai/prompts/review-changes.js.map +1 -0
  56. package/dist/ai/prompts/types.d.ts +6 -0
  57. package/dist/ai/prompts/types.js +2 -0
  58. package/dist/ai/prompts/types.js.map +1 -0
  59. package/dist/app.d.ts +14 -0
  60. package/dist/app.js +40 -0
  61. package/dist/app.js.map +1 -0
  62. package/dist/cli.d.ts +2 -0
  63. package/dist/cli.js +79 -0
  64. package/dist/cli.js.map +1 -0
  65. package/dist/commands/get.d.ts +8 -0
  66. package/dist/commands/get.js +73 -0
  67. package/dist/commands/get.js.map +1 -0
  68. package/dist/commands/init.d.ts +3 -0
  69. package/dist/commands/init.js +113 -0
  70. package/dist/commands/init.js.map +1 -0
  71. package/dist/commands/mcp/helpers.d.ts +15 -0
  72. package/dist/commands/mcp/helpers.js +21 -0
  73. package/dist/commands/mcp/helpers.js.map +1 -0
  74. package/dist/commands/mcp/pull.d.ts +3 -0
  75. package/dist/commands/mcp/pull.js +85 -0
  76. package/dist/commands/mcp/pull.js.map +1 -0
  77. package/dist/commands/mcp/server.d.ts +2 -0
  78. package/dist/commands/mcp/server.js +80 -0
  79. package/dist/commands/mcp/server.js.map +1 -0
  80. package/dist/commands/mcp/specs.d.ts +2 -0
  81. package/dist/commands/mcp/specs.js +325 -0
  82. package/dist/commands/mcp/specs.js.map +1 -0
  83. package/dist/commands/mcp/tickets.d.ts +3 -0
  84. package/dist/commands/mcp/tickets.js +77 -0
  85. package/dist/commands/mcp/tickets.js.map +1 -0
  86. package/dist/commands/pull.d.ts +10 -0
  87. package/dist/commands/pull.js +61 -0
  88. package/dist/commands/pull.js.map +1 -0
  89. package/dist/commands/status.d.ts +2 -0
  90. package/dist/commands/status.js +102 -0
  91. package/dist/commands/status.js.map +1 -0
  92. package/dist/components/ticket-renderer.d.ts +5 -0
  93. package/dist/components/ticket-renderer.js +89 -0
  94. package/dist/components/ticket-renderer.js.map +1 -0
  95. package/dist/contexts/config-context.d.ts +17 -0
  96. package/dist/contexts/config-context.js +77 -0
  97. package/dist/contexts/config-context.js.map +1 -0
  98. package/dist/contexts/error-context.d.ts +12 -0
  99. package/dist/contexts/error-context.js +28 -0
  100. package/dist/contexts/error-context.js.map +1 -0
  101. package/dist/helpers/config.d.ts +4 -0
  102. package/dist/helpers/config.js +29 -0
  103. package/dist/helpers/config.js.map +1 -0
  104. package/dist/helpers/fs.d.ts +8 -0
  105. package/dist/helpers/fs.js +83 -0
  106. package/dist/helpers/fs.js.map +1 -0
  107. package/dist/helpers/init.d.ts +2 -0
  108. package/dist/helpers/init.js +18 -0
  109. package/dist/helpers/init.js.map +1 -0
  110. package/dist/helpers/preflight.d.ts +8 -0
  111. package/dist/helpers/preflight.js +77 -0
  112. package/dist/helpers/preflight.js.map +1 -0
  113. package/dist/helpers/pull.d.ts +9 -0
  114. package/dist/helpers/pull.js +79 -0
  115. package/dist/helpers/pull.js.map +1 -0
  116. package/dist/helpers/symlink.d.ts +9 -0
  117. package/dist/helpers/symlink.js +104 -0
  118. package/dist/helpers/symlink.js.map +1 -0
  119. package/dist/helpers/tickets.d.ts +4 -0
  120. package/dist/helpers/tickets.js +56 -0
  121. package/dist/helpers/tickets.js.map +1 -0
  122. package/dist/hooks/use-async.d.ts +6 -0
  123. package/dist/hooks/use-async.js +37 -0
  124. package/dist/hooks/use-async.js.map +1 -0
  125. package/dist/plugins/atlassian/adf-to-markdown.d.ts +11 -0
  126. package/dist/plugins/atlassian/adf-to-markdown.js +121 -0
  127. package/dist/plugins/atlassian/adf-to-markdown.js.map +1 -0
  128. package/dist/plugins/atlassian/auth-step.d.ts +10 -0
  129. package/dist/plugins/atlassian/auth-step.js +59 -0
  130. package/dist/plugins/atlassian/auth-step.js.map +1 -0
  131. package/dist/plugins/atlassian/confluence-client.d.ts +24 -0
  132. package/dist/plugins/atlassian/confluence-client.js +250 -0
  133. package/dist/plugins/atlassian/confluence-client.js.map +1 -0
  134. package/dist/plugins/atlassian/data.d.ts +18 -0
  135. package/dist/plugins/atlassian/data.js +12 -0
  136. package/dist/plugins/atlassian/data.js.map +1 -0
  137. package/dist/plugins/atlassian/index.d.ts +2 -0
  138. package/dist/plugins/atlassian/index.js +57 -0
  139. package/dist/plugins/atlassian/index.js.map +1 -0
  140. package/dist/plugins/atlassian/init-step.d.ts +11 -0
  141. package/dist/plugins/atlassian/init-step.js +54 -0
  142. package/dist/plugins/atlassian/init-step.js.map +1 -0
  143. package/dist/plugins/atlassian/jira-client.d.ts +38 -0
  144. package/dist/plugins/atlassian/jira-client.js +308 -0
  145. package/dist/plugins/atlassian/jira-client.js.map +1 -0
  146. package/dist/plugins/atlassian/specs-step.d.ts +13 -0
  147. package/dist/plugins/atlassian/specs-step.js +71 -0
  148. package/dist/plugins/atlassian/specs-step.js.map +1 -0
  149. package/dist/plugins/atlassian/tickets-step.d.ts +8 -0
  150. package/dist/plugins/atlassian/tickets-step.js +45 -0
  151. package/dist/plugins/atlassian/tickets-step.js.map +1 -0
  152. package/dist/plugins/claude-code/agents.d.ts +4 -0
  153. package/dist/plugins/claude-code/agents.js +56 -0
  154. package/dist/plugins/claude-code/agents.js.map +1 -0
  155. package/dist/plugins/claude-code/commands.d.ts +4 -0
  156. package/dist/plugins/claude-code/commands.js +54 -0
  157. package/dist/plugins/claude-code/commands.js.map +1 -0
  158. package/dist/plugins/claude-code/index.d.ts +2 -0
  159. package/dist/plugins/claude-code/index.js +57 -0
  160. package/dist/plugins/claude-code/index.js.map +1 -0
  161. package/dist/plugins/cursor/index.d.ts +2 -0
  162. package/dist/plugins/cursor/index.js +60 -0
  163. package/dist/plugins/cursor/index.js.map +1 -0
  164. package/dist/plugins/index.d.ts +1 -0
  165. package/dist/plugins/index.js +16 -0
  166. package/dist/plugins/index.js.map +1 -0
  167. package/dist/plugins/local/index.d.ts +2 -0
  168. package/dist/plugins/local/index.js +53 -0
  169. package/dist/plugins/local/index.js.map +1 -0
  170. package/dist/plugins/local/init-step.d.ts +9 -0
  171. package/dist/plugins/local/init-step.js +24 -0
  172. package/dist/plugins/local/init-step.js.map +1 -0
  173. package/dist/plugins/local/local-spec-provider.d.ts +9 -0
  174. package/dist/plugins/local/local-spec-provider.js +66 -0
  175. package/dist/plugins/local/local-spec-provider.js.map +1 -0
  176. package/dist/plugins/local/local-ticket-provider.d.ts +24 -0
  177. package/dist/plugins/local/local-ticket-provider.js +89 -0
  178. package/dist/plugins/local/local-ticket-provider.js.map +1 -0
  179. package/dist/plugins/none/index.d.ts +2 -0
  180. package/dist/plugins/none/index.js +78 -0
  181. package/dist/plugins/none/index.js.map +1 -0
  182. package/dist/plugins/other-ai/index.d.ts +2 -0
  183. package/dist/plugins/other-ai/index.js +48 -0
  184. package/dist/plugins/other-ai/index.js.map +1 -0
  185. package/dist/plugins/registry.d.ts +4 -0
  186. package/dist/plugins/registry.js +18 -0
  187. package/dist/plugins/registry.js.map +1 -0
  188. package/dist/plugins/resolve.d.ts +8 -0
  189. package/dist/plugins/resolve.js +23 -0
  190. package/dist/plugins/resolve.js.map +1 -0
  191. package/dist/plugins/types.d.ts +36 -0
  192. package/dist/plugins/types.js +2 -0
  193. package/dist/plugins/types.js.map +1 -0
  194. package/dist/plugins/vscode-copilot/agents.d.ts +4 -0
  195. package/dist/plugins/vscode-copilot/agents.js +51 -0
  196. package/dist/plugins/vscode-copilot/agents.js.map +1 -0
  197. package/dist/plugins/vscode-copilot/index.d.ts +2 -0
  198. package/dist/plugins/vscode-copilot/index.js +59 -0
  199. package/dist/plugins/vscode-copilot/index.js.map +1 -0
  200. package/dist/plugins/vscode-copilot/prompts.d.ts +4 -0
  201. package/dist/plugins/vscode-copilot/prompts.js +60 -0
  202. package/dist/plugins/vscode-copilot/prompts.js.map +1 -0
  203. package/dist/schemas/config.d.ts +24 -0
  204. package/dist/schemas/config.js +38 -0
  205. package/dist/schemas/config.js.map +1 -0
  206. package/dist/types.d.ts +84 -0
  207. package/dist/types.js +2 -0
  208. package/dist/types.js.map +1 -0
  209. package/dist/ui/confirm.d.ts +7 -0
  210. package/dist/ui/confirm.js +19 -0
  211. package/dist/ui/confirm.js.map +1 -0
  212. package/dist/ui/error-display.d.ts +6 -0
  213. package/dist/ui/error-display.js +23 -0
  214. package/dist/ui/error-display.js.map +1 -0
  215. package/dist/ui/masked-input.d.ts +9 -0
  216. package/dist/ui/masked-input.js +25 -0
  217. package/dist/ui/masked-input.js.map +1 -0
  218. package/dist/ui/multi-select.d.ts +13 -0
  219. package/dist/ui/multi-select.js +127 -0
  220. package/dist/ui/multi-select.js.map +1 -0
  221. package/dist/ui/select-input.d.ts +12 -0
  222. package/dist/ui/select-input.js +81 -0
  223. package/dist/ui/select-input.js.map +1 -0
  224. package/dist/ui/spinner.d.ts +6 -0
  225. package/dist/ui/spinner.js +18 -0
  226. package/dist/ui/spinner.js.map +1 -0
  227. package/dist/ui/text-input.d.ts +9 -0
  228. package/dist/ui/text-input.js +23 -0
  229. package/dist/ui/text-input.js.map +1 -0
  230. package/dist/wizard/passthrough-step.d.ts +6 -0
  231. package/dist/wizard/passthrough-step.js +8 -0
  232. package/dist/wizard/passthrough-step.js.map +1 -0
  233. package/dist/wizard/plugin-select-step.d.ts +10 -0
  234. package/dist/wizard/plugin-select-step.js +31 -0
  235. package/dist/wizard/plugin-select-step.js.map +1 -0
  236. package/dist/wizard/summary-step.d.ts +2 -0
  237. package/dist/wizard/summary-step.js +97 -0
  238. package/dist/wizard/summary-step.js.map +1 -0
  239. package/package.json +79 -0
@@ -0,0 +1,79 @@
1
+ import { readFile, writeFile } from 'node:fs/promises';
2
+ import { join, relative } from 'node:path';
3
+ import { resolveTicketProvider, resolveSpecProvider, hasCapability, } from '../plugins/resolve.js';
4
+ import { walkMdFiles } from './fs.js';
5
+ export async function pullTickets(config, options = {}) {
6
+ if (!hasCapability(config, 'tickets'))
7
+ return;
8
+ const provider = resolveTicketProvider(config);
9
+ const aiDir = join(process.cwd(), '.ai');
10
+ const destPath = join(aiDir, 'tickets');
11
+ await provider.sync(destPath, {
12
+ dryRun: options.dryRun ?? false,
13
+ updateLocal: options.updateLocal ?? false,
14
+ });
15
+ if (!options.dryRun) {
16
+ await generateIndex(aiDir, destPath, 'Ticket Index', 'ticket-index.md');
17
+ }
18
+ }
19
+ export async function pullSpecs(config, options = {}) {
20
+ if (!hasCapability(config, 'specs'))
21
+ return;
22
+ const provider = resolveSpecProvider(config);
23
+ const aiDir = join(process.cwd(), '.ai');
24
+ const destPath = join(aiDir, 'specs');
25
+ await provider.sync(destPath, {
26
+ dryRun: options.dryRun ?? false,
27
+ updateLocal: options.updateLocal ?? false,
28
+ });
29
+ if (!options.dryRun) {
30
+ await generateIndex(aiDir, destPath, 'Specifications Index', 'specification-index.md');
31
+ }
32
+ }
33
+ async function generateIndex(aiDir, dir, title, filename) {
34
+ const entries = [];
35
+ for await (const filePath of walkMdFiles(dir)) {
36
+ const relPath = relative(aiDir, filePath);
37
+ const entryTitle = await extractTitle(filePath);
38
+ entries.push({ relativePath: relPath, title: entryTitle });
39
+ }
40
+ entries.sort((a, b) => a.relativePath.localeCompare(b.relativePath));
41
+ const lines = [`# ${title}`, ''];
42
+ let currentGroup = '';
43
+ for (const entry of entries) {
44
+ const parts = entry.relativePath.split('/');
45
+ const group = parts.length > 2 ? parts.slice(1, -1).join('/') : '';
46
+ if (group !== currentGroup) {
47
+ if (currentGroup !== '' || lines.length > 2) {
48
+ lines.push('');
49
+ }
50
+ if (group) {
51
+ lines.push(`## ${group}`);
52
+ lines.push('');
53
+ }
54
+ currentGroup = group;
55
+ }
56
+ lines.push(`- [${entry.title}](${entry.relativePath})`);
57
+ }
58
+ lines.push('');
59
+ await writeFile(join(aiDir, filename), lines.join('\n'), 'utf-8');
60
+ }
61
+ async function extractTitle(filePath) {
62
+ try {
63
+ const content = await readFile(filePath, 'utf-8');
64
+ const match = /^#\s+(.+)$/m.exec(content);
65
+ if (match)
66
+ return match[1].trim();
67
+ }
68
+ catch {
69
+ /* ignore read errors */
70
+ }
71
+ // Fallback: derive from filename
72
+ const name = filePath.slice(filePath.lastIndexOf('/') + 1);
73
+ return name.replace(/\.md$/, '').replaceAll('-', ' ');
74
+ }
75
+ export async function pullAll(config, options = {}) {
76
+ await pullTickets(config, options);
77
+ await pullSpecs(config, options);
78
+ }
79
+ //# sourceMappingURL=pull.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"pull.js","sourceRoot":"","sources":["../../source/helpers/pull.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAE,SAAS,EAAC,MAAM,kBAAkB,CAAC;AACrD,OAAO,EAAC,IAAI,EAAE,QAAQ,EAAC,MAAM,WAAW,CAAC;AAEzC,OAAO,EACN,qBAAqB,EACrB,mBAAmB,EACnB,aAAa,GACb,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAC,WAAW,EAAC,MAAM,SAAS,CAAC;AAOpC,MAAM,CAAC,KAAK,UAAU,WAAW,CAChC,MAAiB,EACjB,UAAuB,EAAE;IAEzB,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,SAAS,CAAC;QAAE,OAAO;IAE9C,MAAM,QAAQ,GAAG,qBAAqB,CAAC,MAAM,CAAC,CAAC;IAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,EAAE,SAAS,CAAC,CAAC;IACxC,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE;QAC7B,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK;QAC/B,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,KAAK;KACzC,CAAC,CAAC;IAEH,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACrB,MAAM,aAAa,CAAC,KAAK,EAAE,QAAQ,EAAE,cAAc,EAAE,iBAAiB,CAAC,CAAC;IACzE,CAAC;AACF,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,SAAS,CAC9B,MAAiB,EACjB,UAAuB,EAAE;IAEzB,IAAI,CAAC,aAAa,CAAC,MAAM,EAAE,OAAO,CAAC;QAAE,OAAO;IAE5C,MAAM,QAAQ,GAAG,mBAAmB,CAAC,MAAM,CAAC,CAAC;IAC7C,MAAM,KAAK,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,EAAE,KAAK,CAAC,CAAC;IACzC,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC;IACtC,MAAM,QAAQ,CAAC,IAAI,CAAC,QAAQ,EAAE;QAC7B,MAAM,EAAE,OAAO,CAAC,MAAM,IAAI,KAAK;QAC/B,WAAW,EAAE,OAAO,CAAC,WAAW,IAAI,KAAK;KACzC,CAAC,CAAC;IAEH,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC;QACrB,MAAM,aAAa,CAClB,KAAK,EACL,QAAQ,EACR,sBAAsB,EACtB,wBAAwB,CACxB,CAAC;IACH,CAAC;AACF,CAAC;AAED,KAAK,UAAU,aAAa,CAC3B,KAAa,EACb,GAAW,EACX,KAAa,EACb,QAAgB;IAEhB,MAAM,OAAO,GAAiD,EAAE,CAAC;IACjE,IAAI,KAAK,EAAE,MAAM,QAAQ,IAAI,WAAW,CAAC,GAAG,CAAC,EAAE,CAAC;QAC/C,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,EAAE,QAAQ,CAAC,CAAC;QAC1C,MAAM,UAAU,GAAG,MAAM,YAAY,CAAC,QAAQ,CAAC,CAAC;QAChD,OAAO,CAAC,IAAI,CAAC,EAAC,YAAY,EAAE,OAAO,EAAE,KAAK,EAAE,UAAU,EAAC,CAAC,CAAC;IAC1D,CAAC;IAED,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,CAAC,aAAa,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC;IAErE,MAAM,KAAK,GAAa,CAAC,KAAK,KAAK,EAAE,EAAE,EAAE,CAAC,CAAC;IAE3C,IAAI,YAAY,GAAG,EAAE,CAAC;IACtB,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC7B,MAAM,KAAK,GAAG,KAAK,CAAC,YAAY,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;QAC5C,MAAM,KAAK,GAAG,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;QAEnE,IAAI,KAAK,KAAK,YAAY,EAAE,CAAC;YAC5B,IAAI,YAAY,KAAK,EAAE,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBAC7C,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAChB,CAAC;YAED,IAAI,KAAK,EAAE,CAAC;gBACX,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC;gBAC1B,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YAChB,CAAC;YAED,YAAY,GAAG,KAAK,CAAC;QACtB,CAAC;QAED,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,CAAC,KAAK,KAAK,KAAK,CAAC,YAAY,GAAG,CAAC,CAAC;IACzD,CAAC;IAED,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IAEf,MAAM,SAAS,CAAC,IAAI,CAAC,KAAK,EAAE,QAAQ,CAAC,EAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,OAAO,CAAC,CAAC;AACnE,CAAC;AAED,KAAK,UAAU,YAAY,CAAC,QAAgB;IAC3C,IAAI,CAAC;QACJ,MAAM,OAAO,GAAG,MAAM,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QAClD,MAAM,KAAK,GAAG,aAAa,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;QAC1C,IAAI,KAAK;YAAE,OAAO,KAAK,CAAC,CAAC,CAAE,CAAC,IAAI,EAAE,CAAC;IACpC,CAAC;IAAC,MAAM,CAAC;QACR,wBAAwB;IACzB,CAAC;IAED,iCAAiC;IACjC,MAAM,IAAI,GAAG,QAAQ,CAAC,KAAK,CAAC,QAAQ,CAAC,WAAW,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;IAC3D,OAAO,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,UAAU,CAAC,GAAG,EAAE,GAAG,CAAC,CAAC;AACvD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,OAAO,CAC5B,MAAiB,EACjB,UAAuB,EAAE;IAEzB,MAAM,WAAW,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACnC,MAAM,SAAS,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAClC,CAAC"}
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Remove a path if it is a symlink. No-op otherwise.
3
+ */
4
+ export declare function removeIfSymlink(path: string): Promise<boolean>;
5
+ /**
6
+ * Try to symlink linkPath → targetPath.
7
+ * If symlinking fails, fall back to copying .md files.
8
+ */
9
+ export declare function linkOrCopy(linkPath: string, targetPath: string): Promise<void>;
@@ -0,0 +1,104 @@
1
+ import { symlink, lstat, readlink, unlink, mkdir, readdir, stat, copyFile, rm, } from 'node:fs/promises';
2
+ import { join, relative, dirname, resolve } from 'node:path';
3
+ /**
4
+ * Remove a path if it is a symlink. No-op otherwise.
5
+ */
6
+ export async function removeIfSymlink(path) {
7
+ try {
8
+ const info = await lstat(path);
9
+ if (info.isSymbolicLink()) {
10
+ await unlink(path);
11
+ return true;
12
+ }
13
+ }
14
+ catch (error) {
15
+ if (error.code === 'ENOENT')
16
+ return false;
17
+ throw error;
18
+ }
19
+ return false;
20
+ }
21
+ /**
22
+ * Try to create a directory symlink at `linkPath` pointing to `targetPath`.
23
+ * Uses relative paths for portability.
24
+ * Returns true on success, throws on failure.
25
+ */
26
+ async function ensureSymlink(linkPath, targetPath) {
27
+ const absTarget = resolve(targetPath);
28
+ const absLink = resolve(linkPath);
29
+ // Ensure parent directory exists
30
+ await mkdir(dirname(absLink), { recursive: true });
31
+ // Check if symlink already exists and points to the right place
32
+ const relTarget = relative(dirname(absLink), absTarget);
33
+ try {
34
+ const info = await lstat(absLink);
35
+ if (info.isSymbolicLink()) {
36
+ const current = await readlink(absLink);
37
+ if (current === relTarget) {
38
+ return; // Already correct
39
+ }
40
+ await unlink(absLink);
41
+ }
42
+ else {
43
+ // It's a real file/directory — remove it
44
+ await rm(absLink, { recursive: true });
45
+ }
46
+ }
47
+ catch (error) {
48
+ if (error.code !== 'ENOENT')
49
+ throw error;
50
+ }
51
+ await symlink(relTarget, absLink, 'dir');
52
+ }
53
+ /**
54
+ * Copy .md files from source to dest directory (recursively).
55
+ */
56
+ async function copyLocalFiles(sourcePath, destPath) {
57
+ await mkdir(destPath, { recursive: true });
58
+ await copyRecursive(sourcePath, destPath, sourcePath);
59
+ }
60
+ async function copyRecursive(dir, destBase, sourceBase) {
61
+ let entries;
62
+ try {
63
+ entries = await readdir(dir, { withFileTypes: true });
64
+ }
65
+ catch {
66
+ return;
67
+ }
68
+ for (const entry of entries) {
69
+ const fullPath = join(dir, entry.name);
70
+ if (entry.isDirectory()) {
71
+ await copyRecursive(fullPath, destBase, sourceBase);
72
+ continue;
73
+ }
74
+ if (!entry.name.endsWith('.md'))
75
+ continue;
76
+ // Preserve relative directory structure
77
+ const rel = relative(sourceBase, fullPath);
78
+ const destFile = join(destBase, rel);
79
+ await mkdir(dirname(destFile), { recursive: true });
80
+ await copyFile(fullPath, destFile);
81
+ }
82
+ }
83
+ /**
84
+ * Try to symlink linkPath → targetPath.
85
+ * If symlinking fails, fall back to copying .md files.
86
+ */
87
+ export async function linkOrCopy(linkPath, targetPath) {
88
+ // Verify target exists
89
+ try {
90
+ await stat(targetPath);
91
+ }
92
+ catch {
93
+ throw new Error(`Local path does not exist: ${targetPath}`);
94
+ }
95
+ try {
96
+ await ensureSymlink(linkPath, targetPath);
97
+ }
98
+ catch {
99
+ // Symlink failed — fall back to copying files
100
+ await removeIfSymlink(linkPath);
101
+ await copyLocalFiles(targetPath, linkPath);
102
+ }
103
+ }
104
+ //# sourceMappingURL=symlink.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"symlink.js","sourceRoot":"","sources":["../../source/helpers/symlink.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { Ticket, TicketProvider } from '../types.js';
2
+ export declare function projectFromKey(key: string): string;
3
+ export declare function fetchAllIssues(provider: TicketProvider, issueKey: string, recursive: boolean): Promise<Ticket[]>;
4
+ export declare function listLocalTicketKeys(baseDir: string): Promise<Set<string>>;
@@ -0,0 +1,56 @@
1
+ import { readdir } from 'node:fs/promises';
2
+ import { join } from 'node:path';
3
+ export function projectFromKey(key) {
4
+ const idx = key.lastIndexOf('-');
5
+ return idx > 0 ? key.slice(0, idx) : key;
6
+ }
7
+ export async function fetchAllIssues(provider, issueKey, recursive) {
8
+ const visited = new Set();
9
+ const tickets = [];
10
+ async function visit(key) {
11
+ if (visited.has(key))
12
+ return;
13
+ visited.add(key);
14
+ const { ticket, linkedKeys } = await provider.fetchIssue(key);
15
+ tickets.push(ticket);
16
+ if (!recursive)
17
+ return;
18
+ for (const linkedKey of linkedKeys) {
19
+ if (visited.has(linkedKey))
20
+ continue;
21
+ try {
22
+ await visit(linkedKey);
23
+ }
24
+ catch (error) {
25
+ const message = error instanceof Error ? error.message : String(error);
26
+ if (!message.includes('(404)'))
27
+ throw error;
28
+ }
29
+ }
30
+ }
31
+ await visit(issueKey);
32
+ return tickets;
33
+ }
34
+ export async function listLocalTicketKeys(baseDir) {
35
+ const keys = new Set();
36
+ try {
37
+ const projectEntries = await readdir(baseDir, { withFileTypes: true });
38
+ for (const projectEntry of projectEntries) {
39
+ if (!projectEntry.isDirectory())
40
+ continue;
41
+ const projectPath = join(baseDir, projectEntry.name);
42
+ const entries = await readdir(projectPath, { withFileTypes: true });
43
+ for (const entry of entries) {
44
+ if (entry.isFile() && entry.name.endsWith('.md')) {
45
+ keys.add(entry.name.slice(0, -3));
46
+ }
47
+ }
48
+ }
49
+ }
50
+ catch (error) {
51
+ if (error.code !== 'ENOENT')
52
+ throw error;
53
+ }
54
+ return keys;
55
+ }
56
+ //# sourceMappingURL=tickets.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"tickets.js","sourceRoot":"","sources":["../../source/helpers/tickets.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,OAAO,EAAC,MAAM,kBAAkB,CAAC;AACzC,OAAO,EAAC,IAAI,EAAC,MAAM,WAAW,CAAC;AAG/B,MAAM,UAAU,cAAc,CAAC,GAAW;IACzC,MAAM,GAAG,GAAG,GAAG,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;IACjC,OAAO,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;AAC1C,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CACnC,QAAwB,EACxB,QAAgB,EAChB,SAAkB;IAElB,MAAM,OAAO,GAAG,IAAI,GAAG,EAAU,CAAC;IAClC,MAAM,OAAO,GAAa,EAAE,CAAC;IAE7B,KAAK,UAAU,KAAK,CAAC,GAAW;QAC/B,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC;YAAE,OAAO;QAC7B,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAEjB,MAAM,EAAC,MAAM,EAAE,UAAU,EAAC,GAAG,MAAM,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;QAC5D,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAErB,IAAI,CAAC,SAAS;YAAE,OAAO;QAEvB,KAAK,MAAM,SAAS,IAAI,UAAU,EAAE,CAAC;YACpC,IAAI,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;gBAAE,SAAS;YACrC,IAAI,CAAC;gBACJ,MAAM,KAAK,CAAC,SAAS,CAAC,CAAC;YACxB,CAAC;YAAC,OAAO,KAAc,EAAE,CAAC;gBACzB,MAAM,OAAO,GACZ,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACxD,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAC;oBAAE,MAAM,KAAK,CAAC;YAC7C,CAAC;QACF,CAAC;IACF,CAAC;IAED,MAAM,KAAK,CAAC,QAAQ,CAAC,CAAC;IACtB,OAAO,OAAO,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACxC,OAAe;IAEf,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,IAAI,CAAC;QACJ,MAAM,cAAc,GAAG,MAAM,OAAO,CAAC,OAAO,EAAE,EAAC,aAAa,EAAE,IAAI,EAAC,CAAC,CAAC;QACrE,KAAK,MAAM,YAAY,IAAI,cAAc,EAAE,CAAC;YAC3C,IAAI,CAAC,YAAY,CAAC,WAAW,EAAE;gBAAE,SAAS;YAC1C,MAAM,WAAW,GAAG,IAAI,CAAC,OAAO,EAAE,YAAY,CAAC,IAAI,CAAC,CAAC;YACrD,MAAM,OAAO,GAAG,MAAM,OAAO,CAAC,WAAW,EAAE,EAAC,aAAa,EAAE,IAAI,EAAC,CAAC,CAAC;YAClE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC7B,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;oBAClD,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;gBACnC,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;IAAC,OAAO,KAAc,EAAE,CAAC;QACzB,IAAK,KAA+B,CAAC,IAAI,KAAK,QAAQ;YAAE,MAAM,KAAK,CAAC;IACrE,CAAC;IAED,OAAO,IAAI,CAAC;AACb,CAAC"}
@@ -0,0 +1,6 @@
1
+ export interface AsyncState<T> {
2
+ loading: boolean;
3
+ error: Error | null;
4
+ result: T | null;
5
+ }
6
+ export declare function useAsync<T>(fn: () => Promise<T>): AsyncState<T>;
@@ -0,0 +1,37 @@
1
+ import { useState, useEffect, useRef } from 'react';
2
+ export function useAsync(fn) {
3
+ const [state, setState] = useState({
4
+ loading: true,
5
+ error: null,
6
+ result: null,
7
+ });
8
+ const fnRef = useRef(fn);
9
+ fnRef.current = fn;
10
+ useEffect(() => {
11
+ let cancelled = false;
12
+ void (async () => {
13
+ try {
14
+ const result = await fnRef.current();
15
+ if (!cancelled) {
16
+ setState({ loading: false, error: null, result });
17
+ }
18
+ }
19
+ catch (error) {
20
+ if (!cancelled) {
21
+ setState({
22
+ loading: false,
23
+ error: error instanceof Error
24
+ ? error
25
+ : new Error(String(error)),
26
+ result: null,
27
+ });
28
+ }
29
+ }
30
+ })();
31
+ return () => {
32
+ cancelled = true;
33
+ };
34
+ }, []);
35
+ return state;
36
+ }
37
+ //# sourceMappingURL=use-async.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"use-async.js","sourceRoot":"","sources":["../../source/hooks/use-async.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,QAAQ,EAAE,SAAS,EAAE,MAAM,EAAC,MAAM,OAAO,CAAC;AAQlD,MAAM,UAAU,QAAQ,CAAI,EAAoB;IAC/C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAgB;QACjD,OAAO,EAAE,IAAI;QACb,KAAK,EAAE,IAAI;QACX,MAAM,EAAE,IAAI;KACZ,CAAC,CAAC;IAEH,MAAM,KAAK,GAAG,MAAM,CAAC,EAAE,CAAC,CAAC;IACzB,KAAK,CAAC,OAAO,GAAG,EAAE,CAAC;IAEnB,SAAS,CAAC,GAAG,EAAE;QACd,IAAI,SAAS,GAAG,KAAK,CAAC;QAEtB,KAAK,CAAC,KAAK,IAAI,EAAE;YAChB,IAAI,CAAC;gBACJ,MAAM,MAAM,GAAG,MAAM,KAAK,CAAC,OAAO,EAAE,CAAC;gBACrC,IAAI,CAAC,SAAS,EAAE,CAAC;oBAChB,QAAQ,CAAC,EAAC,OAAO,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAC,CAAC,CAAC;gBACjD,CAAC;YACF,CAAC;YAAC,OAAO,KAAc,EAAE,CAAC;gBACzB,IAAI,CAAC,SAAS,EAAE,CAAC;oBAChB,QAAQ,CAAC;wBACR,OAAO,EAAE,KAAK;wBACd,KAAK,EACJ,KAAK,YAAY,KAAK;4BACrB,CAAC,CAAC,KAAK;4BACP,CAAC,CAAC,IAAI,KAAK,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;wBAC5B,MAAM,EAAE,IAAI;qBACZ,CAAC,CAAC;gBACJ,CAAC;YACF,CAAC;QACF,CAAC,CAAC,EAAE,CAAC;QAEL,OAAO,GAAG,EAAE;YACX,SAAS,GAAG,IAAI,CAAC;QAClB,CAAC,CAAC;IACH,CAAC,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,KAAK,CAAC;AACd,CAAC"}
@@ -0,0 +1,11 @@
1
+ export interface AdfNode {
2
+ type: string;
3
+ text?: string;
4
+ content?: AdfNode[];
5
+ attrs?: Record<string, unknown>;
6
+ marks?: Array<{
7
+ type: string;
8
+ attrs?: Record<string, unknown>;
9
+ }>;
10
+ }
11
+ export declare function adfToMarkdown(node: AdfNode | null | undefined): string;
@@ -0,0 +1,121 @@
1
+ function applyMarks(text, marks) {
2
+ if (!marks)
3
+ return text;
4
+ let result = text;
5
+ for (const mark of marks) {
6
+ switch (mark.type) {
7
+ case 'strong': {
8
+ result = `**${result}**`;
9
+ break;
10
+ }
11
+ case 'em': {
12
+ result = `*${result}*`;
13
+ break;
14
+ }
15
+ case 'code': {
16
+ result = `\`${result}\``;
17
+ break;
18
+ }
19
+ case 'link': {
20
+ result = `[${result}](${mark.attrs?.['href'] ?? ''})`;
21
+ break;
22
+ }
23
+ default: {
24
+ break;
25
+ }
26
+ }
27
+ }
28
+ return result;
29
+ }
30
+ function convertChildren(node, ctx) {
31
+ if (!node.content)
32
+ return '';
33
+ return node.content.map(child => convertNode(child, ctx)).join('');
34
+ }
35
+ function convertNode(node, ctx = {}) {
36
+ switch (node.type) {
37
+ case 'doc': {
38
+ return convertChildren(node, ctx);
39
+ }
40
+ case 'paragraph': {
41
+ const text = convertChildren(node, ctx);
42
+ return text + '\n\n';
43
+ }
44
+ case 'text': {
45
+ return applyMarks(node.text ?? '', node.marks);
46
+ }
47
+ case 'hardBreak': {
48
+ return '\n';
49
+ }
50
+ case 'heading': {
51
+ const level = node.attrs?.['level'] ?? 1;
52
+ const prefix = '#'.repeat(level);
53
+ const text = convertChildren(node, ctx);
54
+ return `${prefix} ${text}\n\n`;
55
+ }
56
+ case 'bulletList': {
57
+ return convertChildren(node, { ...ctx, listType: 'bullet' });
58
+ }
59
+ case 'orderedList': {
60
+ return convertChildren(node, { ...ctx, listType: 'ordered' });
61
+ }
62
+ case 'listItem': {
63
+ const indent = ctx.indent ?? 0;
64
+ const prefix = ' '.repeat(indent * 2) +
65
+ (ctx.listType === 'ordered' ? '1. ' : '- ');
66
+ const parts = [];
67
+ for (const child of node.content ?? []) {
68
+ if (child.type === 'bulletList' ||
69
+ child.type === 'orderedList') {
70
+ parts.push(convertNode(child, {
71
+ ...ctx,
72
+ indent: (ctx.indent ?? 0) + 1,
73
+ }));
74
+ continue;
75
+ }
76
+ const text = convertChildren(child, ctx);
77
+ parts.push(`${prefix}${text}\n`);
78
+ }
79
+ return parts.join('');
80
+ }
81
+ case 'codeBlock': {
82
+ const lang = node.attrs?.['language'] ?? '';
83
+ const text = convertChildren(node, ctx);
84
+ return `\`\`\`${lang}\n${text}\n\`\`\`\n\n`;
85
+ }
86
+ case 'blockquote': {
87
+ const inner = convertChildren(node, ctx).trimEnd();
88
+ const lines = inner.split('\n');
89
+ return lines.map(line => `> ${line}`).join('\n') + '\n\n';
90
+ }
91
+ case 'rule': {
92
+ return '---\n\n';
93
+ }
94
+ case 'inlineCard': {
95
+ const url = node.attrs?.['url'];
96
+ return url ? `<${url}>` : '';
97
+ }
98
+ case 'mention': {
99
+ const text = node.attrs?.['text'] ?? '@unknown';
100
+ return text;
101
+ }
102
+ case 'mediaSingle': {
103
+ return convertChildren(node, ctx);
104
+ }
105
+ case 'media': {
106
+ const alt = node.attrs?.['alt'] ??
107
+ node.attrs?.['id'] ??
108
+ 'image';
109
+ return `[${alt}]\n\n`;
110
+ }
111
+ default: {
112
+ return '';
113
+ }
114
+ }
115
+ }
116
+ export function adfToMarkdown(node) {
117
+ if (!node)
118
+ return '';
119
+ return convertNode(node).trim();
120
+ }
121
+ //# sourceMappingURL=adf-to-markdown.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adf-to-markdown.js","sourceRoot":"","sources":["../../../source/plugins/atlassian/adf-to-markdown.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ import React from 'react';
2
+ import { AtlassianAuth, AtlassianAuthFor, AtlassianAuthMap } from './data.js';
3
+ type Props = {
4
+ authFor: AtlassianAuthFor;
5
+ authMap: AtlassianAuthMap;
6
+ onComplete: (authFor: AtlassianAuthFor, auth: AtlassianAuth) => void;
7
+ defaults?: Partial<AtlassianAuth>;
8
+ };
9
+ export default function AtlassianAuthStep({ onComplete, defaults, authFor, authMap, }: Props): React.JSX.Element;
10
+ export {};
@@ -0,0 +1,59 @@
1
+ import React, { useState } from 'react';
2
+ import { Box, Text } from 'ink';
3
+ import TextInput from '../../ui/text-input.js';
4
+ import MaskedInput from '../../ui/masked-input.js';
5
+ import Confirm from '../../ui/confirm.js';
6
+ export default function AtlassianAuthStep({ onComplete, defaults, authFor, authMap, }) {
7
+ const [step, setStep] = useState('baseUrl');
8
+ const [baseUrl, setBaseUrl] = useState('');
9
+ const [email, setEmail] = useState('');
10
+ const [forceSet, setForceSet] = useState(false);
11
+ if (authFor === 'confluence' && authMap.jira && !forceSet) {
12
+ return (React.createElement(Confirm, { message: `Use the same credentials for Confluence as Jira?`, onConfirm: confirmed => {
13
+ if (confirmed) {
14
+ onComplete('all', authMap.jira);
15
+ }
16
+ else {
17
+ setForceSet(true);
18
+ }
19
+ } }));
20
+ }
21
+ switch (step) {
22
+ case 'baseUrl': {
23
+ return (React.createElement(TextInput, { label: "Atlassian base URL", placeholder: "https://yoursite.atlassian.net", defaultValue: defaults?.baseUrl, onSubmit: value => {
24
+ if (!value.startsWith('https://')) {
25
+ return;
26
+ }
27
+ setBaseUrl(value);
28
+ setStep('email');
29
+ } }));
30
+ }
31
+ case 'email': {
32
+ return (React.createElement(Box, { flexDirection: "column" },
33
+ React.createElement(Text, { dimColor: true },
34
+ "Base URL: ",
35
+ baseUrl),
36
+ React.createElement(TextInput, { label: "Email", defaultValue: defaults?.email, onSubmit: value => {
37
+ setEmail(value);
38
+ setStep('token');
39
+ } })));
40
+ }
41
+ case 'token': {
42
+ return (React.createElement(Box, { flexDirection: "column" },
43
+ React.createElement(Text, { dimColor: true },
44
+ "Base URL: ",
45
+ baseUrl),
46
+ React.createElement(Text, { dimColor: true },
47
+ "Email: ",
48
+ email),
49
+ React.createElement(MaskedInput, { label: "API token", defaultValue: defaults?.token, onSubmit: value => {
50
+ onComplete(authFor, {
51
+ baseUrl,
52
+ email,
53
+ token: value,
54
+ });
55
+ } })));
56
+ }
57
+ }
58
+ }
59
+ //# sourceMappingURL=auth-step.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"auth-step.js","sourceRoot":"","sources":["../../../source/plugins/atlassian/auth-step.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAC,QAAQ,EAAC,MAAM,OAAO,CAAC;AACtC,OAAO,EAAC,GAAG,EAAE,IAAI,EAAC,MAAM,KAAK,CAAC;AAC9B,OAAO,SAAS,MAAM,wBAAwB,CAAC;AAC/C,OAAO,WAAW,MAAM,0BAA0B,CAAC;AACnD,OAAO,OAAO,MAAM,qBAAqB,CAAC;AAW1C,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,EACzC,UAAU,EACV,QAAQ,EACR,OAAO,EACP,OAAO,GACA;IACP,MAAM,CAAC,IAAI,EAAE,OAAO,CAAC,GAAG,QAAQ,CAAO,SAAS,CAAC,CAAC;IAClD,MAAM,CAAC,OAAO,EAAE,UAAU,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IAC3C,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAC,EAAE,CAAC,CAAC;IACvC,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC;IAEhD,IAAI,OAAO,KAAK,YAAY,IAAI,OAAO,CAAC,IAAI,IAAI,CAAC,QAAQ,EAAE,CAAC;QAC3D,OAAO,CACN,oBAAC,OAAO,IACP,OAAO,EAAE,kDAAkD,EAC3D,SAAS,EAAE,SAAS,CAAC,EAAE;gBACtB,IAAI,SAAS,EAAE,CAAC;oBACf,UAAU,CAAC,KAAK,EAAE,OAAO,CAAC,IAAK,CAAC,CAAC;gBAClC,CAAC;qBAAM,CAAC;oBACP,WAAW,CAAC,IAAI,CAAC,CAAC;gBACnB,CAAC;YACF,CAAC,GACA,CACF,CAAC;IACH,CAAC;IAED,QAAQ,IAAI,EAAE,CAAC;QACd,KAAK,SAAS,CAAC,CAAC,CAAC;YAChB,OAAO,CACN,oBAAC,SAAS,IACT,KAAK,EAAC,oBAAoB,EAC1B,WAAW,EAAC,gCAAgC,EAC5C,YAAY,EAAE,QAAQ,EAAE,OAAO,EAC/B,QAAQ,EAAE,KAAK,CAAC,EAAE;oBACjB,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,CAAC;wBACnC,OAAO;oBACR,CAAC;oBAED,UAAU,CAAC,KAAK,CAAC,CAAC;oBAClB,OAAO,CAAC,OAAO,CAAC,CAAC;gBAClB,CAAC,GACA,CACF,CAAC;QACH,CAAC;QAED,KAAK,OAAO,CAAC,CAAC,CAAC;YACd,OAAO,CACN,oBAAC,GAAG,IAAC,aAAa,EAAC,QAAQ;gBAC1B,oBAAC,IAAI,IAAC,QAAQ;;oBAAY,OAAO,CAAQ;gBACzC,oBAAC,SAAS,IACT,KAAK,EAAC,OAAO,EACb,YAAY,EAAE,QAAQ,EAAE,KAAK,EAC7B,QAAQ,EAAE,KAAK,CAAC,EAAE;wBACjB,QAAQ,CAAC,KAAK,CAAC,CAAC;wBAChB,OAAO,CAAC,OAAO,CAAC,CAAC;oBAClB,CAAC,GACA,CACG,CACN,CAAC;QACH,CAAC;QAED,KAAK,OAAO,CAAC,CAAC,CAAC;YACd,OAAO,CACN,oBAAC,GAAG,IAAC,aAAa,EAAC,QAAQ;gBAC1B,oBAAC,IAAI,IAAC,QAAQ;;oBAAY,OAAO,CAAQ;gBACzC,oBAAC,IAAI,IAAC,QAAQ;;oBAAS,KAAK,CAAQ;gBACpC,oBAAC,WAAW,IACX,KAAK,EAAC,WAAW,EACjB,YAAY,EAAE,QAAQ,EAAE,KAAK,EAC7B,QAAQ,EAAE,KAAK,CAAC,EAAE;wBACjB,UAAU,CAAC,OAAO,EAAE;4BACnB,OAAO;4BACP,KAAK;4BACL,KAAK,EAAE,KAAK;yBACZ,CAAC,CAAC;oBACJ,CAAC,GACA,CACG,CACN,CAAC;QACH,CAAC;IACF,CAAC;AACF,CAAC"}
@@ -0,0 +1,24 @@
1
+ import type { Space, SpecPage, SpecProvider, SyncOptions, SyncResult } from '../../types.js';
2
+ export interface ConfluenceProviderConfig {
3
+ baseUrl: string;
4
+ email: string;
5
+ token: string;
6
+ }
7
+ export declare class ConfluenceProvider implements SpecProvider {
8
+ private readonly client;
9
+ private readonly spaces;
10
+ private readonly ancestor?;
11
+ constructor(config: ConfluenceProviderConfig, spaces: string[], ancestor?: string);
12
+ fetchSpaces(): Promise<Space[]>;
13
+ fetchPages(spaceKey: string, ancestorTitle?: string): Promise<SpecPage[]>;
14
+ sync(destPath: string, options?: SyncOptions): Promise<SyncResult>;
15
+ private static sanitizeFilename;
16
+ private static buildFilePath;
17
+ private static renderSpecPage;
18
+ private static parseUpdatedDate;
19
+ private static isRemoteNewer;
20
+ private fetchAllPages;
21
+ private fetchSpacePages;
22
+ private fetchDescendants;
23
+ private findPageByTitle;
24
+ }