@geekmidas/cli 0.13.0 → 0.15.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (80) hide show
  1. package/dist/{bundler-DskIqW2t.mjs → bundler-D7cM_FWw.mjs} +34 -10
  2. package/dist/bundler-D7cM_FWw.mjs.map +1 -0
  3. package/dist/{bundler-B1qy9b-j.cjs → bundler-Nuew7Xcn.cjs} +33 -9
  4. package/dist/bundler-Nuew7Xcn.cjs.map +1 -0
  5. package/dist/config.d.cts +1 -1
  6. package/dist/config.d.mts +1 -1
  7. package/dist/dokploy-api-B7KxOQr3.cjs +3 -0
  8. package/dist/dokploy-api-C7F9VykY.cjs +317 -0
  9. package/dist/dokploy-api-C7F9VykY.cjs.map +1 -0
  10. package/dist/dokploy-api-CaETb2L6.mjs +305 -0
  11. package/dist/dokploy-api-CaETb2L6.mjs.map +1 -0
  12. package/dist/dokploy-api-DHvfmWbi.mjs +3 -0
  13. package/dist/{encryption-Dyf_r1h-.cjs → encryption-D7Efcdi9.cjs} +1 -1
  14. package/dist/{encryption-Dyf_r1h-.cjs.map → encryption-D7Efcdi9.cjs.map} +1 -1
  15. package/dist/{encryption-C8H-38Yy.mjs → encryption-h4Nb6W-M.mjs} +1 -1
  16. package/dist/{encryption-C8H-38Yy.mjs.map → encryption-h4Nb6W-M.mjs.map} +1 -1
  17. package/dist/index.cjs +1508 -1073
  18. package/dist/index.cjs.map +1 -1
  19. package/dist/index.mjs +1508 -1073
  20. package/dist/index.mjs.map +1 -1
  21. package/dist/{openapi-Bt_1FDpT.cjs → openapi-C89hhkZC.cjs} +3 -3
  22. package/dist/{openapi-Bt_1FDpT.cjs.map → openapi-C89hhkZC.cjs.map} +1 -1
  23. package/dist/{openapi-BfFlOBCG.mjs → openapi-CZVcfxk-.mjs} +3 -3
  24. package/dist/{openapi-BfFlOBCG.mjs.map → openapi-CZVcfxk-.mjs.map} +1 -1
  25. package/dist/{openapi-react-query-B6XTeGqS.mjs → openapi-react-query-CM2_qlW9.mjs} +1 -1
  26. package/dist/{openapi-react-query-B6XTeGqS.mjs.map → openapi-react-query-CM2_qlW9.mjs.map} +1 -1
  27. package/dist/{openapi-react-query-B-sNWHFU.cjs → openapi-react-query-iKjfLzff.cjs} +1 -1
  28. package/dist/{openapi-react-query-B-sNWHFU.cjs.map → openapi-react-query-iKjfLzff.cjs.map} +1 -1
  29. package/dist/openapi-react-query.cjs +1 -1
  30. package/dist/openapi-react-query.mjs +1 -1
  31. package/dist/openapi.cjs +1 -1
  32. package/dist/openapi.d.cts +1 -1
  33. package/dist/openapi.d.mts +1 -1
  34. package/dist/openapi.mjs +1 -1
  35. package/dist/{storage-kSxTjkNb.mjs → storage-BaOP55oq.mjs} +16 -2
  36. package/dist/storage-BaOP55oq.mjs.map +1 -0
  37. package/dist/{storage-Bj1E26lU.cjs → storage-Bn3K9Ccu.cjs} +21 -1
  38. package/dist/storage-Bn3K9Ccu.cjs.map +1 -0
  39. package/dist/storage-UfyTn7Zm.cjs +7 -0
  40. package/dist/storage-nkGIjeXt.mjs +3 -0
  41. package/dist/{types-BhkZc-vm.d.cts → types-BgaMXsUa.d.cts} +3 -1
  42. package/dist/{types-BR0M2v_c.d.mts.map → types-BgaMXsUa.d.cts.map} +1 -1
  43. package/dist/{types-BR0M2v_c.d.mts → types-iFk5ms7y.d.mts} +3 -1
  44. package/dist/{types-BhkZc-vm.d.cts.map → types-iFk5ms7y.d.mts.map} +1 -1
  45. package/package.json +4 -4
  46. package/src/auth/__tests__/credentials.spec.ts +127 -0
  47. package/src/auth/__tests__/index.spec.ts +69 -0
  48. package/src/auth/credentials.ts +33 -0
  49. package/src/auth/index.ts +57 -50
  50. package/src/build/__tests__/bundler.spec.ts +5 -4
  51. package/src/build/__tests__/endpoint-analyzer.spec.ts +623 -0
  52. package/src/build/__tests__/handler-templates.spec.ts +272 -0
  53. package/src/build/bundler.ts +61 -8
  54. package/src/build/index.ts +21 -0
  55. package/src/build/types.ts +6 -0
  56. package/src/deploy/__tests__/docker.spec.ts +44 -6
  57. package/src/deploy/__tests__/dokploy-api.spec.ts +698 -0
  58. package/src/deploy/__tests__/dokploy.spec.ts +196 -6
  59. package/src/deploy/__tests__/index.spec.ts +401 -0
  60. package/src/deploy/__tests__/init.spec.ts +147 -16
  61. package/src/deploy/docker.ts +109 -5
  62. package/src/deploy/dokploy-api.ts +581 -0
  63. package/src/deploy/dokploy.ts +66 -93
  64. package/src/deploy/index.ts +630 -32
  65. package/src/deploy/init.ts +192 -249
  66. package/src/deploy/types.ts +24 -2
  67. package/src/dev/__tests__/index.spec.ts +95 -0
  68. package/src/docker/__tests__/templates.spec.ts +144 -0
  69. package/src/docker/index.ts +96 -6
  70. package/src/docker/templates.ts +114 -27
  71. package/src/generators/EndpointGenerator.ts +2 -2
  72. package/src/index.ts +34 -13
  73. package/src/secrets/storage.ts +15 -0
  74. package/src/types.ts +2 -0
  75. package/dist/bundler-B1qy9b-j.cjs.map +0 -1
  76. package/dist/bundler-DskIqW2t.mjs.map +0 -1
  77. package/dist/storage-BOOpAF8N.cjs +0 -5
  78. package/dist/storage-Bj1E26lU.cjs.map +0 -1
  79. package/dist/storage-kSxTjkNb.mjs.map +0 -1
  80. package/dist/storage-tgZSUnKl.mjs +0 -3
@@ -164,4 +164,4 @@ function capitalize(str) {
164
164
 
165
165
  //#endregion
166
166
  export { generateReactQueryCommand };
167
- //# sourceMappingURL=openapi-react-query-B6XTeGqS.mjs.map
167
+ //# sourceMappingURL=openapi-react-query-CM2_qlW9.mjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"openapi-react-query-B6XTeGqS.mjs","names":["options: ReactQueryOptions","spec: OpenAPISpec","operations: OperationInfo[]","operation: any","schema: any","_spec: OpenAPISpec","apiName: string","op: OperationInfo","paramParts: string[]","str: string"],"sources":["../src/openapi-react-query.ts"],"sourcesContent":["#!/usr/bin/env -S npx tsx\n\nimport { exec } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { promisify } from 'node:util';\n\nconst execAsync = promisify(exec);\n\ninterface ReactQueryOptions {\n\tinput?: string;\n\toutput?: string;\n\tname?: string;\n}\n\ninterface OpenAPISpec {\n\topenapi: string;\n\tinfo?: {\n\t\ttitle?: string;\n\t\tversion?: string;\n\t};\n\tpaths: Record<string, Record<string, any>>;\n}\n\nexport async function generateReactQueryCommand(\n\toptions: ReactQueryOptions = {},\n): Promise<void> {\n\tconst logger = console;\n\n\ttry {\n\t\t// Read OpenAPI spec\n\t\tconst inputPath = options.input || join(process.cwd(), 'openapi.json');\n\n\t\tif (!existsSync(inputPath)) {\n\t\t\tthrow new Error(\n\t\t\t\t`OpenAPI spec not found at ${inputPath}. Run 'npx @geekmidas/cli openapi' first.`,\n\t\t\t);\n\t\t}\n\n\t\tconst specContent = await readFile(inputPath, 'utf-8');\n\t\tconst spec: OpenAPISpec = JSON.parse(specContent);\n\n\t\t// Generate TypeScript types from OpenAPI spec\n\t\tconst outputDir = dirname(\n\t\t\toptions.output || join(process.cwd(), 'src', 'api', 'hooks.ts'),\n\t\t);\n\t\tconst typesPath = join(outputDir, 'openapi-types.d.ts');\n\n\t\tlogger.log('Generating TypeScript types from OpenAPI spec...');\n\n\t\ttry {\n\t\t\t// Use npx to run openapi-typescript\n\t\t\tawait execAsync(\n\t\t\t\t`npx openapi-typescript \"${inputPath}\" -o \"${typesPath}\"`,\n\t\t\t\t{ cwd: process.cwd() },\n\t\t\t);\n\t\t\tlogger.log(`TypeScript types generated: ${typesPath}`);\n\t\t} catch (_error) {\n\t\t\tlogger.warn(\n\t\t\t\t'Could not generate types with openapi-typescript. Install it for better type inference.',\n\t\t\t);\n\t\t\tlogger.warn('Run: npm install -D openapi-typescript');\n\n\t\t\t// Generate basic types file\n\t\t\tawait mkdir(dirname(typesPath), { recursive: true });\n\t\t\tawait writeFile(\n\t\t\t\ttypesPath,\n\t\t\t\t`// Auto-generated placeholder types\nexport interface paths {\n [path: string]: {\n [method: string]: {\n operationId?: string;\n parameters?: any;\n requestBody?: any;\n responses?: any;\n };\n };\n}\n`,\n\t\t\t);\n\t\t}\n\n\t\t// Extract operation info\n\t\tconst operations = extractOperations(spec);\n\n\t\t// Generate TypeScript code\n\t\tconst code = generateReactQueryCode(\n\t\t\tspec,\n\t\t\toperations,\n\t\t\toptions.name || 'API',\n\t\t);\n\n\t\t// Write output\n\t\tconst outputPath =\n\t\t\toptions.output || join(process.cwd(), 'src', 'api', 'hooks.ts');\n\t\tawait mkdir(dirname(outputPath), { recursive: true });\n\t\tawait writeFile(outputPath, code);\n\n\t\tlogger.log(`React Query hooks generated: ${outputPath}`);\n\t\tlogger.log(`Generated ${operations.length} hooks`);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`React Query generation failed: ${(error as Error).message}`,\n\t\t);\n\t}\n}\n\ninterface OperationInfo {\n\toperationId: string;\n\tpath: string;\n\tmethod: string;\n\tendpoint: string; // Full endpoint like 'GET /users/{id}'\n\tparameters?: Array<{ name: string; in: string; required?: boolean }>;\n\trequestBody?: boolean;\n\tresponseType?: string;\n}\n\nfunction extractOperations(spec: OpenAPISpec): OperationInfo[] {\n\tconst operations: OperationInfo[] = [];\n\n\tObject.entries(spec.paths).forEach(([path, methods]) => {\n\t\tObject.entries(methods).forEach(([method, operation]) => {\n\t\t\tif (operation.operationId) {\n\t\t\t\toperations.push({\n\t\t\t\t\toperationId: operation.operationId,\n\t\t\t\t\tpath,\n\t\t\t\t\tmethod: method.toUpperCase(),\n\t\t\t\t\tendpoint: `${method.toUpperCase()} ${path}`,\n\t\t\t\t\tparameters: operation.parameters,\n\t\t\t\t\trequestBody: !!operation.requestBody,\n\t\t\t\t\tresponseType: extractResponseType(operation),\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t});\n\n\treturn operations;\n}\n\nfunction extractResponseType(operation: any): string {\n\tconst responses = operation.responses;\n\tif (!responses) return 'unknown';\n\n\tconst successResponse = responses['200'] || responses['201'];\n\tif (!successResponse?.content?.['application/json']?.schema) {\n\t\treturn 'unknown';\n\t}\n\n\t// Basic type inference from schema\n\tconst schema = successResponse.content['application/json'].schema;\n\treturn schemaToTypeString(schema);\n}\n\nfunction schemaToTypeString(schema: any): string {\n\tif (!schema) return 'unknown';\n\n\tswitch (schema.type) {\n\t\tcase 'string':\n\t\t\treturn 'string';\n\t\tcase 'number':\n\t\tcase 'integer':\n\t\t\treturn 'number';\n\t\tcase 'boolean':\n\t\t\treturn 'boolean';\n\t\tcase 'array':\n\t\t\treturn `Array<${schemaToTypeString(schema.items)}>`;\n\t\tcase 'object':\n\t\t\tif (schema.properties) {\n\t\t\t\tconst props = Object.entries(schema.properties)\n\t\t\t\t\t.map(\n\t\t\t\t\t\t([key, value]: [string, any]) =>\n\t\t\t\t\t\t\t`${key}: ${schemaToTypeString(value)}`,\n\t\t\t\t\t)\n\t\t\t\t\t.join('; ');\n\t\t\t\treturn `{ ${props} }`;\n\t\t\t}\n\t\t\treturn 'Record<string, unknown>';\n\t\tdefault:\n\t\t\treturn 'unknown';\n\t}\n}\n\nfunction generateReactQueryCode(\n\t_spec: OpenAPISpec,\n\toperations: OperationInfo[],\n\tapiName: string,\n): string {\n\tconst imports = `import { createTypedQueryClient } from '@geekmidas/client';\nimport type { paths } from './openapi-types';\n\n// Create typed query client\nexport const ${apiName.toLowerCase()} = createTypedQueryClient<paths>({\n baseURL: process.env.NEXT_PUBLIC_API_URL || '/api',\n});\n\n// Export individual hooks for better DX\n`;\n\n\tconst queryHooks = operations\n\t\t.filter((op) => op.method === 'GET')\n\t\t.map((op) => generateQueryHook(op, apiName))\n\t\t.join('\\n\\n');\n\n\tconst mutationHooks = operations\n\t\t.filter((op) => op.method !== 'GET')\n\t\t.map((op) => generateMutationHook(op, apiName))\n\t\t.join('\\n\\n');\n\n\tconst typeExports = generateTypeExports(operations);\n\n\treturn `${imports}\n// Query Hooks\n${queryHooks}\n\n// Mutation Hooks\n${mutationHooks}\n\n// Type exports for convenience\n${typeExports}\n\n// Re-export the api for advanced usage\nexport { ${apiName.toLowerCase()} };\n`;\n}\n\nfunction generateQueryHook(op: OperationInfo, apiName: string): string {\n\tconst hookName = `use${capitalize(op.operationId)}`;\n\tconst endpoint = op.endpoint;\n\tconst hasParams = op.parameters?.some((p) => p.in === 'path');\n\tconst hasQuery = op.parameters?.some((p) => p.in === 'query');\n\n\t// Generate properly typed hook\n\tlet params = '';\n\tlet args = '';\n\n\tif (hasParams || hasQuery) {\n\t\tconst paramParts: string[] = [];\n\t\tif (hasParams) {\n\t\t\tconst pathParams =\n\t\t\t\top.parameters?.filter((p) => p.in === 'path').map((p) => p.name) || [];\n\t\t\tparamParts.push(\n\t\t\t\t`params: { ${pathParams.map((p) => `${p}: string`).join('; ')} }`,\n\t\t\t);\n\t\t}\n\t\tif (hasQuery) {\n\t\t\tparamParts.push(`query?: Record<string, any>`);\n\t\t}\n\t\tparams = `config: { ${paramParts.join('; ')} }, `;\n\t\targs = ', config';\n\t}\n\n\treturn `export const ${hookName} = (\n ${params}options?: Parameters<typeof ${apiName.toLowerCase()}.useQuery>[2]\n) => {\n return ${apiName.toLowerCase()}.useQuery('${endpoint}' as any${args}, options);\n};`;\n}\n\nfunction generateMutationHook(op: OperationInfo, apiName: string): string {\n\tconst hookName = `use${capitalize(op.operationId)}`;\n\tconst endpoint = op.endpoint;\n\n\treturn `export const ${hookName} = (\n options?: Parameters<typeof ${apiName.toLowerCase()}.useMutation>[1]\n) => {\n return ${apiName.toLowerCase()}.useMutation('${endpoint}' as any, options);\n};`;\n}\n\nfunction generateTypeExports(operations: OperationInfo[]): string {\n\tconst exports = operations.map((op) => {\n\t\tconst typeName = capitalize(op.operationId);\n\t\tconst isQuery = op.method === 'GET';\n\n\t\tif (isQuery) {\n\t\t\treturn `export type ${typeName}Response = Awaited<ReturnType<ReturnType<typeof use${typeName}>['data']>>;`;\n\t\t} else {\n\t\t\treturn `export type ${typeName}Response = Awaited<ReturnType<ReturnType<typeof use${typeName}>['mutateAsync']>>;`;\n\t\t}\n\t});\n\n\treturn exports.join('\\n');\n}\n\nfunction capitalize(str: string): string {\n\treturn str.charAt(0).toUpperCase() + str.slice(1);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"openapi-react-query-CM2_qlW9.mjs","names":["options: ReactQueryOptions","spec: OpenAPISpec","operations: OperationInfo[]","operation: any","schema: any","_spec: OpenAPISpec","apiName: string","op: OperationInfo","paramParts: string[]","str: string"],"sources":["../src/openapi-react-query.ts"],"sourcesContent":["#!/usr/bin/env -S npx tsx\n\nimport { exec } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { promisify } from 'node:util';\n\nconst execAsync = promisify(exec);\n\ninterface ReactQueryOptions {\n\tinput?: string;\n\toutput?: string;\n\tname?: string;\n}\n\ninterface OpenAPISpec {\n\topenapi: string;\n\tinfo?: {\n\t\ttitle?: string;\n\t\tversion?: string;\n\t};\n\tpaths: Record<string, Record<string, any>>;\n}\n\nexport async function generateReactQueryCommand(\n\toptions: ReactQueryOptions = {},\n): Promise<void> {\n\tconst logger = console;\n\n\ttry {\n\t\t// Read OpenAPI spec\n\t\tconst inputPath = options.input || join(process.cwd(), 'openapi.json');\n\n\t\tif (!existsSync(inputPath)) {\n\t\t\tthrow new Error(\n\t\t\t\t`OpenAPI spec not found at ${inputPath}. Run 'npx @geekmidas/cli openapi' first.`,\n\t\t\t);\n\t\t}\n\n\t\tconst specContent = await readFile(inputPath, 'utf-8');\n\t\tconst spec: OpenAPISpec = JSON.parse(specContent);\n\n\t\t// Generate TypeScript types from OpenAPI spec\n\t\tconst outputDir = dirname(\n\t\t\toptions.output || join(process.cwd(), 'src', 'api', 'hooks.ts'),\n\t\t);\n\t\tconst typesPath = join(outputDir, 'openapi-types.d.ts');\n\n\t\tlogger.log('Generating TypeScript types from OpenAPI spec...');\n\n\t\ttry {\n\t\t\t// Use npx to run openapi-typescript\n\t\t\tawait execAsync(\n\t\t\t\t`npx openapi-typescript \"${inputPath}\" -o \"${typesPath}\"`,\n\t\t\t\t{ cwd: process.cwd() },\n\t\t\t);\n\t\t\tlogger.log(`TypeScript types generated: ${typesPath}`);\n\t\t} catch (_error) {\n\t\t\tlogger.warn(\n\t\t\t\t'Could not generate types with openapi-typescript. Install it for better type inference.',\n\t\t\t);\n\t\t\tlogger.warn('Run: npm install -D openapi-typescript');\n\n\t\t\t// Generate basic types file\n\t\t\tawait mkdir(dirname(typesPath), { recursive: true });\n\t\t\tawait writeFile(\n\t\t\t\ttypesPath,\n\t\t\t\t`// Auto-generated placeholder types\nexport interface paths {\n [path: string]: {\n [method: string]: {\n operationId?: string;\n parameters?: any;\n requestBody?: any;\n responses?: any;\n };\n };\n}\n`,\n\t\t\t);\n\t\t}\n\n\t\t// Extract operation info\n\t\tconst operations = extractOperations(spec);\n\n\t\t// Generate TypeScript code\n\t\tconst code = generateReactQueryCode(\n\t\t\tspec,\n\t\t\toperations,\n\t\t\toptions.name || 'API',\n\t\t);\n\n\t\t// Write output\n\t\tconst outputPath =\n\t\t\toptions.output || join(process.cwd(), 'src', 'api', 'hooks.ts');\n\t\tawait mkdir(dirname(outputPath), { recursive: true });\n\t\tawait writeFile(outputPath, code);\n\n\t\tlogger.log(`React Query hooks generated: ${outputPath}`);\n\t\tlogger.log(`Generated ${operations.length} hooks`);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`React Query generation failed: ${(error as Error).message}`,\n\t\t);\n\t}\n}\n\ninterface OperationInfo {\n\toperationId: string;\n\tpath: string;\n\tmethod: string;\n\tendpoint: string; // Full endpoint like 'GET /users/{id}'\n\tparameters?: Array<{ name: string; in: string; required?: boolean }>;\n\trequestBody?: boolean;\n\tresponseType?: string;\n}\n\nfunction extractOperations(spec: OpenAPISpec): OperationInfo[] {\n\tconst operations: OperationInfo[] = [];\n\n\tObject.entries(spec.paths).forEach(([path, methods]) => {\n\t\tObject.entries(methods).forEach(([method, operation]) => {\n\t\t\tif (operation.operationId) {\n\t\t\t\toperations.push({\n\t\t\t\t\toperationId: operation.operationId,\n\t\t\t\t\tpath,\n\t\t\t\t\tmethod: method.toUpperCase(),\n\t\t\t\t\tendpoint: `${method.toUpperCase()} ${path}`,\n\t\t\t\t\tparameters: operation.parameters,\n\t\t\t\t\trequestBody: !!operation.requestBody,\n\t\t\t\t\tresponseType: extractResponseType(operation),\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t});\n\n\treturn operations;\n}\n\nfunction extractResponseType(operation: any): string {\n\tconst responses = operation.responses;\n\tif (!responses) return 'unknown';\n\n\tconst successResponse = responses['200'] || responses['201'];\n\tif (!successResponse?.content?.['application/json']?.schema) {\n\t\treturn 'unknown';\n\t}\n\n\t// Basic type inference from schema\n\tconst schema = successResponse.content['application/json'].schema;\n\treturn schemaToTypeString(schema);\n}\n\nfunction schemaToTypeString(schema: any): string {\n\tif (!schema) return 'unknown';\n\n\tswitch (schema.type) {\n\t\tcase 'string':\n\t\t\treturn 'string';\n\t\tcase 'number':\n\t\tcase 'integer':\n\t\t\treturn 'number';\n\t\tcase 'boolean':\n\t\t\treturn 'boolean';\n\t\tcase 'array':\n\t\t\treturn `Array<${schemaToTypeString(schema.items)}>`;\n\t\tcase 'object':\n\t\t\tif (schema.properties) {\n\t\t\t\tconst props = Object.entries(schema.properties)\n\t\t\t\t\t.map(\n\t\t\t\t\t\t([key, value]: [string, any]) =>\n\t\t\t\t\t\t\t`${key}: ${schemaToTypeString(value)}`,\n\t\t\t\t\t)\n\t\t\t\t\t.join('; ');\n\t\t\t\treturn `{ ${props} }`;\n\t\t\t}\n\t\t\treturn 'Record<string, unknown>';\n\t\tdefault:\n\t\t\treturn 'unknown';\n\t}\n}\n\nfunction generateReactQueryCode(\n\t_spec: OpenAPISpec,\n\toperations: OperationInfo[],\n\tapiName: string,\n): string {\n\tconst imports = `import { createTypedQueryClient } from '@geekmidas/client';\nimport type { paths } from './openapi-types';\n\n// Create typed query client\nexport const ${apiName.toLowerCase()} = createTypedQueryClient<paths>({\n baseURL: process.env.NEXT_PUBLIC_API_URL || '/api',\n});\n\n// Export individual hooks for better DX\n`;\n\n\tconst queryHooks = operations\n\t\t.filter((op) => op.method === 'GET')\n\t\t.map((op) => generateQueryHook(op, apiName))\n\t\t.join('\\n\\n');\n\n\tconst mutationHooks = operations\n\t\t.filter((op) => op.method !== 'GET')\n\t\t.map((op) => generateMutationHook(op, apiName))\n\t\t.join('\\n\\n');\n\n\tconst typeExports = generateTypeExports(operations);\n\n\treturn `${imports}\n// Query Hooks\n${queryHooks}\n\n// Mutation Hooks\n${mutationHooks}\n\n// Type exports for convenience\n${typeExports}\n\n// Re-export the api for advanced usage\nexport { ${apiName.toLowerCase()} };\n`;\n}\n\nfunction generateQueryHook(op: OperationInfo, apiName: string): string {\n\tconst hookName = `use${capitalize(op.operationId)}`;\n\tconst endpoint = op.endpoint;\n\tconst hasParams = op.parameters?.some((p) => p.in === 'path');\n\tconst hasQuery = op.parameters?.some((p) => p.in === 'query');\n\n\t// Generate properly typed hook\n\tlet params = '';\n\tlet args = '';\n\n\tif (hasParams || hasQuery) {\n\t\tconst paramParts: string[] = [];\n\t\tif (hasParams) {\n\t\t\tconst pathParams =\n\t\t\t\top.parameters?.filter((p) => p.in === 'path').map((p) => p.name) || [];\n\t\t\tparamParts.push(\n\t\t\t\t`params: { ${pathParams.map((p) => `${p}: string`).join('; ')} }`,\n\t\t\t);\n\t\t}\n\t\tif (hasQuery) {\n\t\t\tparamParts.push(`query?: Record<string, any>`);\n\t\t}\n\t\tparams = `config: { ${paramParts.join('; ')} }, `;\n\t\targs = ', config';\n\t}\n\n\treturn `export const ${hookName} = (\n ${params}options?: Parameters<typeof ${apiName.toLowerCase()}.useQuery>[2]\n) => {\n return ${apiName.toLowerCase()}.useQuery('${endpoint}' as any${args}, options);\n};`;\n}\n\nfunction generateMutationHook(op: OperationInfo, apiName: string): string {\n\tconst hookName = `use${capitalize(op.operationId)}`;\n\tconst endpoint = op.endpoint;\n\n\treturn `export const ${hookName} = (\n options?: Parameters<typeof ${apiName.toLowerCase()}.useMutation>[1]\n) => {\n return ${apiName.toLowerCase()}.useMutation('${endpoint}' as any, options);\n};`;\n}\n\nfunction generateTypeExports(operations: OperationInfo[]): string {\n\tconst exports = operations.map((op) => {\n\t\tconst typeName = capitalize(op.operationId);\n\t\tconst isQuery = op.method === 'GET';\n\n\t\tif (isQuery) {\n\t\t\treturn `export type ${typeName}Response = Awaited<ReturnType<ReturnType<typeof use${typeName}>['data']>>;`;\n\t\t} else {\n\t\t\treturn `export type ${typeName}Response = Awaited<ReturnType<ReturnType<typeof use${typeName}>['mutateAsync']>>;`;\n\t\t}\n\t});\n\n\treturn exports.join('\\n');\n}\n\nfunction capitalize(str: string): string {\n\treturn str.charAt(0).toUpperCase() + str.slice(1);\n}\n"],"mappings":"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"}
@@ -170,4 +170,4 @@ Object.defineProperty(exports, 'generateReactQueryCommand', {
170
170
  return generateReactQueryCommand;
171
171
  }
172
172
  });
173
- //# sourceMappingURL=openapi-react-query-B-sNWHFU.cjs.map
173
+ //# sourceMappingURL=openapi-react-query-iKjfLzff.cjs.map
@@ -1 +1 @@
1
- {"version":3,"file":"openapi-react-query-B-sNWHFU.cjs","names":["exec","options: ReactQueryOptions","spec: OpenAPISpec","operations: OperationInfo[]","operation: any","schema: any","_spec: OpenAPISpec","apiName: string","op: OperationInfo","paramParts: string[]","exports","str: string"],"sources":["../src/openapi-react-query.ts"],"sourcesContent":["#!/usr/bin/env -S npx tsx\n\nimport { exec } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { promisify } from 'node:util';\n\nconst execAsync = promisify(exec);\n\ninterface ReactQueryOptions {\n\tinput?: string;\n\toutput?: string;\n\tname?: string;\n}\n\ninterface OpenAPISpec {\n\topenapi: string;\n\tinfo?: {\n\t\ttitle?: string;\n\t\tversion?: string;\n\t};\n\tpaths: Record<string, Record<string, any>>;\n}\n\nexport async function generateReactQueryCommand(\n\toptions: ReactQueryOptions = {},\n): Promise<void> {\n\tconst logger = console;\n\n\ttry {\n\t\t// Read OpenAPI spec\n\t\tconst inputPath = options.input || join(process.cwd(), 'openapi.json');\n\n\t\tif (!existsSync(inputPath)) {\n\t\t\tthrow new Error(\n\t\t\t\t`OpenAPI spec not found at ${inputPath}. Run 'npx @geekmidas/cli openapi' first.`,\n\t\t\t);\n\t\t}\n\n\t\tconst specContent = await readFile(inputPath, 'utf-8');\n\t\tconst spec: OpenAPISpec = JSON.parse(specContent);\n\n\t\t// Generate TypeScript types from OpenAPI spec\n\t\tconst outputDir = dirname(\n\t\t\toptions.output || join(process.cwd(), 'src', 'api', 'hooks.ts'),\n\t\t);\n\t\tconst typesPath = join(outputDir, 'openapi-types.d.ts');\n\n\t\tlogger.log('Generating TypeScript types from OpenAPI spec...');\n\n\t\ttry {\n\t\t\t// Use npx to run openapi-typescript\n\t\t\tawait execAsync(\n\t\t\t\t`npx openapi-typescript \"${inputPath}\" -o \"${typesPath}\"`,\n\t\t\t\t{ cwd: process.cwd() },\n\t\t\t);\n\t\t\tlogger.log(`TypeScript types generated: ${typesPath}`);\n\t\t} catch (_error) {\n\t\t\tlogger.warn(\n\t\t\t\t'Could not generate types with openapi-typescript. Install it for better type inference.',\n\t\t\t);\n\t\t\tlogger.warn('Run: npm install -D openapi-typescript');\n\n\t\t\t// Generate basic types file\n\t\t\tawait mkdir(dirname(typesPath), { recursive: true });\n\t\t\tawait writeFile(\n\t\t\t\ttypesPath,\n\t\t\t\t`// Auto-generated placeholder types\nexport interface paths {\n [path: string]: {\n [method: string]: {\n operationId?: string;\n parameters?: any;\n requestBody?: any;\n responses?: any;\n };\n };\n}\n`,\n\t\t\t);\n\t\t}\n\n\t\t// Extract operation info\n\t\tconst operations = extractOperations(spec);\n\n\t\t// Generate TypeScript code\n\t\tconst code = generateReactQueryCode(\n\t\t\tspec,\n\t\t\toperations,\n\t\t\toptions.name || 'API',\n\t\t);\n\n\t\t// Write output\n\t\tconst outputPath =\n\t\t\toptions.output || join(process.cwd(), 'src', 'api', 'hooks.ts');\n\t\tawait mkdir(dirname(outputPath), { recursive: true });\n\t\tawait writeFile(outputPath, code);\n\n\t\tlogger.log(`React Query hooks generated: ${outputPath}`);\n\t\tlogger.log(`Generated ${operations.length} hooks`);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`React Query generation failed: ${(error as Error).message}`,\n\t\t);\n\t}\n}\n\ninterface OperationInfo {\n\toperationId: string;\n\tpath: string;\n\tmethod: string;\n\tendpoint: string; // Full endpoint like 'GET /users/{id}'\n\tparameters?: Array<{ name: string; in: string; required?: boolean }>;\n\trequestBody?: boolean;\n\tresponseType?: string;\n}\n\nfunction extractOperations(spec: OpenAPISpec): OperationInfo[] {\n\tconst operations: OperationInfo[] = [];\n\n\tObject.entries(spec.paths).forEach(([path, methods]) => {\n\t\tObject.entries(methods).forEach(([method, operation]) => {\n\t\t\tif (operation.operationId) {\n\t\t\t\toperations.push({\n\t\t\t\t\toperationId: operation.operationId,\n\t\t\t\t\tpath,\n\t\t\t\t\tmethod: method.toUpperCase(),\n\t\t\t\t\tendpoint: `${method.toUpperCase()} ${path}`,\n\t\t\t\t\tparameters: operation.parameters,\n\t\t\t\t\trequestBody: !!operation.requestBody,\n\t\t\t\t\tresponseType: extractResponseType(operation),\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t});\n\n\treturn operations;\n}\n\nfunction extractResponseType(operation: any): string {\n\tconst responses = operation.responses;\n\tif (!responses) return 'unknown';\n\n\tconst successResponse = responses['200'] || responses['201'];\n\tif (!successResponse?.content?.['application/json']?.schema) {\n\t\treturn 'unknown';\n\t}\n\n\t// Basic type inference from schema\n\tconst schema = successResponse.content['application/json'].schema;\n\treturn schemaToTypeString(schema);\n}\n\nfunction schemaToTypeString(schema: any): string {\n\tif (!schema) return 'unknown';\n\n\tswitch (schema.type) {\n\t\tcase 'string':\n\t\t\treturn 'string';\n\t\tcase 'number':\n\t\tcase 'integer':\n\t\t\treturn 'number';\n\t\tcase 'boolean':\n\t\t\treturn 'boolean';\n\t\tcase 'array':\n\t\t\treturn `Array<${schemaToTypeString(schema.items)}>`;\n\t\tcase 'object':\n\t\t\tif (schema.properties) {\n\t\t\t\tconst props = Object.entries(schema.properties)\n\t\t\t\t\t.map(\n\t\t\t\t\t\t([key, value]: [string, any]) =>\n\t\t\t\t\t\t\t`${key}: ${schemaToTypeString(value)}`,\n\t\t\t\t\t)\n\t\t\t\t\t.join('; ');\n\t\t\t\treturn `{ ${props} }`;\n\t\t\t}\n\t\t\treturn 'Record<string, unknown>';\n\t\tdefault:\n\t\t\treturn 'unknown';\n\t}\n}\n\nfunction generateReactQueryCode(\n\t_spec: OpenAPISpec,\n\toperations: OperationInfo[],\n\tapiName: string,\n): string {\n\tconst imports = `import { createTypedQueryClient } from '@geekmidas/client';\nimport type { paths } from './openapi-types';\n\n// Create typed query client\nexport const ${apiName.toLowerCase()} = createTypedQueryClient<paths>({\n baseURL: process.env.NEXT_PUBLIC_API_URL || '/api',\n});\n\n// Export individual hooks for better DX\n`;\n\n\tconst queryHooks = operations\n\t\t.filter((op) => op.method === 'GET')\n\t\t.map((op) => generateQueryHook(op, apiName))\n\t\t.join('\\n\\n');\n\n\tconst mutationHooks = operations\n\t\t.filter((op) => op.method !== 'GET')\n\t\t.map((op) => generateMutationHook(op, apiName))\n\t\t.join('\\n\\n');\n\n\tconst typeExports = generateTypeExports(operations);\n\n\treturn `${imports}\n// Query Hooks\n${queryHooks}\n\n// Mutation Hooks\n${mutationHooks}\n\n// Type exports for convenience\n${typeExports}\n\n// Re-export the api for advanced usage\nexport { ${apiName.toLowerCase()} };\n`;\n}\n\nfunction generateQueryHook(op: OperationInfo, apiName: string): string {\n\tconst hookName = `use${capitalize(op.operationId)}`;\n\tconst endpoint = op.endpoint;\n\tconst hasParams = op.parameters?.some((p) => p.in === 'path');\n\tconst hasQuery = op.parameters?.some((p) => p.in === 'query');\n\n\t// Generate properly typed hook\n\tlet params = '';\n\tlet args = '';\n\n\tif (hasParams || hasQuery) {\n\t\tconst paramParts: string[] = [];\n\t\tif (hasParams) {\n\t\t\tconst pathParams =\n\t\t\t\top.parameters?.filter((p) => p.in === 'path').map((p) => p.name) || [];\n\t\t\tparamParts.push(\n\t\t\t\t`params: { ${pathParams.map((p) => `${p}: string`).join('; ')} }`,\n\t\t\t);\n\t\t}\n\t\tif (hasQuery) {\n\t\t\tparamParts.push(`query?: Record<string, any>`);\n\t\t}\n\t\tparams = `config: { ${paramParts.join('; ')} }, `;\n\t\targs = ', config';\n\t}\n\n\treturn `export const ${hookName} = (\n ${params}options?: Parameters<typeof ${apiName.toLowerCase()}.useQuery>[2]\n) => {\n return ${apiName.toLowerCase()}.useQuery('${endpoint}' as any${args}, options);\n};`;\n}\n\nfunction generateMutationHook(op: OperationInfo, apiName: string): string {\n\tconst hookName = `use${capitalize(op.operationId)}`;\n\tconst endpoint = op.endpoint;\n\n\treturn `export const ${hookName} = (\n options?: Parameters<typeof ${apiName.toLowerCase()}.useMutation>[1]\n) => {\n return ${apiName.toLowerCase()}.useMutation('${endpoint}' as any, options);\n};`;\n}\n\nfunction generateTypeExports(operations: OperationInfo[]): string {\n\tconst exports = operations.map((op) => {\n\t\tconst typeName = capitalize(op.operationId);\n\t\tconst isQuery = op.method === 'GET';\n\n\t\tif (isQuery) {\n\t\t\treturn `export type ${typeName}Response = Awaited<ReturnType<ReturnType<typeof use${typeName}>['data']>>;`;\n\t\t} else {\n\t\t\treturn `export type ${typeName}Response = Awaited<ReturnType<ReturnType<typeof use${typeName}>['mutateAsync']>>;`;\n\t\t}\n\t});\n\n\treturn exports.join('\\n');\n}\n\nfunction capitalize(str: string): string {\n\treturn str.charAt(0).toUpperCase() + str.slice(1);\n}\n"],"mappings":"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"}
1
+ {"version":3,"file":"openapi-react-query-iKjfLzff.cjs","names":["exec","options: ReactQueryOptions","spec: OpenAPISpec","operations: OperationInfo[]","operation: any","schema: any","_spec: OpenAPISpec","apiName: string","op: OperationInfo","paramParts: string[]","exports","str: string"],"sources":["../src/openapi-react-query.ts"],"sourcesContent":["#!/usr/bin/env -S npx tsx\n\nimport { exec } from 'node:child_process';\nimport { existsSync } from 'node:fs';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { dirname, join } from 'node:path';\nimport { promisify } from 'node:util';\n\nconst execAsync = promisify(exec);\n\ninterface ReactQueryOptions {\n\tinput?: string;\n\toutput?: string;\n\tname?: string;\n}\n\ninterface OpenAPISpec {\n\topenapi: string;\n\tinfo?: {\n\t\ttitle?: string;\n\t\tversion?: string;\n\t};\n\tpaths: Record<string, Record<string, any>>;\n}\n\nexport async function generateReactQueryCommand(\n\toptions: ReactQueryOptions = {},\n): Promise<void> {\n\tconst logger = console;\n\n\ttry {\n\t\t// Read OpenAPI spec\n\t\tconst inputPath = options.input || join(process.cwd(), 'openapi.json');\n\n\t\tif (!existsSync(inputPath)) {\n\t\t\tthrow new Error(\n\t\t\t\t`OpenAPI spec not found at ${inputPath}. Run 'npx @geekmidas/cli openapi' first.`,\n\t\t\t);\n\t\t}\n\n\t\tconst specContent = await readFile(inputPath, 'utf-8');\n\t\tconst spec: OpenAPISpec = JSON.parse(specContent);\n\n\t\t// Generate TypeScript types from OpenAPI spec\n\t\tconst outputDir = dirname(\n\t\t\toptions.output || join(process.cwd(), 'src', 'api', 'hooks.ts'),\n\t\t);\n\t\tconst typesPath = join(outputDir, 'openapi-types.d.ts');\n\n\t\tlogger.log('Generating TypeScript types from OpenAPI spec...');\n\n\t\ttry {\n\t\t\t// Use npx to run openapi-typescript\n\t\t\tawait execAsync(\n\t\t\t\t`npx openapi-typescript \"${inputPath}\" -o \"${typesPath}\"`,\n\t\t\t\t{ cwd: process.cwd() },\n\t\t\t);\n\t\t\tlogger.log(`TypeScript types generated: ${typesPath}`);\n\t\t} catch (_error) {\n\t\t\tlogger.warn(\n\t\t\t\t'Could not generate types with openapi-typescript. Install it for better type inference.',\n\t\t\t);\n\t\t\tlogger.warn('Run: npm install -D openapi-typescript');\n\n\t\t\t// Generate basic types file\n\t\t\tawait mkdir(dirname(typesPath), { recursive: true });\n\t\t\tawait writeFile(\n\t\t\t\ttypesPath,\n\t\t\t\t`// Auto-generated placeholder types\nexport interface paths {\n [path: string]: {\n [method: string]: {\n operationId?: string;\n parameters?: any;\n requestBody?: any;\n responses?: any;\n };\n };\n}\n`,\n\t\t\t);\n\t\t}\n\n\t\t// Extract operation info\n\t\tconst operations = extractOperations(spec);\n\n\t\t// Generate TypeScript code\n\t\tconst code = generateReactQueryCode(\n\t\t\tspec,\n\t\t\toperations,\n\t\t\toptions.name || 'API',\n\t\t);\n\n\t\t// Write output\n\t\tconst outputPath =\n\t\t\toptions.output || join(process.cwd(), 'src', 'api', 'hooks.ts');\n\t\tawait mkdir(dirname(outputPath), { recursive: true });\n\t\tawait writeFile(outputPath, code);\n\n\t\tlogger.log(`React Query hooks generated: ${outputPath}`);\n\t\tlogger.log(`Generated ${operations.length} hooks`);\n\t} catch (error) {\n\t\tthrow new Error(\n\t\t\t`React Query generation failed: ${(error as Error).message}`,\n\t\t);\n\t}\n}\n\ninterface OperationInfo {\n\toperationId: string;\n\tpath: string;\n\tmethod: string;\n\tendpoint: string; // Full endpoint like 'GET /users/{id}'\n\tparameters?: Array<{ name: string; in: string; required?: boolean }>;\n\trequestBody?: boolean;\n\tresponseType?: string;\n}\n\nfunction extractOperations(spec: OpenAPISpec): OperationInfo[] {\n\tconst operations: OperationInfo[] = [];\n\n\tObject.entries(spec.paths).forEach(([path, methods]) => {\n\t\tObject.entries(methods).forEach(([method, operation]) => {\n\t\t\tif (operation.operationId) {\n\t\t\t\toperations.push({\n\t\t\t\t\toperationId: operation.operationId,\n\t\t\t\t\tpath,\n\t\t\t\t\tmethod: method.toUpperCase(),\n\t\t\t\t\tendpoint: `${method.toUpperCase()} ${path}`,\n\t\t\t\t\tparameters: operation.parameters,\n\t\t\t\t\trequestBody: !!operation.requestBody,\n\t\t\t\t\tresponseType: extractResponseType(operation),\n\t\t\t\t});\n\t\t\t}\n\t\t});\n\t});\n\n\treturn operations;\n}\n\nfunction extractResponseType(operation: any): string {\n\tconst responses = operation.responses;\n\tif (!responses) return 'unknown';\n\n\tconst successResponse = responses['200'] || responses['201'];\n\tif (!successResponse?.content?.['application/json']?.schema) {\n\t\treturn 'unknown';\n\t}\n\n\t// Basic type inference from schema\n\tconst schema = successResponse.content['application/json'].schema;\n\treturn schemaToTypeString(schema);\n}\n\nfunction schemaToTypeString(schema: any): string {\n\tif (!schema) return 'unknown';\n\n\tswitch (schema.type) {\n\t\tcase 'string':\n\t\t\treturn 'string';\n\t\tcase 'number':\n\t\tcase 'integer':\n\t\t\treturn 'number';\n\t\tcase 'boolean':\n\t\t\treturn 'boolean';\n\t\tcase 'array':\n\t\t\treturn `Array<${schemaToTypeString(schema.items)}>`;\n\t\tcase 'object':\n\t\t\tif (schema.properties) {\n\t\t\t\tconst props = Object.entries(schema.properties)\n\t\t\t\t\t.map(\n\t\t\t\t\t\t([key, value]: [string, any]) =>\n\t\t\t\t\t\t\t`${key}: ${schemaToTypeString(value)}`,\n\t\t\t\t\t)\n\t\t\t\t\t.join('; ');\n\t\t\t\treturn `{ ${props} }`;\n\t\t\t}\n\t\t\treturn 'Record<string, unknown>';\n\t\tdefault:\n\t\t\treturn 'unknown';\n\t}\n}\n\nfunction generateReactQueryCode(\n\t_spec: OpenAPISpec,\n\toperations: OperationInfo[],\n\tapiName: string,\n): string {\n\tconst imports = `import { createTypedQueryClient } from '@geekmidas/client';\nimport type { paths } from './openapi-types';\n\n// Create typed query client\nexport const ${apiName.toLowerCase()} = createTypedQueryClient<paths>({\n baseURL: process.env.NEXT_PUBLIC_API_URL || '/api',\n});\n\n// Export individual hooks for better DX\n`;\n\n\tconst queryHooks = operations\n\t\t.filter((op) => op.method === 'GET')\n\t\t.map((op) => generateQueryHook(op, apiName))\n\t\t.join('\\n\\n');\n\n\tconst mutationHooks = operations\n\t\t.filter((op) => op.method !== 'GET')\n\t\t.map((op) => generateMutationHook(op, apiName))\n\t\t.join('\\n\\n');\n\n\tconst typeExports = generateTypeExports(operations);\n\n\treturn `${imports}\n// Query Hooks\n${queryHooks}\n\n// Mutation Hooks\n${mutationHooks}\n\n// Type exports for convenience\n${typeExports}\n\n// Re-export the api for advanced usage\nexport { ${apiName.toLowerCase()} };\n`;\n}\n\nfunction generateQueryHook(op: OperationInfo, apiName: string): string {\n\tconst hookName = `use${capitalize(op.operationId)}`;\n\tconst endpoint = op.endpoint;\n\tconst hasParams = op.parameters?.some((p) => p.in === 'path');\n\tconst hasQuery = op.parameters?.some((p) => p.in === 'query');\n\n\t// Generate properly typed hook\n\tlet params = '';\n\tlet args = '';\n\n\tif (hasParams || hasQuery) {\n\t\tconst paramParts: string[] = [];\n\t\tif (hasParams) {\n\t\t\tconst pathParams =\n\t\t\t\top.parameters?.filter((p) => p.in === 'path').map((p) => p.name) || [];\n\t\t\tparamParts.push(\n\t\t\t\t`params: { ${pathParams.map((p) => `${p}: string`).join('; ')} }`,\n\t\t\t);\n\t\t}\n\t\tif (hasQuery) {\n\t\t\tparamParts.push(`query?: Record<string, any>`);\n\t\t}\n\t\tparams = `config: { ${paramParts.join('; ')} }, `;\n\t\targs = ', config';\n\t}\n\n\treturn `export const ${hookName} = (\n ${params}options?: Parameters<typeof ${apiName.toLowerCase()}.useQuery>[2]\n) => {\n return ${apiName.toLowerCase()}.useQuery('${endpoint}' as any${args}, options);\n};`;\n}\n\nfunction generateMutationHook(op: OperationInfo, apiName: string): string {\n\tconst hookName = `use${capitalize(op.operationId)}`;\n\tconst endpoint = op.endpoint;\n\n\treturn `export const ${hookName} = (\n options?: Parameters<typeof ${apiName.toLowerCase()}.useMutation>[1]\n) => {\n return ${apiName.toLowerCase()}.useMutation('${endpoint}' as any, options);\n};`;\n}\n\nfunction generateTypeExports(operations: OperationInfo[]): string {\n\tconst exports = operations.map((op) => {\n\t\tconst typeName = capitalize(op.operationId);\n\t\tconst isQuery = op.method === 'GET';\n\n\t\tif (isQuery) {\n\t\t\treturn `export type ${typeName}Response = Awaited<ReturnType<ReturnType<typeof use${typeName}>['data']>>;`;\n\t\t} else {\n\t\t\treturn `export type ${typeName}Response = Awaited<ReturnType<ReturnType<typeof use${typeName}>['mutateAsync']>>;`;\n\t\t}\n\t});\n\n\treturn exports.join('\\n');\n}\n\nfunction capitalize(str: string): string {\n\treturn str.charAt(0).toUpperCase() + str.slice(1);\n}\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env -S npx tsx
2
- const require_openapi_react_query = require('./openapi-react-query-B-sNWHFU.cjs');
2
+ const require_openapi_react_query = require('./openapi-react-query-iKjfLzff.cjs');
3
3
 
4
4
  exports.generateReactQueryCommand = require_openapi_react_query.generateReactQueryCommand;
@@ -1,4 +1,4 @@
1
1
  #!/usr/bin/env -S npx tsx
2
- import { generateReactQueryCommand } from "./openapi-react-query-B6XTeGqS.mjs";
2
+ import { generateReactQueryCommand } from "./openapi-react-query-CM2_qlW9.mjs";
3
3
 
4
4
  export { generateReactQueryCommand };
package/dist/openapi.cjs CHANGED
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env -S npx tsx
2
2
  require('./config-AmInkU7k.cjs');
3
- const require_openapi = require('./openapi-Bt_1FDpT.cjs');
3
+ const require_openapi = require('./openapi-C89hhkZC.cjs');
4
4
 
5
5
  exports.OPENAPI_OUTPUT_PATH = require_openapi.OPENAPI_OUTPUT_PATH;
6
6
  exports.generateOpenApi = require_openapi.generateOpenApi;
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env -S npx tsx
2
- import { GkmConfig, OpenApiConfig } from "./types-BhkZc-vm.cjs";
2
+ import { GkmConfig, OpenApiConfig } from "./types-BgaMXsUa.cjs";
3
3
 
4
4
  //#region src/openapi.d.ts
5
5
  interface OpenAPIOptions {
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env -S npx tsx
2
- import { GkmConfig, OpenApiConfig } from "./types-BR0M2v_c.mjs";
2
+ import { GkmConfig, OpenApiConfig } from "./types-iFk5ms7y.mjs";
3
3
 
4
4
  //#region src/openapi.d.ts
5
5
  interface OpenAPIOptions {
package/dist/openapi.mjs CHANGED
@@ -1,5 +1,5 @@
1
1
  #!/usr/bin/env -S npx tsx
2
2
  import "./config-DYULeEv8.mjs";
3
- import { OPENAPI_OUTPUT_PATH, generateOpenApi, openapiCommand, resolveOpenApiConfig } from "./openapi-BfFlOBCG.mjs";
3
+ import { OPENAPI_OUTPUT_PATH, generateOpenApi, openapiCommand, resolveOpenApiConfig } from "./openapi-CZVcfxk-.mjs";
4
4
 
5
5
  export { OPENAPI_OUTPUT_PATH, generateOpenApi, openapiCommand, resolveOpenApiConfig };
@@ -24,6 +24,20 @@ function secretsExist(stage, cwd = process.cwd()) {
24
24
  return existsSync(getSecretsPath(stage, cwd));
25
25
  }
26
26
  /**
27
+ * Initialize an empty StageSecrets object for a stage.
28
+ */
29
+ function initStageSecrets(stage) {
30
+ const now = (/* @__PURE__ */ new Date()).toISOString();
31
+ return {
32
+ stage,
33
+ createdAt: now,
34
+ updatedAt: now,
35
+ services: {},
36
+ urls: {},
37
+ custom: {}
38
+ };
39
+ }
40
+ /**
27
41
  * Read secrets for a stage.
28
42
  * @returns StageSecrets or null if not found
29
43
  */
@@ -129,5 +143,5 @@ function validateEnvironmentVariables(requiredVars, secrets) {
129
143
  }
130
144
 
131
145
  //#endregion
132
- export { getSecretsDir, getSecretsPath, maskPassword, readStageSecrets, secretsExist, setCustomSecret, toEmbeddableSecrets, validateEnvironmentVariables, writeStageSecrets };
133
- //# sourceMappingURL=storage-kSxTjkNb.mjs.map
146
+ export { getSecretsDir, getSecretsPath, initStageSecrets, maskPassword, readStageSecrets, secretsExist, setCustomSecret, toEmbeddableSecrets, validateEnvironmentVariables, writeStageSecrets };
147
+ //# sourceMappingURL=storage-BaOP55oq.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-BaOP55oq.mjs","names":["stage: string","secrets: StageSecrets","key: string","value: string","updated: StageSecrets","password: string","requiredVars: string[]","missing: string[]","provided: string[]"],"sources":["../src/secrets/storage.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { EmbeddableSecrets, StageSecrets } from './types';\n\n/** Default secrets directory relative to project root */\nconst SECRETS_DIR = '.gkm/secrets';\n\n/**\n * Get the secrets directory path.\n */\nexport function getSecretsDir(cwd = process.cwd()): string {\n\treturn join(cwd, SECRETS_DIR);\n}\n\n/**\n * Get the secrets file path for a stage.\n */\nexport function getSecretsPath(stage: string, cwd = process.cwd()): string {\n\treturn join(getSecretsDir(cwd), `${stage}.json`);\n}\n\n/**\n * Check if secrets exist for a stage.\n */\nexport function secretsExist(stage: string, cwd = process.cwd()): boolean {\n\treturn existsSync(getSecretsPath(stage, cwd));\n}\n\n/**\n * Initialize an empty StageSecrets object for a stage.\n */\nexport function initStageSecrets(stage: string): StageSecrets {\n\tconst now = new Date().toISOString();\n\treturn {\n\t\tstage,\n\t\tcreatedAt: now,\n\t\tupdatedAt: now,\n\t\tservices: {},\n\t\turls: {},\n\t\tcustom: {},\n\t};\n}\n\n/**\n * Read secrets for a stage.\n * @returns StageSecrets or null if not found\n */\nexport async function readStageSecrets(\n\tstage: string,\n\tcwd = process.cwd(),\n): Promise<StageSecrets | null> {\n\tconst path = getSecretsPath(stage, cwd);\n\n\tif (!existsSync(path)) {\n\t\treturn null;\n\t}\n\n\tconst content = await readFile(path, 'utf-8');\n\treturn JSON.parse(content) as StageSecrets;\n}\n\n/**\n * Write secrets for a stage.\n */\nexport async function writeStageSecrets(\n\tsecrets: StageSecrets,\n\tcwd = process.cwd(),\n): Promise<void> {\n\tconst dir = getSecretsDir(cwd);\n\tconst path = getSecretsPath(secrets.stage, cwd);\n\n\t// Ensure directory exists\n\tawait mkdir(dir, { recursive: true });\n\n\t// Write with pretty formatting\n\tawait writeFile(path, JSON.stringify(secrets, null, 2), 'utf-8');\n}\n\n/**\n * Convert StageSecrets to embeddable format (flat key-value pairs).\n * This is what gets encrypted and embedded in the bundle.\n */\nexport function toEmbeddableSecrets(secrets: StageSecrets): EmbeddableSecrets {\n\treturn {\n\t\t...secrets.urls,\n\t\t...secrets.custom,\n\t\t// Also include individual service credentials if needed\n\t\t...(secrets.services.postgres && {\n\t\t\tPOSTGRES_USER: secrets.services.postgres.username,\n\t\t\tPOSTGRES_PASSWORD: secrets.services.postgres.password,\n\t\t\tPOSTGRES_DB: secrets.services.postgres.database ?? 'app',\n\t\t\tPOSTGRES_HOST: secrets.services.postgres.host,\n\t\t\tPOSTGRES_PORT: String(secrets.services.postgres.port),\n\t\t}),\n\t\t...(secrets.services.redis && {\n\t\t\tREDIS_PASSWORD: secrets.services.redis.password,\n\t\t\tREDIS_HOST: secrets.services.redis.host,\n\t\t\tREDIS_PORT: String(secrets.services.redis.port),\n\t\t}),\n\t\t...(secrets.services.rabbitmq && {\n\t\t\tRABBITMQ_USER: secrets.services.rabbitmq.username,\n\t\t\tRABBITMQ_PASSWORD: secrets.services.rabbitmq.password,\n\t\t\tRABBITMQ_HOST: secrets.services.rabbitmq.host,\n\t\t\tRABBITMQ_PORT: String(secrets.services.rabbitmq.port),\n\t\t\tRABBITMQ_VHOST: secrets.services.rabbitmq.vhost ?? '/',\n\t\t}),\n\t};\n}\n\n/**\n * Update a custom secret in the secrets file.\n */\nexport async function setCustomSecret(\n\tstage: string,\n\tkey: string,\n\tvalue: string,\n\tcwd = process.cwd(),\n): Promise<StageSecrets> {\n\tconst secrets = await readStageSecrets(stage, cwd);\n\n\tif (!secrets) {\n\t\tthrow new Error(\n\t\t\t`Secrets not found for stage \"${stage}\". Run \"gkm secrets:init --stage ${stage}\" first.`,\n\t\t);\n\t}\n\n\tconst updated: StageSecrets = {\n\t\t...secrets,\n\t\tupdatedAt: new Date().toISOString(),\n\t\tcustom: {\n\t\t\t...secrets.custom,\n\t\t\t[key]: value,\n\t\t},\n\t};\n\n\tawait writeStageSecrets(updated, cwd);\n\treturn updated;\n}\n\n/**\n * Mask a password for display (show first 4 and last 2 chars).\n */\nexport function maskPassword(password: string): string {\n\tif (password.length <= 8) {\n\t\treturn '********';\n\t}\n\treturn `${password.slice(0, 4)}${'*'.repeat(password.length - 6)}${password.slice(-2)}`;\n}\n\n/**\n * Result of environment variable validation.\n */\nexport interface EnvValidationResult {\n\t/** Whether all required environment variables are present */\n\tvalid: boolean;\n\t/** List of missing environment variable names */\n\tmissing: string[];\n\t/** List of environment variables that are provided */\n\tprovided: string[];\n\t/** List of environment variables that were required */\n\trequired: string[];\n}\n\n/**\n * Validate that all required environment variables are present in secrets.\n *\n * @param requiredVars - Array of environment variable names required by the application\n * @param secrets - Stage secrets to validate against\n * @returns Validation result with missing and provided variables\n *\n * @example\n * ```typescript\n * const required = ['DATABASE_URL', 'API_KEY', 'JWT_SECRET'];\n * const secrets = await readStageSecrets('production');\n * const result = validateEnvironmentVariables(required, secrets);\n *\n * if (!result.valid) {\n * console.error(`Missing environment variables: ${result.missing.join(', ')}`);\n * }\n * ```\n */\nexport function validateEnvironmentVariables(\n\trequiredVars: string[],\n\tsecrets: StageSecrets,\n): EnvValidationResult {\n\tconst embeddable = toEmbeddableSecrets(secrets);\n\tconst availableVars = new Set(Object.keys(embeddable));\n\n\tconst missing: string[] = [];\n\tconst provided: string[] = [];\n\n\tfor (const varName of requiredVars) {\n\t\tif (availableVars.has(varName)) {\n\t\t\tprovided.push(varName);\n\t\t} else {\n\t\t\tmissing.push(varName);\n\t\t}\n\t}\n\n\treturn {\n\t\tvalid: missing.length === 0,\n\t\tmissing: missing.sort(),\n\t\tprovided: provided.sort(),\n\t\trequired: [...requiredVars].sort(),\n\t};\n}\n"],"mappings":"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"}
@@ -25,6 +25,20 @@ function secretsExist(stage, cwd = process.cwd()) {
25
25
  return (0, node_fs.existsSync)(getSecretsPath(stage, cwd));
26
26
  }
27
27
  /**
28
+ * Initialize an empty StageSecrets object for a stage.
29
+ */
30
+ function initStageSecrets(stage) {
31
+ const now = (/* @__PURE__ */ new Date()).toISOString();
32
+ return {
33
+ stage,
34
+ createdAt: now,
35
+ updatedAt: now,
36
+ services: {},
37
+ urls: {},
38
+ custom: {}
39
+ };
40
+ }
41
+ /**
28
42
  * Read secrets for a stage.
29
43
  * @returns StageSecrets or null if not found
30
44
  */
@@ -142,6 +156,12 @@ Object.defineProperty(exports, 'getSecretsPath', {
142
156
  return getSecretsPath;
143
157
  }
144
158
  });
159
+ Object.defineProperty(exports, 'initStageSecrets', {
160
+ enumerable: true,
161
+ get: function () {
162
+ return initStageSecrets;
163
+ }
164
+ });
145
165
  Object.defineProperty(exports, 'maskPassword', {
146
166
  enumerable: true,
147
167
  get: function () {
@@ -184,4 +204,4 @@ Object.defineProperty(exports, 'writeStageSecrets', {
184
204
  return writeStageSecrets;
185
205
  }
186
206
  });
187
- //# sourceMappingURL=storage-Bj1E26lU.cjs.map
207
+ //# sourceMappingURL=storage-Bn3K9Ccu.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"storage-Bn3K9Ccu.cjs","names":["stage: string","secrets: StageSecrets","key: string","value: string","updated: StageSecrets","password: string","requiredVars: string[]","missing: string[]","provided: string[]"],"sources":["../src/secrets/storage.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { mkdir, readFile, writeFile } from 'node:fs/promises';\nimport { join } from 'node:path';\nimport type { EmbeddableSecrets, StageSecrets } from './types';\n\n/** Default secrets directory relative to project root */\nconst SECRETS_DIR = '.gkm/secrets';\n\n/**\n * Get the secrets directory path.\n */\nexport function getSecretsDir(cwd = process.cwd()): string {\n\treturn join(cwd, SECRETS_DIR);\n}\n\n/**\n * Get the secrets file path for a stage.\n */\nexport function getSecretsPath(stage: string, cwd = process.cwd()): string {\n\treturn join(getSecretsDir(cwd), `${stage}.json`);\n}\n\n/**\n * Check if secrets exist for a stage.\n */\nexport function secretsExist(stage: string, cwd = process.cwd()): boolean {\n\treturn existsSync(getSecretsPath(stage, cwd));\n}\n\n/**\n * Initialize an empty StageSecrets object for a stage.\n */\nexport function initStageSecrets(stage: string): StageSecrets {\n\tconst now = new Date().toISOString();\n\treturn {\n\t\tstage,\n\t\tcreatedAt: now,\n\t\tupdatedAt: now,\n\t\tservices: {},\n\t\turls: {},\n\t\tcustom: {},\n\t};\n}\n\n/**\n * Read secrets for a stage.\n * @returns StageSecrets or null if not found\n */\nexport async function readStageSecrets(\n\tstage: string,\n\tcwd = process.cwd(),\n): Promise<StageSecrets | null> {\n\tconst path = getSecretsPath(stage, cwd);\n\n\tif (!existsSync(path)) {\n\t\treturn null;\n\t}\n\n\tconst content = await readFile(path, 'utf-8');\n\treturn JSON.parse(content) as StageSecrets;\n}\n\n/**\n * Write secrets for a stage.\n */\nexport async function writeStageSecrets(\n\tsecrets: StageSecrets,\n\tcwd = process.cwd(),\n): Promise<void> {\n\tconst dir = getSecretsDir(cwd);\n\tconst path = getSecretsPath(secrets.stage, cwd);\n\n\t// Ensure directory exists\n\tawait mkdir(dir, { recursive: true });\n\n\t// Write with pretty formatting\n\tawait writeFile(path, JSON.stringify(secrets, null, 2), 'utf-8');\n}\n\n/**\n * Convert StageSecrets to embeddable format (flat key-value pairs).\n * This is what gets encrypted and embedded in the bundle.\n */\nexport function toEmbeddableSecrets(secrets: StageSecrets): EmbeddableSecrets {\n\treturn {\n\t\t...secrets.urls,\n\t\t...secrets.custom,\n\t\t// Also include individual service credentials if needed\n\t\t...(secrets.services.postgres && {\n\t\t\tPOSTGRES_USER: secrets.services.postgres.username,\n\t\t\tPOSTGRES_PASSWORD: secrets.services.postgres.password,\n\t\t\tPOSTGRES_DB: secrets.services.postgres.database ?? 'app',\n\t\t\tPOSTGRES_HOST: secrets.services.postgres.host,\n\t\t\tPOSTGRES_PORT: String(secrets.services.postgres.port),\n\t\t}),\n\t\t...(secrets.services.redis && {\n\t\t\tREDIS_PASSWORD: secrets.services.redis.password,\n\t\t\tREDIS_HOST: secrets.services.redis.host,\n\t\t\tREDIS_PORT: String(secrets.services.redis.port),\n\t\t}),\n\t\t...(secrets.services.rabbitmq && {\n\t\t\tRABBITMQ_USER: secrets.services.rabbitmq.username,\n\t\t\tRABBITMQ_PASSWORD: secrets.services.rabbitmq.password,\n\t\t\tRABBITMQ_HOST: secrets.services.rabbitmq.host,\n\t\t\tRABBITMQ_PORT: String(secrets.services.rabbitmq.port),\n\t\t\tRABBITMQ_VHOST: secrets.services.rabbitmq.vhost ?? '/',\n\t\t}),\n\t};\n}\n\n/**\n * Update a custom secret in the secrets file.\n */\nexport async function setCustomSecret(\n\tstage: string,\n\tkey: string,\n\tvalue: string,\n\tcwd = process.cwd(),\n): Promise<StageSecrets> {\n\tconst secrets = await readStageSecrets(stage, cwd);\n\n\tif (!secrets) {\n\t\tthrow new Error(\n\t\t\t`Secrets not found for stage \"${stage}\". Run \"gkm secrets:init --stage ${stage}\" first.`,\n\t\t);\n\t}\n\n\tconst updated: StageSecrets = {\n\t\t...secrets,\n\t\tupdatedAt: new Date().toISOString(),\n\t\tcustom: {\n\t\t\t...secrets.custom,\n\t\t\t[key]: value,\n\t\t},\n\t};\n\n\tawait writeStageSecrets(updated, cwd);\n\treturn updated;\n}\n\n/**\n * Mask a password for display (show first 4 and last 2 chars).\n */\nexport function maskPassword(password: string): string {\n\tif (password.length <= 8) {\n\t\treturn '********';\n\t}\n\treturn `${password.slice(0, 4)}${'*'.repeat(password.length - 6)}${password.slice(-2)}`;\n}\n\n/**\n * Result of environment variable validation.\n */\nexport interface EnvValidationResult {\n\t/** Whether all required environment variables are present */\n\tvalid: boolean;\n\t/** List of missing environment variable names */\n\tmissing: string[];\n\t/** List of environment variables that are provided */\n\tprovided: string[];\n\t/** List of environment variables that were required */\n\trequired: string[];\n}\n\n/**\n * Validate that all required environment variables are present in secrets.\n *\n * @param requiredVars - Array of environment variable names required by the application\n * @param secrets - Stage secrets to validate against\n * @returns Validation result with missing and provided variables\n *\n * @example\n * ```typescript\n * const required = ['DATABASE_URL', 'API_KEY', 'JWT_SECRET'];\n * const secrets = await readStageSecrets('production');\n * const result = validateEnvironmentVariables(required, secrets);\n *\n * if (!result.valid) {\n * console.error(`Missing environment variables: ${result.missing.join(', ')}`);\n * }\n * ```\n */\nexport function validateEnvironmentVariables(\n\trequiredVars: string[],\n\tsecrets: StageSecrets,\n): EnvValidationResult {\n\tconst embeddable = toEmbeddableSecrets(secrets);\n\tconst availableVars = new Set(Object.keys(embeddable));\n\n\tconst missing: string[] = [];\n\tconst provided: string[] = [];\n\n\tfor (const varName of requiredVars) {\n\t\tif (availableVars.has(varName)) {\n\t\t\tprovided.push(varName);\n\t\t} else {\n\t\t\tmissing.push(varName);\n\t\t}\n\t}\n\n\treturn {\n\t\tvalid: missing.length === 0,\n\t\tmissing: missing.sort(),\n\t\tprovided: provided.sort(),\n\t\trequired: [...requiredVars].sort(),\n\t};\n}\n"],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ const require_storage = require('./storage-Bn3K9Ccu.cjs');
2
+
3
+ exports.initStageSecrets = require_storage.initStageSecrets;
4
+ exports.readStageSecrets = require_storage.readStageSecrets;
5
+ exports.toEmbeddableSecrets = require_storage.toEmbeddableSecrets;
6
+ exports.validateEnvironmentVariables = require_storage.validateEnvironmentVariables;
7
+ exports.writeStageSecrets = require_storage.writeStageSecrets;
@@ -0,0 +1,3 @@
1
+ import { getSecretsDir, getSecretsPath, initStageSecrets, maskPassword, readStageSecrets, secretsExist, setCustomSecret, toEmbeddableSecrets, validateEnvironmentVariables, writeStageSecrets } from "./storage-BaOP55oq.mjs";
2
+
3
+ export { initStageSecrets, readStageSecrets, toEmbeddableSecrets, validateEnvironmentVariables, writeStageSecrets };
@@ -155,6 +155,8 @@ interface DokployProviderConfig {
155
155
  applicationId: string;
156
156
  /** Container registry (overrides docker.registry if set) */
157
157
  registry?: string;
158
+ /** Registry ID in Dokploy (recommended for private registries) */
159
+ registryId?: string;
158
160
  }
159
161
  interface ProvidersConfig {
160
162
  aws?: {
@@ -259,4 +261,4 @@ interface GkmConfig {
259
261
  }
260
262
  //#endregion
261
263
  export { GkmConfig, OpenApiConfig };
262
- //# sourceMappingURL=types-BhkZc-vm.d.cts.map
264
+ //# sourceMappingURL=types-BgaMXsUa.d.cts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types-BR0M2v_c.d.mts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":";;AASiB,KAFL,MAAA,GAEmB,MAAA,GAAA,MAAA,EAAA;AAKd,UALA,cAAA,CAKoB;EAIpB,OAAA,CAAA,EAAA,OAAA;EAIA,SAAA,CAAA,EAAA,MAAA;AA4BjB;AAcY,UAlDK,mBAAA,SAA4B,cAkDf,CAAA,CAG9B;AAAiC,UAjDhB,eAAA,SAAwB,cAiDR,CAAA;AACM,UA9CtB,gBAAA,CA8CsB;EAAa;EAGnC,OAAA,CAAA,EAAA,OAAY;EAAA;EAAA,MAwBhB,CAAA,EAAA,OAAA;EAAqB;EAAqB,MAAA,CAAA,EAAA,OAAA;EAItC;EAAa,WAAA,CAAA,EAAA,MAAA;EAAA;EAIA,gBAJQ,CAAA,EAAA,OAAA;EAAc;EAOxC,QAAA,CAAA,EAAO,MAAA,EAAA;EAEF;EAiBA,WAAA,CAAA,EAAA,SAAY,GAAA,SAAA;EASZ;EAWA,OAAA,CAAA,EAAA,OAAW;EA6BX;AAWjB;;;;;;EAQoC,iBAGhB,CAAA,EAAA,OAAA;;AAEsB;AAGzB,UAvJA,aAAA,CAuJS;EAAA;;;;EAGX,KACA,CAAA,EAAA,MAAA;EAAM;;;;EA+BoB,OAmBpB,CAAA,EAAA,MAAA;;;AA8BC,KA7NV,kBAAA,GA6NU,UAAA,GAAA,OAAA,GAAA,UAAA;;KA1NV,qBAAA,WACL,gCAAgC;UAGtB,YAAA;;;;;;;;;;;;;;;;;;;;;;;;eAwBJ,wBAAwB;;;UAIpB,YAAA,SAAqB;;;;eAIxB;;KAGF,OAAA;UAEK,eAAA;;;;;;;;;;;;;;;;UAiBA,YAAA;;;;;;;;UASA,aAAA;;;;;;;;;;UAWA,WAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;UA6BA,qBAAA;;;;;;;;;;UAWA,eAAA;;;qBAGC;qBACA;;;4BAGO;wBACJ;;;qBAGD;;sBAEC;;UAGJ,SAAA;UACR;cACI;UACJ;gBACM;;;cAGF;;;;;;;;;;UAUJ;;;;;;;;iCAQuB;;;;;;;;;;8BAUH;;;;;;;;;;;;;;;;;;;sBAmBR;;YAEV;;;;;;;;;;;;;;;;;;;;;;;;;;;;WA4BD"}
1
+ {"version":3,"file":"types-BgaMXsUa.d.cts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":";;AASiB,KAFL,MAAA,GAEmB,MAAA,GAAA,MAAA,EAAA;AAKd,UALA,cAAA,CAKoB;EAIpB,OAAA,CAAA,EAAA,OAAA;EAIA,SAAA,CAAA,EAAA,MAAA;AA4BjB;AAcY,UAlDK,mBAAA,SAA4B,cAkDf,CAAA,CAG9B;AAAiC,UAjDhB,eAAA,SAAwB,cAiDR,CAAA;AACM,UA9CtB,gBAAA,CA8CsB;EAAa;EAGnC,OAAA,CAAA,EAAA,OAAY;EAAA;EAAA,MAwBhB,CAAA,EAAA,OAAA;EAAqB;EAAqB,MAAA,CAAA,EAAA,OAAA;EAItC;EAAa,WAAA,CAAA,EAAA,MAAA;EAAA;EAIA,gBAJQ,CAAA,EAAA,OAAA;EAAc;EAOxC,QAAA,CAAA,EAAO,MAAA,EAAA;EAEF;EAiBA,WAAA,CAAA,EAAA,SAAY,GAAA,SAAA;EASZ;EAWA,OAAA,CAAA,EAAA,OAAW;EA6BX;AAajB;;;;;;EAQoC,iBAGhB,CAAA,EAAA,OAAA;;AAEsB;AAGzB,UAzJA,aAAA,CAyJS;EAAA;;;;EAGX,KACA,CAAA,EAAA,MAAA;EAAM;;;;EA+BoB,OAmBpB,CAAA,EAAA,MAAA;;;AA8BC,KA/NV,kBAAA,GA+NU,UAAA,GAAA,OAAA,GAAA,UAAA;;KA5NV,qBAAA,WACL,gCAAgC;UAGtB,YAAA;;;;;;;;;;;;;;;;;;;;;;;;eAwBJ,wBAAwB;;;UAIpB,YAAA,SAAqB;;;;eAIxB;;KAGF,OAAA;UAEK,eAAA;;;;;;;;;;;;;;;;UAiBA,YAAA;;;;;;;;UASA,aAAA;;;;;;;;;;UAWA,WAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;UA6BA,qBAAA;;;;;;;;;;;;UAaA,eAAA;;;qBAGC;qBACA;;;4BAGO;wBACJ;;;qBAGD;;sBAEC;;UAGJ,SAAA;UACR;cACI;UACJ;gBACM;;;cAGF;;;;;;;;;;UAUJ;;;;;;;;iCAQuB;;;;;;;;;;8BAUH;;;;;;;;;;;;;;;;;;;sBAmBR;;YAEV;;;;;;;;;;;;;;;;;;;;;;;;;;;;WA4BD"}
@@ -155,6 +155,8 @@ interface DokployProviderConfig {
155
155
  applicationId: string;
156
156
  /** Container registry (overrides docker.registry if set) */
157
157
  registry?: string;
158
+ /** Registry ID in Dokploy (recommended for private registries) */
159
+ registryId?: string;
158
160
  }
159
161
  interface ProvidersConfig {
160
162
  aws?: {
@@ -259,4 +261,4 @@ interface GkmConfig {
259
261
  }
260
262
  //#endregion
261
263
  export { GkmConfig, OpenApiConfig };
262
- //# sourceMappingURL=types-BR0M2v_c.d.mts.map
264
+ //# sourceMappingURL=types-iFk5ms7y.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types-BhkZc-vm.d.cts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":";;AASiB,KAFL,MAAA,GAEmB,MAAA,GAAA,MAAA,EAAA;AAKd,UALA,cAAA,CAKoB;EAIpB,OAAA,CAAA,EAAA,OAAA;EAIA,SAAA,CAAA,EAAA,MAAA;AA4BjB;AAcY,UAlDK,mBAAA,SAA4B,cAkDf,CAAA,CAG9B;AAAiC,UAjDhB,eAAA,SAAwB,cAiDR,CAAA;AACM,UA9CtB,gBAAA,CA8CsB;EAAa;EAGnC,OAAA,CAAA,EAAA,OAAY;EAAA;EAAA,MAwBhB,CAAA,EAAA,OAAA;EAAqB;EAAqB,MAAA,CAAA,EAAA,OAAA;EAItC;EAAa,WAAA,CAAA,EAAA,MAAA;EAAA;EAIA,gBAJQ,CAAA,EAAA,OAAA;EAAc;EAOxC,QAAA,CAAA,EAAO,MAAA,EAAA;EAEF;EAiBA,WAAA,CAAA,EAAA,SAAY,GAAA,SAAA;EASZ;EAWA,OAAA,CAAA,EAAA,OAAW;EA6BX;AAWjB;;;;;;EAQoC,iBAGhB,CAAA,EAAA,OAAA;;AAEsB;AAGzB,UAvJA,aAAA,CAuJS;EAAA;;;;EAGX,KACA,CAAA,EAAA,MAAA;EAAM;;;;EA+BoB,OAmBpB,CAAA,EAAA,MAAA;;;AA8BC,KA7NV,kBAAA,GA6NU,UAAA,GAAA,OAAA,GAAA,UAAA;;KA1NV,qBAAA,WACL,gCAAgC;UAGtB,YAAA;;;;;;;;;;;;;;;;;;;;;;;;eAwBJ,wBAAwB;;;UAIpB,YAAA,SAAqB;;;;eAIxB;;KAGF,OAAA;UAEK,eAAA;;;;;;;;;;;;;;;;UAiBA,YAAA;;;;;;;;UASA,aAAA;;;;;;;;;;UAWA,WAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;UA6BA,qBAAA;;;;;;;;;;UAWA,eAAA;;;qBAGC;qBACA;;;4BAGO;wBACJ;;;qBAGD;;sBAEC;;UAGJ,SAAA;UACR;cACI;UACJ;gBACM;;;cAGF;;;;;;;;;;UAUJ;;;;;;;;iCAQuB;;;;;;;;;;8BAUH;;;;;;;;;;;;;;;;;;;sBAmBR;;YAEV;;;;;;;;;;;;;;;;;;;;;;;;;;;;WA4BD"}
1
+ {"version":3,"file":"types-iFk5ms7y.d.mts","names":[],"sources":["../src/types.ts"],"sourcesContent":[],"mappings":";;AASiB,KAFL,MAAA,GAEmB,MAAA,GAAA,MAAA,EAAA;AAKd,UALA,cAAA,CAKoB;EAIpB,OAAA,CAAA,EAAA,OAAA;EAIA,SAAA,CAAA,EAAA,MAAA;AA4BjB;AAcY,UAlDK,mBAAA,SAA4B,cAkDf,CAAA,CAG9B;AAAiC,UAjDhB,eAAA,SAAwB,cAiDR,CAAA;AACM,UA9CtB,gBAAA,CA8CsB;EAAa;EAGnC,OAAA,CAAA,EAAA,OAAY;EAAA;EAAA,MAwBhB,CAAA,EAAA,OAAA;EAAqB;EAAqB,MAAA,CAAA,EAAA,OAAA;EAItC;EAAa,WAAA,CAAA,EAAA,MAAA;EAAA;EAIA,gBAJQ,CAAA,EAAA,OAAA;EAAc;EAOxC,QAAA,CAAA,EAAO,MAAA,EAAA;EAEF;EAiBA,WAAA,CAAA,EAAA,SAAY,GAAA,SAAA;EASZ;EAWA,OAAA,CAAA,EAAA,OAAW;EA6BX;AAajB;;;;;;EAQoC,iBAGhB,CAAA,EAAA,OAAA;;AAEsB;AAGzB,UAzJA,aAAA,CAyJS;EAAA;;;;EAGX,KACA,CAAA,EAAA,MAAA;EAAM;;;;EA+BoB,OAmBpB,CAAA,EAAA,MAAA;;;AA8BC,KA/NV,kBAAA,GA+NU,UAAA,GAAA,OAAA,GAAA,UAAA;;KA5NV,qBAAA,WACL,gCAAgC;UAGtB,YAAA;;;;;;;;;;;;;;;;;;;;;;;;eAwBJ,wBAAwB;;;UAIpB,YAAA,SAAqB;;;;eAIxB;;KAGF,OAAA;UAEK,eAAA;;;;;;;;;;;;;;;;UAiBA,YAAA;;;;;;;;UASA,aAAA;;;;;;;;;;UAWA,WAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;UA6BA,qBAAA;;;;;;;;;;;;UAaA,eAAA;;;qBAGC;qBACA;;;4BAGO;wBACJ;;;qBAGD;;sBAEC;;UAGJ,SAAA;UACR;cACI;UACJ;gBACM;;;cAGF;;;;;;;;;;UAUJ;;;;;;;;iCAQuB;;;;;;;;;;8BAUH;;;;;;;;;;;;;;;;;;;sBAmBR;;YAEV;;;;;;;;;;;;;;;;;;;;;;;;;;;;WA4BD"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geekmidas/cli",
3
- "version": "0.13.0",
3
+ "version": "0.15.0",
4
4
  "description": "CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs",
5
5
  "private": false,
6
6
  "type": "module",
@@ -54,10 +54,10 @@
54
54
  },
55
55
  "peerDependencies": {
56
56
  "@geekmidas/constructs": "~0.5.0",
57
- "@geekmidas/envkit": "~0.3.0",
58
- "@geekmidas/logger": "~0.4.0",
59
57
  "@geekmidas/schema": "~0.1.0",
60
- "@geekmidas/telescope": "~0.4.0"
58
+ "@geekmidas/telescope": "~0.4.0",
59
+ "@geekmidas/envkit": "~0.3.0",
60
+ "@geekmidas/logger": "~0.4.0"
61
61
  },
62
62
  "peerDependenciesMeta": {
63
63
  "@geekmidas/telescope": {
@@ -8,10 +8,12 @@ import {
8
8
  getCredentialsDir,
9
9
  getCredentialsPath,
10
10
  getDokployCredentials,
11
+ getDokployRegistryId,
11
12
  getDokployToken,
12
13
  readCredentials,
13
14
  removeDokployCredentials,
14
15
  storeDokployCredentials,
16
+ storeDokployRegistryId,
15
17
  writeCredentials,
16
18
  } from '../credentials';
17
19
 
@@ -201,4 +203,129 @@ describe('credentials storage', () => {
201
203
  expect(token).toBe('stored-token');
202
204
  });
203
205
  });
206
+
207
+ describe('storeDokployRegistryId', () => {
208
+ it('should throw error when no dokploy credentials exist', async () => {
209
+ await expect(
210
+ storeDokployRegistryId('reg_123', { root: tempDir }),
211
+ ).rejects.toThrow('Dokploy credentials not found');
212
+ });
213
+
214
+ it('should store registryId with existing credentials', async () => {
215
+ await storeDokployCredentials('token', 'https://test.com', {
216
+ root: tempDir,
217
+ });
218
+
219
+ await storeDokployRegistryId('reg_123', { root: tempDir });
220
+
221
+ const creds = await readCredentials({ root: tempDir });
222
+ expect(creds.dokploy?.registryId).toBe('reg_123');
223
+ });
224
+
225
+ it('should overwrite existing registryId', async () => {
226
+ await storeDokployCredentials('token', 'https://test.com', {
227
+ root: tempDir,
228
+ });
229
+ await storeDokployRegistryId('old_reg', { root: tempDir });
230
+ await storeDokployRegistryId('new_reg', { root: tempDir });
231
+
232
+ const creds = await readCredentials({ root: tempDir });
233
+ expect(creds.dokploy?.registryId).toBe('new_reg');
234
+ });
235
+ });
236
+
237
+ describe('getDokployRegistryId', () => {
238
+ it('should return undefined when no credentials exist', async () => {
239
+ const registryId = await getDokployRegistryId({ root: tempDir });
240
+ expect(registryId).toBeUndefined();
241
+ });
242
+
243
+ it('should return undefined when credentials exist but no registryId', async () => {
244
+ await storeDokployCredentials('token', 'https://test.com', {
245
+ root: tempDir,
246
+ });
247
+
248
+ const registryId = await getDokployRegistryId({ root: tempDir });
249
+ expect(registryId).toBeUndefined();
250
+ });
251
+
252
+ it('should return stored registryId', async () => {
253
+ await storeDokployCredentials('token', 'https://test.com', {
254
+ root: tempDir,
255
+ });
256
+ await storeDokployRegistryId('reg_456', { root: tempDir });
257
+
258
+ const registryId = await getDokployRegistryId({ root: tempDir });
259
+ expect(registryId).toBe('reg_456');
260
+ });
261
+ });
262
+
263
+ describe('getDokployCredentials with registryId', () => {
264
+ it('should return registryId when stored', async () => {
265
+ await storeDokployCredentials('token', 'https://test.com', {
266
+ root: tempDir,
267
+ });
268
+ await storeDokployRegistryId('reg_789', { root: tempDir });
269
+
270
+ const creds = await getDokployCredentials({ root: tempDir });
271
+ expect(creds).toEqual({
272
+ token: 'token',
273
+ endpoint: 'https://test.com',
274
+ registryId: 'reg_789',
275
+ });
276
+ });
277
+
278
+ it('should return undefined registryId when not stored', async () => {
279
+ await storeDokployCredentials('token', 'https://test.com', {
280
+ root: tempDir,
281
+ });
282
+
283
+ const creds = await getDokployCredentials({ root: tempDir });
284
+ expect(creds?.registryId).toBeUndefined();
285
+ });
286
+ });
287
+
288
+ describe('getDokployEndpoint', () => {
289
+ it('should return null when no credentials exist', async () => {
290
+ const { getDokployEndpoint } = await import('../credentials');
291
+ const endpoint = await getDokployEndpoint({ root: tempDir });
292
+ expect(endpoint).toBeNull();
293
+ });
294
+
295
+ it('should return stored endpoint', async () => {
296
+ const { getDokployEndpoint } = await import('../credentials');
297
+ await storeDokployCredentials('token', 'https://my-dokploy.com', {
298
+ root: tempDir,
299
+ });
300
+
301
+ const endpoint = await getDokployEndpoint({ root: tempDir });
302
+ expect(endpoint).toBe('https://my-dokploy.com');
303
+ });
304
+ });
305
+
306
+ describe('removeAllCredentials', () => {
307
+ it('should remove credentials file', async () => {
308
+ const { removeAllCredentials } = await import('../credentials');
309
+ await storeDokployCredentials('token', 'https://test.com', {
310
+ root: tempDir,
311
+ });
312
+
313
+ // Verify file exists
314
+ const pathBefore = getCredentialsPath({ root: tempDir });
315
+ expect(existsSync(pathBefore)).toBe(true);
316
+
317
+ await removeAllCredentials({ root: tempDir });
318
+
319
+ // Verify file is removed
320
+ expect(existsSync(pathBefore)).toBe(false);
321
+ });
322
+
323
+ it('should not throw when credentials file does not exist', async () => {
324
+ const { removeAllCredentials } = await import('../credentials');
325
+ // Should not throw
326
+ await expect(
327
+ removeAllCredentials({ root: tempDir }),
328
+ ).resolves.toBeUndefined();
329
+ });
330
+ });
204
331
  });
@@ -166,3 +166,72 @@ describe('URL normalization', () => {
166
166
  expect(() => new URL('invalid-url')).toThrow();
167
167
  });
168
168
  });
169
+
170
+ describe('logoutCommand', () => {
171
+ let tempDir: string;
172
+
173
+ beforeEach(async () => {
174
+ tempDir = join(tmpdir(), `gkm-logout-test-${Date.now()}`);
175
+ await mkdir(tempDir, { recursive: true });
176
+ });
177
+
178
+ afterEach(async () => {
179
+ if (existsSync(tempDir)) {
180
+ await rm(tempDir, { recursive: true });
181
+ }
182
+ });
183
+
184
+ it('should remove dokploy credentials', async () => {
185
+ // First store credentials
186
+ await storeDokployCredentials('my-token', 'https://dokploy.example.com', {
187
+ root: tempDir,
188
+ });
189
+
190
+ // Verify they exist
191
+ let creds = await getDokployCredentials({ root: tempDir });
192
+ expect(creds).not.toBeNull();
193
+
194
+ // Remove credentials
195
+ const removed = await removeDokployCredentials({ root: tempDir });
196
+ expect(removed).toBe(true);
197
+
198
+ // Verify they're gone
199
+ creds = await getDokployCredentials({ root: tempDir });
200
+ expect(creds).toBeNull();
201
+ });
202
+
203
+ it('should return false when no credentials to remove', async () => {
204
+ const removed = await removeDokployCredentials({ root: tempDir });
205
+ expect(removed).toBe(false);
206
+ });
207
+ });
208
+
209
+ describe('whoamiCommand helpers', () => {
210
+ let tempDir: string;
211
+
212
+ beforeEach(async () => {
213
+ tempDir = join(tmpdir(), `gkm-whoami-test-${Date.now()}`);
214
+ await mkdir(tempDir, { recursive: true });
215
+ });
216
+
217
+ afterEach(async () => {
218
+ if (existsSync(tempDir)) {
219
+ await rm(tempDir, { recursive: true });
220
+ }
221
+ });
222
+
223
+ it('should return null when no credentials stored', async () => {
224
+ const creds = await getDokployCredentials({ root: tempDir });
225
+ expect(creds).toBeNull();
226
+ });
227
+
228
+ it('should return credentials when stored', async () => {
229
+ await storeDokployCredentials('test-token', 'https://test.example.com', {
230
+ root: tempDir,
231
+ });
232
+
233
+ const creds = await getDokployCredentials({ root: tempDir });
234
+ expect(creds).not.toBeNull();
235
+ expect(creds!.endpoint).toBe('https://test.example.com');
236
+ });
237
+ });