squads-cli 0.6.1 → 0.7.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 (112) hide show
  1. package/README.md +196 -1152
  2. package/dist/auth-YW3UPFSB.js +23 -0
  3. package/dist/autonomy-BWTVDEAT.js +102 -0
  4. package/dist/autonomy-BWTVDEAT.js.map +1 -0
  5. package/dist/chunk-3KCWNZWW.js +401 -0
  6. package/dist/chunk-3KCWNZWW.js.map +1 -0
  7. package/dist/chunk-67RO2HKR.js +174 -0
  8. package/dist/chunk-67RO2HKR.js.map +1 -0
  9. package/dist/chunk-7JVD7RD4.js +275 -0
  10. package/dist/chunk-7JVD7RD4.js.map +1 -0
  11. package/dist/chunk-BODLDQY7.js +452 -0
  12. package/dist/chunk-BODLDQY7.js.map +1 -0
  13. package/dist/chunk-FFFCFZ6A.js +121 -0
  14. package/dist/chunk-FFFCFZ6A.js.map +1 -0
  15. package/dist/chunk-FIWT2NMM.js +165 -0
  16. package/dist/chunk-FIWT2NMM.js.map +1 -0
  17. package/dist/chunk-L6GQCHDF.js +222 -0
  18. package/dist/chunk-L6GQCHDF.js.map +1 -0
  19. package/dist/{chunk-O7UV3FWI.js → chunk-LDM62TIX.js} +2 -2
  20. package/dist/chunk-LDM62TIX.js.map +1 -0
  21. package/dist/chunk-LOA3KWYJ.js +294 -0
  22. package/dist/chunk-LOA3KWYJ.js.map +1 -0
  23. package/dist/chunk-NA45DFXY.js +616 -0
  24. package/dist/chunk-NA45DFXY.js.map +1 -0
  25. package/dist/{chunk-4CMAEQQY.js → chunk-NQN6JPI7.js} +4 -3
  26. package/dist/chunk-NQN6JPI7.js.map +1 -0
  27. package/dist/chunk-OQJHPULO.js +103 -0
  28. package/dist/chunk-OQJHPULO.js.map +1 -0
  29. package/dist/chunk-QHNUMM4V.js +87 -0
  30. package/dist/chunk-QHNUMM4V.js.map +1 -0
  31. package/dist/chunk-RM6BWILN.js +74 -0
  32. package/dist/chunk-RM6BWILN.js.map +1 -0
  33. package/dist/chunk-WBR5J7EX.js +90 -0
  34. package/dist/chunk-WBR5J7EX.js.map +1 -0
  35. package/dist/chunk-Z2UKDBNL.js +162 -0
  36. package/dist/chunk-Z2UKDBNL.js.map +1 -0
  37. package/dist/cli.js +2151 -12594
  38. package/dist/cli.js.map +1 -1
  39. package/dist/context-M2A2DOFV.js +291 -0
  40. package/dist/context-M2A2DOFV.js.map +1 -0
  41. package/dist/context-feed-JMNW4GAM.js +391 -0
  42. package/dist/context-feed-JMNW4GAM.js.map +1 -0
  43. package/dist/cost-N37I4UTA.js +274 -0
  44. package/dist/cost-N37I4UTA.js.map +1 -0
  45. package/dist/create-554W5HNU.js +286 -0
  46. package/dist/create-554W5HNU.js.map +1 -0
  47. package/dist/daemon-XWPQPPPN.js +546 -0
  48. package/dist/daemon-XWPQPPPN.js.map +1 -0
  49. package/dist/dashboard-L7YKVQEB.js +945 -0
  50. package/dist/dashboard-L7YKVQEB.js.map +1 -0
  51. package/dist/dashboard-MFNRLCEE.js +794 -0
  52. package/dist/dashboard-MFNRLCEE.js.map +1 -0
  53. package/dist/doctor-RG75M5RO.js +346 -0
  54. package/dist/doctor-RG75M5RO.js.map +1 -0
  55. package/dist/env-config-KCLDBKYX.js +21 -0
  56. package/dist/exec-JQKBF7BL.js +197 -0
  57. package/dist/exec-JQKBF7BL.js.map +1 -0
  58. package/dist/feedback-KA2UYBZG.js +229 -0
  59. package/dist/feedback-KA2UYBZG.js.map +1 -0
  60. package/dist/github-UQTM5KMS.js +23 -0
  61. package/dist/goal-EOPC5ZCD.js +168 -0
  62. package/dist/goal-EOPC5ZCD.js.map +1 -0
  63. package/dist/health-3FZDOSR5.js +209 -0
  64. package/dist/health-3FZDOSR5.js.map +1 -0
  65. package/dist/history-TFVXJEDH.js +229 -0
  66. package/dist/history-TFVXJEDH.js.map +1 -0
  67. package/dist/index.js +1 -1
  68. package/dist/index.js.map +1 -1
  69. package/dist/init-UOWTNMIE.js +747 -0
  70. package/dist/init-UOWTNMIE.js.map +1 -0
  71. package/dist/kpi-2SQ2WCVT.js +413 -0
  72. package/dist/kpi-2SQ2WCVT.js.map +1 -0
  73. package/dist/learn-6ERTERAO.js +269 -0
  74. package/dist/learn-6ERTERAO.js.map +1 -0
  75. package/dist/list-KSOMUBMB.js +92 -0
  76. package/dist/list-KSOMUBMB.js.map +1 -0
  77. package/dist/login-ST6PAXYE.js +155 -0
  78. package/dist/login-ST6PAXYE.js.map +1 -0
  79. package/dist/memory-3CSNKXIL.js +562 -0
  80. package/dist/memory-3CSNKXIL.js.map +1 -0
  81. package/dist/progress-FKG4V2VH.js +202 -0
  82. package/dist/progress-FKG4V2VH.js.map +1 -0
  83. package/dist/providers-66PDCORB.js +65 -0
  84. package/dist/providers-66PDCORB.js.map +1 -0
  85. package/dist/results-2MJFLWEO.js +224 -0
  86. package/dist/results-2MJFLWEO.js.map +1 -0
  87. package/dist/run-72OQLH5A.js +2685 -0
  88. package/dist/run-72OQLH5A.js.map +1 -0
  89. package/dist/session-6H67XPAQ.js +64 -0
  90. package/dist/session-6H67XPAQ.js.map +1 -0
  91. package/dist/{chunk-NHGLXN2F.js → sessions-GVQIMN4W.js} +23 -459
  92. package/dist/sessions-GVQIMN4W.js.map +1 -0
  93. package/dist/{squad-parser-4BI3G4RS.js → squad-parser-CM3HOIWM.js} +2 -2
  94. package/dist/squad-parser-CM3HOIWM.js.map +1 -0
  95. package/dist/stats-ONZI557Q.js +335 -0
  96. package/dist/stats-ONZI557Q.js.map +1 -0
  97. package/dist/status-FYH42FTB.js +346 -0
  98. package/dist/status-FYH42FTB.js.map +1 -0
  99. package/dist/sync-HJZJNXHW.js +800 -0
  100. package/dist/sync-HJZJNXHW.js.map +1 -0
  101. package/dist/update-B4WMUOPO.js +83 -0
  102. package/dist/update-B4WMUOPO.js.map +1 -0
  103. package/dist/{update-ALJKFFM7.js → update-L7FGHN6W.js} +2 -2
  104. package/dist/update-L7FGHN6W.js.map +1 -0
  105. package/package.json +18 -10
  106. package/dist/chunk-4CMAEQQY.js.map +0 -1
  107. package/dist/chunk-NHGLXN2F.js.map +0 -1
  108. package/dist/chunk-O7UV3FWI.js.map +0 -1
  109. package/dist/sessions-6PB7ALCE.js +0 -16
  110. /package/dist/{sessions-6PB7ALCE.js.map → auth-YW3UPFSB.js.map} +0 -0
  111. /package/dist/{squad-parser-4BI3G4RS.js.map → env-config-KCLDBKYX.js.map} +0 -0
  112. /package/dist/{update-ALJKFFM7.js.map → github-UQTM5KMS.js.map} +0 -0
@@ -0,0 +1,162 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/lib/auth.ts
4
+ import { existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync } from "fs";
5
+ import { join } from "path";
6
+ import { homedir } from "os";
7
+ import http from "http";
8
+ var PERSONAL_DOMAINS = [
9
+ "gmail.com",
10
+ "googlemail.com",
11
+ "yahoo.com",
12
+ "yahoo.co.uk",
13
+ "yahoo.fr",
14
+ "hotmail.com",
15
+ "outlook.com",
16
+ "live.com",
17
+ "msn.com",
18
+ "icloud.com",
19
+ "me.com",
20
+ "mac.com",
21
+ "aol.com",
22
+ "protonmail.com",
23
+ "proton.me",
24
+ "zoho.com",
25
+ "mail.com",
26
+ "yandex.com",
27
+ "yandex.ru",
28
+ "gmx.com",
29
+ "gmx.de",
30
+ "fastmail.com",
31
+ "tutanota.com",
32
+ "hey.com"
33
+ ];
34
+ var AUTH_DIR = join(homedir(), ".squads-cli");
35
+ var AUTH_PATH = join(AUTH_DIR, "auth.json");
36
+ function isPersonalEmail(email) {
37
+ const domain = email.split("@")[1]?.toLowerCase();
38
+ return PERSONAL_DOMAINS.includes(domain);
39
+ }
40
+ function getEmailDomain(email) {
41
+ return email.split("@")[1]?.toLowerCase() || "";
42
+ }
43
+ function saveSession(session) {
44
+ if (!existsSync(AUTH_DIR)) {
45
+ mkdirSync(AUTH_DIR, { recursive: true, mode: 448 });
46
+ }
47
+ writeFileSync(AUTH_PATH, JSON.stringify(session, null, 2), { mode: 384 });
48
+ }
49
+ function loadSession() {
50
+ if (!existsSync(AUTH_PATH)) return null;
51
+ try {
52
+ return JSON.parse(readFileSync(AUTH_PATH, "utf-8"));
53
+ } catch {
54
+ return null;
55
+ }
56
+ }
57
+ function clearSession() {
58
+ try {
59
+ if (existsSync(AUTH_PATH)) {
60
+ unlinkSync(AUTH_PATH);
61
+ }
62
+ } catch {
63
+ }
64
+ }
65
+ function isLoggedIn() {
66
+ const session = loadSession();
67
+ return session !== null && session.status === "active";
68
+ }
69
+ async function verifyToken(apiUrl, token) {
70
+ const controller = new AbortController();
71
+ const timeout = setTimeout(() => controller.abort(), 5e3);
72
+ try {
73
+ const response = await fetch(`${apiUrl}/auth/cli/verify`, {
74
+ headers: { Authorization: `Bearer ${token}` },
75
+ signal: controller.signal
76
+ });
77
+ clearTimeout(timeout);
78
+ if (!response.ok) return null;
79
+ const data = await response.json();
80
+ return {
81
+ email: String(data.email ?? ""),
82
+ tenantId: Number(data.tenant_id ?? 0),
83
+ tenantSlug: String(data.tenant_slug ?? ""),
84
+ tenantName: String(data.tenant_name ?? ""),
85
+ status: String(data.status ?? "")
86
+ };
87
+ } catch {
88
+ clearTimeout(timeout);
89
+ return null;
90
+ }
91
+ }
92
+ function escapeHtml(str) {
93
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;").replace(/'/g, "&#039;");
94
+ }
95
+ function startAuthCallbackServer(port = 54321) {
96
+ return new Promise((resolve, reject) => {
97
+ const server = http.createServer((req, res) => {
98
+ const url = new URL(req.url || "", `http://localhost:${port}`);
99
+ if (url.pathname === "/callback") {
100
+ const email = url.searchParams.get("email");
101
+ const token = url.searchParams.get("token");
102
+ const error = url.searchParams.get("error");
103
+ if (error) {
104
+ res.writeHead(200, { "Content-Type": "text/html" });
105
+ res.end(`
106
+ <html>
107
+ <body style="font-family: system-ui; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0;">
108
+ <div style="text-align: center;">
109
+ <h1 style="color: #ef4444;">Authentication failed: ${escapeHtml(error)}</h1>
110
+ <p>You can close this window.</p>
111
+ </div>
112
+ </body>
113
+ </html>
114
+ `);
115
+ server.close();
116
+ reject(new Error(error));
117
+ return;
118
+ }
119
+ if (email && token) {
120
+ res.writeHead(200, { "Content-Type": "text/html" });
121
+ res.end(`
122
+ <html>
123
+ <body style="font-family: system-ui; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0;">
124
+ <div style="text-align: center;">
125
+ <h1 style="color: #10b981;">Logged in!</h1>
126
+ <p>Welcome, ${escapeHtml(email)}</p>
127
+ <p style="color: #6b7280;">You can close this window and return to your terminal.</p>
128
+ </div>
129
+ </body>
130
+ </html>
131
+ `);
132
+ server.close();
133
+ resolve({ email, token });
134
+ } else {
135
+ res.writeHead(400, { "Content-Type": "text/plain" });
136
+ res.end("Missing email or token");
137
+ }
138
+ } else {
139
+ res.writeHead(404);
140
+ res.end();
141
+ }
142
+ });
143
+ server.listen(port, () => {
144
+ });
145
+ setTimeout(() => {
146
+ server.close();
147
+ reject(new Error("Login timed out"));
148
+ }, 5 * 60 * 1e3);
149
+ });
150
+ }
151
+
152
+ export {
153
+ isPersonalEmail,
154
+ getEmailDomain,
155
+ saveSession,
156
+ loadSession,
157
+ clearSession,
158
+ isLoggedIn,
159
+ verifyToken,
160
+ startAuthCallbackServer
161
+ };
162
+ //# sourceMappingURL=chunk-Z2UKDBNL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/lib/auth.ts"],"sourcesContent":["import { existsSync, readFileSync, writeFileSync, mkdirSync, unlinkSync } from 'fs';\nimport { join } from 'path';\nimport { homedir } from 'os';\nimport http from 'http';\n\n// Personal email domains to reject\nconst PERSONAL_DOMAINS = [\n 'gmail.com', 'googlemail.com',\n 'yahoo.com', 'yahoo.co.uk', 'yahoo.fr',\n 'hotmail.com', 'outlook.com', 'live.com', 'msn.com',\n 'icloud.com', 'me.com', 'mac.com',\n 'aol.com',\n 'protonmail.com', 'proton.me',\n 'zoho.com',\n 'mail.com',\n 'yandex.com', 'yandex.ru',\n 'gmx.com', 'gmx.de',\n 'fastmail.com',\n 'tutanota.com',\n 'hey.com',\n];\n\nconst AUTH_DIR = join(homedir(), '.squads-cli');\nconst AUTH_PATH = join(AUTH_DIR, 'auth.json');\n\nexport interface AuthSession {\n email: string;\n domain: string;\n status: 'pending' | 'contacted' | 'active';\n createdAt: string;\n accessToken?: string;\n}\n\nexport function isPersonalEmail(email: string): boolean {\n const domain = email.split('@')[1]?.toLowerCase();\n return PERSONAL_DOMAINS.includes(domain);\n}\n\nexport function getEmailDomain(email: string): string {\n return email.split('@')[1]?.toLowerCase() || '';\n}\n\nexport function saveSession(session: AuthSession): void {\n if (!existsSync(AUTH_DIR)) {\n mkdirSync(AUTH_DIR, { recursive: true, mode: 0o700 });\n }\n writeFileSync(AUTH_PATH, JSON.stringify(session, null, 2), { mode: 0o600 });\n}\n\nexport function loadSession(): AuthSession | null {\n if (!existsSync(AUTH_PATH)) return null;\n try {\n return JSON.parse(readFileSync(AUTH_PATH, 'utf-8'));\n } catch {\n return null;\n }\n}\n\nexport function clearSession(): void {\n try {\n if (existsSync(AUTH_PATH)) {\n unlinkSync(AUTH_PATH);\n }\n } catch {\n // File already removed or inaccessible\n }\n}\n\nexport function isLoggedIn(): boolean {\n const session = loadSession();\n return session !== null && session.status === 'active';\n}\n\nexport interface VerifiedUser {\n email: string;\n tenantId: number;\n tenantSlug: string;\n tenantName: string;\n status: string;\n}\n\n// Verify a token against the API and return user data (null on failure)\nexport async function verifyToken(apiUrl: string, token: string): Promise<VerifiedUser | null> {\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 5000);\n try {\n const response = await fetch(`${apiUrl}/auth/cli/verify`, {\n headers: { Authorization: `Bearer ${token}` },\n signal: controller.signal,\n });\n clearTimeout(timeout);\n if (!response.ok) return null;\n const data = await response.json() as Record<string, unknown>;\n return {\n email: String(data.email ?? ''),\n tenantId: Number(data.tenant_id ?? 0),\n tenantSlug: String(data.tenant_slug ?? ''),\n tenantName: String(data.tenant_name ?? ''),\n status: String(data.status ?? ''),\n };\n } catch {\n clearTimeout(timeout);\n return null;\n }\n}\n\n// Escape HTML special characters to prevent XSS\nfunction escapeHtml(str: string): string {\n return str\n .replace(/&/g, '&amp;')\n .replace(/</g, '&lt;')\n .replace(/>/g, '&gt;')\n .replace(/\"/g, '&quot;')\n .replace(/'/g, '&#039;');\n}\n\n// Local callback server for OAuth flow\nexport function startAuthCallbackServer(port: number = 54321): Promise<{ email: string; token: string }> {\n return new Promise((resolve, reject) => {\n const server = http.createServer((req, res) => {\n const url = new URL(req.url || '', `http://localhost:${port}`);\n\n if (url.pathname === '/callback') {\n const email = url.searchParams.get('email');\n const token = url.searchParams.get('token');\n const error = url.searchParams.get('error');\n\n if (error) {\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(`\n <html>\n <body style=\"font-family: system-ui; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0;\">\n <div style=\"text-align: center;\">\n <h1 style=\"color: #ef4444;\">Authentication failed: ${escapeHtml(error)}</h1>\n <p>You can close this window.</p>\n </div>\n </body>\n </html>\n `);\n server.close();\n reject(new Error(error));\n return;\n }\n\n if (email && token) {\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(`\n <html>\n <body style=\"font-family: system-ui; display: flex; justify-content: center; align-items: center; height: 100vh; margin: 0;\">\n <div style=\"text-align: center;\">\n <h1 style=\"color: #10b981;\">Logged in!</h1>\n <p>Welcome, ${escapeHtml(email)}</p>\n <p style=\"color: #6b7280;\">You can close this window and return to your terminal.</p>\n </div>\n </body>\n </html>\n `);\n server.close();\n resolve({ email, token });\n } else {\n res.writeHead(400, { 'Content-Type': 'text/plain' });\n res.end('Missing email or token');\n }\n } else {\n res.writeHead(404);\n res.end();\n }\n });\n\n server.listen(port, () => {\n // Server started\n });\n\n // Timeout after 5 minutes\n setTimeout(() => {\n server.close();\n reject(new Error('Login timed out'));\n }, 5 * 60 * 1000);\n });\n}\n"],"mappings":"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","names":[]}