@flight-framework/cli 0.2.1 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -8,7 +8,7 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
8
8
 
9
9
  // src/index.ts
10
10
  import { cac } from "cac";
11
- import pc6 from "picocolors";
11
+ import pc7 from "picocolors";
12
12
 
13
13
  // src/version.ts
14
14
  var VERSION = "0.0.1";
@@ -1017,14 +1017,16 @@ async function startSSRServer(vite, root, port, host) {
1017
1017
  const Component = mod.default;
1018
1018
  const { render } = await vite.ssrLoadModule("/src/entry-server.tsx");
1019
1019
  if (typeof render === "function" && Component) {
1020
- appHtml = await render(url, { Component });
1020
+ const request = new Request(new URL(url, `http://${req.headers.host || "localhost"}`).href);
1021
+ appHtml = await render({ url, request, Component });
1021
1022
  }
1022
1023
  }
1023
1024
  }
1024
1025
  if (!appHtml) {
1025
1026
  const { render } = await vite.ssrLoadModule("/src/entry-server.tsx");
1026
1027
  if (typeof render === "function") {
1027
- appHtml = await render(url);
1028
+ const request = new Request(new URL(url, `http://${req.headers.host || "localhost"}`).href);
1029
+ appHtml = await render({ url, request });
1028
1030
  }
1029
1031
  }
1030
1032
  if (appHtml) {
@@ -1832,18 +1834,471 @@ ${pc5.cyan("Quick example:")}
1832
1834
  console.log(`${pc5.dim("Docs:")} https://flight.dev/docs/packages/${packageName}`);
1833
1835
  }
1834
1836
 
1837
+ // src/commands/adapter-create.ts
1838
+ import { existsSync as existsSync7, mkdirSync as mkdirSync4, writeFileSync as writeFileSync5 } from "fs";
1839
+ import { join as join6 } from "path";
1840
+ import pc6 from "picocolors";
1841
+ async function adapterCreateCommand(name, options = {}) {
1842
+ const cwd = process.cwd();
1843
+ const adapterName = name.toLowerCase().replace(/[^a-z0-9-]/g, "-");
1844
+ const packageName = `@flight-framework/adapter-${adapterName}`;
1845
+ const outputDir = options.outputDir || join6(cwd, "packages", `adapter-${adapterName}`);
1846
+ const type = options.type || "node";
1847
+ const includeValidation = options.validation || false;
1848
+ console.log(pc6.cyan(`
1849
+ Creating adapter: ${packageName}
1850
+ `));
1851
+ if (existsSync7(outputDir)) {
1852
+ console.error(pc6.red(` Error: Directory already exists: ${outputDir}`));
1853
+ process.exit(1);
1854
+ }
1855
+ mkdirSync4(join6(outputDir, "src"), { recursive: true });
1856
+ mkdirSync4(join6(outputDir, "tests"), { recursive: true });
1857
+ const files = generateAdapterFiles(adapterName, packageName, type, includeValidation);
1858
+ for (const [filePath, content] of Object.entries(files)) {
1859
+ const fullPath = join6(outputDir, filePath);
1860
+ writeFileSync5(fullPath, content, "utf-8");
1861
+ console.log(pc6.green(` \u2713 Created ${filePath}`));
1862
+ }
1863
+ console.log(pc6.cyan(`
1864
+ Adapter created successfully!
1865
+
1866
+ Next steps:
1867
+ 1. cd packages/adapter-${adapterName}
1868
+ 2. Implement your adapter logic in src/index.ts
1869
+ 3. Run: pnpm build
1870
+ 4. Test: pnpm test
1871
+
1872
+ Documentation:
1873
+ https://flight.dev/docs/adapters/custom
1874
+ `));
1875
+ }
1876
+ function generateAdapterFiles(name, packageName, type, includeValidation) {
1877
+ const pascalName = name.split("-").map((s) => s.charAt(0).toUpperCase() + s.slice(1)).join("");
1878
+ return {
1879
+ "package.json": generatePackageJson(packageName, includeValidation),
1880
+ "tsconfig.json": generateTsConfig(),
1881
+ "tsup.config.ts": generateTsupConfig(),
1882
+ "src/index.ts": generateAdapterSource(name, pascalName, type, includeValidation),
1883
+ "tests/adapter.test.ts": generateAdapterTest(name, pascalName),
1884
+ "README.md": generateReadme(name, packageName)
1885
+ };
1886
+ }
1887
+ function generatePackageJson(packageName, includeValidation) {
1888
+ const pkg = {
1889
+ name: packageName,
1890
+ version: "0.1.0",
1891
+ description: `Flight adapter for custom platform`,
1892
+ type: "module",
1893
+ main: "./dist/index.js",
1894
+ types: "./dist/index.d.ts",
1895
+ exports: {
1896
+ ".": {
1897
+ types: "./dist/index.d.ts",
1898
+ import: "./dist/index.js"
1899
+ }
1900
+ },
1901
+ scripts: {
1902
+ build: "tsup",
1903
+ test: "vitest run",
1904
+ "test:watch": "vitest"
1905
+ },
1906
+ dependencies: {
1907
+ "@flight-framework/core": "^0.4.0"
1908
+ },
1909
+ devDependencies: {
1910
+ tsup: "^8.0.0",
1911
+ typescript: "^5.0.0",
1912
+ vitest: "^2.0.0",
1913
+ ...includeValidation ? { zod: "^3.23.0" } : {}
1914
+ },
1915
+ peerDependencies: includeValidation ? {
1916
+ zod: "^3.0.0"
1917
+ } : void 0,
1918
+ peerDependenciesMeta: includeValidation ? {
1919
+ zod: { optional: true }
1920
+ } : void 0
1921
+ };
1922
+ return JSON.stringify(pkg, null, 2);
1923
+ }
1924
+ function generateTsConfig() {
1925
+ return JSON.stringify({
1926
+ extends: "../../tsconfig.base.json",
1927
+ compilerOptions: {
1928
+ outDir: "./dist",
1929
+ rootDir: "./src"
1930
+ },
1931
+ include: ["src"]
1932
+ }, null, 2);
1933
+ }
1934
+ function generateTsupConfig() {
1935
+ return `import { defineConfig } from 'tsup';
1936
+
1937
+ export default defineConfig({
1938
+ entry: ['src/index.ts'],
1939
+ format: ['esm'],
1940
+ dts: true,
1941
+ clean: true,
1942
+ target: 'node20',
1943
+ });
1944
+ `;
1945
+ }
1946
+ function generateAdapterSource(name, pascalName, type, includeValidation) {
1947
+ if (includeValidation) {
1948
+ return `/**
1949
+ * Flight Adapter - ${pascalName}
1950
+ *
1951
+ * Custom deployment adapter with optional Zod validation.
1952
+ */
1953
+
1954
+ import { createValidatedAdapter, type AdapterBuilder } from '@flight-framework/core/adapters';
1955
+ import { z } from 'zod';
1956
+
1957
+ // ============================================================================
1958
+ // Options Schema (Optional - Zod validation)
1959
+ // ============================================================================
1960
+
1961
+ const optionsSchema = z.object({
1962
+ /** Server port */
1963
+ port: z.number().default(3000),
1964
+ /** Enable health check endpoint */
1965
+ healthCheck: z.boolean().default(true),
1966
+ /** Custom environment variables */
1967
+ env: z.record(z.string()).optional(),
1968
+ });
1969
+
1970
+ export type ${pascalName}AdapterOptions = z.infer<typeof optionsSchema>;
1971
+
1972
+ // ============================================================================
1973
+ // Adapter Implementation
1974
+ // ============================================================================
1975
+
1976
+ export default createValidatedAdapter('${name}', optionsSchema, (options) => ({
1977
+ async adapt(builder: AdapterBuilder) {
1978
+ builder.log.info(\`Building for ${pascalName} platform...\`);
1979
+ builder.log.info(\`Port: \${options.port}\`);
1980
+
1981
+ // Generate server entry
1982
+ await generateServerEntry(builder, options);
1983
+
1984
+ // Generate platform-specific config
1985
+ await generatePlatformConfig(builder, options);
1986
+
1987
+ builder.log.info('Build complete!');
1988
+ },
1989
+
1990
+ supports: {
1991
+ node: () => ${type === "node" || type === "container"},
1992
+ edge: () => ${type === "edge" || type === "serverless"},
1993
+ streaming: () => ${type === "node"},
1994
+ websockets: () => ${type === "node"},
1995
+ },
1996
+
1997
+ emulate: () => ({
1998
+ env: {
1999
+ ${name.toUpperCase().replace(/-/g, "_")}_PLATFORM: 'true',
2000
+ PORT: String(options.port),
2001
+ },
2002
+ }),
2003
+ }));
2004
+
2005
+ // ============================================================================
2006
+ // Generator Functions
2007
+ // ============================================================================
2008
+
2009
+ async function generateServerEntry(builder: AdapterBuilder, options: ${pascalName}AdapterOptions): Promise<void> {
2010
+ const serverCode = \`
2011
+ import { createUniversalHandler } from '@flight-framework/core/adapters';
2012
+ import manifest from './manifest.js';
2013
+
2014
+ const handler = createUniversalHandler(manifest);
2015
+
2016
+ const server = Bun.serve({
2017
+ port: \${options.port},
2018
+ fetch: handler,
2019
+ });
2020
+
2021
+ console.log(\\\`Server running at http://localhost:\${options.port}\\\`);
2022
+ \`;
2023
+
2024
+ await builder.writeFile('server.ts', serverCode.trim());
2025
+ }
2026
+
2027
+ async function generatePlatformConfig(builder: AdapterBuilder, options: ${pascalName}AdapterOptions): Promise<void> {
2028
+ const config = {
2029
+ name: '${name}-app',
2030
+ port: options.port,
2031
+ healthCheck: options.healthCheck ? '/health' : null,
2032
+ };
2033
+
2034
+ await builder.writeFile('platform.json', JSON.stringify(config, null, 2));
2035
+ }
2036
+ `;
2037
+ }
2038
+ return `/**
2039
+ * Flight Adapter - ${pascalName}
2040
+ *
2041
+ * Custom deployment adapter for ${pascalName} platform.
2042
+ *
2043
+ * @example
2044
+ * \`\`\`typescript
2045
+ * import ${name.replace(/-/g, "")} from '${name.includes("@") ? name : `@flight-framework/adapter-${name}`}';
2046
+ *
2047
+ * export default defineConfig({
2048
+ * adapter: ${name.replace(/-/g, "")}({
2049
+ * port: 3000,
2050
+ * }),
2051
+ * });
2052
+ * \`\`\`
2053
+ */
2054
+
2055
+ import { createAdapter, type AdapterBuilder } from '@flight-framework/core/adapters';
2056
+
2057
+ // ============================================================================
2058
+ // Options Interface
2059
+ // ============================================================================
2060
+
2061
+ export interface ${pascalName}AdapterOptions {
2062
+ /** Server port (default: 3000) */
2063
+ port?: number;
2064
+ /** Enable health check endpoint (default: true) */
2065
+ healthCheck?: boolean;
2066
+ /** Custom environment variables */
2067
+ env?: Record<string, string>;
2068
+ }
2069
+
2070
+ // ============================================================================
2071
+ // Adapter Implementation
2072
+ // ============================================================================
2073
+
2074
+ export default function ${name.replace(/-/g, "")}Adapter(options: ${pascalName}AdapterOptions = {}) {
2075
+ const {
2076
+ port = 3000,
2077
+ healthCheck = true,
2078
+ env = {},
2079
+ } = options;
2080
+
2081
+ return createAdapter({
2082
+ name: '${name}',
2083
+
2084
+ async adapt(builder: AdapterBuilder) {
2085
+ builder.log.info(\`Building for ${pascalName} platform...\`);
2086
+ builder.log.info(\`Port: \${port}\`);
2087
+
2088
+ // Generate server entry
2089
+ await generateServerEntry(builder, port, healthCheck);
2090
+
2091
+ // Generate platform-specific config
2092
+ await generatePlatformConfig(builder, port, healthCheck);
2093
+
2094
+ builder.log.info('Build complete!');
2095
+ },
2096
+
2097
+ supports: {
2098
+ node: () => ${type === "node" || type === "container"},
2099
+ edge: () => ${type === "edge" || type === "serverless"},
2100
+ streaming: () => ${type === "node"},
2101
+ websockets: () => ${type === "node"},
2102
+ },
2103
+
2104
+ emulate: () => ({
2105
+ env: {
2106
+ ${name.toUpperCase().replace(/-/g, "_")}_PLATFORM: 'true',
2107
+ PORT: String(port),
2108
+ ...env,
2109
+ },
2110
+ }),
2111
+ });
2112
+ }
2113
+
2114
+ // ============================================================================
2115
+ // Generator Functions
2116
+ // ============================================================================
2117
+
2118
+ async function generateServerEntry(
2119
+ builder: AdapterBuilder,
2120
+ port: number,
2121
+ healthCheck: boolean
2122
+ ): Promise<void> {
2123
+ const serverCode = \`
2124
+ import { createServer } from 'node:http';
2125
+ import { createUniversalHandler } from '@flight-framework/core/adapters';
2126
+ import manifest from './manifest.js';
2127
+
2128
+ const handler = createUniversalHandler(manifest);
2129
+
2130
+ const server = createServer(async (req, res) => {
2131
+ const url = req.url || '/';
2132
+
2133
+ // Health check endpoint
2134
+ if (url === '/health' && \${healthCheck}) {
2135
+ res.writeHead(200, { 'Content-Type': 'application/json' });
2136
+ res.end(JSON.stringify({ status: 'ok' }));
2137
+ return;
2138
+ }
2139
+
2140
+ // Handle request with Flight
2141
+ const webReq = new Request(\\\`http://localhost\${url}\\\`, {
2142
+ method: req.method,
2143
+ headers: Object.fromEntries(
2144
+ Object.entries(req.headers).filter(([_, v]) => v != null).map(([k, v]) => [k, String(v)])
2145
+ ),
2146
+ });
2147
+
2148
+ const response = await handler(webReq);
2149
+
2150
+ res.writeHead(response.status, Object.fromEntries(response.headers));
2151
+ res.end(await response.text());
2152
+ });
2153
+
2154
+ server.listen(\${port}, () => {
2155
+ console.log(\\\`Server running at http://localhost:\${port}\\\`);
2156
+ });
2157
+ \`;
2158
+
2159
+ await builder.writeFile('server.mjs', serverCode.trim());
2160
+ }
2161
+
2162
+ async function generatePlatformConfig(
2163
+ builder: AdapterBuilder,
2164
+ port: number,
2165
+ healthCheck: boolean
2166
+ ): Promise<void> {
2167
+ const config = {
2168
+ name: '${name}-app',
2169
+ port,
2170
+ healthCheck: healthCheck ? '/health' : null,
2171
+ };
2172
+
2173
+ await builder.writeFile('platform.json', JSON.stringify(config, null, 2));
2174
+ }
2175
+ `;
2176
+ }
2177
+ function generateAdapterTest(name, pascalName) {
2178
+ return `/**
2179
+ * ${pascalName} Adapter Tests
2180
+ */
2181
+
2182
+ import { describe, it, expect, vi } from 'vitest';
2183
+ import adapter from '../src/index.js';
2184
+
2185
+ describe('adapter-${name}', () => {
2186
+ const createMockBuilder = () => ({
2187
+ manifest: {
2188
+ entries: {},
2189
+ files: [],
2190
+ routes: [],
2191
+ },
2192
+ root: '/test',
2193
+ outDir: '/test/dist',
2194
+ readFile: vi.fn(),
2195
+ writeFile: vi.fn(),
2196
+ copy: vi.fn(),
2197
+ glob: vi.fn(),
2198
+ log: {
2199
+ info: vi.fn(),
2200
+ warn: vi.fn(),
2201
+ error: vi.fn(),
2202
+ },
2203
+ });
2204
+
2205
+ it('should have correct name', () => {
2206
+ const instance = adapter();
2207
+ expect(instance.name).toBe('${name}');
2208
+ });
2209
+
2210
+ it('should generate server entry', async () => {
2211
+ const instance = adapter({ port: 4000 });
2212
+ const builder = createMockBuilder();
2213
+
2214
+ await instance.adapt(builder);
2215
+
2216
+ expect(builder.writeFile).toHaveBeenCalledWith(
2217
+ 'server.mjs',
2218
+ expect.stringContaining('4000')
2219
+ );
2220
+ });
2221
+
2222
+ it('should generate platform config', async () => {
2223
+ const instance = adapter();
2224
+ const builder = createMockBuilder();
2225
+
2226
+ await instance.adapt(builder);
2227
+
2228
+ expect(builder.writeFile).toHaveBeenCalledWith(
2229
+ 'platform.json',
2230
+ expect.any(String)
2231
+ );
2232
+ });
2233
+
2234
+ it('should declare supported features', () => {
2235
+ const instance = adapter();
2236
+
2237
+ expect(instance.supports?.node?.()).toBeDefined();
2238
+ expect(instance.supports?.streaming?.()).toBeDefined();
2239
+ });
2240
+
2241
+ it('should provide emulation environment', () => {
2242
+ const instance = adapter({ port: 5000 });
2243
+ const emulation = instance.emulate?.();
2244
+
2245
+ expect(emulation?.env?.PORT).toBe('5000');
2246
+ expect(emulation?.env?.${name.toUpperCase().replace(/-/g, "_")}_PLATFORM).toBe('true');
2247
+ });
2248
+ });
2249
+ `;
2250
+ }
2251
+ function generateReadme(name, packageName) {
2252
+ return `# ${packageName}
2253
+
2254
+ Flight adapter for ${name} platform.
2255
+
2256
+ ## Installation
2257
+
2258
+ \`\`\`bash
2259
+ npm install ${packageName}
2260
+ \`\`\`
2261
+
2262
+ ## Usage
2263
+
2264
+ \`\`\`typescript
2265
+ import { defineConfig } from '@flight-framework/core';
2266
+ import ${name.replace(/-/g, "")} from '${packageName}';
2267
+
2268
+ export default defineConfig({
2269
+ adapter: ${name.replace(/-/g, "")}({
2270
+ port: 3000,
2271
+ healthCheck: true,
2272
+ }),
2273
+ });
2274
+ \`\`\`
2275
+
2276
+ ## Options
2277
+
2278
+ | Option | Type | Default | Description |
2279
+ |--------|------|---------|-------------|
2280
+ | \`port\` | \`number\` | \`3000\` | Server port |
2281
+ | \`healthCheck\` | \`boolean\` | \`true\` | Enable health check endpoint |
2282
+ | \`env\` | \`Record<string, string>\` | \`{}\` | Custom environment variables |
2283
+
2284
+ ## License
2285
+
2286
+ MIT
2287
+ `;
2288
+ }
2289
+
1835
2290
  // src/index.ts
1836
2291
  var cli = cac("flight");
1837
2292
  var LOGO = `
1838
- ${pc6.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557")}
1839
- ${pc6.cyan(" \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D")}
1840
- ${pc6.cyan(" \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 ")}
1841
- ${pc6.cyan(" \u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2551 ")}
1842
- ${pc6.cyan(" \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 ")}
1843
- ${pc6.cyan(" \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D ")}
2293
+ ${pc7.cyan(" \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2557 \u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557")}
2294
+ ${pc7.cyan(" \u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\u255A\u2550\u2550\u2588\u2588\u2554\u2550\u2550\u255D")}
2295
+ ${pc7.cyan(" \u2588\u2588\u2588\u2588\u2588\u2557 \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2588\u2557\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2551 \u2588\u2588\u2551 ")}
2296
+ ${pc7.cyan(" \u2588\u2588\u2554\u2550\u2550\u255D \u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2551 \u2588\u2588\u2551\u2588\u2588\u2554\u2550\u2550\u2588\u2588\u2551 \u2588\u2588\u2551 ")}
2297
+ ${pc7.cyan(" \u2588\u2588\u2551 \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2557\u2588\u2588\u2551\u255A\u2588\u2588\u2588\u2588\u2588\u2588\u2554\u255D\u2588\u2588\u2551 \u2588\u2588\u2551 \u2588\u2588\u2551 ")}
2298
+ ${pc7.cyan(" \u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u2550\u255D\u255A\u2550\u255D \u255A\u2550\u2550\u2550\u2550\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D \u255A\u2550\u255D ")}
1844
2299
 
1845
- ${pc6.dim("The Agnostic Full-Stack Framework")}
1846
- ${pc6.dim("Maximum Flexibility. Zero Lock-in.")}
2300
+ ${pc7.dim("The Agnostic Full-Stack Framework")}
2301
+ ${pc7.dim("Maximum Flexibility. Zero Lock-in.")}
1847
2302
  `;
1848
2303
  function printLogo() {
1849
2304
  console.log(LOGO);
@@ -1857,6 +2312,7 @@ cli.command("build", "Build for production").option("--outDir <dir>", "Output di
1857
2312
  cli.command("preview", "Preview production build").option("-p, --port <port>", "Port to listen on").option("-h, --host <host>", "Host to bind to").option("--open", "Open browser on start").action(previewCommand);
1858
2313
  cli.command("routes:generate", "Generate route manifest from routes directory").option("--routesDir <dir>", "Routes directory", { default: "src/routes" }).option("--outputDir <dir>", "Output directory", { default: "src/.flight" }).action(routesGenerateCommand);
1859
2314
  cli.command("types:generate", "Generate TypeScript types for routes and environment").option("--routesDir <dir>", "Routes directory", { default: "src/routes" }).option("--outputDir <dir>", "Output directory", { default: "src/.flight" }).option("--routes", "Generate route types", { default: true }).option("--env", "Generate environment variable types").option("--watch", "Watch for changes and regenerate").action(typesGenerateCommand);
2315
+ cli.command("adapter:create <name>", "Create a new adapter package").option("-t, --type <type>", "Platform type (node, edge, container, serverless)", { default: "node" }).option("--validation", "Include Zod validation example").option("--outputDir <dir>", "Output directory").action(adapterCreateCommand);
1860
2316
  function run() {
1861
2317
  try {
1862
2318
  cli.parse(process.argv, { run: false });
@@ -1865,7 +2321,7 @@ function run() {
1865
2321
  }
1866
2322
  cli.runMatchedCommand();
1867
2323
  } catch (error) {
1868
- console.error(pc6.red("Error:"), error instanceof Error ? error.message : error);
2324
+ console.error(pc7.red("Error:"), error instanceof Error ? error.message : error);
1869
2325
  process.exit(1);
1870
2326
  }
1871
2327
  }