@beaulewis/saas-cli 1.0.0 → 1.0.2

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 (48) hide show
  1. package/README.md +121 -2
  2. package/dist/chunk-FGZ7PLMQ.js +38 -0
  3. package/dist/chunk-FGZ7PLMQ.js.map +1 -0
  4. package/dist/{chunk-5BCEXHNM.js → chunk-JTMQREZ6.js} +57 -38
  5. package/dist/chunk-JTMQREZ6.js.map +1 -0
  6. package/dist/chunk-N2ONDKDL.js +28 -0
  7. package/dist/chunk-N2ONDKDL.js.map +1 -0
  8. package/dist/{chunk-N4OIAZSA.js → chunk-O53ZYAOB.js} +6 -4
  9. package/dist/{chunk-N4OIAZSA.js.map → chunk-O53ZYAOB.js.map} +1 -1
  10. package/dist/{chunk-3KD5CFV3.js → chunk-T7ZSH2YP.js} +2 -2
  11. package/dist/{chunk-ZD2ZSBK3.js → chunk-VG47XMO6.js} +158 -11
  12. package/dist/chunk-VG47XMO6.js.map +1 -0
  13. package/dist/{dart-DXLFNGHR.js → dart-WFKEB4KF.js} +5 -4
  14. package/dist/{dart-DXLFNGHR.js.map → dart-WFKEB4KF.js.map} +1 -1
  15. package/dist/{drift-XYY4D366.js → drift-XIAPJPJ4.js} +10 -5
  16. package/dist/drift-XIAPJPJ4.js.map +1 -0
  17. package/dist/error-U45TQYWL.js +20 -0
  18. package/dist/error-U45TQYWL.js.map +1 -0
  19. package/dist/{flutter-J5BYPVIW.js → flutter-PUTNWBGH.js} +5 -4
  20. package/dist/{flutter-J5BYPVIW.js.map → flutter-PUTNWBGH.js.map} +1 -1
  21. package/dist/{freezed-QXFQ4GJC.js → freezed-RF4SOWLU.js} +9 -4
  22. package/dist/freezed-RF4SOWLU.js.map +1 -0
  23. package/dist/{gorouter-QBMTTFVR.js → gorouter-F5XDDQPJ.js} +9 -4
  24. package/dist/gorouter-F5XDDQPJ.js.map +1 -0
  25. package/dist/index.js +166 -105
  26. package/dist/index.js.map +1 -1
  27. package/dist/{package-QO75XHBD.js → package-IKHU3CJM.js} +5 -4
  28. package/dist/{package-QO75XHBD.js.map → package-IKHU3CJM.js.map} +1 -1
  29. package/dist/{powersync-I3LR7TDN.js → powersync-P7WQ7LFM.js} +9 -4
  30. package/dist/powersync-P7WQ7LFM.js.map +1 -0
  31. package/dist/{repository-BAOVD3NG.js → repository-7F22RXMA.js} +9 -4
  32. package/dist/repository-7F22RXMA.js.map +1 -0
  33. package/dist/{riverpod-XUU656PM.js → riverpod-6JWBNWS4.js} +9 -4
  34. package/dist/riverpod-6JWBNWS4.js.map +1 -0
  35. package/dist/types-VBEUX6S5.js +11 -0
  36. package/dist/types-VBEUX6S5.js.map +1 -0
  37. package/dist/{widget-YDKHPRXM.js → widget-JPM73WJ2.js} +5 -4
  38. package/dist/{widget-YDKHPRXM.js.map → widget-JPM73WJ2.js.map} +1 -1
  39. package/package.json +2 -1
  40. package/dist/chunk-5BCEXHNM.js.map +0 -1
  41. package/dist/chunk-ZD2ZSBK3.js.map +0 -1
  42. package/dist/drift-XYY4D366.js.map +0 -1
  43. package/dist/freezed-QXFQ4GJC.js.map +0 -1
  44. package/dist/gorouter-QBMTTFVR.js.map +0 -1
  45. package/dist/powersync-I3LR7TDN.js.map +0 -1
  46. package/dist/repository-BAOVD3NG.js.map +0 -1
  47. package/dist/riverpod-XUU656PM.js.map +0 -1
  48. /package/dist/{chunk-3KD5CFV3.js.map → chunk-T7ZSH2YP.js.map} +0 -0
package/README.md CHANGED
@@ -7,9 +7,11 @@
7
7
  Live documentation · AI-powered assistance · Code generation · Backend integrations
8
8
 
9
9
  [![npm version](https://img.shields.io/npm/v/@beaulewis/saas-cli.svg?style=flat-square)](https://www.npmjs.com/package/@beaulewis/saas-cli)
10
+ [![npm downloads](https://img.shields.io/npm/dm/@beaulewis/saas-cli.svg?style=flat-square)](https://www.npmjs.com/package/@beaulewis/saas-cli)
10
11
  [![license](https://img.shields.io/npm/l/@beaulewis/saas-cli.svg?style=flat-square)](https://github.com/Beaulewis1977/saas-cli/blob/main/LICENSE)
11
- [![CI](https://img.shields.io/github/actions/workflow/status/Beaulewis1977/saas-cli/ci.yml?branch=main&style=flat-square&label=CI)](https://github.com/Beaulewis1977/saas-cli/actions/workflows/ci.yml)
12
+ [![CI](https://img.shields.io/github/actions/workflow/status/Beaulewis1977/saas-cli/ci.yml?branch=develop&style=flat-square&label=CI)](https://github.com/Beaulewis1977/saas-cli/actions/workflows/ci.yml)
12
13
  [![node](https://img.shields.io/node/v/@beaulewis/saas-cli.svg?style=flat-square)](https://nodejs.org)
14
+ [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](https://github.com/Beaulewis1977/saas-cli/pulls)
13
15
 
14
16
  </div>
15
17
 
@@ -18,6 +20,7 @@ Live documentation · AI-powered assistance · Code generation · Backend integr
18
20
  ## Table of Contents
19
21
 
20
22
  - [Features](#features)
23
+ - [Requirements](#requirements)
21
24
  - [Installation](#installation)
22
25
  - [Quick Start](#quick-start)
23
26
  - [Commands](#commands)
@@ -53,6 +56,39 @@ Live documentation · AI-powered assistance · Code generation · Backend integr
53
56
 
54
57
  ---
55
58
 
59
+ ## Requirements
60
+
61
+ ### Core Requirement
62
+
63
+ - **Node.js 20+** - [Download](https://nodejs.org/)
64
+
65
+ ### External CLI Dependencies
66
+
67
+ Some commands require external CLIs to be installed. The table below shows which CLIs are needed for each command:
68
+
69
+ | Command | Required CLI | Installation |
70
+ |---------|--------------|--------------|
71
+ | `saas init flutter` | Flutter SDK | [flutter.dev/get-started/install](https://docs.flutter.dev/get-started/install) |
72
+ | `saas init add` | Flutter SDK | [flutter.dev/get-started/install](https://docs.flutter.dev/get-started/install) |
73
+ | `saas init worker` | Wrangler CLI | `npm install -g wrangler` |
74
+ | `saas init supabase` | Supabase CLI | `npm install -g supabase` or `brew install supabase/tap/supabase` |
75
+ | `saas video *` | FFmpeg | `brew install ffmpeg` (macOS) or `apt install ffmpeg` (Linux) |
76
+ | `saas cf *` | Wrangler CLI | `npm install -g wrangler` |
77
+ | `saas supabase *` | Supabase CLI | `npm install -g supabase` or `brew install supabase/tap/supabase` |
78
+
79
+ ### Commands Without External Dependencies
80
+
81
+ These commands work out of the box with just Node.js:
82
+
83
+ - `saas docs` - Documentation lookup (requires `CONTEXT7_API_KEY`)
84
+ - `saas ask` - AI questions (requires `PERPLEXITY_API_KEY`)
85
+ - `saas gen` - Code generation
86
+ - `saas redis` - Redis management (requires `REDIS_URL`)
87
+ - `saas push` - Push notifications (requires OneSignal keys)
88
+ - `saas flags` - Feature flags (requires PostHog keys)
89
+
90
+ ---
91
+
56
92
  ## Installation
57
93
 
58
94
  ```bash
@@ -273,7 +309,86 @@ saas init add riverpod,drift,freezed
273
309
 
274
310
  ## Environment Variables
275
311
 
276
- Create a `.env` file in your project root or set these in your shell configuration.
312
+ The CLI reads environment variables for API keys and service credentials. You have two options:
313
+
314
+ ### Option 1: Project `.env` File (Recommended)
315
+
316
+ Create a `.env` file in your project directory. This allows different API keys per project.
317
+
318
+ ```bash
319
+ # Create .env in your project root (add to .gitignore!)
320
+ touch .env
321
+ ```
322
+
323
+ **Copy this template into your `.env` file:**
324
+
325
+ ```ini
326
+ # Documentation (Context7)
327
+ CONTEXT7_API_KEY=
328
+
329
+ # AI Questions (Perplexity)
330
+ PERPLEXITY_API_KEY=
331
+
332
+ # Supabase
333
+ SUPABASE_PROJECT_REF=
334
+ SUPABASE_ACCESS_TOKEN=
335
+
336
+ # Redis
337
+ REDIS_URL=
338
+
339
+ # Cloudflare Workers
340
+ CF_API_TOKEN=
341
+
342
+ # Push Notifications (OneSignal)
343
+ ONESIGNAL_APP_ID=
344
+ ONESIGNAL_API_KEY=
345
+
346
+ # Feature Flags (PostHog)
347
+ POSTHOG_API_KEY=
348
+ POSTHOG_PROJECT_ID=
349
+ ```
350
+
351
+ **Add `.env` to your `.gitignore` to avoid committing secrets:**
352
+
353
+ ```gitignore
354
+ .env
355
+ ```
356
+
357
+ ### Option 2: Shell Exports (Global)
358
+
359
+ Add these to your `~/.bashrc`, `~/.zshrc`, or shell config for system-wide access:
360
+
361
+ ```bash
362
+ # Documentation (Context7)
363
+ export CONTEXT7_API_KEY="your-key-here"
364
+
365
+ # AI Questions (Perplexity)
366
+ export PERPLEXITY_API_KEY="pplx-your-key-here"
367
+
368
+ # Supabase
369
+ export SUPABASE_PROJECT_REF="your-project-ref"
370
+ export SUPABASE_ACCESS_TOKEN="your-access-token"
371
+
372
+ # Redis
373
+ export REDIS_URL="redis://localhost:6379"
374
+
375
+ # Cloudflare Workers
376
+ export CF_API_TOKEN="your-cloudflare-token"
377
+
378
+ # Push Notifications (OneSignal)
379
+ export ONESIGNAL_APP_ID="your-app-id"
380
+ export ONESIGNAL_API_KEY="your-api-key"
381
+
382
+ # Feature Flags (PostHog)
383
+ export POSTHOG_API_KEY="your-posthog-key"
384
+ export POSTHOG_PROJECT_ID="your-project-id"
385
+ ```
386
+
387
+ After adding, reload your shell: `source ~/.bashrc` or `source ~/.zshrc`
388
+
389
+ > **Note:** Shell-exported environment variables take precedence over `.env` file values. If you have both, the shell export wins.
390
+
391
+ ### Variable Reference
277
392
 
278
393
  | Variable | Description | Required For |
279
394
  |----------|-------------|--------------|
@@ -328,6 +443,10 @@ This CLI executes external tools (FFmpeg, Wrangler, Flutter, Supabase CLI) via s
328
443
 
329
444
  Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md) for development guidelines.
330
445
 
446
+ - **Bug reports:** [Open an issue](https://github.com/Beaulewis1977/saas-cli/issues/new)
447
+ - **Feature requests:** [Start a discussion](https://github.com/Beaulewis1977/saas-cli/discussions)
448
+ - **Pull requests:** Fork, create a branch, and submit a PR
449
+
331
450
  ```bash
332
451
  # Clone and install
333
452
  git clone https://github.com/Beaulewis1977/saas-cli.git
@@ -0,0 +1,38 @@
1
+ // src/types/index.ts
2
+ var MODEL_ALIASES = {
3
+ sonar: "sonar",
4
+ pro: "sonar-pro",
5
+ reasoning: "sonar-reasoning-pro",
6
+ deep: "sonar-deep-research"
7
+ };
8
+ var LIBRARY_IDS = {
9
+ flutter: "/websites/flutter_cn",
10
+ dart: "/websites/dart_dev",
11
+ riverpod: "/rrousselgit/riverpod",
12
+ drift: "/simolus3/drift",
13
+ go_router: "/websites/flutter_cn",
14
+ gorouter: "/websites/flutter_cn",
15
+ supabase: "/supabase/supabase-js",
16
+ powersync: "/powersync-ja/powersync-js",
17
+ freezed: "/rrousselgit/freezed",
18
+ bloc: "/felangel/bloc",
19
+ dio: "/cfug/dio",
20
+ hive: "/isar/hive",
21
+ isar: "/isar/isar",
22
+ firebase: "/firebase/flutterfire"
23
+ };
24
+ var EXIT_CODES = {
25
+ SUCCESS: 0,
26
+ GENERAL_ERROR: 1,
27
+ USAGE_ERROR: 2,
28
+ CONFIG_ERROR: 3,
29
+ NETWORK_ERROR: 4,
30
+ AUTH_ERROR: 5
31
+ };
32
+
33
+ export {
34
+ MODEL_ALIASES,
35
+ LIBRARY_IDS,
36
+ EXIT_CODES
37
+ };
38
+ //# sourceMappingURL=chunk-FGZ7PLMQ.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/types/index.ts"],"sourcesContent":["/**\n * Global CLI configuration stored in ~/.config/saas-cli/config.yaml\n */\nexport interface GlobalConfig {\n context7?: {\n enabled?: boolean;\n apiKey?: string;\n };\n perplexity?: {\n apiKey?: string;\n defaultModel?: PerplexityModel;\n };\n supabase?: {\n projectRef?: string;\n url?: string;\n serviceKey?: string;\n };\n redis?: {\n url?: string;\n };\n cloudflare?: {\n accountId?: string;\n apiToken?: string;\n };\n onesignal?: {\n appId?: string;\n apiKey?: string;\n };\n posthog?: {\n projectId?: string;\n apiKey?: string;\n };\n defaults?: {\n outputFormat?: OutputFormat;\n cacheTtl?: number;\n };\n}\n\n/**\n * Project-level configuration stored in ./saas.yaml\n */\nexport interface ProjectConfig {\n project?: {\n name?: string;\n type?: 'flutter' | 'dart' | 'other';\n };\n flutter?: {\n path?: string;\n };\n supabase?: {\n path?: string;\n typesOutput?: string;\n };\n templates?: Record<string, { path: string }>;\n}\n\n/**\n * Output format options\n */\nexport type OutputFormat = 'pretty' | 'json' | 'minimal';\n\n/**\n * Global CLI options available on all commands\n */\nexport interface GlobalOptions {\n json?: boolean;\n verbose?: boolean;\n debug?: boolean;\n}\n\n/**\n * Perplexity AI model options\n */\nexport type PerplexityModel = 'sonar' | 'sonar-pro' | 'sonar-reasoning-pro' | 'sonar-deep-research';\n\n/**\n * Model aliases for user-friendly names\n */\nexport const MODEL_ALIASES: Record<string, PerplexityModel> = {\n sonar: 'sonar',\n pro: 'sonar-pro',\n reasoning: 'sonar-reasoning-pro',\n deep: 'sonar-deep-research',\n};\n\n/**\n * Context7 library ID mapping for common Flutter/Dart packages\n */\nexport const LIBRARY_IDS: Record<string, string> = {\n flutter: '/websites/flutter_cn',\n dart: '/websites/dart_dev',\n riverpod: '/rrousselgit/riverpod',\n drift: '/simolus3/drift',\n go_router: '/websites/flutter_cn',\n gorouter: '/websites/flutter_cn',\n supabase: '/supabase/supabase-js',\n powersync: '/powersync-ja/powersync-js',\n freezed: '/rrousselgit/freezed',\n bloc: '/felangel/bloc',\n dio: '/cfug/dio',\n hive: '/isar/hive',\n isar: '/isar/isar',\n firebase: '/firebase/flutterfire',\n};\n\n/**\n * Context7 API response types\n */\nexport interface Context7SearchResult {\n libraryId: string;\n name?: string;\n description?: string;\n}\n\nexport interface Context7DocsResult {\n content: string;\n source?: string;\n title?: string;\n}\n\n/**\n * Perplexity API response types\n */\nexport interface PerplexityResponse {\n choices: Array<{\n message: {\n content: string;\n role: string;\n };\n }>;\n citations?: string[];\n usage: {\n prompt_tokens: number;\n completion_tokens: number;\n };\n}\n\nexport interface PerplexityAskOptions {\n model?: PerplexityModel;\n maxTokens?: number;\n temperature?: number;\n searchRecencyFilter?: 'day' | 'week' | 'month' | 'year';\n searchDomainFilter?: string[];\n returnSources?: boolean;\n}\n\n/**\n * Column specification for code generation\n */\nexport interface ColumnSpec {\n name: string;\n type: string;\n isPrimaryKey?: boolean;\n isForeignKey?: boolean;\n foreignKeyTable?: string;\n foreignKeyColumn?: string;\n isNullable?: boolean;\n defaultValue?: string;\n isAutoIncrement?: boolean;\n}\n\n/**\n * RLS policy types for Supabase\n */\nexport type RLSPolicyType = 'user-owned' | 'team-owned' | 'public-read' | 'admin-only';\n\n/**\n * Command exit codes\n */\nexport const EXIT_CODES = {\n SUCCESS: 0,\n GENERAL_ERROR: 1,\n USAGE_ERROR: 2,\n CONFIG_ERROR: 3,\n NETWORK_ERROR: 4,\n AUTH_ERROR: 5,\n} as const;\n\nexport type ExitCode = (typeof EXIT_CODES)[keyof typeof EXIT_CODES];\n"],"mappings":";AA8EO,IAAM,gBAAiD;AAAA,EAC5D,OAAO;AAAA,EACP,KAAK;AAAA,EACL,WAAW;AAAA,EACX,MAAM;AACR;AAKO,IAAM,cAAsC;AAAA,EACjD,SAAS;AAAA,EACT,MAAM;AAAA,EACN,UAAU;AAAA,EACV,OAAO;AAAA,EACP,WAAW;AAAA,EACX,UAAU;AAAA,EACV,UAAU;AAAA,EACV,WAAW;AAAA,EACX,SAAS;AAAA,EACT,MAAM;AAAA,EACN,KAAK;AAAA,EACL,MAAM;AAAA,EACN,MAAM;AAAA,EACN,UAAU;AACZ;AAkEO,IAAM,aAAa;AAAA,EACxB,SAAS;AAAA,EACT,eAAe;AAAA,EACf,aAAa;AAAA,EACb,cAAc;AAAA,EACd,eAAe;AAAA,EACf,YAAY;AACd;","names":[]}
@@ -1,39 +1,9 @@
1
- // src/utils/error.ts
2
- import pc from "picocolors";
3
-
4
- // src/types/index.ts
5
- var MODEL_ALIASES = {
6
- sonar: "sonar",
7
- pro: "sonar-pro",
8
- reasoning: "sonar-reasoning-pro",
9
- deep: "sonar-deep-research"
10
- };
11
- var LIBRARY_IDS = {
12
- flutter: "/websites/flutter_cn",
13
- dart: "/websites/dart_dev",
14
- riverpod: "/rrousselgit/riverpod",
15
- drift: "/simolus3/drift",
16
- go_router: "/websites/flutter_cn",
17
- gorouter: "/websites/flutter_cn",
18
- supabase: "/supabase/supabase-js",
19
- powersync: "/powersync-ja/powersync-js",
20
- freezed: "/rrousselgit/freezed",
21
- bloc: "/felangel/bloc",
22
- dio: "/cfug/dio",
23
- hive: "/isar/hive",
24
- isar: "/isar/isar",
25
- firebase: "/firebase/flutterfire"
26
- };
27
- var EXIT_CODES = {
28
- SUCCESS: 0,
29
- GENERAL_ERROR: 1,
30
- USAGE_ERROR: 2,
31
- CONFIG_ERROR: 3,
32
- NETWORK_ERROR: 4,
33
- AUTH_ERROR: 5
34
- };
1
+ import {
2
+ EXIT_CODES
3
+ } from "./chunk-FGZ7PLMQ.js";
35
4
 
36
5
  // src/utils/error.ts
6
+ import pc from "picocolors";
37
7
  var CLIError = class extends Error {
38
8
  constructor(message, exitCode = EXIT_CODES.GENERAL_ERROR, hint, seeAlso) {
39
9
  super(message);
@@ -95,14 +65,63 @@ function handleError(error) {
95
65
  console.error(pc.dim(String(error)));
96
66
  process.exit(EXIT_CODES.GENERAL_ERROR);
97
67
  }
68
+ function createAPIErrorHandler(service) {
69
+ return (error) => {
70
+ if (error instanceof APIError) {
71
+ handleError(error);
72
+ }
73
+ if (error && typeof error === "object" && "response" in error) {
74
+ const response = error.response;
75
+ const statusCode = response?.statusCode;
76
+ let hint;
77
+ switch (statusCode) {
78
+ case 401:
79
+ hint = `Check your ${service.toUpperCase()}_API_KEY environment variable`;
80
+ break;
81
+ case 403:
82
+ hint = `Your API key may not have permission for this operation`;
83
+ break;
84
+ case 429:
85
+ hint = `Rate limited. Wait a moment and try again`;
86
+ break;
87
+ case 404:
88
+ hint = `Resource not found. Check if the library or endpoint exists`;
89
+ break;
90
+ case 500:
91
+ case 502:
92
+ case 503:
93
+ hint = `${service} service is temporarily unavailable. Try again later`;
94
+ break;
95
+ }
96
+ const apiError = new APIError(
97
+ `${service} API request failed (${statusCode})`,
98
+ service,
99
+ statusCode,
100
+ hint
101
+ );
102
+ handleError(apiError);
103
+ }
104
+ const message = error instanceof Error ? error.message : String(error);
105
+ handleError(new APIError(message, service));
106
+ };
107
+ }
108
+ function withErrorHandler(fn) {
109
+ return async (...args) => {
110
+ try {
111
+ return await fn(...args);
112
+ } catch (error) {
113
+ handleError(error);
114
+ }
115
+ };
116
+ }
98
117
 
99
118
  export {
100
- MODEL_ALIASES,
101
- LIBRARY_IDS,
102
119
  CLIError,
103
120
  APIError,
104
121
  ConfigError,
105
122
  AuthError,
106
- handleError
123
+ handleError,
124
+ createAPIErrorHandler,
125
+ withErrorHandler
107
126
  };
108
- //# sourceMappingURL=chunk-5BCEXHNM.js.map
127
+ //# sourceMappingURL=chunk-JTMQREZ6.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/error.ts"],"sourcesContent":["import pc from 'picocolors';\nimport { EXIT_CODES, type ExitCode } from '../types/index.js';\n\n/**\n * Custom CLI error with exit code and helpful hints\n */\nexport class CLIError extends Error {\n constructor(\n message: string,\n public exitCode: ExitCode = EXIT_CODES.GENERAL_ERROR,\n public hint?: string,\n public seeAlso?: string,\n ) {\n super(message);\n this.name = 'CLIError';\n }\n}\n\n/**\n * API-specific error with service context\n */\nexport class APIError extends CLIError {\n constructor(\n message: string,\n public service: string,\n public statusCode?: number,\n hint?: string,\n ) {\n super(message, EXIT_CODES.NETWORK_ERROR, hint);\n this.name = 'APIError';\n }\n}\n\n/**\n * Configuration error\n */\nexport class ConfigError extends CLIError {\n constructor(message: string, hint?: string) {\n super(message, EXIT_CODES.CONFIG_ERROR, hint);\n this.name = 'ConfigError';\n }\n}\n\n/**\n * Authentication error\n */\nexport class AuthError extends CLIError {\n constructor(message: string, hint?: string) {\n super(message, EXIT_CODES.AUTH_ERROR, hint);\n this.name = 'AuthError';\n }\n}\n\n/**\n * Format error message for display\n */\nfunction formatError(error: CLIError): string {\n const lines: string[] = [];\n\n // Main error message\n lines.push(pc.red(`Error: ${error.message}`));\n\n // Add hint if available\n if (error.hint) {\n lines.push(pc.yellow(`Hint: ${error.hint}`));\n }\n\n // Add see also if available\n if (error.seeAlso) {\n lines.push(pc.dim(`See: ${error.seeAlso}`));\n }\n\n return lines.join('\\n');\n}\n\n/**\n * Handle errors and exit appropriately\n */\nexport function handleError(error: unknown): never {\n // Handle CLIError instances\n if (error instanceof CLIError) {\n console.error(formatError(error));\n\n // Show stack trace in debug mode\n if (process.env.DEBUG) {\n console.error(pc.dim('\\nStack trace:'));\n console.error(pc.dim(error.stack ?? ''));\n }\n\n process.exit(error.exitCode);\n }\n\n // Handle standard errors\n if (error instanceof Error) {\n console.error(pc.red(`Error: ${error.message}`));\n\n if (process.env.DEBUG) {\n console.error(pc.dim('\\nStack trace:'));\n console.error(pc.dim(error.stack ?? ''));\n }\n\n process.exit(EXIT_CODES.GENERAL_ERROR);\n }\n\n // Handle unknown errors\n console.error(pc.red('An unexpected error occurred'));\n console.error(pc.dim(String(error)));\n process.exit(EXIT_CODES.GENERAL_ERROR);\n}\n\n/**\n * Create an API error handler for a specific service\n */\nexport function createAPIErrorHandler(service: string) {\n return (error: unknown): never => {\n if (error instanceof APIError) {\n handleError(error);\n }\n\n // Handle got/HTTP errors\n if (error && typeof error === 'object' && 'response' in error) {\n const response = (error as { response?: { statusCode?: number; body?: unknown } }).response;\n const statusCode = response?.statusCode;\n\n let hint: string | undefined;\n\n switch (statusCode) {\n case 401:\n hint = `Check your ${service.toUpperCase()}_API_KEY environment variable`;\n break;\n case 403:\n hint = `Your API key may not have permission for this operation`;\n break;\n case 429:\n hint = `Rate limited. Wait a moment and try again`;\n break;\n case 404:\n hint = `Resource not found. Check if the library or endpoint exists`;\n break;\n case 500:\n case 502:\n case 503:\n hint = `${service} service is temporarily unavailable. Try again later`;\n break;\n }\n\n const apiError = new APIError(\n `${service} API request failed (${statusCode})`,\n service,\n statusCode,\n hint,\n );\n\n handleError(apiError);\n }\n\n // Re-throw as generic API error\n const message = error instanceof Error ? error.message : String(error);\n handleError(new APIError(message, service));\n };\n}\n\n/**\n * Wrap an async function with error handling\n */\nexport function withErrorHandler<T extends (...args: unknown[]) => Promise<unknown>>(\n fn: T,\n): (...args: Parameters<T>) => Promise<Awaited<ReturnType<T>>> {\n return async (...args: Parameters<T>): Promise<Awaited<ReturnType<T>>> => {\n try {\n return (await fn(...args)) as Awaited<ReturnType<T>>;\n } catch (error) {\n handleError(error);\n }\n };\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,28 @@
1
+ import {
2
+ CLIError
3
+ } from "./chunk-JTMQREZ6.js";
4
+ import {
5
+ EXIT_CODES
6
+ } from "./chunk-FGZ7PLMQ.js";
7
+
8
+ // src/utils/path.ts
9
+ import { isAbsolute, normalize, relative, resolve, sep } from "path";
10
+ function validateOutputPath(userPath, baseDir = process.cwd()) {
11
+ const normalizedBase = normalize(resolve(baseDir));
12
+ const normalizedPath = normalize(resolve(baseDir, userPath));
13
+ const relativePath = relative(normalizedBase, normalizedPath);
14
+ const escapesBase = relativePath === ".." || relativePath.startsWith(`..${sep}`) || isAbsolute(relativePath);
15
+ if (escapesBase) {
16
+ throw new CLIError(
17
+ `Output path escapes project directory: "${userPath}"`,
18
+ EXIT_CODES.GENERAL_ERROR,
19
+ 'Output path must be within the current project directory. Use relative paths like "./lib/output.dart".'
20
+ );
21
+ }
22
+ return normalizedPath;
23
+ }
24
+
25
+ export {
26
+ validateOutputPath
27
+ };
28
+ //# sourceMappingURL=chunk-N2ONDKDL.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/utils/path.ts"],"sourcesContent":["import { isAbsolute, normalize, relative, resolve, sep } from 'node:path';\nimport { EXIT_CODES } from '../types/index.js';\nimport { CLIError } from './error.js';\n\n/**\n * Validate and normalize an output file path, preventing path traversal attacks.\n * Ensures the output path is within the specified base directory (defaults to cwd).\n *\n * @param userPath - The user-provided output path\n * @param baseDir - The base directory to restrict output to (defaults to process.cwd())\n * @returns The normalized absolute path if valid\n * @throws CLIError if the path escapes the base directory\n */\nexport function validateOutputPath(userPath: string, baseDir: string = process.cwd()): string {\n // Normalize and resolve the path\n const normalizedBase = normalize(resolve(baseDir));\n const normalizedPath = normalize(resolve(baseDir, userPath));\n\n // Check if the resolved path is within the base directory\n const relativePath = relative(normalizedBase, normalizedPath);\n\n // Segment-aware check: reject '..' or '../...' but allow '..hidden' filenames\n const escapesBase =\n relativePath === '..' || relativePath.startsWith(`..${sep}`) || isAbsolute(relativePath);\n\n if (escapesBase) {\n throw new CLIError(\n `Output path escapes project directory: \"${userPath}\"`,\n EXIT_CODES.GENERAL_ERROR,\n 'Output path must be within the current project directory. Use relative paths like \"./lib/output.dart\".',\n );\n }\n\n return normalizedPath;\n}\n"],"mappings":";;;;;;;;AAAA,SAAS,YAAY,WAAW,UAAU,SAAS,WAAW;AAavD,SAAS,mBAAmB,UAAkB,UAAkB,QAAQ,IAAI,GAAW;AAE5F,QAAM,iBAAiB,UAAU,QAAQ,OAAO,CAAC;AACjD,QAAM,iBAAiB,UAAU,QAAQ,SAAS,QAAQ,CAAC;AAG3D,QAAM,eAAe,SAAS,gBAAgB,cAAc;AAG5D,QAAM,cACJ,iBAAiB,QAAQ,aAAa,WAAW,KAAK,GAAG,EAAE,KAAK,WAAW,YAAY;AAEzF,MAAI,aAAa;AACf,UAAM,IAAI;AAAA,MACR,2CAA2C,QAAQ;AAAA,MACnD,WAAW;AAAA,MACX;AAAA,IACF;AAAA,EACF;AAEA,SAAO;AACT;","names":[]}
@@ -2,11 +2,13 @@ import {
2
2
  cacheKey,
3
3
  cachedFetch,
4
4
  createAuthenticatedClient
5
- } from "./chunk-3KD5CFV3.js";
5
+ } from "./chunk-T7ZSH2YP.js";
6
+ import {
7
+ APIError
8
+ } from "./chunk-JTMQREZ6.js";
6
9
  import {
7
- APIError,
8
10
  LIBRARY_IDS
9
- } from "./chunk-5BCEXHNM.js";
11
+ } from "./chunk-FGZ7PLMQ.js";
10
12
 
11
13
  // src/services/context7.ts
12
14
  var CONTEXT7_BASE_URL = "https://context7.com/api/v2";
@@ -107,4 +109,4 @@ function getContext7Client(apiKey) {
107
109
  export {
108
110
  getContext7Client
109
111
  };
110
- //# sourceMappingURL=chunk-N4OIAZSA.js.map
112
+ //# sourceMappingURL=chunk-O53ZYAOB.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/services/context7.ts"],"sourcesContent":["import type { Got } from 'got';\nimport { LIBRARY_IDS } from '../types/index.js';\nimport { cachedFetch, cacheKey } from '../utils/cache.js';\nimport { APIError } from '../utils/error.js';\nimport { createAuthenticatedClient } from './http.js';\n\nconst CONTEXT7_BASE_URL = 'https://context7.com/api/v2';\n\n/**\n * Context7 API client for documentation lookup\n */\nexport class Context7Client {\n private client: Got;\n\n constructor(apiKey: string) {\n this.client = createAuthenticatedClient(CONTEXT7_BASE_URL, apiKey);\n }\n\n /**\n * Resolve a library name to its Context7 library ID\n */\n async resolveLibrary(libraryName: string, query: string): Promise<string> {\n // Check if we have a known mapping\n const normalizedName = libraryName.toLowerCase().replace(/-/g, '_');\n if (LIBRARY_IDS[normalizedName]) {\n return LIBRARY_IDS[normalizedName] as string;\n }\n\n // Search for the library\n try {\n const response = await this.client\n .get('libs/search', {\n searchParams: {\n libraryName,\n query,\n },\n })\n .json<{ results?: Array<{ libraryId: string; name: string }> }>();\n\n if (response.results && response.results.length > 0 && response.results[0]) {\n return response.results[0].libraryId;\n }\n\n // Fallback: try to construct a likely ID\n return `/${libraryName}/${libraryName}`;\n } catch (_error) {\n // If search fails, try the fallback pattern\n return `/${libraryName}/${libraryName}`;\n }\n }\n\n /**\n * Query documentation for a specific library\n */\n async queryDocs(libraryId: string, query: string): Promise<string> {\n try {\n const response = await this.client\n .get('context', {\n searchParams: {\n libraryId,\n query,\n tokens: 8000,\n },\n })\n .text();\n\n // API returns markdown text directly\n if (!response || response.trim() === '') {\n return 'No documentation found for this query.';\n }\n\n return response;\n } catch (error) {\n if (error && typeof error === 'object' && 'response' in error) {\n const response = (error as { response?: { statusCode?: number } }).response;\n const statusCode = response?.statusCode;\n\n if (statusCode === 202) {\n throw new APIError(\n 'Library is being indexed',\n 'Context7',\n 202,\n 'The library is being indexed. Please try again in a few minutes.',\n );\n }\n\n if (statusCode === 404) {\n throw new APIError(\n 'Library not found',\n 'Context7',\n 404,\n `Could not find library: ${libraryId}. Try a different package name.`,\n );\n }\n }\n\n throw error;\n }\n }\n\n /**\n * Search for documentation (combines resolve + query)\n */\n async search(library: string, query: string): Promise<string> {\n const key = cacheKey('context7', library, query);\n\n return cachedFetch(\n key,\n async () => {\n const libraryId = await this.resolveLibrary(library, query);\n return this.queryDocs(libraryId, query);\n },\n 3600 * 1000, // 1 hour cache\n );\n }\n}\n\n// Singleton instance cache\nlet clientInstance: Context7Client | null = null;\nlet currentApiKey: string | null = null;\n\n/**\n * Get or create a Context7 client instance\n */\nexport function getContext7Client(apiKey: string): Context7Client {\n if (!clientInstance || currentApiKey !== apiKey) {\n clientInstance = new Context7Client(apiKey);\n currentApiKey = apiKey;\n }\n return clientInstance;\n}\n"],"mappings":";;;;;;;;;;;AAMA,IAAM,oBAAoB;AAKnB,IAAM,iBAAN,MAAqB;AAAA,EAClB;AAAA,EAER,YAAY,QAAgB;AAC1B,SAAK,SAAS,0BAA0B,mBAAmB,MAAM;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,aAAqB,OAAgC;AAExE,UAAM,iBAAiB,YAAY,YAAY,EAAE,QAAQ,MAAM,GAAG;AAClE,QAAI,YAAY,cAAc,GAAG;AAC/B,aAAO,YAAY,cAAc;AAAA,IACnC;AAGA,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,OACzB,IAAI,eAAe;AAAA,QAClB,cAAc;AAAA,UACZ;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC,EACA,KAA+D;AAElE,UAAI,SAAS,WAAW,SAAS,QAAQ,SAAS,KAAK,SAAS,QAAQ,CAAC,GAAG;AAC1E,eAAO,SAAS,QAAQ,CAAC,EAAE;AAAA,MAC7B;AAGA,aAAO,IAAI,WAAW,IAAI,WAAW;AAAA,IACvC,SAAS,QAAQ;AAEf,aAAO,IAAI,WAAW,IAAI,WAAW;AAAA,IACvC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAU,WAAmB,OAAgC;AACjE,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,OACzB,IAAI,WAAW;AAAA,QACd,cAAc;AAAA,UACZ;AAAA,UACA;AAAA,UACA,QAAQ;AAAA,QACV;AAAA,MACF,CAAC,EACA,KAAK;AAGR,UAAI,CAAC,YAAY,SAAS,KAAK,MAAM,IAAI;AACvC,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,SAAS,OAAO,UAAU,YAAY,cAAc,OAAO;AAC7D,cAAM,WAAY,MAAiD;AACnE,cAAM,aAAa,UAAU;AAE7B,YAAI,eAAe,KAAK;AACtB,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAEA,YAAI,eAAe,KAAK;AACtB,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,YACA;AAAA,YACA,2BAA2B,SAAS;AAAA,UACtC;AAAA,QACF;AAAA,MACF;AAEA,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAO,SAAiB,OAAgC;AAC5D,UAAM,MAAM,SAAS,YAAY,SAAS,KAAK;AAE/C,WAAO;AAAA,MACL;AAAA,MACA,YAAY;AACV,cAAM,YAAY,MAAM,KAAK,eAAe,SAAS,KAAK;AAC1D,eAAO,KAAK,UAAU,WAAW,KAAK;AAAA,MACxC;AAAA,MACA,OAAO;AAAA;AAAA,IACT;AAAA,EACF;AACF;AAGA,IAAI,iBAAwC;AAC5C,IAAI,gBAA+B;AAK5B,SAAS,kBAAkB,QAAgC;AAChE,MAAI,CAAC,kBAAkB,kBAAkB,QAAQ;AAC/C,qBAAiB,IAAI,eAAe,MAAM;AAC1C,oBAAgB;AAAA,EAClB;AACA,SAAO;AACT;","names":[]}
1
+ {"version":3,"sources":["../src/services/context7.ts"],"sourcesContent":["import type { Got } from 'got';\nimport { LIBRARY_IDS } from '../types/index.js';\nimport { cachedFetch, cacheKey } from '../utils/cache.js';\nimport { APIError } from '../utils/error.js';\nimport { createAuthenticatedClient } from './http.js';\n\nconst CONTEXT7_BASE_URL = 'https://context7.com/api/v2';\n\n/**\n * Context7 API client for documentation lookup\n */\nexport class Context7Client {\n private client: Got;\n\n constructor(apiKey: string) {\n this.client = createAuthenticatedClient(CONTEXT7_BASE_URL, apiKey);\n }\n\n /**\n * Resolve a library name to its Context7 library ID\n */\n async resolveLibrary(libraryName: string, query: string): Promise<string> {\n // Check if we have a known mapping\n const normalizedName = libraryName.toLowerCase().replace(/-/g, '_');\n if (LIBRARY_IDS[normalizedName]) {\n return LIBRARY_IDS[normalizedName] as string;\n }\n\n // Search for the library\n try {\n const response = await this.client\n .get('libs/search', {\n searchParams: {\n libraryName,\n query,\n },\n })\n .json<{ results?: Array<{ libraryId: string; name: string }> }>();\n\n if (response.results && response.results.length > 0 && response.results[0]) {\n return response.results[0].libraryId;\n }\n\n // Fallback: try to construct a likely ID\n return `/${libraryName}/${libraryName}`;\n } catch (_error) {\n // If search fails, try the fallback pattern\n return `/${libraryName}/${libraryName}`;\n }\n }\n\n /**\n * Query documentation for a specific library\n */\n async queryDocs(libraryId: string, query: string): Promise<string> {\n try {\n const response = await this.client\n .get('context', {\n searchParams: {\n libraryId,\n query,\n tokens: 8000,\n },\n })\n .text();\n\n // API returns markdown text directly\n if (!response || response.trim() === '') {\n return 'No documentation found for this query.';\n }\n\n return response;\n } catch (error) {\n if (error && typeof error === 'object' && 'response' in error) {\n const response = (error as { response?: { statusCode?: number } }).response;\n const statusCode = response?.statusCode;\n\n if (statusCode === 202) {\n throw new APIError(\n 'Library is being indexed',\n 'Context7',\n 202,\n 'The library is being indexed. Please try again in a few minutes.',\n );\n }\n\n if (statusCode === 404) {\n throw new APIError(\n 'Library not found',\n 'Context7',\n 404,\n `Could not find library: ${libraryId}. Try a different package name.`,\n );\n }\n }\n\n throw error;\n }\n }\n\n /**\n * Search for documentation (combines resolve + query)\n */\n async search(library: string, query: string): Promise<string> {\n const key = cacheKey('context7', library, query);\n\n return cachedFetch(\n key,\n async () => {\n const libraryId = await this.resolveLibrary(library, query);\n return this.queryDocs(libraryId, query);\n },\n 3600 * 1000, // 1 hour cache\n );\n }\n}\n\n// Singleton instance cache\nlet clientInstance: Context7Client | null = null;\nlet currentApiKey: string | null = null;\n\n/**\n * Get or create a Context7 client instance\n */\nexport function getContext7Client(apiKey: string): Context7Client {\n if (!clientInstance || currentApiKey !== apiKey) {\n clientInstance = new Context7Client(apiKey);\n currentApiKey = apiKey;\n }\n return clientInstance;\n}\n"],"mappings":";;;;;;;;;;;;;AAMA,IAAM,oBAAoB;AAKnB,IAAM,iBAAN,MAAqB;AAAA,EAClB;AAAA,EAER,YAAY,QAAgB;AAC1B,SAAK,SAAS,0BAA0B,mBAAmB,MAAM;AAAA,EACnE;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,eAAe,aAAqB,OAAgC;AAExE,UAAM,iBAAiB,YAAY,YAAY,EAAE,QAAQ,MAAM,GAAG;AAClE,QAAI,YAAY,cAAc,GAAG;AAC/B,aAAO,YAAY,cAAc;AAAA,IACnC;AAGA,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,OACzB,IAAI,eAAe;AAAA,QAClB,cAAc;AAAA,UACZ;AAAA,UACA;AAAA,QACF;AAAA,MACF,CAAC,EACA,KAA+D;AAElE,UAAI,SAAS,WAAW,SAAS,QAAQ,SAAS,KAAK,SAAS,QAAQ,CAAC,GAAG;AAC1E,eAAO,SAAS,QAAQ,CAAC,EAAE;AAAA,MAC7B;AAGA,aAAO,IAAI,WAAW,IAAI,WAAW;AAAA,IACvC,SAAS,QAAQ;AAEf,aAAO,IAAI,WAAW,IAAI,WAAW;AAAA,IACvC;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,UAAU,WAAmB,OAAgC;AACjE,QAAI;AACF,YAAM,WAAW,MAAM,KAAK,OACzB,IAAI,WAAW;AAAA,QACd,cAAc;AAAA,UACZ;AAAA,UACA;AAAA,UACA,QAAQ;AAAA,QACV;AAAA,MACF,CAAC,EACA,KAAK;AAGR,UAAI,CAAC,YAAY,SAAS,KAAK,MAAM,IAAI;AACvC,eAAO;AAAA,MACT;AAEA,aAAO;AAAA,IACT,SAAS,OAAO;AACd,UAAI,SAAS,OAAO,UAAU,YAAY,cAAc,OAAO;AAC7D,cAAM,WAAY,MAAiD;AACnE,cAAM,aAAa,UAAU;AAE7B,YAAI,eAAe,KAAK;AACtB,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,YACA;AAAA,YACA;AAAA,UACF;AAAA,QACF;AAEA,YAAI,eAAe,KAAK;AACtB,gBAAM,IAAI;AAAA,YACR;AAAA,YACA;AAAA,YACA;AAAA,YACA,2BAA2B,SAAS;AAAA,UACtC;AAAA,QACF;AAAA,MACF;AAEA,YAAM;AAAA,IACR;AAAA,EACF;AAAA;AAAA;AAAA;AAAA,EAKA,MAAM,OAAO,SAAiB,OAAgC;AAC5D,UAAM,MAAM,SAAS,YAAY,SAAS,KAAK;AAE/C,WAAO;AAAA,MACL;AAAA,MACA,YAAY;AACV,cAAM,YAAY,MAAM,KAAK,eAAe,SAAS,KAAK;AAC1D,eAAO,KAAK,UAAU,WAAW,KAAK;AAAA,MACxC;AAAA,MACA,OAAO;AAAA;AAAA,IACT;AAAA,EACF;AACF;AAGA,IAAI,iBAAwC;AAC5C,IAAI,gBAA+B;AAK5B,SAAS,kBAAkB,QAAgC;AAChE,MAAI,CAAC,kBAAkB,kBAAkB,QAAQ;AAC/C,qBAAiB,IAAI,eAAe,MAAM;AAC1C,oBAAgB;AAAA,EAClB;AACA,SAAO;AACT;","names":[]}
@@ -1,6 +1,6 @@
1
1
  import {
2
2
  ConfigError
3
- } from "./chunk-5BCEXHNM.js";
3
+ } from "./chunk-JTMQREZ6.js";
4
4
 
5
5
  // src/utils/config.ts
6
6
  import { existsSync } from "fs";
@@ -193,4 +193,4 @@ export {
193
193
  formatTable,
194
194
  formatBox
195
195
  };
196
- //# sourceMappingURL=chunk-3KD5CFV3.js.map
196
+ //# sourceMappingURL=chunk-T7ZSH2YP.js.map