@flightdev/helpers 0.1.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.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2024-2026 Flight Contributors
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,151 @@
1
+ # @flight-framework/helpers
2
+
3
+ Optional helper utilities for Flight Framework. **Suggestions, not impositions.**
4
+
5
+ ## Philosophy
6
+
7
+ This package provides utilities that **suggest** configurations based on your project. It never applies anything automatically. You decide whether to use the suggestions or not.
8
+
9
+ ## Installation
10
+
11
+ ```bash
12
+ npm install @flight-framework/helpers
13
+ ```
14
+
15
+ ## Usage
16
+
17
+ ### Detect UI Framework
18
+
19
+ ```typescript
20
+ import { detectFramework } from '@flight-framework/helpers/detect';
21
+
22
+ const result = await detectFramework();
23
+
24
+ console.log(result);
25
+ // {
26
+ // framework: 'react',
27
+ // confidence: 'high',
28
+ // source: 'package.json',
29
+ // reasoning: 'Found react and react-dom in dependencies'
30
+ // }
31
+
32
+ // You decide what to do with this information
33
+ if (result.framework) {
34
+ console.log(`Detected: ${result.framework}`);
35
+ } else {
36
+ console.log('No framework detected, using vanilla');
37
+ }
38
+ ```
39
+
40
+ ### Detect Deployment Target
41
+
42
+ ```typescript
43
+ import { detectDeploymentTarget } from '@flight-framework/helpers/detect';
44
+
45
+ const result = await detectDeploymentTarget();
46
+
47
+ console.log(result);
48
+ // {
49
+ // adapter: 'vercel',
50
+ // confidence: 'high',
51
+ // source: 'environment',
52
+ // reasoning: 'VERCEL environment variable detected'
53
+ // }
54
+
55
+ // You decide whether to use this
56
+ console.log(`Suggested adapter: ${result.adapter}`);
57
+ console.log(`To install: npm install @flight-framework/adapter-${result.adapter}`);
58
+ ```
59
+
60
+ ### Suggest Defaults
61
+
62
+ ```typescript
63
+ import { suggestDefaults } from '@flight-framework/helpers/suggest';
64
+
65
+ const suggestions = await suggestDefaults();
66
+
67
+ console.log(suggestions);
68
+ // {
69
+ // framework: 'react',
70
+ // adapter: 'vercel',
71
+ // rendering: 'ssr',
72
+ // bundler: 'vite',
73
+ // confidence: {
74
+ // framework: 'high',
75
+ // adapter: 'high'
76
+ // }
77
+ // }
78
+
79
+ // Use in your config if you want
80
+ // flight.config.ts
81
+ import { defineConfig } from '@flight-framework/core';
82
+
83
+ export default defineConfig({
84
+ ui: {
85
+ // Use suggestion or override
86
+ framework: suggestions.framework ?? 'react',
87
+ },
88
+ });
89
+ ```
90
+
91
+ ## API Reference
92
+
93
+ ### detectFramework(root?: string)
94
+
95
+ Detects the UI framework used in the project.
96
+
97
+ **Returns:**
98
+ ```typescript
99
+ interface FrameworkDetection {
100
+ framework: 'react' | 'vue' | 'svelte' | 'solid' | 'preact' | 'qwik' | 'lit' | 'htmx' | 'angular' | null;
101
+ confidence: 'high' | 'medium' | 'low';
102
+ source: string;
103
+ reasoning: string;
104
+ }
105
+ ```
106
+
107
+ ### detectDeploymentTarget(root?: string)
108
+
109
+ Detects the deployment environment.
110
+
111
+ **Returns:**
112
+ ```typescript
113
+ interface DeploymentDetection {
114
+ adapter: 'node' | 'vercel' | 'netlify' | 'cloudflare' | 'aws' | 'docker' | 'fly' | 'deno' | 'bun' | null;
115
+ confidence: 'high' | 'medium' | 'low';
116
+ source: string;
117
+ reasoning: string;
118
+ }
119
+ ```
120
+
121
+ ### suggestDefaults(root?: string)
122
+
123
+ Returns suggested configuration based on detected context.
124
+
125
+ **Returns:**
126
+ ```typescript
127
+ interface SuggestedDefaults {
128
+ framework: string | null;
129
+ adapter: string | null;
130
+ rendering: 'ssr' | 'csr' | 'ssg';
131
+ bundler: 'vite' | 'esbuild' | 'rolldown';
132
+ confidence: {
133
+ framework: 'high' | 'medium' | 'low';
134
+ adapter: 'high' | 'medium' | 'low';
135
+ };
136
+ }
137
+ ```
138
+
139
+ ## Important
140
+
141
+ This package:
142
+ - **Never** applies configuration automatically
143
+ - **Never** installs packages
144
+ - **Never** modifies files
145
+ - Only **returns information** for you to use
146
+
147
+ You are always in control.
148
+
149
+ ## License
150
+
151
+ MIT
@@ -0,0 +1,42 @@
1
+ import { F as FrameworkDetection, D as DeploymentDetection } from '../types-0ONEhDBI.js';
2
+
3
+ /**
4
+ * Detection utilities for Flight Framework
5
+ *
6
+ * These functions DETECT and REPORT. They never apply or install anything.
7
+ */
8
+
9
+ /**
10
+ * Detect the UI framework used in the project.
11
+ *
12
+ * This function ONLY detects and reports. It never installs or configures anything.
13
+ *
14
+ * @param root - Project root directory (defaults to current working directory)
15
+ * @returns Detection result with framework, confidence, and reasoning
16
+ *
17
+ * @example
18
+ * ```typescript
19
+ * const result = await detectFramework();
20
+ * console.log(result.framework); // 'react' | 'vue' | null | ...
21
+ * console.log(result.reasoning); // 'Found react in package.json dependencies'
22
+ * ```
23
+ */
24
+ declare function detectFramework(root?: string): Promise<FrameworkDetection>;
25
+ /**
26
+ * Detect the deployment target/environment.
27
+ *
28
+ * This function ONLY detects and reports. It never installs or configures anything.
29
+ *
30
+ * @param root - Project root directory (defaults to current working directory)
31
+ * @returns Detection result with adapter, confidence, and reasoning
32
+ *
33
+ * @example
34
+ * ```typescript
35
+ * const result = await detectDeploymentTarget();
36
+ * console.log(result.adapter); // 'vercel' | 'node' | null | ...
37
+ * console.log(result.reasoning); // 'VERCEL environment variable detected'
38
+ * ```
39
+ */
40
+ declare function detectDeploymentTarget(root?: string): Promise<DeploymentDetection>;
41
+
42
+ export { detectDeploymentTarget, detectFramework };
@@ -0,0 +1,257 @@
1
+ // src/detect/index.ts
2
+ import { readFile, access } from "fs/promises";
3
+ import { join } from "path";
4
+ async function exists(path) {
5
+ try {
6
+ await access(path);
7
+ return true;
8
+ } catch {
9
+ return false;
10
+ }
11
+ }
12
+ async function readPackageJson(root) {
13
+ try {
14
+ const content = await readFile(join(root, "package.json"), "utf-8");
15
+ return JSON.parse(content);
16
+ } catch {
17
+ return null;
18
+ }
19
+ }
20
+ function getDependencies(pkg) {
21
+ const deps = pkg["dependencies"] ?? {};
22
+ const devDeps = pkg["devDependencies"] ?? {};
23
+ return { ...deps, ...devDeps };
24
+ }
25
+ async function detectFramework(root = process.cwd()) {
26
+ const pkg = await readPackageJson(root);
27
+ if (pkg) {
28
+ const deps = getDependencies(pkg);
29
+ if (deps["react"] && deps["react-dom"]) {
30
+ return {
31
+ framework: "react",
32
+ confidence: "high",
33
+ source: "package.json",
34
+ reasoning: "Found react and react-dom in dependencies"
35
+ };
36
+ }
37
+ if (deps["vue"]) {
38
+ return {
39
+ framework: "vue",
40
+ confidence: "high",
41
+ source: "package.json",
42
+ reasoning: "Found vue in dependencies"
43
+ };
44
+ }
45
+ if (deps["svelte"]) {
46
+ return {
47
+ framework: "svelte",
48
+ confidence: "high",
49
+ source: "package.json",
50
+ reasoning: "Found svelte in dependencies"
51
+ };
52
+ }
53
+ if (deps["solid-js"]) {
54
+ return {
55
+ framework: "solid",
56
+ confidence: "high",
57
+ source: "package.json",
58
+ reasoning: "Found solid-js in dependencies"
59
+ };
60
+ }
61
+ if (deps["preact"]) {
62
+ return {
63
+ framework: "preact",
64
+ confidence: "high",
65
+ source: "package.json",
66
+ reasoning: "Found preact in dependencies"
67
+ };
68
+ }
69
+ if (deps["@builder.io/qwik"]) {
70
+ return {
71
+ framework: "qwik",
72
+ confidence: "high",
73
+ source: "package.json",
74
+ reasoning: "Found @builder.io/qwik in dependencies"
75
+ };
76
+ }
77
+ if (deps["@angular/core"]) {
78
+ return {
79
+ framework: "angular",
80
+ confidence: "high",
81
+ source: "package.json",
82
+ reasoning: "Found @angular/core in dependencies"
83
+ };
84
+ }
85
+ if (deps["lit"]) {
86
+ return {
87
+ framework: "lit",
88
+ confidence: "high",
89
+ source: "package.json",
90
+ reasoning: "Found lit in dependencies"
91
+ };
92
+ }
93
+ if (deps["htmx.org"]) {
94
+ return {
95
+ framework: "htmx",
96
+ confidence: "high",
97
+ source: "package.json",
98
+ reasoning: "Found htmx.org in dependencies"
99
+ };
100
+ }
101
+ }
102
+ if (await exists(join(root, "svelte.config.js")) || await exists(join(root, "svelte.config.ts"))) {
103
+ return {
104
+ framework: "svelte",
105
+ confidence: "medium",
106
+ source: "config file",
107
+ reasoning: "Found svelte.config.js/ts"
108
+ };
109
+ }
110
+ if (await exists(join(root, "angular.json"))) {
111
+ return {
112
+ framework: "angular",
113
+ confidence: "medium",
114
+ source: "config file",
115
+ reasoning: "Found angular.json"
116
+ };
117
+ }
118
+ if (await exists(join(root, "vue.config.js"))) {
119
+ return {
120
+ framework: "vue",
121
+ confidence: "medium",
122
+ source: "config file",
123
+ reasoning: "Found vue.config.js"
124
+ };
125
+ }
126
+ return {
127
+ framework: null,
128
+ confidence: "low",
129
+ source: "none",
130
+ reasoning: "No UI framework detected. This is fine - Flight works with vanilla JS/HTML too."
131
+ };
132
+ }
133
+ async function detectDeploymentTarget(root = process.cwd()) {
134
+ if (process.env["VERCEL"]) {
135
+ return {
136
+ adapter: "vercel",
137
+ confidence: "high",
138
+ source: "environment",
139
+ reasoning: "VERCEL environment variable detected"
140
+ };
141
+ }
142
+ if (process.env["NETLIFY"]) {
143
+ return {
144
+ adapter: "netlify",
145
+ confidence: "high",
146
+ source: "environment",
147
+ reasoning: "NETLIFY environment variable detected"
148
+ };
149
+ }
150
+ if (process.env["CF_PAGES"] || process.env["CLOUDFLARE_WORKERS"]) {
151
+ return {
152
+ adapter: "cloudflare",
153
+ confidence: "high",
154
+ source: "environment",
155
+ reasoning: "Cloudflare environment variable detected"
156
+ };
157
+ }
158
+ if (process.env["AWS_LAMBDA_FUNCTION_NAME"]) {
159
+ return {
160
+ adapter: "aws",
161
+ confidence: "high",
162
+ source: "environment",
163
+ reasoning: "AWS Lambda environment detected"
164
+ };
165
+ }
166
+ if (process.env["FLY_APP_NAME"]) {
167
+ return {
168
+ adapter: "fly",
169
+ confidence: "high",
170
+ source: "environment",
171
+ reasoning: "Fly.io environment detected"
172
+ };
173
+ }
174
+ if (process.env["DENO_DEPLOYMENT_ID"]) {
175
+ return {
176
+ adapter: "deno",
177
+ confidence: "high",
178
+ source: "environment",
179
+ reasoning: "Deno Deploy environment detected"
180
+ };
181
+ }
182
+ if (await exists(join(root, "vercel.json"))) {
183
+ return {
184
+ adapter: "vercel",
185
+ confidence: "medium",
186
+ source: "config file",
187
+ reasoning: "Found vercel.json"
188
+ };
189
+ }
190
+ if (await exists(join(root, "netlify.toml"))) {
191
+ return {
192
+ adapter: "netlify",
193
+ confidence: "medium",
194
+ source: "config file",
195
+ reasoning: "Found netlify.toml"
196
+ };
197
+ }
198
+ if (await exists(join(root, "wrangler.toml"))) {
199
+ return {
200
+ adapter: "cloudflare",
201
+ confidence: "medium",
202
+ source: "config file",
203
+ reasoning: "Found wrangler.toml"
204
+ };
205
+ }
206
+ if (await exists(join(root, "fly.toml"))) {
207
+ return {
208
+ adapter: "fly",
209
+ confidence: "medium",
210
+ source: "config file",
211
+ reasoning: "Found fly.toml"
212
+ };
213
+ }
214
+ if (await exists(join(root, "Dockerfile"))) {
215
+ return {
216
+ adapter: "docker",
217
+ confidence: "medium",
218
+ source: "config file",
219
+ reasoning: "Found Dockerfile"
220
+ };
221
+ }
222
+ if (await exists(join(root, "serverless.yml")) || await exists(join(root, "serverless.yaml"))) {
223
+ return {
224
+ adapter: "aws",
225
+ confidence: "medium",
226
+ source: "config file",
227
+ reasoning: "Found serverless.yml"
228
+ };
229
+ }
230
+ if (typeof Bun !== "undefined") {
231
+ return {
232
+ adapter: "bun",
233
+ confidence: "high",
234
+ source: "runtime",
235
+ reasoning: "Running in Bun runtime"
236
+ };
237
+ }
238
+ if (typeof Deno !== "undefined") {
239
+ return {
240
+ adapter: "deno",
241
+ confidence: "high",
242
+ source: "runtime",
243
+ reasoning: "Running in Deno runtime"
244
+ };
245
+ }
246
+ return {
247
+ adapter: "node",
248
+ confidence: "low",
249
+ source: "default",
250
+ reasoning: "No specific deployment target detected. Defaulting to Node.js (works everywhere)."
251
+ };
252
+ }
253
+ export {
254
+ detectDeploymentTarget,
255
+ detectFramework
256
+ };
257
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/detect/index.ts"],"sourcesContent":["/**\r\n * Detection utilities for Flight Framework\r\n * \r\n * These functions DETECT and REPORT. They never apply or install anything.\r\n */\r\n\r\nimport { readFile, access } from 'node:fs/promises';\r\nimport { join } from 'node:path';\r\nimport type {\r\n FrameworkDetection,\r\n DeploymentDetection,\r\n UIFramework,\r\n DeploymentAdapter,\r\n} from '../types.js';\r\n\r\n/**\r\n * Check if a file exists\r\n */\r\nasync function exists(path: string): Promise<boolean> {\r\n try {\r\n await access(path);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Read and parse package.json\r\n */\r\nasync function readPackageJson(root: string): Promise<Record<string, unknown> | null> {\r\n try {\r\n const content = await readFile(join(root, 'package.json'), 'utf-8');\r\n return JSON.parse(content) as Record<string, unknown>;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Get all dependencies from package.json\r\n */\r\nfunction getDependencies(pkg: Record<string, unknown>): Record<string, string> {\r\n const deps = (pkg['dependencies'] ?? {}) as Record<string, string>;\r\n const devDeps = (pkg['devDependencies'] ?? {}) as Record<string, string>;\r\n return { ...deps, ...devDeps };\r\n}\r\n\r\n/**\r\n * Detect the UI framework used in the project.\r\n * \r\n * This function ONLY detects and reports. It never installs or configures anything.\r\n * \r\n * @param root - Project root directory (defaults to current working directory)\r\n * @returns Detection result with framework, confidence, and reasoning\r\n * \r\n * @example\r\n * ```typescript\r\n * const result = await detectFramework();\r\n * console.log(result.framework); // 'react' | 'vue' | null | ...\r\n * console.log(result.reasoning); // 'Found react in package.json dependencies'\r\n * ```\r\n */\r\nexport async function detectFramework(root: string = process.cwd()): Promise<FrameworkDetection> {\r\n // Check 1: package.json dependencies (highest confidence)\r\n const pkg = await readPackageJson(root);\r\n if (pkg) {\r\n const deps = getDependencies(pkg);\r\n\r\n // React\r\n if (deps['react'] && deps['react-dom']) {\r\n return {\r\n framework: 'react',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found react and react-dom in dependencies',\r\n };\r\n }\r\n\r\n // Vue\r\n if (deps['vue']) {\r\n return {\r\n framework: 'vue',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found vue in dependencies',\r\n };\r\n }\r\n\r\n // Svelte\r\n if (deps['svelte']) {\r\n return {\r\n framework: 'svelte',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found svelte in dependencies',\r\n };\r\n }\r\n\r\n // Solid\r\n if (deps['solid-js']) {\r\n return {\r\n framework: 'solid',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found solid-js in dependencies',\r\n };\r\n }\r\n\r\n // Preact\r\n if (deps['preact']) {\r\n return {\r\n framework: 'preact',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found preact in dependencies',\r\n };\r\n }\r\n\r\n // Qwik\r\n if (deps['@builder.io/qwik']) {\r\n return {\r\n framework: 'qwik',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found @builder.io/qwik in dependencies',\r\n };\r\n }\r\n\r\n // Angular\r\n if (deps['@angular/core']) {\r\n return {\r\n framework: 'angular',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found @angular/core in dependencies',\r\n };\r\n }\r\n\r\n // Lit\r\n if (deps['lit']) {\r\n return {\r\n framework: 'lit',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found lit in dependencies',\r\n };\r\n }\r\n\r\n // HTMX\r\n if (deps['htmx.org']) {\r\n return {\r\n framework: 'htmx',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found htmx.org in dependencies',\r\n };\r\n }\r\n }\r\n\r\n // Check 2: Config files (medium confidence)\r\n if (await exists(join(root, 'svelte.config.js')) || await exists(join(root, 'svelte.config.ts'))) {\r\n return {\r\n framework: 'svelte',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found svelte.config.js/ts',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'angular.json'))) {\r\n return {\r\n framework: 'angular',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found angular.json',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'vue.config.js'))) {\r\n return {\r\n framework: 'vue',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found vue.config.js',\r\n };\r\n }\r\n\r\n // No framework detected\r\n return {\r\n framework: null,\r\n confidence: 'low',\r\n source: 'none',\r\n reasoning: 'No UI framework detected. This is fine - Flight works with vanilla JS/HTML too.',\r\n };\r\n}\r\n\r\n/**\r\n * Detect the deployment target/environment.\r\n * \r\n * This function ONLY detects and reports. It never installs or configures anything.\r\n * \r\n * @param root - Project root directory (defaults to current working directory)\r\n * @returns Detection result with adapter, confidence, and reasoning\r\n * \r\n * @example\r\n * ```typescript\r\n * const result = await detectDeploymentTarget();\r\n * console.log(result.adapter); // 'vercel' | 'node' | null | ...\r\n * console.log(result.reasoning); // 'VERCEL environment variable detected'\r\n * ```\r\n */\r\nexport async function detectDeploymentTarget(root: string = process.cwd()): Promise<DeploymentDetection> {\r\n // Check 1: Environment variables (highest confidence - we're running in the environment)\r\n if (process.env['VERCEL']) {\r\n return {\r\n adapter: 'vercel',\r\n confidence: 'high',\r\n source: 'environment',\r\n reasoning: 'VERCEL environment variable detected',\r\n };\r\n }\r\n\r\n if (process.env['NETLIFY']) {\r\n return {\r\n adapter: 'netlify',\r\n confidence: 'high',\r\n source: 'environment',\r\n reasoning: 'NETLIFY environment variable detected',\r\n };\r\n }\r\n\r\n if (process.env['CF_PAGES'] || process.env['CLOUDFLARE_WORKERS']) {\r\n return {\r\n adapter: 'cloudflare',\r\n confidence: 'high',\r\n source: 'environment',\r\n reasoning: 'Cloudflare environment variable detected',\r\n };\r\n }\r\n\r\n if (process.env['AWS_LAMBDA_FUNCTION_NAME']) {\r\n return {\r\n adapter: 'aws',\r\n confidence: 'high',\r\n source: 'environment',\r\n reasoning: 'AWS Lambda environment detected',\r\n };\r\n }\r\n\r\n if (process.env['FLY_APP_NAME']) {\r\n return {\r\n adapter: 'fly',\r\n confidence: 'high',\r\n source: 'environment',\r\n reasoning: 'Fly.io environment detected',\r\n };\r\n }\r\n\r\n if (process.env['DENO_DEPLOYMENT_ID']) {\r\n return {\r\n adapter: 'deno',\r\n confidence: 'high',\r\n source: 'environment',\r\n reasoning: 'Deno Deploy environment detected',\r\n };\r\n }\r\n\r\n // Check 2: Config files (medium confidence - user intent)\r\n if (await exists(join(root, 'vercel.json'))) {\r\n return {\r\n adapter: 'vercel',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found vercel.json',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'netlify.toml'))) {\r\n return {\r\n adapter: 'netlify',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found netlify.toml',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'wrangler.toml'))) {\r\n return {\r\n adapter: 'cloudflare',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found wrangler.toml',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'fly.toml'))) {\r\n return {\r\n adapter: 'fly',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found fly.toml',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'Dockerfile'))) {\r\n return {\r\n adapter: 'docker',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found Dockerfile',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'serverless.yml')) || await exists(join(root, 'serverless.yaml'))) {\r\n return {\r\n adapter: 'aws',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found serverless.yml',\r\n };\r\n }\r\n\r\n // Check 3: Runtime detection\r\n // @ts-expect-error - Bun global\r\n if (typeof Bun !== 'undefined') {\r\n return {\r\n adapter: 'bun',\r\n confidence: 'high',\r\n source: 'runtime',\r\n reasoning: 'Running in Bun runtime',\r\n };\r\n }\r\n\r\n // @ts-expect-error - Deno global\r\n if (typeof Deno !== 'undefined') {\r\n return {\r\n adapter: 'deno',\r\n confidence: 'high',\r\n source: 'runtime',\r\n reasoning: 'Running in Deno runtime',\r\n };\r\n }\r\n\r\n // Default: Node.js (always available)\r\n return {\r\n adapter: 'node',\r\n confidence: 'low',\r\n source: 'default',\r\n reasoning: 'No specific deployment target detected. Defaulting to Node.js (works everywhere).',\r\n };\r\n}\r\n"],"mappings":"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","names":[]}
@@ -0,0 +1,3 @@
1
+ export { detectDeploymentTarget, detectFramework } from './detect/index.js';
2
+ export { suggestDefaults } from './suggest/index.js';
3
+ export { C as ConfidenceLevel, D as DeploymentDetection, F as FrameworkDetection, S as SuggestedDefaults } from './types-0ONEhDBI.js';
package/dist/index.js ADDED
@@ -0,0 +1,287 @@
1
+ // src/detect/index.ts
2
+ import { readFile, access } from "fs/promises";
3
+ import { join } from "path";
4
+ async function exists(path) {
5
+ try {
6
+ await access(path);
7
+ return true;
8
+ } catch {
9
+ return false;
10
+ }
11
+ }
12
+ async function readPackageJson(root) {
13
+ try {
14
+ const content = await readFile(join(root, "package.json"), "utf-8");
15
+ return JSON.parse(content);
16
+ } catch {
17
+ return null;
18
+ }
19
+ }
20
+ function getDependencies(pkg) {
21
+ const deps = pkg["dependencies"] ?? {};
22
+ const devDeps = pkg["devDependencies"] ?? {};
23
+ return { ...deps, ...devDeps };
24
+ }
25
+ async function detectFramework(root = process.cwd()) {
26
+ const pkg = await readPackageJson(root);
27
+ if (pkg) {
28
+ const deps = getDependencies(pkg);
29
+ if (deps["react"] && deps["react-dom"]) {
30
+ return {
31
+ framework: "react",
32
+ confidence: "high",
33
+ source: "package.json",
34
+ reasoning: "Found react and react-dom in dependencies"
35
+ };
36
+ }
37
+ if (deps["vue"]) {
38
+ return {
39
+ framework: "vue",
40
+ confidence: "high",
41
+ source: "package.json",
42
+ reasoning: "Found vue in dependencies"
43
+ };
44
+ }
45
+ if (deps["svelte"]) {
46
+ return {
47
+ framework: "svelte",
48
+ confidence: "high",
49
+ source: "package.json",
50
+ reasoning: "Found svelte in dependencies"
51
+ };
52
+ }
53
+ if (deps["solid-js"]) {
54
+ return {
55
+ framework: "solid",
56
+ confidence: "high",
57
+ source: "package.json",
58
+ reasoning: "Found solid-js in dependencies"
59
+ };
60
+ }
61
+ if (deps["preact"]) {
62
+ return {
63
+ framework: "preact",
64
+ confidence: "high",
65
+ source: "package.json",
66
+ reasoning: "Found preact in dependencies"
67
+ };
68
+ }
69
+ if (deps["@builder.io/qwik"]) {
70
+ return {
71
+ framework: "qwik",
72
+ confidence: "high",
73
+ source: "package.json",
74
+ reasoning: "Found @builder.io/qwik in dependencies"
75
+ };
76
+ }
77
+ if (deps["@angular/core"]) {
78
+ return {
79
+ framework: "angular",
80
+ confidence: "high",
81
+ source: "package.json",
82
+ reasoning: "Found @angular/core in dependencies"
83
+ };
84
+ }
85
+ if (deps["lit"]) {
86
+ return {
87
+ framework: "lit",
88
+ confidence: "high",
89
+ source: "package.json",
90
+ reasoning: "Found lit in dependencies"
91
+ };
92
+ }
93
+ if (deps["htmx.org"]) {
94
+ return {
95
+ framework: "htmx",
96
+ confidence: "high",
97
+ source: "package.json",
98
+ reasoning: "Found htmx.org in dependencies"
99
+ };
100
+ }
101
+ }
102
+ if (await exists(join(root, "svelte.config.js")) || await exists(join(root, "svelte.config.ts"))) {
103
+ return {
104
+ framework: "svelte",
105
+ confidence: "medium",
106
+ source: "config file",
107
+ reasoning: "Found svelte.config.js/ts"
108
+ };
109
+ }
110
+ if (await exists(join(root, "angular.json"))) {
111
+ return {
112
+ framework: "angular",
113
+ confidence: "medium",
114
+ source: "config file",
115
+ reasoning: "Found angular.json"
116
+ };
117
+ }
118
+ if (await exists(join(root, "vue.config.js"))) {
119
+ return {
120
+ framework: "vue",
121
+ confidence: "medium",
122
+ source: "config file",
123
+ reasoning: "Found vue.config.js"
124
+ };
125
+ }
126
+ return {
127
+ framework: null,
128
+ confidence: "low",
129
+ source: "none",
130
+ reasoning: "No UI framework detected. This is fine - Flight works with vanilla JS/HTML too."
131
+ };
132
+ }
133
+ async function detectDeploymentTarget(root = process.cwd()) {
134
+ if (process.env["VERCEL"]) {
135
+ return {
136
+ adapter: "vercel",
137
+ confidence: "high",
138
+ source: "environment",
139
+ reasoning: "VERCEL environment variable detected"
140
+ };
141
+ }
142
+ if (process.env["NETLIFY"]) {
143
+ return {
144
+ adapter: "netlify",
145
+ confidence: "high",
146
+ source: "environment",
147
+ reasoning: "NETLIFY environment variable detected"
148
+ };
149
+ }
150
+ if (process.env["CF_PAGES"] || process.env["CLOUDFLARE_WORKERS"]) {
151
+ return {
152
+ adapter: "cloudflare",
153
+ confidence: "high",
154
+ source: "environment",
155
+ reasoning: "Cloudflare environment variable detected"
156
+ };
157
+ }
158
+ if (process.env["AWS_LAMBDA_FUNCTION_NAME"]) {
159
+ return {
160
+ adapter: "aws",
161
+ confidence: "high",
162
+ source: "environment",
163
+ reasoning: "AWS Lambda environment detected"
164
+ };
165
+ }
166
+ if (process.env["FLY_APP_NAME"]) {
167
+ return {
168
+ adapter: "fly",
169
+ confidence: "high",
170
+ source: "environment",
171
+ reasoning: "Fly.io environment detected"
172
+ };
173
+ }
174
+ if (process.env["DENO_DEPLOYMENT_ID"]) {
175
+ return {
176
+ adapter: "deno",
177
+ confidence: "high",
178
+ source: "environment",
179
+ reasoning: "Deno Deploy environment detected"
180
+ };
181
+ }
182
+ if (await exists(join(root, "vercel.json"))) {
183
+ return {
184
+ adapter: "vercel",
185
+ confidence: "medium",
186
+ source: "config file",
187
+ reasoning: "Found vercel.json"
188
+ };
189
+ }
190
+ if (await exists(join(root, "netlify.toml"))) {
191
+ return {
192
+ adapter: "netlify",
193
+ confidence: "medium",
194
+ source: "config file",
195
+ reasoning: "Found netlify.toml"
196
+ };
197
+ }
198
+ if (await exists(join(root, "wrangler.toml"))) {
199
+ return {
200
+ adapter: "cloudflare",
201
+ confidence: "medium",
202
+ source: "config file",
203
+ reasoning: "Found wrangler.toml"
204
+ };
205
+ }
206
+ if (await exists(join(root, "fly.toml"))) {
207
+ return {
208
+ adapter: "fly",
209
+ confidence: "medium",
210
+ source: "config file",
211
+ reasoning: "Found fly.toml"
212
+ };
213
+ }
214
+ if (await exists(join(root, "Dockerfile"))) {
215
+ return {
216
+ adapter: "docker",
217
+ confidence: "medium",
218
+ source: "config file",
219
+ reasoning: "Found Dockerfile"
220
+ };
221
+ }
222
+ if (await exists(join(root, "serverless.yml")) || await exists(join(root, "serverless.yaml"))) {
223
+ return {
224
+ adapter: "aws",
225
+ confidence: "medium",
226
+ source: "config file",
227
+ reasoning: "Found serverless.yml"
228
+ };
229
+ }
230
+ if (typeof Bun !== "undefined") {
231
+ return {
232
+ adapter: "bun",
233
+ confidence: "high",
234
+ source: "runtime",
235
+ reasoning: "Running in Bun runtime"
236
+ };
237
+ }
238
+ if (typeof Deno !== "undefined") {
239
+ return {
240
+ adapter: "deno",
241
+ confidence: "high",
242
+ source: "runtime",
243
+ reasoning: "Running in Deno runtime"
244
+ };
245
+ }
246
+ return {
247
+ adapter: "node",
248
+ confidence: "low",
249
+ source: "default",
250
+ reasoning: "No specific deployment target detected. Defaulting to Node.js (works everywhere)."
251
+ };
252
+ }
253
+
254
+ // src/suggest/index.ts
255
+ async function suggestDefaults(root = process.cwd()) {
256
+ const [frameworkResult, adapterResult] = await Promise.all([
257
+ detectFramework(root),
258
+ detectDeploymentTarget(root)
259
+ ]);
260
+ let rendering = "ssr";
261
+ if (frameworkResult.framework === "htmx") {
262
+ rendering = "ssr";
263
+ }
264
+ if (frameworkResult.framework === "qwik") {
265
+ rendering = "ssr";
266
+ }
267
+ if (adapterResult.adapter === "static") {
268
+ rendering = "ssg";
269
+ }
270
+ const bundler = "vite";
271
+ return {
272
+ framework: frameworkResult.framework,
273
+ adapter: adapterResult.adapter,
274
+ rendering,
275
+ bundler,
276
+ confidence: {
277
+ framework: frameworkResult.confidence,
278
+ adapter: adapterResult.confidence
279
+ }
280
+ };
281
+ }
282
+ export {
283
+ detectDeploymentTarget,
284
+ detectFramework,
285
+ suggestDefaults
286
+ };
287
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/detect/index.ts","../src/suggest/index.ts"],"sourcesContent":["/**\r\n * Detection utilities for Flight Framework\r\n * \r\n * These functions DETECT and REPORT. They never apply or install anything.\r\n */\r\n\r\nimport { readFile, access } from 'node:fs/promises';\r\nimport { join } from 'node:path';\r\nimport type {\r\n FrameworkDetection,\r\n DeploymentDetection,\r\n UIFramework,\r\n DeploymentAdapter,\r\n} from '../types.js';\r\n\r\n/**\r\n * Check if a file exists\r\n */\r\nasync function exists(path: string): Promise<boolean> {\r\n try {\r\n await access(path);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Read and parse package.json\r\n */\r\nasync function readPackageJson(root: string): Promise<Record<string, unknown> | null> {\r\n try {\r\n const content = await readFile(join(root, 'package.json'), 'utf-8');\r\n return JSON.parse(content) as Record<string, unknown>;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Get all dependencies from package.json\r\n */\r\nfunction getDependencies(pkg: Record<string, unknown>): Record<string, string> {\r\n const deps = (pkg['dependencies'] ?? {}) as Record<string, string>;\r\n const devDeps = (pkg['devDependencies'] ?? {}) as Record<string, string>;\r\n return { ...deps, ...devDeps };\r\n}\r\n\r\n/**\r\n * Detect the UI framework used in the project.\r\n * \r\n * This function ONLY detects and reports. It never installs or configures anything.\r\n * \r\n * @param root - Project root directory (defaults to current working directory)\r\n * @returns Detection result with framework, confidence, and reasoning\r\n * \r\n * @example\r\n * ```typescript\r\n * const result = await detectFramework();\r\n * console.log(result.framework); // 'react' | 'vue' | null | ...\r\n * console.log(result.reasoning); // 'Found react in package.json dependencies'\r\n * ```\r\n */\r\nexport async function detectFramework(root: string = process.cwd()): Promise<FrameworkDetection> {\r\n // Check 1: package.json dependencies (highest confidence)\r\n const pkg = await readPackageJson(root);\r\n if (pkg) {\r\n const deps = getDependencies(pkg);\r\n\r\n // React\r\n if (deps['react'] && deps['react-dom']) {\r\n return {\r\n framework: 'react',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found react and react-dom in dependencies',\r\n };\r\n }\r\n\r\n // Vue\r\n if (deps['vue']) {\r\n return {\r\n framework: 'vue',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found vue in dependencies',\r\n };\r\n }\r\n\r\n // Svelte\r\n if (deps['svelte']) {\r\n return {\r\n framework: 'svelte',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found svelte in dependencies',\r\n };\r\n }\r\n\r\n // Solid\r\n if (deps['solid-js']) {\r\n return {\r\n framework: 'solid',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found solid-js in dependencies',\r\n };\r\n }\r\n\r\n // Preact\r\n if (deps['preact']) {\r\n return {\r\n framework: 'preact',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found preact in dependencies',\r\n };\r\n }\r\n\r\n // Qwik\r\n if (deps['@builder.io/qwik']) {\r\n return {\r\n framework: 'qwik',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found @builder.io/qwik in dependencies',\r\n };\r\n }\r\n\r\n // Angular\r\n if (deps['@angular/core']) {\r\n return {\r\n framework: 'angular',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found @angular/core in dependencies',\r\n };\r\n }\r\n\r\n // Lit\r\n if (deps['lit']) {\r\n return {\r\n framework: 'lit',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found lit in dependencies',\r\n };\r\n }\r\n\r\n // HTMX\r\n if (deps['htmx.org']) {\r\n return {\r\n framework: 'htmx',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found htmx.org in dependencies',\r\n };\r\n }\r\n }\r\n\r\n // Check 2: Config files (medium confidence)\r\n if (await exists(join(root, 'svelte.config.js')) || await exists(join(root, 'svelte.config.ts'))) {\r\n return {\r\n framework: 'svelte',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found svelte.config.js/ts',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'angular.json'))) {\r\n return {\r\n framework: 'angular',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found angular.json',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'vue.config.js'))) {\r\n return {\r\n framework: 'vue',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found vue.config.js',\r\n };\r\n }\r\n\r\n // No framework detected\r\n return {\r\n framework: null,\r\n confidence: 'low',\r\n source: 'none',\r\n reasoning: 'No UI framework detected. This is fine - Flight works with vanilla JS/HTML too.',\r\n };\r\n}\r\n\r\n/**\r\n * Detect the deployment target/environment.\r\n * \r\n * This function ONLY detects and reports. It never installs or configures anything.\r\n * \r\n * @param root - Project root directory (defaults to current working directory)\r\n * @returns Detection result with adapter, confidence, and reasoning\r\n * \r\n * @example\r\n * ```typescript\r\n * const result = await detectDeploymentTarget();\r\n * console.log(result.adapter); // 'vercel' | 'node' | null | ...\r\n * console.log(result.reasoning); // 'VERCEL environment variable detected'\r\n * ```\r\n */\r\nexport async function detectDeploymentTarget(root: string = process.cwd()): Promise<DeploymentDetection> {\r\n // Check 1: Environment variables (highest confidence - we're running in the environment)\r\n if (process.env['VERCEL']) {\r\n return {\r\n adapter: 'vercel',\r\n confidence: 'high',\r\n source: 'environment',\r\n reasoning: 'VERCEL environment variable detected',\r\n };\r\n }\r\n\r\n if (process.env['NETLIFY']) {\r\n return {\r\n adapter: 'netlify',\r\n confidence: 'high',\r\n source: 'environment',\r\n reasoning: 'NETLIFY environment variable detected',\r\n };\r\n }\r\n\r\n if (process.env['CF_PAGES'] || process.env['CLOUDFLARE_WORKERS']) {\r\n return {\r\n adapter: 'cloudflare',\r\n confidence: 'high',\r\n source: 'environment',\r\n reasoning: 'Cloudflare environment variable detected',\r\n };\r\n }\r\n\r\n if (process.env['AWS_LAMBDA_FUNCTION_NAME']) {\r\n return {\r\n adapter: 'aws',\r\n confidence: 'high',\r\n source: 'environment',\r\n reasoning: 'AWS Lambda environment detected',\r\n };\r\n }\r\n\r\n if (process.env['FLY_APP_NAME']) {\r\n return {\r\n adapter: 'fly',\r\n confidence: 'high',\r\n source: 'environment',\r\n reasoning: 'Fly.io environment detected',\r\n };\r\n }\r\n\r\n if (process.env['DENO_DEPLOYMENT_ID']) {\r\n return {\r\n adapter: 'deno',\r\n confidence: 'high',\r\n source: 'environment',\r\n reasoning: 'Deno Deploy environment detected',\r\n };\r\n }\r\n\r\n // Check 2: Config files (medium confidence - user intent)\r\n if (await exists(join(root, 'vercel.json'))) {\r\n return {\r\n adapter: 'vercel',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found vercel.json',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'netlify.toml'))) {\r\n return {\r\n adapter: 'netlify',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found netlify.toml',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'wrangler.toml'))) {\r\n return {\r\n adapter: 'cloudflare',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found wrangler.toml',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'fly.toml'))) {\r\n return {\r\n adapter: 'fly',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found fly.toml',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'Dockerfile'))) {\r\n return {\r\n adapter: 'docker',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found Dockerfile',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'serverless.yml')) || await exists(join(root, 'serverless.yaml'))) {\r\n return {\r\n adapter: 'aws',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found serverless.yml',\r\n };\r\n }\r\n\r\n // Check 3: Runtime detection\r\n // @ts-expect-error - Bun global\r\n if (typeof Bun !== 'undefined') {\r\n return {\r\n adapter: 'bun',\r\n confidence: 'high',\r\n source: 'runtime',\r\n reasoning: 'Running in Bun runtime',\r\n };\r\n }\r\n\r\n // @ts-expect-error - Deno global\r\n if (typeof Deno !== 'undefined') {\r\n return {\r\n adapter: 'deno',\r\n confidence: 'high',\r\n source: 'runtime',\r\n reasoning: 'Running in Deno runtime',\r\n };\r\n }\r\n\r\n // Default: Node.js (always available)\r\n return {\r\n adapter: 'node',\r\n confidence: 'low',\r\n source: 'default',\r\n reasoning: 'No specific deployment target detected. Defaulting to Node.js (works everywhere).',\r\n };\r\n}\r\n","/**\r\n * Suggestion utilities for Flight Framework\r\n * \r\n * These functions SUGGEST configurations based on detected context.\r\n * They never apply anything automatically. You decide.\r\n */\r\n\r\nimport { detectFramework, detectDeploymentTarget } from '../detect/index.js';\r\nimport type { SuggestedDefaults } from '../types.js';\r\n\r\n/**\r\n * Suggest default configuration based on project analysis.\r\n * \r\n * This function ONLY suggests. It never applies, installs, or modifies anything.\r\n * You are free to use these suggestions, modify them, or ignore them entirely.\r\n * \r\n * @param root - Project root directory (defaults to current working directory)\r\n * @returns Suggested defaults with confidence levels\r\n * \r\n * @example\r\n * ```typescript\r\n * const suggestions = await suggestDefaults();\r\n * \r\n * // Use suggestions in your config (optional)\r\n * export default {\r\n * ui: { framework: suggestions.framework ?? 'react' },\r\n * };\r\n * \r\n * // Or ignore them entirely\r\n * export default {\r\n * ui: { framework: 'vue' },\r\n * };\r\n * ```\r\n */\r\nexport async function suggestDefaults(root: string = process.cwd()): Promise<SuggestedDefaults> {\r\n // Detect context\r\n const [frameworkResult, adapterResult] = await Promise.all([\r\n detectFramework(root),\r\n detectDeploymentTarget(root),\r\n ]);\r\n\r\n // Determine rendering mode based on framework\r\n let rendering: 'ssr' | 'csr' | 'ssg' = 'ssr';\r\n\r\n // HTMX and static sites are typically SSR/SSG\r\n if (frameworkResult.framework === 'htmx') {\r\n rendering = 'ssr';\r\n }\r\n\r\n // Qwik uses resumability, SSR is recommended\r\n if (frameworkResult.framework === 'qwik') {\r\n rendering = 'ssr';\r\n }\r\n\r\n // Static adapters should use SSG\r\n if (adapterResult.adapter === 'static') {\r\n rendering = 'ssg';\r\n }\r\n\r\n // Determine bundler\r\n // Vite is the most universal choice\r\n const bundler = 'vite' as const;\r\n\r\n return {\r\n framework: frameworkResult.framework,\r\n adapter: adapterResult.adapter,\r\n rendering,\r\n bundler,\r\n confidence: {\r\n framework: frameworkResult.confidence,\r\n adapter: adapterResult.confidence,\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Log suggestions to console in a helpful format.\r\n * Useful for CLI tools.\r\n * \r\n * @param suggestions - Suggested defaults from suggestDefaults()\r\n */\r\nexport function logSuggestions(suggestions: SuggestedDefaults): void {\r\n console.log('\\n📋 Flight Suggestions (optional)\\n');\r\n\r\n if (suggestions.framework) {\r\n console.log(` UI Framework: ${suggestions.framework} (${suggestions.confidence.framework} confidence)`);\r\n } else {\r\n console.log(' UI Framework: none detected (vanilla JS/HTML works fine)');\r\n }\r\n\r\n if (suggestions.adapter) {\r\n console.log(` Deployment: ${suggestions.adapter} (${suggestions.confidence.adapter} confidence)`);\r\n }\r\n\r\n console.log(` Rendering: ${suggestions.rendering}`);\r\n console.log(` Bundler: ${suggestions.bundler}`);\r\n\r\n console.log('\\n💡 These are suggestions only. You can override any of these in flight.config.ts\\n');\r\n}\r\n"],"mappings":"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","names":[]}
@@ -0,0 +1,43 @@
1
+ import { S as SuggestedDefaults } from '../types-0ONEhDBI.js';
2
+
3
+ /**
4
+ * Suggestion utilities for Flight Framework
5
+ *
6
+ * These functions SUGGEST configurations based on detected context.
7
+ * They never apply anything automatically. You decide.
8
+ */
9
+
10
+ /**
11
+ * Suggest default configuration based on project analysis.
12
+ *
13
+ * This function ONLY suggests. It never applies, installs, or modifies anything.
14
+ * You are free to use these suggestions, modify them, or ignore them entirely.
15
+ *
16
+ * @param root - Project root directory (defaults to current working directory)
17
+ * @returns Suggested defaults with confidence levels
18
+ *
19
+ * @example
20
+ * ```typescript
21
+ * const suggestions = await suggestDefaults();
22
+ *
23
+ * // Use suggestions in your config (optional)
24
+ * export default {
25
+ * ui: { framework: suggestions.framework ?? 'react' },
26
+ * };
27
+ *
28
+ * // Or ignore them entirely
29
+ * export default {
30
+ * ui: { framework: 'vue' },
31
+ * };
32
+ * ```
33
+ */
34
+ declare function suggestDefaults(root?: string): Promise<SuggestedDefaults>;
35
+ /**
36
+ * Log suggestions to console in a helpful format.
37
+ * Useful for CLI tools.
38
+ *
39
+ * @param suggestions - Suggested defaults from suggestDefaults()
40
+ */
41
+ declare function logSuggestions(suggestions: SuggestedDefaults): void;
42
+
43
+ export { logSuggestions, suggestDefaults };
@@ -0,0 +1,300 @@
1
+ // src/detect/index.ts
2
+ import { readFile, access } from "fs/promises";
3
+ import { join } from "path";
4
+ async function exists(path) {
5
+ try {
6
+ await access(path);
7
+ return true;
8
+ } catch {
9
+ return false;
10
+ }
11
+ }
12
+ async function readPackageJson(root) {
13
+ try {
14
+ const content = await readFile(join(root, "package.json"), "utf-8");
15
+ return JSON.parse(content);
16
+ } catch {
17
+ return null;
18
+ }
19
+ }
20
+ function getDependencies(pkg) {
21
+ const deps = pkg["dependencies"] ?? {};
22
+ const devDeps = pkg["devDependencies"] ?? {};
23
+ return { ...deps, ...devDeps };
24
+ }
25
+ async function detectFramework(root = process.cwd()) {
26
+ const pkg = await readPackageJson(root);
27
+ if (pkg) {
28
+ const deps = getDependencies(pkg);
29
+ if (deps["react"] && deps["react-dom"]) {
30
+ return {
31
+ framework: "react",
32
+ confidence: "high",
33
+ source: "package.json",
34
+ reasoning: "Found react and react-dom in dependencies"
35
+ };
36
+ }
37
+ if (deps["vue"]) {
38
+ return {
39
+ framework: "vue",
40
+ confidence: "high",
41
+ source: "package.json",
42
+ reasoning: "Found vue in dependencies"
43
+ };
44
+ }
45
+ if (deps["svelte"]) {
46
+ return {
47
+ framework: "svelte",
48
+ confidence: "high",
49
+ source: "package.json",
50
+ reasoning: "Found svelte in dependencies"
51
+ };
52
+ }
53
+ if (deps["solid-js"]) {
54
+ return {
55
+ framework: "solid",
56
+ confidence: "high",
57
+ source: "package.json",
58
+ reasoning: "Found solid-js in dependencies"
59
+ };
60
+ }
61
+ if (deps["preact"]) {
62
+ return {
63
+ framework: "preact",
64
+ confidence: "high",
65
+ source: "package.json",
66
+ reasoning: "Found preact in dependencies"
67
+ };
68
+ }
69
+ if (deps["@builder.io/qwik"]) {
70
+ return {
71
+ framework: "qwik",
72
+ confidence: "high",
73
+ source: "package.json",
74
+ reasoning: "Found @builder.io/qwik in dependencies"
75
+ };
76
+ }
77
+ if (deps["@angular/core"]) {
78
+ return {
79
+ framework: "angular",
80
+ confidence: "high",
81
+ source: "package.json",
82
+ reasoning: "Found @angular/core in dependencies"
83
+ };
84
+ }
85
+ if (deps["lit"]) {
86
+ return {
87
+ framework: "lit",
88
+ confidence: "high",
89
+ source: "package.json",
90
+ reasoning: "Found lit in dependencies"
91
+ };
92
+ }
93
+ if (deps["htmx.org"]) {
94
+ return {
95
+ framework: "htmx",
96
+ confidence: "high",
97
+ source: "package.json",
98
+ reasoning: "Found htmx.org in dependencies"
99
+ };
100
+ }
101
+ }
102
+ if (await exists(join(root, "svelte.config.js")) || await exists(join(root, "svelte.config.ts"))) {
103
+ return {
104
+ framework: "svelte",
105
+ confidence: "medium",
106
+ source: "config file",
107
+ reasoning: "Found svelte.config.js/ts"
108
+ };
109
+ }
110
+ if (await exists(join(root, "angular.json"))) {
111
+ return {
112
+ framework: "angular",
113
+ confidence: "medium",
114
+ source: "config file",
115
+ reasoning: "Found angular.json"
116
+ };
117
+ }
118
+ if (await exists(join(root, "vue.config.js"))) {
119
+ return {
120
+ framework: "vue",
121
+ confidence: "medium",
122
+ source: "config file",
123
+ reasoning: "Found vue.config.js"
124
+ };
125
+ }
126
+ return {
127
+ framework: null,
128
+ confidence: "low",
129
+ source: "none",
130
+ reasoning: "No UI framework detected. This is fine - Flight works with vanilla JS/HTML too."
131
+ };
132
+ }
133
+ async function detectDeploymentTarget(root = process.cwd()) {
134
+ if (process.env["VERCEL"]) {
135
+ return {
136
+ adapter: "vercel",
137
+ confidence: "high",
138
+ source: "environment",
139
+ reasoning: "VERCEL environment variable detected"
140
+ };
141
+ }
142
+ if (process.env["NETLIFY"]) {
143
+ return {
144
+ adapter: "netlify",
145
+ confidence: "high",
146
+ source: "environment",
147
+ reasoning: "NETLIFY environment variable detected"
148
+ };
149
+ }
150
+ if (process.env["CF_PAGES"] || process.env["CLOUDFLARE_WORKERS"]) {
151
+ return {
152
+ adapter: "cloudflare",
153
+ confidence: "high",
154
+ source: "environment",
155
+ reasoning: "Cloudflare environment variable detected"
156
+ };
157
+ }
158
+ if (process.env["AWS_LAMBDA_FUNCTION_NAME"]) {
159
+ return {
160
+ adapter: "aws",
161
+ confidence: "high",
162
+ source: "environment",
163
+ reasoning: "AWS Lambda environment detected"
164
+ };
165
+ }
166
+ if (process.env["FLY_APP_NAME"]) {
167
+ return {
168
+ adapter: "fly",
169
+ confidence: "high",
170
+ source: "environment",
171
+ reasoning: "Fly.io environment detected"
172
+ };
173
+ }
174
+ if (process.env["DENO_DEPLOYMENT_ID"]) {
175
+ return {
176
+ adapter: "deno",
177
+ confidence: "high",
178
+ source: "environment",
179
+ reasoning: "Deno Deploy environment detected"
180
+ };
181
+ }
182
+ if (await exists(join(root, "vercel.json"))) {
183
+ return {
184
+ adapter: "vercel",
185
+ confidence: "medium",
186
+ source: "config file",
187
+ reasoning: "Found vercel.json"
188
+ };
189
+ }
190
+ if (await exists(join(root, "netlify.toml"))) {
191
+ return {
192
+ adapter: "netlify",
193
+ confidence: "medium",
194
+ source: "config file",
195
+ reasoning: "Found netlify.toml"
196
+ };
197
+ }
198
+ if (await exists(join(root, "wrangler.toml"))) {
199
+ return {
200
+ adapter: "cloudflare",
201
+ confidence: "medium",
202
+ source: "config file",
203
+ reasoning: "Found wrangler.toml"
204
+ };
205
+ }
206
+ if (await exists(join(root, "fly.toml"))) {
207
+ return {
208
+ adapter: "fly",
209
+ confidence: "medium",
210
+ source: "config file",
211
+ reasoning: "Found fly.toml"
212
+ };
213
+ }
214
+ if (await exists(join(root, "Dockerfile"))) {
215
+ return {
216
+ adapter: "docker",
217
+ confidence: "medium",
218
+ source: "config file",
219
+ reasoning: "Found Dockerfile"
220
+ };
221
+ }
222
+ if (await exists(join(root, "serverless.yml")) || await exists(join(root, "serverless.yaml"))) {
223
+ return {
224
+ adapter: "aws",
225
+ confidence: "medium",
226
+ source: "config file",
227
+ reasoning: "Found serverless.yml"
228
+ };
229
+ }
230
+ if (typeof Bun !== "undefined") {
231
+ return {
232
+ adapter: "bun",
233
+ confidence: "high",
234
+ source: "runtime",
235
+ reasoning: "Running in Bun runtime"
236
+ };
237
+ }
238
+ if (typeof Deno !== "undefined") {
239
+ return {
240
+ adapter: "deno",
241
+ confidence: "high",
242
+ source: "runtime",
243
+ reasoning: "Running in Deno runtime"
244
+ };
245
+ }
246
+ return {
247
+ adapter: "node",
248
+ confidence: "low",
249
+ source: "default",
250
+ reasoning: "No specific deployment target detected. Defaulting to Node.js (works everywhere)."
251
+ };
252
+ }
253
+
254
+ // src/suggest/index.ts
255
+ async function suggestDefaults(root = process.cwd()) {
256
+ const [frameworkResult, adapterResult] = await Promise.all([
257
+ detectFramework(root),
258
+ detectDeploymentTarget(root)
259
+ ]);
260
+ let rendering = "ssr";
261
+ if (frameworkResult.framework === "htmx") {
262
+ rendering = "ssr";
263
+ }
264
+ if (frameworkResult.framework === "qwik") {
265
+ rendering = "ssr";
266
+ }
267
+ if (adapterResult.adapter === "static") {
268
+ rendering = "ssg";
269
+ }
270
+ const bundler = "vite";
271
+ return {
272
+ framework: frameworkResult.framework,
273
+ adapter: adapterResult.adapter,
274
+ rendering,
275
+ bundler,
276
+ confidence: {
277
+ framework: frameworkResult.confidence,
278
+ adapter: adapterResult.confidence
279
+ }
280
+ };
281
+ }
282
+ function logSuggestions(suggestions) {
283
+ console.log("\n\u{1F4CB} Flight Suggestions (optional)\n");
284
+ if (suggestions.framework) {
285
+ console.log(` UI Framework: ${suggestions.framework} (${suggestions.confidence.framework} confidence)`);
286
+ } else {
287
+ console.log(" UI Framework: none detected (vanilla JS/HTML works fine)");
288
+ }
289
+ if (suggestions.adapter) {
290
+ console.log(` Deployment: ${suggestions.adapter} (${suggestions.confidence.adapter} confidence)`);
291
+ }
292
+ console.log(` Rendering: ${suggestions.rendering}`);
293
+ console.log(` Bundler: ${suggestions.bundler}`);
294
+ console.log("\n\u{1F4A1} These are suggestions only. You can override any of these in flight.config.ts\n");
295
+ }
296
+ export {
297
+ logSuggestions,
298
+ suggestDefaults
299
+ };
300
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/detect/index.ts","../../src/suggest/index.ts"],"sourcesContent":["/**\r\n * Detection utilities for Flight Framework\r\n * \r\n * These functions DETECT and REPORT. They never apply or install anything.\r\n */\r\n\r\nimport { readFile, access } from 'node:fs/promises';\r\nimport { join } from 'node:path';\r\nimport type {\r\n FrameworkDetection,\r\n DeploymentDetection,\r\n UIFramework,\r\n DeploymentAdapter,\r\n} from '../types.js';\r\n\r\n/**\r\n * Check if a file exists\r\n */\r\nasync function exists(path: string): Promise<boolean> {\r\n try {\r\n await access(path);\r\n return true;\r\n } catch {\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Read and parse package.json\r\n */\r\nasync function readPackageJson(root: string): Promise<Record<string, unknown> | null> {\r\n try {\r\n const content = await readFile(join(root, 'package.json'), 'utf-8');\r\n return JSON.parse(content) as Record<string, unknown>;\r\n } catch {\r\n return null;\r\n }\r\n}\r\n\r\n/**\r\n * Get all dependencies from package.json\r\n */\r\nfunction getDependencies(pkg: Record<string, unknown>): Record<string, string> {\r\n const deps = (pkg['dependencies'] ?? {}) as Record<string, string>;\r\n const devDeps = (pkg['devDependencies'] ?? {}) as Record<string, string>;\r\n return { ...deps, ...devDeps };\r\n}\r\n\r\n/**\r\n * Detect the UI framework used in the project.\r\n * \r\n * This function ONLY detects and reports. It never installs or configures anything.\r\n * \r\n * @param root - Project root directory (defaults to current working directory)\r\n * @returns Detection result with framework, confidence, and reasoning\r\n * \r\n * @example\r\n * ```typescript\r\n * const result = await detectFramework();\r\n * console.log(result.framework); // 'react' | 'vue' | null | ...\r\n * console.log(result.reasoning); // 'Found react in package.json dependencies'\r\n * ```\r\n */\r\nexport async function detectFramework(root: string = process.cwd()): Promise<FrameworkDetection> {\r\n // Check 1: package.json dependencies (highest confidence)\r\n const pkg = await readPackageJson(root);\r\n if (pkg) {\r\n const deps = getDependencies(pkg);\r\n\r\n // React\r\n if (deps['react'] && deps['react-dom']) {\r\n return {\r\n framework: 'react',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found react and react-dom in dependencies',\r\n };\r\n }\r\n\r\n // Vue\r\n if (deps['vue']) {\r\n return {\r\n framework: 'vue',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found vue in dependencies',\r\n };\r\n }\r\n\r\n // Svelte\r\n if (deps['svelte']) {\r\n return {\r\n framework: 'svelte',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found svelte in dependencies',\r\n };\r\n }\r\n\r\n // Solid\r\n if (deps['solid-js']) {\r\n return {\r\n framework: 'solid',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found solid-js in dependencies',\r\n };\r\n }\r\n\r\n // Preact\r\n if (deps['preact']) {\r\n return {\r\n framework: 'preact',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found preact in dependencies',\r\n };\r\n }\r\n\r\n // Qwik\r\n if (deps['@builder.io/qwik']) {\r\n return {\r\n framework: 'qwik',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found @builder.io/qwik in dependencies',\r\n };\r\n }\r\n\r\n // Angular\r\n if (deps['@angular/core']) {\r\n return {\r\n framework: 'angular',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found @angular/core in dependencies',\r\n };\r\n }\r\n\r\n // Lit\r\n if (deps['lit']) {\r\n return {\r\n framework: 'lit',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found lit in dependencies',\r\n };\r\n }\r\n\r\n // HTMX\r\n if (deps['htmx.org']) {\r\n return {\r\n framework: 'htmx',\r\n confidence: 'high',\r\n source: 'package.json',\r\n reasoning: 'Found htmx.org in dependencies',\r\n };\r\n }\r\n }\r\n\r\n // Check 2: Config files (medium confidence)\r\n if (await exists(join(root, 'svelte.config.js')) || await exists(join(root, 'svelte.config.ts'))) {\r\n return {\r\n framework: 'svelte',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found svelte.config.js/ts',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'angular.json'))) {\r\n return {\r\n framework: 'angular',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found angular.json',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'vue.config.js'))) {\r\n return {\r\n framework: 'vue',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found vue.config.js',\r\n };\r\n }\r\n\r\n // No framework detected\r\n return {\r\n framework: null,\r\n confidence: 'low',\r\n source: 'none',\r\n reasoning: 'No UI framework detected. This is fine - Flight works with vanilla JS/HTML too.',\r\n };\r\n}\r\n\r\n/**\r\n * Detect the deployment target/environment.\r\n * \r\n * This function ONLY detects and reports. It never installs or configures anything.\r\n * \r\n * @param root - Project root directory (defaults to current working directory)\r\n * @returns Detection result with adapter, confidence, and reasoning\r\n * \r\n * @example\r\n * ```typescript\r\n * const result = await detectDeploymentTarget();\r\n * console.log(result.adapter); // 'vercel' | 'node' | null | ...\r\n * console.log(result.reasoning); // 'VERCEL environment variable detected'\r\n * ```\r\n */\r\nexport async function detectDeploymentTarget(root: string = process.cwd()): Promise<DeploymentDetection> {\r\n // Check 1: Environment variables (highest confidence - we're running in the environment)\r\n if (process.env['VERCEL']) {\r\n return {\r\n adapter: 'vercel',\r\n confidence: 'high',\r\n source: 'environment',\r\n reasoning: 'VERCEL environment variable detected',\r\n };\r\n }\r\n\r\n if (process.env['NETLIFY']) {\r\n return {\r\n adapter: 'netlify',\r\n confidence: 'high',\r\n source: 'environment',\r\n reasoning: 'NETLIFY environment variable detected',\r\n };\r\n }\r\n\r\n if (process.env['CF_PAGES'] || process.env['CLOUDFLARE_WORKERS']) {\r\n return {\r\n adapter: 'cloudflare',\r\n confidence: 'high',\r\n source: 'environment',\r\n reasoning: 'Cloudflare environment variable detected',\r\n };\r\n }\r\n\r\n if (process.env['AWS_LAMBDA_FUNCTION_NAME']) {\r\n return {\r\n adapter: 'aws',\r\n confidence: 'high',\r\n source: 'environment',\r\n reasoning: 'AWS Lambda environment detected',\r\n };\r\n }\r\n\r\n if (process.env['FLY_APP_NAME']) {\r\n return {\r\n adapter: 'fly',\r\n confidence: 'high',\r\n source: 'environment',\r\n reasoning: 'Fly.io environment detected',\r\n };\r\n }\r\n\r\n if (process.env['DENO_DEPLOYMENT_ID']) {\r\n return {\r\n adapter: 'deno',\r\n confidence: 'high',\r\n source: 'environment',\r\n reasoning: 'Deno Deploy environment detected',\r\n };\r\n }\r\n\r\n // Check 2: Config files (medium confidence - user intent)\r\n if (await exists(join(root, 'vercel.json'))) {\r\n return {\r\n adapter: 'vercel',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found vercel.json',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'netlify.toml'))) {\r\n return {\r\n adapter: 'netlify',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found netlify.toml',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'wrangler.toml'))) {\r\n return {\r\n adapter: 'cloudflare',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found wrangler.toml',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'fly.toml'))) {\r\n return {\r\n adapter: 'fly',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found fly.toml',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'Dockerfile'))) {\r\n return {\r\n adapter: 'docker',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found Dockerfile',\r\n };\r\n }\r\n\r\n if (await exists(join(root, 'serverless.yml')) || await exists(join(root, 'serverless.yaml'))) {\r\n return {\r\n adapter: 'aws',\r\n confidence: 'medium',\r\n source: 'config file',\r\n reasoning: 'Found serverless.yml',\r\n };\r\n }\r\n\r\n // Check 3: Runtime detection\r\n // @ts-expect-error - Bun global\r\n if (typeof Bun !== 'undefined') {\r\n return {\r\n adapter: 'bun',\r\n confidence: 'high',\r\n source: 'runtime',\r\n reasoning: 'Running in Bun runtime',\r\n };\r\n }\r\n\r\n // @ts-expect-error - Deno global\r\n if (typeof Deno !== 'undefined') {\r\n return {\r\n adapter: 'deno',\r\n confidence: 'high',\r\n source: 'runtime',\r\n reasoning: 'Running in Deno runtime',\r\n };\r\n }\r\n\r\n // Default: Node.js (always available)\r\n return {\r\n adapter: 'node',\r\n confidence: 'low',\r\n source: 'default',\r\n reasoning: 'No specific deployment target detected. Defaulting to Node.js (works everywhere).',\r\n };\r\n}\r\n","/**\r\n * Suggestion utilities for Flight Framework\r\n * \r\n * These functions SUGGEST configurations based on detected context.\r\n * They never apply anything automatically. You decide.\r\n */\r\n\r\nimport { detectFramework, detectDeploymentTarget } from '../detect/index.js';\r\nimport type { SuggestedDefaults } from '../types.js';\r\n\r\n/**\r\n * Suggest default configuration based on project analysis.\r\n * \r\n * This function ONLY suggests. It never applies, installs, or modifies anything.\r\n * You are free to use these suggestions, modify them, or ignore them entirely.\r\n * \r\n * @param root - Project root directory (defaults to current working directory)\r\n * @returns Suggested defaults with confidence levels\r\n * \r\n * @example\r\n * ```typescript\r\n * const suggestions = await suggestDefaults();\r\n * \r\n * // Use suggestions in your config (optional)\r\n * export default {\r\n * ui: { framework: suggestions.framework ?? 'react' },\r\n * };\r\n * \r\n * // Or ignore them entirely\r\n * export default {\r\n * ui: { framework: 'vue' },\r\n * };\r\n * ```\r\n */\r\nexport async function suggestDefaults(root: string = process.cwd()): Promise<SuggestedDefaults> {\r\n // Detect context\r\n const [frameworkResult, adapterResult] = await Promise.all([\r\n detectFramework(root),\r\n detectDeploymentTarget(root),\r\n ]);\r\n\r\n // Determine rendering mode based on framework\r\n let rendering: 'ssr' | 'csr' | 'ssg' = 'ssr';\r\n\r\n // HTMX and static sites are typically SSR/SSG\r\n if (frameworkResult.framework === 'htmx') {\r\n rendering = 'ssr';\r\n }\r\n\r\n // Qwik uses resumability, SSR is recommended\r\n if (frameworkResult.framework === 'qwik') {\r\n rendering = 'ssr';\r\n }\r\n\r\n // Static adapters should use SSG\r\n if (adapterResult.adapter === 'static') {\r\n rendering = 'ssg';\r\n }\r\n\r\n // Determine bundler\r\n // Vite is the most universal choice\r\n const bundler = 'vite' as const;\r\n\r\n return {\r\n framework: frameworkResult.framework,\r\n adapter: adapterResult.adapter,\r\n rendering,\r\n bundler,\r\n confidence: {\r\n framework: frameworkResult.confidence,\r\n adapter: adapterResult.confidence,\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Log suggestions to console in a helpful format.\r\n * Useful for CLI tools.\r\n * \r\n * @param suggestions - Suggested defaults from suggestDefaults()\r\n */\r\nexport function logSuggestions(suggestions: SuggestedDefaults): void {\r\n console.log('\\n📋 Flight Suggestions (optional)\\n');\r\n\r\n if (suggestions.framework) {\r\n console.log(` UI Framework: ${suggestions.framework} (${suggestions.confidence.framework} confidence)`);\r\n } else {\r\n console.log(' UI Framework: none detected (vanilla JS/HTML works fine)');\r\n }\r\n\r\n if (suggestions.adapter) {\r\n console.log(` Deployment: ${suggestions.adapter} (${suggestions.confidence.adapter} confidence)`);\r\n }\r\n\r\n console.log(` Rendering: ${suggestions.rendering}`);\r\n console.log(` Bundler: ${suggestions.bundler}`);\r\n\r\n console.log('\\n💡 These are suggestions only. You can override any of these in flight.config.ts\\n');\r\n}\r\n"],"mappings":"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","names":[]}
@@ -0,0 +1,43 @@
1
+ /**
2
+ * Shared types for detection utilities
3
+ */
4
+ type ConfidenceLevel = 'high' | 'medium' | 'low';
5
+ type UIFramework = 'react' | 'vue' | 'svelte' | 'solid' | 'preact' | 'qwik' | 'lit' | 'htmx' | 'angular' | 'vanilla';
6
+ type DeploymentAdapter = 'node' | 'vercel' | 'netlify' | 'cloudflare' | 'aws' | 'docker' | 'fly' | 'deno' | 'bun' | 'static';
7
+ interface FrameworkDetection {
8
+ /** Detected framework, null if none found */
9
+ framework: UIFramework | null;
10
+ /** Confidence level of detection */
11
+ confidence: ConfidenceLevel;
12
+ /** Where the detection came from */
13
+ source: string;
14
+ /** Human-readable explanation */
15
+ reasoning: string;
16
+ }
17
+ interface DeploymentDetection {
18
+ /** Detected deployment target, null if none found */
19
+ adapter: DeploymentAdapter | null;
20
+ /** Confidence level of detection */
21
+ confidence: ConfidenceLevel;
22
+ /** Where the detection came from */
23
+ source: string;
24
+ /** Human-readable explanation */
25
+ reasoning: string;
26
+ }
27
+ interface SuggestedDefaults {
28
+ /** Suggested UI framework */
29
+ framework: UIFramework | null;
30
+ /** Suggested deployment adapter */
31
+ adapter: DeploymentAdapter | null;
32
+ /** Suggested rendering mode */
33
+ rendering: 'ssr' | 'csr' | 'ssg';
34
+ /** Suggested bundler */
35
+ bundler: 'vite' | 'esbuild' | 'rolldown';
36
+ /** Confidence levels for each suggestion */
37
+ confidence: {
38
+ framework: ConfidenceLevel;
39
+ adapter: ConfidenceLevel;
40
+ };
41
+ }
42
+
43
+ export type { ConfidenceLevel as C, DeploymentDetection as D, FrameworkDetection as F, SuggestedDefaults as S };
package/package.json ADDED
@@ -0,0 +1,48 @@
1
+ {
2
+ "name": "@flightdev/helpers",
3
+ "version": "0.1.0",
4
+ "description": "Optional helper utilities for Flight Framework. Suggestions, not impositions.",
5
+ "type": "module",
6
+ "main": "./dist/index.js",
7
+ "module": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "import": "./dist/index.js"
13
+ },
14
+ "./detect": {
15
+ "types": "./dist/detect/index.d.ts",
16
+ "import": "./dist/detect/index.js"
17
+ },
18
+ "./suggest": {
19
+ "types": "./dist/suggest/index.d.ts",
20
+ "import": "./dist/suggest/index.js"
21
+ }
22
+ },
23
+ "files": [
24
+ "dist",
25
+ "README.md"
26
+ ],
27
+ "keywords": [
28
+ "flight",
29
+ "framework",
30
+ "helpers",
31
+ "utilities",
32
+ "detection"
33
+ ],
34
+ "author": "",
35
+ "license": "MIT",
36
+ "peerDependencies": {},
37
+ "devDependencies": {
38
+ "tsup": "^8.0.0",
39
+ "typescript": "^5.3.0",
40
+ "vitest": "^1.0.0"
41
+ },
42
+ "scripts": {
43
+ "build": "tsup",
44
+ "dev": "tsup --watch",
45
+ "test": "vitest",
46
+ "typecheck": "tsc --noEmit"
47
+ }
48
+ }