tailar 0.2.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 (104) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +183 -0
  3. package/README.npm.md +183 -0
  4. package/dist/api/client.d.ts +47 -0
  5. package/dist/api/client.d.ts.map +1 -0
  6. package/dist/api/client.js +329 -0
  7. package/dist/api/client.js.map +1 -0
  8. package/dist/auth/browser.d.ts +11 -0
  9. package/dist/auth/browser.d.ts.map +1 -0
  10. package/dist/auth/browser.js +46 -0
  11. package/dist/auth/browser.js.map +1 -0
  12. package/dist/auth/flow.d.ts +28 -0
  13. package/dist/auth/flow.d.ts.map +1 -0
  14. package/dist/auth/flow.js +171 -0
  15. package/dist/auth/flow.js.map +1 -0
  16. package/dist/auth/storage.d.ts +30 -0
  17. package/dist/auth/storage.d.ts.map +1 -0
  18. package/dist/auth/storage.js +112 -0
  19. package/dist/auth/storage.js.map +1 -0
  20. package/dist/commands/add.d.ts +8 -0
  21. package/dist/commands/add.d.ts.map +1 -0
  22. package/dist/commands/add.js +285 -0
  23. package/dist/commands/add.js.map +1 -0
  24. package/dist/commands/init.d.ts +8 -0
  25. package/dist/commands/init.d.ts.map +1 -0
  26. package/dist/commands/init.js +230 -0
  27. package/dist/commands/init.js.map +1 -0
  28. package/dist/commands/list.d.ts +8 -0
  29. package/dist/commands/list.d.ts.map +1 -0
  30. package/dist/commands/list.js +176 -0
  31. package/dist/commands/list.js.map +1 -0
  32. package/dist/index.d.ts +9 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +83 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/installers/dependencies.d.ts +27 -0
  37. package/dist/installers/dependencies.d.ts.map +1 -0
  38. package/dist/installers/dependencies.js +185 -0
  39. package/dist/installers/dependencies.js.map +1 -0
  40. package/dist/installers/files.d.ts +50 -0
  41. package/dist/installers/files.d.ts.map +1 -0
  42. package/dist/installers/files.js +211 -0
  43. package/dist/installers/files.js.map +1 -0
  44. package/dist/installers/install-feature.d.ts +20 -0
  45. package/dist/installers/install-feature.d.ts.map +1 -0
  46. package/dist/installers/install-feature.js +169 -0
  47. package/dist/installers/install-feature.js.map +1 -0
  48. package/dist/installers/post-install.d.ts +18 -0
  49. package/dist/installers/post-install.d.ts.map +1 -0
  50. package/dist/installers/post-install.js +228 -0
  51. package/dist/installers/post-install.js.map +1 -0
  52. package/dist/installers/templates.d.ts +22 -0
  53. package/dist/installers/templates.d.ts.map +1 -0
  54. package/dist/installers/templates.js +62 -0
  55. package/dist/installers/templates.js.map +1 -0
  56. package/dist/registry/loader.d.ts +21 -0
  57. package/dist/registry/loader.d.ts.map +1 -0
  58. package/dist/registry/loader.js +83 -0
  59. package/dist/registry/loader.js.map +1 -0
  60. package/dist/registry/query.d.ts +55 -0
  61. package/dist/registry/query.d.ts.map +1 -0
  62. package/dist/registry/query.js +123 -0
  63. package/dist/registry/query.js.map +1 -0
  64. package/dist/types/config.d.ts +85 -0
  65. package/dist/types/config.d.ts.map +1 -0
  66. package/dist/types/config.js +7 -0
  67. package/dist/types/config.js.map +1 -0
  68. package/dist/types/index.d.ts +9 -0
  69. package/dist/types/index.d.ts.map +1 -0
  70. package/dist/types/index.js +9 -0
  71. package/dist/types/index.js.map +1 -0
  72. package/dist/types/registry.d.ts +180 -0
  73. package/dist/types/registry.d.ts.map +1 -0
  74. package/dist/types/registry.js +8 -0
  75. package/dist/types/registry.js.map +1 -0
  76. package/dist/types/wizard.d.ts +43 -0
  77. package/dist/types/wizard.d.ts.map +1 -0
  78. package/dist/types/wizard.js +59 -0
  79. package/dist/types/wizard.js.map +1 -0
  80. package/dist/utils/clack-wizard.d.ts +9 -0
  81. package/dist/utils/clack-wizard.d.ts.map +1 -0
  82. package/dist/utils/clack-wizard.js +328 -0
  83. package/dist/utils/clack-wizard.js.map +1 -0
  84. package/dist/utils/config.d.ts +49 -0
  85. package/dist/utils/config.d.ts.map +1 -0
  86. package/dist/utils/config.js +121 -0
  87. package/dist/utils/config.js.map +1 -0
  88. package/dist/utils/logger.d.ts +56 -0
  89. package/dist/utils/logger.d.ts.map +1 -0
  90. package/dist/utils/logger.js +93 -0
  91. package/dist/utils/logger.js.map +1 -0
  92. package/dist/utils/package-manager.d.ts +41 -0
  93. package/dist/utils/package-manager.d.ts.map +1 -0
  94. package/dist/utils/package-manager.js +118 -0
  95. package/dist/utils/package-manager.js.map +1 -0
  96. package/dist/utils/prompts.d.ts +22 -0
  97. package/dist/utils/prompts.d.ts.map +1 -0
  98. package/dist/utils/prompts.js +142 -0
  99. package/dist/utils/prompts.js.map +1 -0
  100. package/dist/utils/validation.d.ts +50 -0
  101. package/dist/utils/validation.d.ts.map +1 -0
  102. package/dist/utils/validation.js +108 -0
  103. package/dist/utils/validation.js.map +1 -0
  104. package/package.json +56 -0
@@ -0,0 +1,329 @@
1
+ /**
2
+ * API Client Module
3
+ *
4
+ * Handles all API interactions with the Tailar web API
5
+ */
6
+ import fetch from "node-fetch";
7
+ import { logger } from "../utils/logger.js";
8
+ import { getAuthHeaders, authenticate, isAuthenticated } from "../auth/flow.js";
9
+ import { getStoredToken, clearToken } from "../auth/storage.js";
10
+ // Lazy-load API_BASE_URL to ensure .env file is loaded first
11
+ // This is a function because .env file is loaded after module imports
12
+ function getApiBaseUrl() {
13
+ return process.env.API_BASE_URL || "https://tailar.dev/api/cli";
14
+ }
15
+ const MAX_RETRIES = 3;
16
+ const RETRY_DELAY = 1000; // 1 second
17
+ /** Avoid infinite spinner when API is unreachable (default tailar.dev or wrong host). */
18
+ const DEFAULT_REQUEST_TIMEOUT_MS = 45_000;
19
+ /**
20
+ * Make an authenticated API request with retry logic
21
+ */
22
+ async function apiRequest(endpoint, options = {}) {
23
+ const { requireAuth = false, retries = MAX_RETRIES, method, body, headers: customHeaders, } = options;
24
+ let attempt = 0;
25
+ let lastError = null;
26
+ while (attempt <= retries) {
27
+ try {
28
+ const headers = {
29
+ "Content-Type": "application/json",
30
+ "User-Agent": "tailar-cli",
31
+ ...(customHeaders || {}),
32
+ };
33
+ // Add auth headers if required
34
+ if (requireAuth) {
35
+ try {
36
+ const authHeaders = await getAuthHeaders();
37
+ Object.assign(headers, authHeaders);
38
+ }
39
+ catch (error) {
40
+ // Not authenticated, try to authenticate
41
+ if (error instanceof Error &&
42
+ error.message.includes("Not authenticated")) {
43
+ logger.info("Authentication required. Starting authentication flow...");
44
+ await authenticate();
45
+ // Retry with new auth headers
46
+ const authHeaders = await getAuthHeaders();
47
+ Object.assign(headers, authHeaders);
48
+ }
49
+ else {
50
+ throw error;
51
+ }
52
+ }
53
+ }
54
+ const fetchInit = {
55
+ method: method || "GET",
56
+ headers,
57
+ };
58
+ if (body) {
59
+ fetchInit.body = body;
60
+ }
61
+ const fullUrl = `${getApiBaseUrl()}${endpoint}`;
62
+ const timeoutMs = Number(process.env.TAILAR_CLI_REQUEST_TIMEOUT_MS) ||
63
+ DEFAULT_REQUEST_TIMEOUT_MS;
64
+ const abortController = new AbortController();
65
+ const timeoutId = setTimeout(() => abortController.abort(), timeoutMs);
66
+ fetchInit.signal = abortController.signal;
67
+ let response;
68
+ try {
69
+ response = await fetch(fullUrl, fetchInit);
70
+ }
71
+ catch (e) {
72
+ const aborted = e instanceof Error &&
73
+ (e.name === "AbortError" || e.message.includes("aborted"));
74
+ if (aborted) {
75
+ throw new Error(`Request timed out after ${timeoutMs}ms (${fullUrl}). ` +
76
+ `If you run the Tailar web app locally, set API_BASE_URL in this project's .env, e.g. API_BASE_URL=http://localhost:3000/api/cli`);
77
+ }
78
+ throw e;
79
+ }
80
+ finally {
81
+ clearTimeout(timeoutId);
82
+ }
83
+ // Handle authentication errors
84
+ if (response.status === 401) {
85
+ if (requireAuth && attempt === 0) {
86
+ // Try to re-authenticate once
87
+ logger.warn("Authentication expired. Re-authenticating...");
88
+ await authenticate();
89
+ attempt++;
90
+ continue;
91
+ }
92
+ throw new Error("Authentication failed. Please run authentication again.");
93
+ }
94
+ // Handle subscription errors
95
+ if (response.status === 403) {
96
+ const errorData = (await response.json().catch(() => ({})));
97
+ const reason = errorData.reason || errorData.error || "Subscription required";
98
+ throw new Error(`Access denied: ${reason}\n` +
99
+ `Visit https://tailar.dev/choose-plan to upgrade your subscription.`);
100
+ }
101
+ // Handle not found errors
102
+ if (response.status === 404) {
103
+ const errorData = (await response.json().catch(() => ({})));
104
+ throw new Error(errorData.error || "Resource not found");
105
+ }
106
+ // Handle other errors
107
+ if (!response.ok) {
108
+ const errorData = (await response.json().catch(() => ({})));
109
+ throw new Error(errorData.error || `API request failed: ${response.statusText}`);
110
+ }
111
+ return (await response.json());
112
+ }
113
+ catch (error) {
114
+ lastError = error instanceof Error ? error : new Error(String(error));
115
+ // Don't retry on authentication/subscription errors
116
+ if (lastError.message.includes("Authentication") ||
117
+ lastError.message.includes("Access denied") ||
118
+ lastError.message.includes("not found")) {
119
+ throw lastError;
120
+ }
121
+ // Retry on network errors
122
+ if (attempt < retries) {
123
+ attempt++;
124
+ await new Promise((resolve) => setTimeout(resolve, RETRY_DELAY * attempt));
125
+ continue;
126
+ }
127
+ throw lastError;
128
+ }
129
+ }
130
+ throw lastError || new Error("API request failed");
131
+ }
132
+ /**
133
+ * Fetch registry.json from API
134
+ */
135
+ export async function fetchRegistry(options = {}) {
136
+ try {
137
+ const params = new URLSearchParams();
138
+ if (options.version) {
139
+ params.append("version", options.version);
140
+ }
141
+ const endpoint = `/registry${params.toString() ? `?${params.toString()}` : ""}`;
142
+ // Registry is public endpoint (no auth required)
143
+ const registry = await apiRequest(endpoint, {
144
+ requireAuth: false,
145
+ method: "GET",
146
+ });
147
+ return registry;
148
+ }
149
+ catch (error) {
150
+ logger.error(`Failed to fetch registry: ${error instanceof Error ? error.message : String(error)}`);
151
+ throw error;
152
+ }
153
+ }
154
+ /**
155
+ * Fetch a single component file from API
156
+ */
157
+ export async function fetchComponentFile(type, name, filePath, options = {}) {
158
+ try {
159
+ const params = new URLSearchParams();
160
+ params.append("path", filePath);
161
+ if (options.variant) {
162
+ params.append("variant", options.variant);
163
+ }
164
+ const endpoint = `/components/${type}/${name}/file?${params.toString()}`;
165
+ // If requireAuth is true, check authentication upfront and use auth headers from the start
166
+ // This prevents repeated authentication prompts for paid components
167
+ if (options.requireAuth === true) {
168
+ // Check if already authenticated
169
+ if (!(await isAuthenticated())) {
170
+ logger.info("Authentication required. Starting authentication flow...");
171
+ await authenticate();
172
+ }
173
+ // Use auth headers from the start
174
+ const response = await fetch(`${getApiBaseUrl()}${endpoint}`, {
175
+ method: "GET",
176
+ headers: {
177
+ "User-Agent": "tailar-cli",
178
+ ...(await getAuthHeaders()),
179
+ },
180
+ });
181
+ if (!response.ok) {
182
+ if (response.status === 403) {
183
+ const errorData = (await response.json().catch(() => ({})));
184
+ const reason = errorData.reason || errorData.error || "Subscription required";
185
+ throw new Error(`Access denied: ${reason}\n` +
186
+ `Visit https://tailar.dev/choose-plan to upgrade your subscription.`);
187
+ }
188
+ throw new Error(`Failed to fetch file: ${response.statusText}`);
189
+ }
190
+ return await response.text();
191
+ }
192
+ // For free components (requireAuth === false or undefined), try without auth first
193
+ // This allows free components to work without authentication
194
+ let response = await fetch(`${getApiBaseUrl()}${endpoint}`, {
195
+ method: "GET",
196
+ headers: {
197
+ "User-Agent": "tailar-cli",
198
+ },
199
+ });
200
+ // Handle 401 responses - component requires authentication
201
+ if (response.status === 401) {
202
+ // Try to authenticate and retry
203
+ logger.info("Authentication required. Starting authentication flow...");
204
+ await authenticate();
205
+ // Retry with auth headers
206
+ const retryResponse = await fetch(`${getApiBaseUrl()}${endpoint}`, {
207
+ method: "GET",
208
+ headers: {
209
+ "User-Agent": "tailar-cli",
210
+ ...(await getAuthHeaders()),
211
+ },
212
+ });
213
+ if (!retryResponse.ok) {
214
+ throw new Error(`Failed to fetch file: ${retryResponse.statusText}`);
215
+ }
216
+ return await retryResponse.text();
217
+ }
218
+ if (response.status === 403) {
219
+ const errorData = (await response.json().catch(() => ({})));
220
+ const reason = errorData.reason || errorData.error || "Subscription required";
221
+ throw new Error(`Access denied: ${reason}\n` +
222
+ `Visit https://tailar.dev/choose-plan to upgrade your subscription.`);
223
+ }
224
+ if (!response.ok) {
225
+ throw new Error(`Failed to fetch file: ${response.statusText}`);
226
+ }
227
+ return await response.text();
228
+ }
229
+ catch (error) {
230
+ if (error instanceof Error && error.message.includes("Access denied")) {
231
+ throw error;
232
+ }
233
+ logger.error(`Failed to fetch component file: ${error instanceof Error ? error.message : String(error)}`);
234
+ throw error;
235
+ }
236
+ }
237
+ /**
238
+ * Fetch component metadata from API
239
+ * @param requireAuth - If true, requires authentication (default: true for proper access checking)
240
+ */
241
+ export async function fetchComponentMetadata(type, name, requireAuth = true) {
242
+ try {
243
+ const endpoint = `/components/${type}/${name}`;
244
+ // Metadata endpoint requires auth for proper subscription checking
245
+ const metadata = await apiRequest(endpoint, {
246
+ requireAuth,
247
+ method: "GET",
248
+ });
249
+ return metadata;
250
+ }
251
+ catch (error) {
252
+ logger.error(`Failed to fetch component metadata: ${error instanceof Error ? error.message : String(error)}`);
253
+ throw error;
254
+ }
255
+ }
256
+ /**
257
+ * Check if user has access to a component (via metadata endpoint)
258
+ * @param registryEntry - Optional registry entry to check subscription requirements before API call
259
+ */
260
+ export async function checkSubscription(type, name, registryEntry) {
261
+ // If registry entry is provided and component doesn't require subscription, allow access immediately
262
+ if (registryEntry &&
263
+ (!registryEntry.requiresSubscription ||
264
+ (registryEntry.subscriptionTier || 0) === 0)) {
265
+ return { accessible: true };
266
+ }
267
+ try {
268
+ // For paid components or when registry entry is not provided, check via API
269
+ // Require auth for proper subscription checking
270
+ const metadata = await fetchComponentMetadata(type, name, true);
271
+ if (!metadata.requiresSubscription) {
272
+ return { accessible: true };
273
+ }
274
+ // For paid components, isAccessible must be explicitly true
275
+ // If it's false, undefined, or missing, deny access
276
+ // This handles the case where unauthenticated users get isAccessible: false
277
+ if (metadata.isAccessible !== true) {
278
+ // If isAccessible is explicitly false, use the reason from API
279
+ if (metadata.isAccessible === false && metadata.reason) {
280
+ return {
281
+ accessible: false,
282
+ reason: metadata.reason,
283
+ };
284
+ }
285
+ // isAccessible is false with no reason: server treated the request as anonymous.
286
+ // This happens when a locally-valid token was revoked server-side.
287
+ // If we have stored credentials, clear them and trigger a fresh auth flow.
288
+ const storedToken = await getStoredToken();
289
+ if (storedToken) {
290
+ logger.warn("Session revoked or expired. Re-authenticating...");
291
+ await clearToken();
292
+ await authenticate();
293
+ // Retry once with the new token
294
+ const retryMetadata = await fetchComponentMetadata(type, name, true);
295
+ if (!retryMetadata.requiresSubscription ||
296
+ retryMetadata.isAccessible === true) {
297
+ return { accessible: true };
298
+ }
299
+ return {
300
+ accessible: false,
301
+ reason: retryMetadata.reason ?? "Subscription required.",
302
+ };
303
+ }
304
+ return {
305
+ accessible: false,
306
+ reason: "Authentication and subscription required. Please authenticate first.",
307
+ };
308
+ }
309
+ return { accessible: true };
310
+ }
311
+ catch (error) {
312
+ // If authentication fails or API error, deny access
313
+ if (error instanceof Error &&
314
+ (error.message.includes("Authentication") ||
315
+ error.message.includes("Not authenticated") ||
316
+ error.message.includes("Authentication required"))) {
317
+ return {
318
+ accessible: false,
319
+ reason: "Authentication required. Please authenticate first.",
320
+ };
321
+ }
322
+ // For other errors, deny access
323
+ return {
324
+ accessible: false,
325
+ reason: error instanceof Error ? error.message : "Failed to verify access",
326
+ };
327
+ }
328
+ }
329
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../../src/api/client.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ /**
2
+ * Browser Utility
3
+ *
4
+ * Cross-platform browser opening functionality
5
+ */
6
+ /**
7
+ * Open URL in default browser
8
+ * Cross-platform support (macOS, Linux, Windows)
9
+ */
10
+ export declare function openBrowser(url: string): Promise<void>;
11
+ //# sourceMappingURL=browser.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.d.ts","sourceRoot":"","sources":["../../src/auth/browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAIH;;;GAGG;AACH,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiC5D"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * Browser Utility
3
+ *
4
+ * Cross-platform browser opening functionality
5
+ */
6
+ import { logger } from "../utils/logger.js";
7
+ /**
8
+ * Open URL in default browser
9
+ * Cross-platform support (macOS, Linux, Windows)
10
+ */
11
+ export async function openBrowser(url) {
12
+ try {
13
+ // Use Node.js built-in child_process for cross-platform support
14
+ const { exec } = await import("child_process");
15
+ const { promisify } = await import("util");
16
+ const execAsync = promisify(exec);
17
+ const platform = process.platform;
18
+ let command;
19
+ if (platform === "win32") {
20
+ // Windows
21
+ command = `start "" "${url}"`;
22
+ }
23
+ else if (platform === "darwin") {
24
+ // macOS
25
+ command = `open "${url}"`;
26
+ }
27
+ else {
28
+ // Linux and other Unix-like systems
29
+ command = `xdg-open "${url}"`;
30
+ }
31
+ await execAsync(command);
32
+ }
33
+ catch (error) {
34
+ // Fallback: try using 'open' package if available
35
+ try {
36
+ const open = (await import("open")).default;
37
+ await open(url);
38
+ }
39
+ catch (fallbackError) {
40
+ logger.error(`Failed to open browser: ${error}`);
41
+ logger.info(`Please open this URL manually: ${url}`);
42
+ throw new Error(`Could not open browser. Please visit: ${url}`);
43
+ }
44
+ }
45
+ }
46
+ //# sourceMappingURL=browser.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"browser.js","sourceRoot":"","sources":["../../src/auth/browser.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAEH,OAAO,EAAE,MAAM,EAAE,MAAM,oBAAoB,CAAC;AAE5C;;;GAGG;AACH,MAAM,CAAC,KAAK,UAAU,WAAW,CAAC,GAAW;IAC3C,IAAI,CAAC;QACH,gEAAgE;QAChE,MAAM,EAAE,IAAI,EAAE,GAAG,MAAM,MAAM,CAAC,eAAe,CAAC,CAAC;QAC/C,MAAM,EAAE,SAAS,EAAE,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;QAC3C,MAAM,SAAS,GAAG,SAAS,CAAC,IAAI,CAAC,CAAC;QAElC,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,CAAC;QAClC,IAAI,OAAe,CAAC;QAEpB,IAAI,QAAQ,KAAK,OAAO,EAAE,CAAC;YACzB,UAAU;YACV,OAAO,GAAG,aAAa,GAAG,GAAG,CAAC;QAChC,CAAC;aAAM,IAAI,QAAQ,KAAK,QAAQ,EAAE,CAAC;YACjC,QAAQ;YACR,OAAO,GAAG,SAAS,GAAG,GAAG,CAAC;QAC5B,CAAC;aAAM,CAAC;YACN,oCAAoC;YACpC,OAAO,GAAG,aAAa,GAAG,GAAG,CAAC;QAChC,CAAC;QAED,MAAM,SAAS,CAAC,OAAO,CAAC,CAAC;IAC3B,CAAC;IAAC,OAAO,KAAK,EAAE,CAAC;QACf,kDAAkD;QAClD,IAAI,CAAC;YACH,MAAM,IAAI,GAAG,CAAC,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC;YAC5C,MAAM,IAAI,CAAC,GAAG,CAAC,CAAC;QAClB,CAAC;QAAC,OAAO,aAAa,EAAE,CAAC;YACvB,MAAM,CAAC,KAAK,CAAC,2BAA2B,KAAK,EAAE,CAAC,CAAC;YACjD,MAAM,CAAC,IAAI,CAAC,kCAAkC,GAAG,EAAE,CAAC,CAAC;YACrD,MAAM,IAAI,KAAK,CAAC,yCAAyC,GAAG,EAAE,CAAC,CAAC;QAClE,CAAC;IACH,CAAC;AACH,CAAC"}
@@ -0,0 +1,28 @@
1
+ /**
2
+ * Auth Flow Module
3
+ *
4
+ * Handles CLI authentication via device code flow
5
+ */
6
+ import { type TokenData } from "./storage.js";
7
+ /**
8
+ * Generate device code and start authentication flow
9
+ */
10
+ export declare function authenticate(): Promise<TokenData>;
11
+ /**
12
+ * Refresh an expired access token
13
+ */
14
+ export declare function refreshToken(refreshTokenValue: string): Promise<TokenData>;
15
+ /**
16
+ * Get Authorization header with current valid token
17
+ * Automatically refreshes token if expired
18
+ */
19
+ export declare function getAuthHeaders(): Promise<Record<string, string>>;
20
+ /**
21
+ * Check if user is authenticated
22
+ */
23
+ export declare function isAuthenticated(): Promise<boolean>;
24
+ /**
25
+ * Logout (clear stored tokens)
26
+ */
27
+ export declare function logout(): Promise<void>;
28
+ //# sourceMappingURL=flow.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow.d.ts","sourceRoot":"","sources":["../../src/auth/flow.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AAMH,OAAO,EAKL,KAAK,SAAS,EACf,MAAM,cAAc,CAAC;AA4BtB;;GAEG;AACH,wBAAsB,YAAY,IAAI,OAAO,CAAC,SAAS,CAAC,CA+FvD;AAED;;GAEG;AACH,wBAAsB,YAAY,CAChC,iBAAiB,EAAE,MAAM,GACxB,OAAO,CAAC,SAAS,CAAC,CAsCpB;AAED;;;GAGG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAsBtE;AAED;;GAEG;AACH,wBAAsB,eAAe,IAAI,OAAO,CAAC,OAAO,CAAC,CAGxD;AAED;;GAEG;AACH,wBAAsB,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAG5C"}
@@ -0,0 +1,171 @@
1
+ /**
2
+ * Auth Flow Module
3
+ *
4
+ * Handles CLI authentication via device code flow
5
+ */
6
+ import fetch from "node-fetch";
7
+ import chalk from "chalk";
8
+ import { logger } from "../utils/logger.js";
9
+ import { openBrowser } from "./browser.js";
10
+ import { getStoredToken, saveToken, clearToken, isTokenValid, } from "./storage.js";
11
+ // Lazy-load API_BASE_URL to ensure .env file is loaded first
12
+ // This is a function because .env file is loaded after module imports
13
+ function getApiBaseUrl() {
14
+ return process.env.API_BASE_URL || "https://tailar.dev/api/cli";
15
+ }
16
+ const POLL_INTERVAL = 2000; // 2 seconds
17
+ const MAX_WAIT_TIME = 10 * 60 * 1000; // 10 minutes
18
+ /**
19
+ * Generate device code and start authentication flow
20
+ */
21
+ export async function authenticate() {
22
+ logger.info("Starting authentication...");
23
+ try {
24
+ // Step 1: Get device code
25
+ const deviceCodeResponse = await fetch(`${getApiBaseUrl()}/device-code`, {
26
+ method: "POST",
27
+ headers: {
28
+ "Content-Type": "application/json",
29
+ },
30
+ });
31
+ if (!deviceCodeResponse.ok) {
32
+ throw new Error(`Failed to get device code: ${deviceCodeResponse.statusText}`);
33
+ }
34
+ const deviceData = (await deviceCodeResponse.json());
35
+ logger.break();
36
+ logger.info("To authenticate, please visit:");
37
+ logger.log(` ${deviceData.verificationUrl}`);
38
+ logger.break();
39
+ logger.info("Enter this code when prompted:");
40
+ logger.log(` ${chalk.bold(deviceData.userCode)}`);
41
+ logger.break();
42
+ // Step 2: Open browser
43
+ try {
44
+ await openBrowser(deviceData.verificationUrl);
45
+ logger.info("Opening browser...");
46
+ }
47
+ catch (error) {
48
+ logger.warn("Could not open browser automatically");
49
+ logger.info(`Please visit: ${deviceData.verificationUrl}`);
50
+ }
51
+ // Step 3: Poll for authorization
52
+ const spinner = logger.spinner("Waiting for authorization...");
53
+ const startTime = Date.now();
54
+ while (Date.now() - startTime < MAX_WAIT_TIME) {
55
+ await new Promise((resolve) => setTimeout(resolve, POLL_INTERVAL));
56
+ const tokenResponse = await fetch(`${getApiBaseUrl()}/token`, {
57
+ method: "POST",
58
+ headers: {
59
+ "Content-Type": "application/json",
60
+ },
61
+ body: JSON.stringify({
62
+ deviceCode: deviceData.deviceCode,
63
+ grantType: "device_code",
64
+ }),
65
+ });
66
+ const tokenData = (await tokenResponse.json());
67
+ if ("error" in tokenData) {
68
+ if (tokenData.error === "authorization_pending") {
69
+ // Still waiting for authorization
70
+ continue;
71
+ }
72
+ else {
73
+ spinner.fail();
74
+ throw new Error(`Authentication failed: ${tokenData.error}`);
75
+ }
76
+ }
77
+ else {
78
+ // Success! We got tokens
79
+ spinner.succeed("Authorization successful!");
80
+ const expiresAt = Math.floor(Date.now() / 1000) + tokenData.expiresIn;
81
+ const tokenDataToStore = {
82
+ accessToken: tokenData.accessToken,
83
+ refreshToken: tokenData.refreshToken,
84
+ expiresAt,
85
+ };
86
+ await saveToken(tokenDataToStore);
87
+ logger.success("Authentication complete!");
88
+ return tokenDataToStore;
89
+ }
90
+ }
91
+ spinner.fail();
92
+ throw new Error("Authentication timeout. Please try again.");
93
+ }
94
+ catch (error) {
95
+ logger.error(`Authentication failed: ${error instanceof Error ? error.message : String(error)}`);
96
+ throw error;
97
+ }
98
+ }
99
+ /**
100
+ * Refresh an expired access token
101
+ */
102
+ export async function refreshToken(refreshTokenValue) {
103
+ try {
104
+ const response = await fetch(`${getApiBaseUrl()}/refresh`, {
105
+ method: "POST",
106
+ headers: {
107
+ "Content-Type": "application/json",
108
+ },
109
+ body: JSON.stringify({
110
+ refreshToken: refreshTokenValue,
111
+ }),
112
+ });
113
+ if (!response.ok) {
114
+ const errorData = (await response.json());
115
+ throw new Error(`Token refresh failed: ${errorData.error || response.statusText}`);
116
+ }
117
+ const tokenData = (await response.json());
118
+ const expiresAt = Math.floor(Date.now() / 1000) + tokenData.expiresIn;
119
+ const tokenDataToStore = {
120
+ accessToken: tokenData.accessToken,
121
+ refreshToken: tokenData.refreshToken,
122
+ expiresAt,
123
+ };
124
+ await saveToken(tokenDataToStore);
125
+ return tokenDataToStore;
126
+ }
127
+ catch (error) {
128
+ logger.error(`Token refresh failed: ${error instanceof Error ? error.message : String(error)}`);
129
+ throw error;
130
+ }
131
+ }
132
+ /**
133
+ * Get Authorization header with current valid token
134
+ * Automatically refreshes token if expired
135
+ */
136
+ export async function getAuthHeaders() {
137
+ let tokenData = await getStoredToken();
138
+ if (!tokenData) {
139
+ throw new Error("Not authenticated. Please run authentication first.");
140
+ }
141
+ // Check if token is expired or about to expire
142
+ if (!isTokenValid(tokenData)) {
143
+ logger.info("Token expired, refreshing...");
144
+ try {
145
+ tokenData = await refreshToken(tokenData.refreshToken);
146
+ }
147
+ catch (error) {
148
+ // Refresh failed, clear token and require re-authentication
149
+ await clearToken();
150
+ throw new Error("Token refresh failed. Please authenticate again.");
151
+ }
152
+ }
153
+ return {
154
+ Authorization: `Bearer ${tokenData.accessToken}`,
155
+ };
156
+ }
157
+ /**
158
+ * Check if user is authenticated
159
+ */
160
+ export async function isAuthenticated() {
161
+ const tokenData = await getStoredToken();
162
+ return tokenData !== null && isTokenValid(tokenData);
163
+ }
164
+ /**
165
+ * Logout (clear stored tokens)
166
+ */
167
+ export async function logout() {
168
+ await clearToken();
169
+ logger.success("Logged out successfully");
170
+ }
171
+ //# sourceMappingURL=flow.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"flow.js","sourceRoot":"","sources":["../../src/auth/flow.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,30 @@
1
+ /**
2
+ * Auth Storage Module
3
+ *
4
+ * Handles storing and retrieving CLI authentication tokens
5
+ * Platform-specific path resolution for credentials file
6
+ */
7
+ export interface TokenData {
8
+ accessToken: string;
9
+ refreshToken: string;
10
+ expiresAt: number;
11
+ userId?: string;
12
+ email?: string;
13
+ }
14
+ /**
15
+ * Read stored token from credentials file
16
+ */
17
+ export declare function getStoredToken(): Promise<TokenData | null>;
18
+ /**
19
+ * Save token to credentials file
20
+ */
21
+ export declare function saveToken(tokenData: TokenData): Promise<void>;
22
+ /**
23
+ * Clear stored token (delete credentials file)
24
+ */
25
+ export declare function clearToken(): Promise<void>;
26
+ /**
27
+ * Check if token exists and is not expired
28
+ */
29
+ export declare function isTokenValid(tokenData: TokenData | null): boolean;
30
+ //# sourceMappingURL=storage.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../src/auth/storage.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAQH,MAAM,WAAW,SAAS;IACxB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AA8BD;;GAEG;AACH,wBAAsB,cAAc,IAAI,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CA2BhE;AAED;;GAEG;AACH,wBAAsB,SAAS,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC,IAAI,CAAC,CAuBnE;AAED;;GAEG;AACH,wBAAsB,UAAU,IAAI,OAAO,CAAC,IAAI,CAAC,CAUhD;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,SAAS,EAAE,SAAS,GAAG,IAAI,GAAG,OAAO,CAUjE"}