@geekmidas/cli 0.18.0 → 0.20.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/{bundler-C74EKlNa.cjs → bundler-CyHg1v_T.cjs} +3 -3
- package/dist/{bundler-C74EKlNa.cjs.map → bundler-CyHg1v_T.cjs.map} +1 -1
- package/dist/{bundler-B6z6HEeh.mjs → bundler-DQIuE3Kn.mjs} +3 -3
- package/dist/{bundler-B6z6HEeh.mjs.map → bundler-DQIuE3Kn.mjs.map} +1 -1
- package/dist/{config-DYULeEv8.mjs → config-BaYqrF3n.mjs} +48 -10
- package/dist/config-BaYqrF3n.mjs.map +1 -0
- package/dist/{config-AmInkU7k.cjs → config-CxrLu8ia.cjs} +53 -9
- package/dist/config-CxrLu8ia.cjs.map +1 -0
- package/dist/config.cjs +4 -1
- package/dist/config.d.cts +27 -2
- package/dist/config.d.cts.map +1 -1
- package/dist/config.d.mts +27 -2
- package/dist/config.d.mts.map +1 -1
- package/dist/config.mjs +3 -2
- package/dist/dokploy-api-B0w17y4_.mjs +3 -0
- package/dist/{dokploy-api-CaETb2L6.mjs → dokploy-api-B9qR2Yn1.mjs} +1 -1
- package/dist/{dokploy-api-CaETb2L6.mjs.map → dokploy-api-B9qR2Yn1.mjs.map} +1 -1
- package/dist/dokploy-api-BnGeUqN4.cjs +3 -0
- package/dist/{dokploy-api-C7F9VykY.cjs → dokploy-api-C5czOZoc.cjs} +1 -1
- package/dist/{dokploy-api-C7F9VykY.cjs.map → dokploy-api-C5czOZoc.cjs.map} +1 -1
- package/dist/{encryption-D7Efcdi9.cjs → encryption-BAz0xQ1Q.cjs} +1 -1
- package/dist/{encryption-D7Efcdi9.cjs.map → encryption-BAz0xQ1Q.cjs.map} +1 -1
- package/dist/{encryption-h4Nb6W-M.mjs → encryption-JtMsiGNp.mjs} +2 -2
- package/dist/{encryption-h4Nb6W-M.mjs.map → encryption-JtMsiGNp.mjs.map} +1 -1
- package/dist/index-CWN-bgrO.d.mts +495 -0
- package/dist/index-CWN-bgrO.d.mts.map +1 -0
- package/dist/index-DEWYvYvg.d.cts +495 -0
- package/dist/index-DEWYvYvg.d.cts.map +1 -0
- package/dist/index.cjs +2640 -564
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +2635 -564
- package/dist/index.mjs.map +1 -1
- package/dist/{openapi-CZVcfxk-.mjs → openapi-CgqR6Jkw.mjs} +3 -3
- package/dist/{openapi-CZVcfxk-.mjs.map → openapi-CgqR6Jkw.mjs.map} +1 -1
- package/dist/{openapi-C89hhkZC.cjs → openapi-DfpxS0xv.cjs} +8 -2
- package/dist/{openapi-C89hhkZC.cjs.map → openapi-DfpxS0xv.cjs.map} +1 -1
- package/dist/{openapi-react-query-CM2_qlW9.mjs → openapi-react-query-5rSortLH.mjs} +1 -1
- package/dist/{openapi-react-query-CM2_qlW9.mjs.map → openapi-react-query-5rSortLH.mjs.map} +1 -1
- package/dist/{openapi-react-query-iKjfLzff.cjs → openapi-react-query-DvNpdDpM.cjs} +1 -1
- package/dist/{openapi-react-query-iKjfLzff.cjs.map → openapi-react-query-DvNpdDpM.cjs.map} +1 -1
- package/dist/openapi-react-query.cjs +1 -1
- package/dist/openapi-react-query.mjs +1 -1
- package/dist/openapi.cjs +3 -2
- package/dist/openapi.d.cts +1 -1
- package/dist/openapi.d.mts +1 -1
- package/dist/openapi.mjs +3 -2
- package/dist/{storage-Bn3K9Ccu.cjs → storage-BPRgh3DU.cjs} +136 -5
- package/dist/storage-BPRgh3DU.cjs.map +1 -0
- package/dist/{storage-nkGIjeXt.mjs → storage-DNj_I11J.mjs} +1 -1
- package/dist/storage-Dhst7BhI.mjs +272 -0
- package/dist/storage-Dhst7BhI.mjs.map +1 -0
- package/dist/{storage-UfyTn7Zm.cjs → storage-fOR8dMu5.cjs} +1 -1
- package/dist/{types-iFk5ms7y.d.mts → types-K2uQJ-FO.d.mts} +2 -2
- package/dist/{types-BgaMXsUa.d.cts.map → types-K2uQJ-FO.d.mts.map} +1 -1
- package/dist/{types-BgaMXsUa.d.cts → types-l53qUmGt.d.cts} +2 -2
- package/dist/{types-iFk5ms7y.d.mts.map → types-l53qUmGt.d.cts.map} +1 -1
- package/dist/workspace/index.cjs +19 -0
- package/dist/workspace/index.d.cts +3 -0
- package/dist/workspace/index.d.mts +3 -0
- package/dist/workspace/index.mjs +3 -0
- package/dist/workspace-CPLEZDZf.mjs +3788 -0
- package/dist/workspace-CPLEZDZf.mjs.map +1 -0
- package/dist/workspace-iWgBlX6h.cjs +3885 -0
- package/dist/workspace-iWgBlX6h.cjs.map +1 -0
- package/package.json +9 -4
- package/src/build/__tests__/workspace-build.spec.ts +215 -0
- package/src/build/index.ts +189 -1
- package/src/config.ts +71 -14
- package/src/deploy/__tests__/docker.spec.ts +1 -1
- package/src/deploy/__tests__/index.spec.ts +305 -1
- package/src/deploy/index.ts +426 -4
- package/src/deploy/types.ts +32 -0
- package/src/dev/__tests__/index.spec.ts +572 -1
- package/src/dev/index.ts +582 -2
- package/src/docker/__tests__/compose.spec.ts +425 -0
- package/src/docker/__tests__/templates.spec.ts +145 -0
- package/src/docker/compose.ts +248 -0
- package/src/docker/index.ts +159 -3
- package/src/docker/templates.ts +219 -4
- package/src/index.ts +24 -0
- package/src/init/__tests__/generators.spec.ts +17 -24
- package/src/init/__tests__/init.spec.ts +157 -5
- package/src/init/generators/auth.ts +220 -0
- package/src/init/generators/config.ts +61 -4
- package/src/init/generators/docker.ts +115 -8
- package/src/init/generators/env.ts +7 -127
- package/src/init/generators/index.ts +1 -0
- package/src/init/generators/models.ts +3 -1
- package/src/init/generators/monorepo.ts +154 -10
- package/src/init/generators/package.ts +5 -3
- package/src/init/generators/web.ts +213 -0
- package/src/init/index.ts +290 -58
- package/src/init/templates/api.ts +38 -29
- package/src/init/templates/index.ts +132 -4
- package/src/init/templates/minimal.ts +33 -35
- package/src/init/templates/serverless.ts +16 -19
- package/src/init/templates/worker.ts +50 -25
- package/src/init/versions.ts +47 -0
- package/src/secrets/keystore.ts +144 -0
- package/src/secrets/storage.ts +109 -6
- package/src/test/index.ts +97 -0
- package/src/workspace/__tests__/client-generator.spec.ts +357 -0
- package/src/workspace/__tests__/index.spec.ts +543 -0
- package/src/workspace/__tests__/schema.spec.ts +519 -0
- package/src/workspace/__tests__/type-inference.spec.ts +251 -0
- package/src/workspace/client-generator.ts +307 -0
- package/src/workspace/index.ts +372 -0
- package/src/workspace/schema.ts +368 -0
- package/src/workspace/types.ts +336 -0
- package/tsconfig.tsbuildinfo +1 -1
- package/tsdown.config.ts +1 -0
- package/dist/config-AmInkU7k.cjs.map +0 -1
- package/dist/config-DYULeEv8.mjs.map +0 -1
- package/dist/dokploy-api-B7KxOQr3.cjs +0 -3
- package/dist/dokploy-api-DHvfmWbi.mjs +0 -3
- package/dist/storage-BaOP55oq.mjs +0 -147
- package/dist/storage-BaOP55oq.mjs.map +0 -1
- package/dist/storage-Bn3K9Ccu.cjs.map +0 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"dokploy-api-C7F9VykY.cjs","names":["message: string","status: number","statusText: string","issues?: Array<{ message: string }>","options: DokployApiOptions","endpoint: string","body?: Record<string, unknown>","method: 'GET' | 'POST' | 'PUT' | 'DELETE'","issues: Array<{ message: string }> | undefined","projectId: string","name: string","description?: string","environmentId: string","applicationId: string","updates: Partial<DokployApplicationUpdate>","env: string","dockerImage: string","options?: {\n\t\t\t/** Registry ID in Dokploy (for pre-configured registries) */\n\t\t\tregistryId?: string;\n\t\t\t/** Registry username (for direct auth) */\n\t\t\tusername?: string;\n\t\t\t/** Registry password (for direct auth) */\n\t\t\tpassword?: string;\n\t\t\t/** Registry URL (for direct auth, e.g., ghcr.io) */\n\t\t\tregistryUrl?: string;\n\t\t}","registryName: string","registryUrl: string","username: string","password: string","options?: {\n\t\t\timagePrefix?: string;\n\t\t}","registryId: string","updates: Partial<{\n\t\t\tregistryName: string;\n\t\t\tregistryUrl: string;\n\t\t\tusername: string;\n\t\t\tpassword: string;\n\t\t\timagePrefix: string;\n\t\t}>","options?: {\n\t\t\tappName?: string;\n\t\t\tdatabaseName?: string;\n\t\t\tdatabaseUser?: string;\n\t\t\tdatabasePassword?: string;\n\t\t\tdockerImage?: string;\n\t\t\tdescription?: string;\n\t\t}","postgresId: string","externalPort: number | null","updates: Partial<DokployPostgresUpdate>","options?: {\n\t\t\tappName?: string;\n\t\t\tdatabasePassword?: string;\n\t\t\tdockerImage?: string;\n\t\t\tdescription?: string;\n\t\t}","redisId: string","updates: Partial<DokployRedisUpdate>"],"sources":["../src/deploy/dokploy-api.ts"],"sourcesContent":["/**\n * Centralized Dokploy API client\n *\n * Handles authentication, error handling, and provides typed methods for all Dokploy API endpoints.\n */\n\nexport interface DokployApiOptions {\n\t/** Dokploy server URL (e.g., https://dokploy.example.com) */\n\tbaseUrl: string;\n\t/** API token for authentication */\n\ttoken: string;\n}\n\nexport interface DokployErrorResponse {\n\tmessage?: string;\n\tissues?: Array<{ message: string }>;\n}\n\nexport class DokployApiError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic status: number,\n\t\tpublic statusText: string,\n\t\tpublic issues?: Array<{ message: string }>,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'DokployApiError';\n\t}\n}\n\n/**\n * Dokploy API client\n */\nexport class DokployApi {\n\tprivate baseUrl: string;\n\tprivate token: string;\n\n\tconstructor(options: DokployApiOptions) {\n\t\tthis.baseUrl = options.baseUrl.replace(/\\/$/, ''); // Remove trailing slash\n\t\tthis.token = options.token;\n\t}\n\n\t/**\n\t * Make a GET request to the Dokploy API\n\t */\n\tasync get<T>(endpoint: string): Promise<T> {\n\t\treturn this.request<T>('GET', endpoint);\n\t}\n\n\t/**\n\t * Make a POST request to the Dokploy API\n\t */\n\tasync post<T>(endpoint: string, body?: Record<string, unknown>): Promise<T> {\n\t\treturn this.request<T>('POST', endpoint, body);\n\t}\n\n\t/**\n\t * Make a request to the Dokploy API\n\t */\n\tprivate async request<T>(\n\t\tmethod: 'GET' | 'POST' | 'PUT' | 'DELETE',\n\t\tendpoint: string,\n\t\tbody?: Record<string, unknown>,\n\t): Promise<T> {\n\t\tconst url = `${this.baseUrl}/api/${endpoint}`;\n\n\t\tconst response = await fetch(url, {\n\t\t\tmethod,\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t'x-api-key': this.token,\n\t\t\t},\n\t\t\tbody: body ? JSON.stringify(body) : undefined,\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tlet errorMessage = `Dokploy API error: ${response.status} ${response.statusText}`;\n\t\t\tlet issues: Array<{ message: string }> | undefined;\n\n\t\t\ttry {\n\t\t\t\tconst errorBody = (await response.json()) as DokployErrorResponse;\n\t\t\t\tif (errorBody.message) {\n\t\t\t\t\terrorMessage = `Dokploy API error: ${errorBody.message}`;\n\t\t\t\t}\n\t\t\t\tif (errorBody.issues?.length) {\n\t\t\t\t\tissues = errorBody.issues;\n\t\t\t\t\terrorMessage += `\\n Issues: ${errorBody.issues.map((i) => i.message).join(', ')}`;\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Ignore JSON parse errors\n\t\t\t}\n\n\t\t\tthrow new DokployApiError(\n\t\t\t\terrorMessage,\n\t\t\t\tresponse.status,\n\t\t\t\tresponse.statusText,\n\t\t\t\tissues,\n\t\t\t);\n\t\t}\n\n\t\t// Handle empty responses (204 No Content or empty body)\n\t\tconst text = await response.text();\n\t\tif (!text || text.trim() === '') {\n\t\t\treturn undefined as T;\n\t\t}\n\t\treturn JSON.parse(text) as T;\n\t}\n\n\t/**\n\t * Validate the API token by making a test request\n\t */\n\tasync validateToken(): Promise<boolean> {\n\t\ttry {\n\t\t\tawait this.get('project.all');\n\t\t\treturn true;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// ============================================\n\t// Project endpoints\n\t// ============================================\n\n\t/**\n\t * List all projects\n\t */\n\tasync listProjects(): Promise<DokployProject[]> {\n\t\treturn this.get<DokployProject[]>('project.all');\n\t}\n\n\t/**\n\t * Get a single project by ID\n\t */\n\tasync getProject(projectId: string): Promise<DokployProjectDetails> {\n\t\treturn this.get<DokployProjectDetails>(\n\t\t\t`project.one?projectId=${projectId}`,\n\t\t);\n\t}\n\n\t/**\n\t * Create a new project\n\t */\n\tasync createProject(\n\t\tname: string,\n\t\tdescription?: string,\n\t): Promise<{ project: DokployProject; environment: DokployEnvironment }> {\n\t\treturn this.post<{\n\t\t\tproject: DokployProject;\n\t\t\tenvironment: DokployEnvironment;\n\t\t}>('project.create', {\n\t\t\tname,\n\t\t\tdescription: description ?? `Created by gkm CLI`,\n\t\t});\n\t}\n\n\t// ============================================\n\t// Environment endpoints\n\t// ============================================\n\n\t/**\n\t * Create an environment in a project\n\t */\n\tasync createEnvironment(\n\t\tprojectId: string,\n\t\tname: string,\n\t\tdescription?: string,\n\t): Promise<DokployEnvironment> {\n\t\treturn this.post<DokployEnvironment>('environment.create', {\n\t\t\tprojectId,\n\t\t\tname,\n\t\t\tdescription: description ?? `${name} environment`,\n\t\t});\n\t}\n\n\t// ============================================\n\t// Application endpoints\n\t// ============================================\n\n\t/**\n\t * Create a new application\n\t */\n\tasync createApplication(\n\t\tname: string,\n\t\tprojectId: string,\n\t\tenvironmentId: string,\n\t): Promise<DokployApplication> {\n\t\treturn this.post<DokployApplication>('application.create', {\n\t\t\tname,\n\t\t\tprojectId,\n\t\t\tenvironmentId,\n\t\t\tappName: name.toLowerCase().replace(/[^a-z0-9-]/g, '-'),\n\t\t});\n\t}\n\n\t/**\n\t * Update an application\n\t */\n\tasync updateApplication(\n\t\tapplicationId: string,\n\t\tupdates: Partial<DokployApplicationUpdate>,\n\t): Promise<void> {\n\t\tawait this.post('application.update', {\n\t\t\tapplicationId,\n\t\t\t...updates,\n\t\t});\n\t}\n\n\t/**\n\t * Save environment variables for an application\n\t */\n\tasync saveApplicationEnv(applicationId: string, env: string): Promise<void> {\n\t\tawait this.post('application.saveEnvironment', {\n\t\t\tapplicationId,\n\t\t\tenv,\n\t\t});\n\t}\n\n\t/**\n\t * Configure application to use Docker provider (pull from registry)\n\t *\n\t * For private registries, either:\n\t * - Use `registryId` if the registry is configured in Dokploy\n\t * - Or provide `username`, `password`, and `registryUrl` directly\n\t */\n\tasync saveDockerProvider(\n\t\tapplicationId: string,\n\t\tdockerImage: string,\n\t\toptions?: {\n\t\t\t/** Registry ID in Dokploy (for pre-configured registries) */\n\t\t\tregistryId?: string;\n\t\t\t/** Registry username (for direct auth) */\n\t\t\tusername?: string;\n\t\t\t/** Registry password (for direct auth) */\n\t\t\tpassword?: string;\n\t\t\t/** Registry URL (for direct auth, e.g., ghcr.io) */\n\t\t\tregistryUrl?: string;\n\t\t},\n\t): Promise<void> {\n\t\tawait this.post('application.saveDockerProvider', {\n\t\t\tapplicationId,\n\t\t\tdockerImage,\n\t\t\t...options,\n\t\t});\n\t}\n\n\t/**\n\t * Deploy an application\n\t */\n\tasync deployApplication(applicationId: string): Promise<void> {\n\t\tawait this.post('application.deploy', { applicationId });\n\t}\n\n\t// ============================================\n\t// Registry endpoints\n\t// ============================================\n\n\t/**\n\t * List all registries\n\t */\n\tasync listRegistries(): Promise<DokployRegistry[]> {\n\t\treturn this.get<DokployRegistry[]>('registry.all');\n\t}\n\n\t/**\n\t * Create a new registry\n\t */\n\tasync createRegistry(\n\t\tregistryName: string,\n\t\tregistryUrl: string,\n\t\tusername: string,\n\t\tpassword: string,\n\t\toptions?: {\n\t\t\timagePrefix?: string;\n\t\t},\n\t): Promise<DokployRegistry> {\n\t\treturn this.post<DokployRegistry>('registry.create', {\n\t\t\tregistryName,\n\t\t\tregistryUrl,\n\t\t\tusername,\n\t\t\tpassword,\n\t\t\timagePrefix: options?.imagePrefix,\n\t\t});\n\t}\n\n\t/**\n\t * Get a registry by ID\n\t */\n\tasync getRegistry(registryId: string): Promise<DokployRegistry> {\n\t\treturn this.get<DokployRegistry>(`registry.one?registryId=${registryId}`);\n\t}\n\n\t/**\n\t * Update a registry\n\t */\n\tasync updateRegistry(\n\t\tregistryId: string,\n\t\tupdates: Partial<{\n\t\t\tregistryName: string;\n\t\t\tregistryUrl: string;\n\t\t\tusername: string;\n\t\t\tpassword: string;\n\t\t\timagePrefix: string;\n\t\t}>,\n\t): Promise<void> {\n\t\tawait this.post('registry.update', { registryId, ...updates });\n\t}\n\n\t/**\n\t * Delete a registry\n\t */\n\tasync deleteRegistry(registryId: string): Promise<void> {\n\t\tawait this.post('registry.remove', { registryId });\n\t}\n\n\t// ============================================\n\t// Postgres endpoints\n\t// ============================================\n\n\t/**\n\t * Create a new Postgres database\n\t */\n\tasync createPostgres(\n\t\tname: string,\n\t\tprojectId: string,\n\t\tenvironmentId: string,\n\t\toptions?: {\n\t\t\tappName?: string;\n\t\t\tdatabaseName?: string;\n\t\t\tdatabaseUser?: string;\n\t\t\tdatabasePassword?: string;\n\t\t\tdockerImage?: string;\n\t\t\tdescription?: string;\n\t\t},\n\t): Promise<DokployPostgres> {\n\t\treturn this.post<DokployPostgres>('postgres.create', {\n\t\t\tname,\n\t\t\tprojectId,\n\t\t\tenvironmentId,\n\t\t\tappName:\n\t\t\t\toptions?.appName ?? name.toLowerCase().replace(/[^a-z0-9-]/g, '-'),\n\t\t\tdatabaseName: options?.databaseName ?? 'app',\n\t\t\tdatabaseUser: options?.databaseUser ?? 'postgres',\n\t\t\tdatabasePassword: options?.databasePassword,\n\t\t\tdockerImage: options?.dockerImage ?? 'postgres:16-alpine',\n\t\t\tdescription: options?.description ?? `Postgres database for ${name}`,\n\t\t});\n\t}\n\n\t/**\n\t * Get a Postgres database by ID\n\t */\n\tasync getPostgres(postgresId: string): Promise<DokployPostgres> {\n\t\treturn this.get<DokployPostgres>(`postgres.one?postgresId=${postgresId}`);\n\t}\n\n\t/**\n\t * Deploy a Postgres database\n\t */\n\tasync deployPostgres(postgresId: string): Promise<void> {\n\t\tawait this.post('postgres.deploy', { postgresId });\n\t}\n\n\t/**\n\t * Save environment variables for Postgres\n\t */\n\tasync savePostgresEnv(postgresId: string, env: string): Promise<void> {\n\t\tawait this.post('postgres.saveEnvironment', { postgresId, env });\n\t}\n\n\t/**\n\t * Set external port for Postgres (for external access)\n\t */\n\tasync savePostgresExternalPort(\n\t\tpostgresId: string,\n\t\texternalPort: number | null,\n\t): Promise<void> {\n\t\tawait this.post('postgres.saveExternalPort', { postgresId, externalPort });\n\t}\n\n\t/**\n\t * Update Postgres configuration\n\t */\n\tasync updatePostgres(\n\t\tpostgresId: string,\n\t\tupdates: Partial<DokployPostgresUpdate>,\n\t): Promise<void> {\n\t\tawait this.post('postgres.update', { postgresId, ...updates });\n\t}\n\n\t// ============================================\n\t// Redis endpoints\n\t// ============================================\n\n\t/**\n\t * Create a new Redis instance\n\t */\n\tasync createRedis(\n\t\tname: string,\n\t\tprojectId: string,\n\t\tenvironmentId: string,\n\t\toptions?: {\n\t\t\tappName?: string;\n\t\t\tdatabasePassword?: string;\n\t\t\tdockerImage?: string;\n\t\t\tdescription?: string;\n\t\t},\n\t): Promise<DokployRedis> {\n\t\treturn this.post<DokployRedis>('redis.create', {\n\t\t\tname,\n\t\t\tprojectId,\n\t\t\tenvironmentId,\n\t\t\tappName:\n\t\t\t\toptions?.appName ?? name.toLowerCase().replace(/[^a-z0-9-]/g, '-'),\n\t\t\tdatabasePassword: options?.databasePassword,\n\t\t\tdockerImage: options?.dockerImage ?? 'redis:7-alpine',\n\t\t\tdescription: options?.description ?? `Redis instance for ${name}`,\n\t\t});\n\t}\n\n\t/**\n\t * Get a Redis instance by ID\n\t */\n\tasync getRedis(redisId: string): Promise<DokployRedis> {\n\t\treturn this.get<DokployRedis>(`redis.one?redisId=${redisId}`);\n\t}\n\n\t/**\n\t * Deploy a Redis instance\n\t */\n\tasync deployRedis(redisId: string): Promise<void> {\n\t\tawait this.post('redis.deploy', { redisId });\n\t}\n\n\t/**\n\t * Save environment variables for Redis\n\t */\n\tasync saveRedisEnv(redisId: string, env: string): Promise<void> {\n\t\tawait this.post('redis.saveEnvironment', { redisId, env });\n\t}\n\n\t/**\n\t * Set external port for Redis (for external access)\n\t */\n\tasync saveRedisExternalPort(\n\t\tredisId: string,\n\t\texternalPort: number | null,\n\t): Promise<void> {\n\t\tawait this.post('redis.saveExternalPort', { redisId, externalPort });\n\t}\n\n\t/**\n\t * Update Redis configuration\n\t */\n\tasync updateRedis(\n\t\tredisId: string,\n\t\tupdates: Partial<DokployRedisUpdate>,\n\t): Promise<void> {\n\t\tawait this.post('redis.update', { redisId, ...updates });\n\t}\n}\n\n// ============================================\n// Type definitions for Dokploy API responses\n// ============================================\n\nexport interface DokployProject {\n\tprojectId: string;\n\tname: string;\n\tdescription: string | null;\n\tcreatedAt?: string;\n\tadminId?: string;\n}\n\nexport interface DokployEnvironment {\n\tenvironmentId: string;\n\tname: string;\n\tdescription: string | null;\n}\n\nexport interface DokployProjectDetails extends DokployProject {\n\tenvironments: DokployEnvironment[];\n}\n\nexport interface DokployApplication {\n\tapplicationId: string;\n\tname: string;\n\tappName: string;\n\tprojectId: string;\n\tenvironmentId?: string;\n}\n\nexport interface DokployApplicationUpdate {\n\tregistryId: string;\n\tdockerImage: string;\n\tsourceType: 'docker';\n}\n\nexport interface DokployRegistry {\n\tregistryId: string;\n\tregistryName: string;\n\tregistryUrl: string;\n\tusername: string;\n\timagePrefix: string | null;\n}\n\nexport interface DokployPostgres {\n\tpostgresId: string;\n\tname: string;\n\tappName: string;\n\tdatabaseName: string;\n\tdatabaseUser: string;\n\tdatabasePassword: string;\n\tdockerImage: string;\n\tdescription: string | null;\n\tprojectId: string;\n\tenvironmentId: string;\n\tapplicationStatus: 'idle' | 'running' | 'done' | 'error';\n\texternalPort: number | null;\n\tcreatedAt?: string;\n}\n\nexport interface DokployPostgresUpdate {\n\tname: string;\n\tappName: string;\n\tdatabaseName: string;\n\tdatabaseUser: string;\n\tdatabasePassword: string;\n\tdockerImage: string;\n\tdescription: string;\n}\n\nexport interface DokployRedis {\n\tredisId: string;\n\tname: string;\n\tappName: string;\n\tdatabasePassword: string;\n\tdockerImage: string;\n\tdescription: string | null;\n\tprojectId: string;\n\tenvironmentId: string;\n\tapplicationStatus: 'idle' | 'running' | 'done' | 'error';\n\texternalPort: number | null;\n\tcreatedAt?: string;\n}\n\nexport interface DokployRedisUpdate {\n\tname: string;\n\tappName: string;\n\tdatabasePassword: string;\n\tdockerImage: string;\n\tdescription: string;\n}\n\n/**\n * Create a Dokploy API client from stored credentials or environment\n */\nexport async function createDokployApi(\n\tendpoint?: string,\n): Promise<DokployApi | null> {\n\tconst { getDokployCredentials } = await import('../auth/credentials');\n\n\t// Try environment variable first\n\tconst envToken = process.env.DOKPLOY_API_TOKEN;\n\tconst envEndpoint = endpoint || process.env.DOKPLOY_ENDPOINT;\n\n\tif (envToken && envEndpoint) {\n\t\treturn new DokployApi({ baseUrl: envEndpoint, token: envToken });\n\t}\n\n\t// Fall back to stored credentials\n\tconst creds = await getDokployCredentials();\n\tif (creds) {\n\t\treturn new DokployApi({\n\t\t\tbaseUrl: endpoint || creds.endpoint,\n\t\t\ttoken: creds.token,\n\t\t});\n\t}\n\n\treturn null;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"dokploy-api-C5czOZoc.cjs","names":["message: string","status: number","statusText: string","issues?: Array<{ message: string }>","options: DokployApiOptions","endpoint: string","body?: Record<string, unknown>","method: 'GET' | 'POST' | 'PUT' | 'DELETE'","issues: Array<{ message: string }> | undefined","projectId: string","name: string","description?: string","environmentId: string","applicationId: string","updates: Partial<DokployApplicationUpdate>","env: string","dockerImage: string","options?: {\n\t\t\t/** Registry ID in Dokploy (for pre-configured registries) */\n\t\t\tregistryId?: string;\n\t\t\t/** Registry username (for direct auth) */\n\t\t\tusername?: string;\n\t\t\t/** Registry password (for direct auth) */\n\t\t\tpassword?: string;\n\t\t\t/** Registry URL (for direct auth, e.g., ghcr.io) */\n\t\t\tregistryUrl?: string;\n\t\t}","registryName: string","registryUrl: string","username: string","password: string","options?: {\n\t\t\timagePrefix?: string;\n\t\t}","registryId: string","updates: Partial<{\n\t\t\tregistryName: string;\n\t\t\tregistryUrl: string;\n\t\t\tusername: string;\n\t\t\tpassword: string;\n\t\t\timagePrefix: string;\n\t\t}>","options?: {\n\t\t\tappName?: string;\n\t\t\tdatabaseName?: string;\n\t\t\tdatabaseUser?: string;\n\t\t\tdatabasePassword?: string;\n\t\t\tdockerImage?: string;\n\t\t\tdescription?: string;\n\t\t}","postgresId: string","externalPort: number | null","updates: Partial<DokployPostgresUpdate>","options?: {\n\t\t\tappName?: string;\n\t\t\tdatabasePassword?: string;\n\t\t\tdockerImage?: string;\n\t\t\tdescription?: string;\n\t\t}","redisId: string","updates: Partial<DokployRedisUpdate>"],"sources":["../src/deploy/dokploy-api.ts"],"sourcesContent":["/**\n * Centralized Dokploy API client\n *\n * Handles authentication, error handling, and provides typed methods for all Dokploy API endpoints.\n */\n\nexport interface DokployApiOptions {\n\t/** Dokploy server URL (e.g., https://dokploy.example.com) */\n\tbaseUrl: string;\n\t/** API token for authentication */\n\ttoken: string;\n}\n\nexport interface DokployErrorResponse {\n\tmessage?: string;\n\tissues?: Array<{ message: string }>;\n}\n\nexport class DokployApiError extends Error {\n\tconstructor(\n\t\tmessage: string,\n\t\tpublic status: number,\n\t\tpublic statusText: string,\n\t\tpublic issues?: Array<{ message: string }>,\n\t) {\n\t\tsuper(message);\n\t\tthis.name = 'DokployApiError';\n\t}\n}\n\n/**\n * Dokploy API client\n */\nexport class DokployApi {\n\tprivate baseUrl: string;\n\tprivate token: string;\n\n\tconstructor(options: DokployApiOptions) {\n\t\tthis.baseUrl = options.baseUrl.replace(/\\/$/, ''); // Remove trailing slash\n\t\tthis.token = options.token;\n\t}\n\n\t/**\n\t * Make a GET request to the Dokploy API\n\t */\n\tasync get<T>(endpoint: string): Promise<T> {\n\t\treturn this.request<T>('GET', endpoint);\n\t}\n\n\t/**\n\t * Make a POST request to the Dokploy API\n\t */\n\tasync post<T>(endpoint: string, body?: Record<string, unknown>): Promise<T> {\n\t\treturn this.request<T>('POST', endpoint, body);\n\t}\n\n\t/**\n\t * Make a request to the Dokploy API\n\t */\n\tprivate async request<T>(\n\t\tmethod: 'GET' | 'POST' | 'PUT' | 'DELETE',\n\t\tendpoint: string,\n\t\tbody?: Record<string, unknown>,\n\t): Promise<T> {\n\t\tconst url = `${this.baseUrl}/api/${endpoint}`;\n\n\t\tconst response = await fetch(url, {\n\t\t\tmethod,\n\t\t\theaders: {\n\t\t\t\t'Content-Type': 'application/json',\n\t\t\t\t'x-api-key': this.token,\n\t\t\t},\n\t\t\tbody: body ? JSON.stringify(body) : undefined,\n\t\t});\n\n\t\tif (!response.ok) {\n\t\t\tlet errorMessage = `Dokploy API error: ${response.status} ${response.statusText}`;\n\t\t\tlet issues: Array<{ message: string }> | undefined;\n\n\t\t\ttry {\n\t\t\t\tconst errorBody = (await response.json()) as DokployErrorResponse;\n\t\t\t\tif (errorBody.message) {\n\t\t\t\t\terrorMessage = `Dokploy API error: ${errorBody.message}`;\n\t\t\t\t}\n\t\t\t\tif (errorBody.issues?.length) {\n\t\t\t\t\tissues = errorBody.issues;\n\t\t\t\t\terrorMessage += `\\n Issues: ${errorBody.issues.map((i) => i.message).join(', ')}`;\n\t\t\t\t}\n\t\t\t} catch {\n\t\t\t\t// Ignore JSON parse errors\n\t\t\t}\n\n\t\t\tthrow new DokployApiError(\n\t\t\t\terrorMessage,\n\t\t\t\tresponse.status,\n\t\t\t\tresponse.statusText,\n\t\t\t\tissues,\n\t\t\t);\n\t\t}\n\n\t\t// Handle empty responses (204 No Content or empty body)\n\t\tconst text = await response.text();\n\t\tif (!text || text.trim() === '') {\n\t\t\treturn undefined as T;\n\t\t}\n\t\treturn JSON.parse(text) as T;\n\t}\n\n\t/**\n\t * Validate the API token by making a test request\n\t */\n\tasync validateToken(): Promise<boolean> {\n\t\ttry {\n\t\t\tawait this.get('project.all');\n\t\t\treturn true;\n\t\t} catch {\n\t\t\treturn false;\n\t\t}\n\t}\n\n\t// ============================================\n\t// Project endpoints\n\t// ============================================\n\n\t/**\n\t * List all projects\n\t */\n\tasync listProjects(): Promise<DokployProject[]> {\n\t\treturn this.get<DokployProject[]>('project.all');\n\t}\n\n\t/**\n\t * Get a single project by ID\n\t */\n\tasync getProject(projectId: string): Promise<DokployProjectDetails> {\n\t\treturn this.get<DokployProjectDetails>(\n\t\t\t`project.one?projectId=${projectId}`,\n\t\t);\n\t}\n\n\t/**\n\t * Create a new project\n\t */\n\tasync createProject(\n\t\tname: string,\n\t\tdescription?: string,\n\t): Promise<{ project: DokployProject; environment: DokployEnvironment }> {\n\t\treturn this.post<{\n\t\t\tproject: DokployProject;\n\t\t\tenvironment: DokployEnvironment;\n\t\t}>('project.create', {\n\t\t\tname,\n\t\t\tdescription: description ?? `Created by gkm CLI`,\n\t\t});\n\t}\n\n\t// ============================================\n\t// Environment endpoints\n\t// ============================================\n\n\t/**\n\t * Create an environment in a project\n\t */\n\tasync createEnvironment(\n\t\tprojectId: string,\n\t\tname: string,\n\t\tdescription?: string,\n\t): Promise<DokployEnvironment> {\n\t\treturn this.post<DokployEnvironment>('environment.create', {\n\t\t\tprojectId,\n\t\t\tname,\n\t\t\tdescription: description ?? `${name} environment`,\n\t\t});\n\t}\n\n\t// ============================================\n\t// Application endpoints\n\t// ============================================\n\n\t/**\n\t * Create a new application\n\t */\n\tasync createApplication(\n\t\tname: string,\n\t\tprojectId: string,\n\t\tenvironmentId: string,\n\t): Promise<DokployApplication> {\n\t\treturn this.post<DokployApplication>('application.create', {\n\t\t\tname,\n\t\t\tprojectId,\n\t\t\tenvironmentId,\n\t\t\tappName: name.toLowerCase().replace(/[^a-z0-9-]/g, '-'),\n\t\t});\n\t}\n\n\t/**\n\t * Update an application\n\t */\n\tasync updateApplication(\n\t\tapplicationId: string,\n\t\tupdates: Partial<DokployApplicationUpdate>,\n\t): Promise<void> {\n\t\tawait this.post('application.update', {\n\t\t\tapplicationId,\n\t\t\t...updates,\n\t\t});\n\t}\n\n\t/**\n\t * Save environment variables for an application\n\t */\n\tasync saveApplicationEnv(applicationId: string, env: string): Promise<void> {\n\t\tawait this.post('application.saveEnvironment', {\n\t\t\tapplicationId,\n\t\t\tenv,\n\t\t});\n\t}\n\n\t/**\n\t * Configure application to use Docker provider (pull from registry)\n\t *\n\t * For private registries, either:\n\t * - Use `registryId` if the registry is configured in Dokploy\n\t * - Or provide `username`, `password`, and `registryUrl` directly\n\t */\n\tasync saveDockerProvider(\n\t\tapplicationId: string,\n\t\tdockerImage: string,\n\t\toptions?: {\n\t\t\t/** Registry ID in Dokploy (for pre-configured registries) */\n\t\t\tregistryId?: string;\n\t\t\t/** Registry username (for direct auth) */\n\t\t\tusername?: string;\n\t\t\t/** Registry password (for direct auth) */\n\t\t\tpassword?: string;\n\t\t\t/** Registry URL (for direct auth, e.g., ghcr.io) */\n\t\t\tregistryUrl?: string;\n\t\t},\n\t): Promise<void> {\n\t\tawait this.post('application.saveDockerProvider', {\n\t\t\tapplicationId,\n\t\t\tdockerImage,\n\t\t\t...options,\n\t\t});\n\t}\n\n\t/**\n\t * Deploy an application\n\t */\n\tasync deployApplication(applicationId: string): Promise<void> {\n\t\tawait this.post('application.deploy', { applicationId });\n\t}\n\n\t// ============================================\n\t// Registry endpoints\n\t// ============================================\n\n\t/**\n\t * List all registries\n\t */\n\tasync listRegistries(): Promise<DokployRegistry[]> {\n\t\treturn this.get<DokployRegistry[]>('registry.all');\n\t}\n\n\t/**\n\t * Create a new registry\n\t */\n\tasync createRegistry(\n\t\tregistryName: string,\n\t\tregistryUrl: string,\n\t\tusername: string,\n\t\tpassword: string,\n\t\toptions?: {\n\t\t\timagePrefix?: string;\n\t\t},\n\t): Promise<DokployRegistry> {\n\t\treturn this.post<DokployRegistry>('registry.create', {\n\t\t\tregistryName,\n\t\t\tregistryUrl,\n\t\t\tusername,\n\t\t\tpassword,\n\t\t\timagePrefix: options?.imagePrefix,\n\t\t});\n\t}\n\n\t/**\n\t * Get a registry by ID\n\t */\n\tasync getRegistry(registryId: string): Promise<DokployRegistry> {\n\t\treturn this.get<DokployRegistry>(`registry.one?registryId=${registryId}`);\n\t}\n\n\t/**\n\t * Update a registry\n\t */\n\tasync updateRegistry(\n\t\tregistryId: string,\n\t\tupdates: Partial<{\n\t\t\tregistryName: string;\n\t\t\tregistryUrl: string;\n\t\t\tusername: string;\n\t\t\tpassword: string;\n\t\t\timagePrefix: string;\n\t\t}>,\n\t): Promise<void> {\n\t\tawait this.post('registry.update', { registryId, ...updates });\n\t}\n\n\t/**\n\t * Delete a registry\n\t */\n\tasync deleteRegistry(registryId: string): Promise<void> {\n\t\tawait this.post('registry.remove', { registryId });\n\t}\n\n\t// ============================================\n\t// Postgres endpoints\n\t// ============================================\n\n\t/**\n\t * Create a new Postgres database\n\t */\n\tasync createPostgres(\n\t\tname: string,\n\t\tprojectId: string,\n\t\tenvironmentId: string,\n\t\toptions?: {\n\t\t\tappName?: string;\n\t\t\tdatabaseName?: string;\n\t\t\tdatabaseUser?: string;\n\t\t\tdatabasePassword?: string;\n\t\t\tdockerImage?: string;\n\t\t\tdescription?: string;\n\t\t},\n\t): Promise<DokployPostgres> {\n\t\treturn this.post<DokployPostgres>('postgres.create', {\n\t\t\tname,\n\t\t\tprojectId,\n\t\t\tenvironmentId,\n\t\t\tappName:\n\t\t\t\toptions?.appName ?? name.toLowerCase().replace(/[^a-z0-9-]/g, '-'),\n\t\t\tdatabaseName: options?.databaseName ?? 'app',\n\t\t\tdatabaseUser: options?.databaseUser ?? 'postgres',\n\t\t\tdatabasePassword: options?.databasePassword,\n\t\t\tdockerImage: options?.dockerImage ?? 'postgres:16-alpine',\n\t\t\tdescription: options?.description ?? `Postgres database for ${name}`,\n\t\t});\n\t}\n\n\t/**\n\t * Get a Postgres database by ID\n\t */\n\tasync getPostgres(postgresId: string): Promise<DokployPostgres> {\n\t\treturn this.get<DokployPostgres>(`postgres.one?postgresId=${postgresId}`);\n\t}\n\n\t/**\n\t * Deploy a Postgres database\n\t */\n\tasync deployPostgres(postgresId: string): Promise<void> {\n\t\tawait this.post('postgres.deploy', { postgresId });\n\t}\n\n\t/**\n\t * Save environment variables for Postgres\n\t */\n\tasync savePostgresEnv(postgresId: string, env: string): Promise<void> {\n\t\tawait this.post('postgres.saveEnvironment', { postgresId, env });\n\t}\n\n\t/**\n\t * Set external port for Postgres (for external access)\n\t */\n\tasync savePostgresExternalPort(\n\t\tpostgresId: string,\n\t\texternalPort: number | null,\n\t): Promise<void> {\n\t\tawait this.post('postgres.saveExternalPort', { postgresId, externalPort });\n\t}\n\n\t/**\n\t * Update Postgres configuration\n\t */\n\tasync updatePostgres(\n\t\tpostgresId: string,\n\t\tupdates: Partial<DokployPostgresUpdate>,\n\t): Promise<void> {\n\t\tawait this.post('postgres.update', { postgresId, ...updates });\n\t}\n\n\t// ============================================\n\t// Redis endpoints\n\t// ============================================\n\n\t/**\n\t * Create a new Redis instance\n\t */\n\tasync createRedis(\n\t\tname: string,\n\t\tprojectId: string,\n\t\tenvironmentId: string,\n\t\toptions?: {\n\t\t\tappName?: string;\n\t\t\tdatabasePassword?: string;\n\t\t\tdockerImage?: string;\n\t\t\tdescription?: string;\n\t\t},\n\t): Promise<DokployRedis> {\n\t\treturn this.post<DokployRedis>('redis.create', {\n\t\t\tname,\n\t\t\tprojectId,\n\t\t\tenvironmentId,\n\t\t\tappName:\n\t\t\t\toptions?.appName ?? name.toLowerCase().replace(/[^a-z0-9-]/g, '-'),\n\t\t\tdatabasePassword: options?.databasePassword,\n\t\t\tdockerImage: options?.dockerImage ?? 'redis:7-alpine',\n\t\t\tdescription: options?.description ?? `Redis instance for ${name}`,\n\t\t});\n\t}\n\n\t/**\n\t * Get a Redis instance by ID\n\t */\n\tasync getRedis(redisId: string): Promise<DokployRedis> {\n\t\treturn this.get<DokployRedis>(`redis.one?redisId=${redisId}`);\n\t}\n\n\t/**\n\t * Deploy a Redis instance\n\t */\n\tasync deployRedis(redisId: string): Promise<void> {\n\t\tawait this.post('redis.deploy', { redisId });\n\t}\n\n\t/**\n\t * Save environment variables for Redis\n\t */\n\tasync saveRedisEnv(redisId: string, env: string): Promise<void> {\n\t\tawait this.post('redis.saveEnvironment', { redisId, env });\n\t}\n\n\t/**\n\t * Set external port for Redis (for external access)\n\t */\n\tasync saveRedisExternalPort(\n\t\tredisId: string,\n\t\texternalPort: number | null,\n\t): Promise<void> {\n\t\tawait this.post('redis.saveExternalPort', { redisId, externalPort });\n\t}\n\n\t/**\n\t * Update Redis configuration\n\t */\n\tasync updateRedis(\n\t\tredisId: string,\n\t\tupdates: Partial<DokployRedisUpdate>,\n\t): Promise<void> {\n\t\tawait this.post('redis.update', { redisId, ...updates });\n\t}\n}\n\n// ============================================\n// Type definitions for Dokploy API responses\n// ============================================\n\nexport interface DokployProject {\n\tprojectId: string;\n\tname: string;\n\tdescription: string | null;\n\tcreatedAt?: string;\n\tadminId?: string;\n}\n\nexport interface DokployEnvironment {\n\tenvironmentId: string;\n\tname: string;\n\tdescription: string | null;\n}\n\nexport interface DokployProjectDetails extends DokployProject {\n\tenvironments: DokployEnvironment[];\n}\n\nexport interface DokployApplication {\n\tapplicationId: string;\n\tname: string;\n\tappName: string;\n\tprojectId: string;\n\tenvironmentId?: string;\n}\n\nexport interface DokployApplicationUpdate {\n\tregistryId: string;\n\tdockerImage: string;\n\tsourceType: 'docker';\n}\n\nexport interface DokployRegistry {\n\tregistryId: string;\n\tregistryName: string;\n\tregistryUrl: string;\n\tusername: string;\n\timagePrefix: string | null;\n}\n\nexport interface DokployPostgres {\n\tpostgresId: string;\n\tname: string;\n\tappName: string;\n\tdatabaseName: string;\n\tdatabaseUser: string;\n\tdatabasePassword: string;\n\tdockerImage: string;\n\tdescription: string | null;\n\tprojectId: string;\n\tenvironmentId: string;\n\tapplicationStatus: 'idle' | 'running' | 'done' | 'error';\n\texternalPort: number | null;\n\tcreatedAt?: string;\n}\n\nexport interface DokployPostgresUpdate {\n\tname: string;\n\tappName: string;\n\tdatabaseName: string;\n\tdatabaseUser: string;\n\tdatabasePassword: string;\n\tdockerImage: string;\n\tdescription: string;\n}\n\nexport interface DokployRedis {\n\tredisId: string;\n\tname: string;\n\tappName: string;\n\tdatabasePassword: string;\n\tdockerImage: string;\n\tdescription: string | null;\n\tprojectId: string;\n\tenvironmentId: string;\n\tapplicationStatus: 'idle' | 'running' | 'done' | 'error';\n\texternalPort: number | null;\n\tcreatedAt?: string;\n}\n\nexport interface DokployRedisUpdate {\n\tname: string;\n\tappName: string;\n\tdatabasePassword: string;\n\tdockerImage: string;\n\tdescription: string;\n}\n\n/**\n * Create a Dokploy API client from stored credentials or environment\n */\nexport async function createDokployApi(\n\tendpoint?: string,\n): Promise<DokployApi | null> {\n\tconst { getDokployCredentials } = await import('../auth/credentials');\n\n\t// Try environment variable first\n\tconst envToken = process.env.DOKPLOY_API_TOKEN;\n\tconst envEndpoint = endpoint || process.env.DOKPLOY_ENDPOINT;\n\n\tif (envToken && envEndpoint) {\n\t\treturn new DokployApi({ baseUrl: envEndpoint, token: envToken });\n\t}\n\n\t// Fall back to stored credentials\n\tconst creds = await getDokployCredentials();\n\tif (creds) {\n\t\treturn new DokployApi({\n\t\t\tbaseUrl: endpoint || creds.endpoint,\n\t\t\ttoken: creds.token,\n\t\t});\n\t}\n\n\treturn null;\n}\n"],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encryption-
|
|
1
|
+
{"version":3,"file":"encryption-BAz0xQ1Q.cjs","names":["secrets: EmbeddableSecrets","payload: EncryptedPayload"],"sources":["../src/secrets/encryption.ts"],"sourcesContent":["import { createCipheriv, createDecipheriv, randomBytes } from 'node:crypto';\nimport type { EmbeddableSecrets, EncryptedPayload } from './types';\n\n/** AES-256-GCM configuration */\nconst ALGORITHM = 'aes-256-gcm';\nconst KEY_LENGTH = 32; // 256 bits\nconst IV_LENGTH = 12; // 96 bits for GCM\nconst AUTH_TAG_LENGTH = 16; // 128 bits\n\n/**\n * Encrypt secrets for embedding in a bundle.\n * Uses AES-256-GCM with a randomly generated ephemeral key.\n *\n * @param secrets - Key-value pairs to encrypt\n * @returns Encrypted payload with ephemeral master key\n */\nexport function encryptSecrets(secrets: EmbeddableSecrets): EncryptedPayload {\n\t// Generate ephemeral key and IV\n\tconst masterKey = randomBytes(KEY_LENGTH);\n\tconst iv = randomBytes(IV_LENGTH);\n\n\t// Serialize secrets to JSON\n\tconst plaintext = JSON.stringify(secrets);\n\n\t// Encrypt\n\tconst cipher = createCipheriv(ALGORITHM, masterKey, iv);\n\tconst ciphertext = Buffer.concat([\n\t\tcipher.update(plaintext, 'utf-8'),\n\t\tcipher.final(),\n\t]);\n\n\t// Get auth tag\n\tconst authTag = cipher.getAuthTag();\n\n\t// Combine ciphertext + auth tag\n\tconst combined = Buffer.concat([ciphertext, authTag]);\n\n\treturn {\n\t\tencrypted: combined.toString('base64'),\n\t\tiv: iv.toString('hex'),\n\t\tmasterKey: masterKey.toString('hex'),\n\t};\n}\n\n/**\n * Decrypt secrets from an encrypted payload.\n * Used at runtime to decrypt embedded credentials.\n *\n * @param encrypted - Base64 encoded ciphertext + auth tag\n * @param iv - Hex encoded IV\n * @param masterKey - Hex encoded master key\n * @returns Decrypted secrets\n */\nexport function decryptSecrets(\n\tencrypted: string,\n\tiv: string,\n\tmasterKey: string,\n): EmbeddableSecrets {\n\t// Decode inputs\n\tconst key = Buffer.from(masterKey, 'hex');\n\tconst ivBuffer = Buffer.from(iv, 'hex');\n\tconst combined = Buffer.from(encrypted, 'base64');\n\n\t// Split ciphertext and auth tag\n\tconst ciphertext = combined.subarray(0, -AUTH_TAG_LENGTH);\n\tconst authTag = combined.subarray(-AUTH_TAG_LENGTH);\n\n\t// Decrypt\n\tconst decipher = createDecipheriv(ALGORITHM, key, ivBuffer);\n\tdecipher.setAuthTag(authTag);\n\n\tconst plaintext = Buffer.concat([\n\t\tdecipher.update(ciphertext),\n\t\tdecipher.final(),\n\t]);\n\n\treturn JSON.parse(plaintext.toString('utf-8')) as EmbeddableSecrets;\n}\n\n/**\n * Generate the define options for tsdown/esbuild.\n * These will be injected at build time.\n */\nexport function generateDefineOptions(\n\tpayload: EncryptedPayload,\n): Record<string, string> {\n\treturn {\n\t\t__GKM_ENCRYPTED_CREDENTIALS__: JSON.stringify(payload.encrypted),\n\t\t__GKM_CREDENTIALS_IV__: JSON.stringify(payload.iv),\n\t};\n}\n"],"mappings":";;;;;AAIA,MAAM,YAAY;AAClB,MAAM,aAAa;AACnB,MAAM,YAAY;;;;;;;;AAUlB,SAAgB,eAAeA,SAA8C;CAE5E,MAAM,YAAY,6BAAY,WAAW;CACzC,MAAM,KAAK,6BAAY,UAAU;CAGjC,MAAM,YAAY,KAAK,UAAU,QAAQ;CAGzC,MAAM,SAAS,gCAAe,WAAW,WAAW,GAAG;CACvD,MAAM,aAAa,OAAO,OAAO,CAChC,OAAO,OAAO,WAAW,QAAQ,EACjC,OAAO,OAAO,AACd,EAAC;CAGF,MAAM,UAAU,OAAO,YAAY;CAGnC,MAAM,WAAW,OAAO,OAAO,CAAC,YAAY,OAAQ,EAAC;AAErD,QAAO;EACN,WAAW,SAAS,SAAS,SAAS;EACtC,IAAI,GAAG,SAAS,MAAM;EACtB,WAAW,UAAU,SAAS,MAAM;CACpC;AACD;;;;;AAyCD,SAAgB,sBACfC,SACyB;AACzB,QAAO;EACN,+BAA+B,KAAK,UAAU,QAAQ,UAAU;EAChE,wBAAwB,KAAK,UAAU,QAAQ,GAAG;CAClD;AACD"}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { createCipheriv, randomBytes } from "node:crypto";
|
|
1
|
+
import { createCipheriv, createDecipheriv, randomBytes } from "node:crypto";
|
|
2
2
|
|
|
3
3
|
//#region src/secrets/encryption.ts
|
|
4
4
|
/** AES-256-GCM configuration */
|
|
@@ -39,4 +39,4 @@ function generateDefineOptions(payload) {
|
|
|
39
39
|
|
|
40
40
|
//#endregion
|
|
41
41
|
export { encryptSecrets, generateDefineOptions };
|
|
42
|
-
//# sourceMappingURL=encryption-
|
|
42
|
+
//# sourceMappingURL=encryption-JtMsiGNp.mjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"encryption-
|
|
1
|
+
{"version":3,"file":"encryption-JtMsiGNp.mjs","names":["secrets: EmbeddableSecrets","payload: EncryptedPayload"],"sources":["../src/secrets/encryption.ts"],"sourcesContent":["import { createCipheriv, createDecipheriv, randomBytes } from 'node:crypto';\nimport type { EmbeddableSecrets, EncryptedPayload } from './types';\n\n/** AES-256-GCM configuration */\nconst ALGORITHM = 'aes-256-gcm';\nconst KEY_LENGTH = 32; // 256 bits\nconst IV_LENGTH = 12; // 96 bits for GCM\nconst AUTH_TAG_LENGTH = 16; // 128 bits\n\n/**\n * Encrypt secrets for embedding in a bundle.\n * Uses AES-256-GCM with a randomly generated ephemeral key.\n *\n * @param secrets - Key-value pairs to encrypt\n * @returns Encrypted payload with ephemeral master key\n */\nexport function encryptSecrets(secrets: EmbeddableSecrets): EncryptedPayload {\n\t// Generate ephemeral key and IV\n\tconst masterKey = randomBytes(KEY_LENGTH);\n\tconst iv = randomBytes(IV_LENGTH);\n\n\t// Serialize secrets to JSON\n\tconst plaintext = JSON.stringify(secrets);\n\n\t// Encrypt\n\tconst cipher = createCipheriv(ALGORITHM, masterKey, iv);\n\tconst ciphertext = Buffer.concat([\n\t\tcipher.update(plaintext, 'utf-8'),\n\t\tcipher.final(),\n\t]);\n\n\t// Get auth tag\n\tconst authTag = cipher.getAuthTag();\n\n\t// Combine ciphertext + auth tag\n\tconst combined = Buffer.concat([ciphertext, authTag]);\n\n\treturn {\n\t\tencrypted: combined.toString('base64'),\n\t\tiv: iv.toString('hex'),\n\t\tmasterKey: masterKey.toString('hex'),\n\t};\n}\n\n/**\n * Decrypt secrets from an encrypted payload.\n * Used at runtime to decrypt embedded credentials.\n *\n * @param encrypted - Base64 encoded ciphertext + auth tag\n * @param iv - Hex encoded IV\n * @param masterKey - Hex encoded master key\n * @returns Decrypted secrets\n */\nexport function decryptSecrets(\n\tencrypted: string,\n\tiv: string,\n\tmasterKey: string,\n): EmbeddableSecrets {\n\t// Decode inputs\n\tconst key = Buffer.from(masterKey, 'hex');\n\tconst ivBuffer = Buffer.from(iv, 'hex');\n\tconst combined = Buffer.from(encrypted, 'base64');\n\n\t// Split ciphertext and auth tag\n\tconst ciphertext = combined.subarray(0, -AUTH_TAG_LENGTH);\n\tconst authTag = combined.subarray(-AUTH_TAG_LENGTH);\n\n\t// Decrypt\n\tconst decipher = createDecipheriv(ALGORITHM, key, ivBuffer);\n\tdecipher.setAuthTag(authTag);\n\n\tconst plaintext = Buffer.concat([\n\t\tdecipher.update(ciphertext),\n\t\tdecipher.final(),\n\t]);\n\n\treturn JSON.parse(plaintext.toString('utf-8')) as EmbeddableSecrets;\n}\n\n/**\n * Generate the define options for tsdown/esbuild.\n * These will be injected at build time.\n */\nexport function generateDefineOptions(\n\tpayload: EncryptedPayload,\n): Record<string, string> {\n\treturn {\n\t\t__GKM_ENCRYPTED_CREDENTIALS__: JSON.stringify(payload.encrypted),\n\t\t__GKM_CREDENTIALS_IV__: JSON.stringify(payload.iv),\n\t};\n}\n"],"mappings":";;;;AAIA,MAAM,YAAY;AAClB,MAAM,aAAa;AACnB,MAAM,YAAY;;;;;;;;AAUlB,SAAgB,eAAeA,SAA8C;CAE5E,MAAM,YAAY,YAAY,WAAW;CACzC,MAAM,KAAK,YAAY,UAAU;CAGjC,MAAM,YAAY,KAAK,UAAU,QAAQ;CAGzC,MAAM,SAAS,eAAe,WAAW,WAAW,GAAG;CACvD,MAAM,aAAa,OAAO,OAAO,CAChC,OAAO,OAAO,WAAW,QAAQ,EACjC,OAAO,OAAO,AACd,EAAC;CAGF,MAAM,UAAU,OAAO,YAAY;CAGnC,MAAM,WAAW,OAAO,OAAO,CAAC,YAAY,OAAQ,EAAC;AAErD,QAAO;EACN,WAAW,SAAS,SAAS,SAAS;EACtC,IAAI,GAAG,SAAS,MAAM;EACtB,WAAW,UAAU,SAAS,MAAM;CACpC;AACD;;;;;AAyCD,SAAgB,sBACfC,SACyB;AACzB,QAAO;EACN,+BAA+B,KAAK,UAAU,QAAQ,UAAU;EAChE,wBAAwB,KAAK,UAAU,QAAQ,GAAG;CAClD;AACD"}
|
|
@@ -0,0 +1,495 @@
|
|
|
1
|
+
import { GkmConfig, HooksConfig, OpenApiConfig, ProvidersConfig, Routes, Runtime, StudioConfig, TelescopeConfig } from "./types-K2uQJ-FO.mjs";
|
|
2
|
+
import { z } from "zod/v4";
|
|
3
|
+
|
|
4
|
+
//#region src/workspace/types.d.ts
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Deploy target for an app.
|
|
8
|
+
* Currently only 'dokploy' is supported.
|
|
9
|
+
* Future: 'vercel' | 'cloudflare'
|
|
10
|
+
*/
|
|
11
|
+
type DeployTarget = 'dokploy' | 'vercel' | 'cloudflare';
|
|
12
|
+
/**
|
|
13
|
+
* Service image configuration for custom Docker images.
|
|
14
|
+
*/
|
|
15
|
+
interface ServiceImageConfig {
|
|
16
|
+
/** Docker image version/tag (e.g., '18-alpine') */
|
|
17
|
+
version?: string;
|
|
18
|
+
/** Full Docker image reference (overrides version) */
|
|
19
|
+
image?: string;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Mail service configuration.
|
|
23
|
+
*/
|
|
24
|
+
interface MailServiceConfig extends ServiceImageConfig {
|
|
25
|
+
/** SMTP configuration for production */
|
|
26
|
+
smtp?: {
|
|
27
|
+
host: string;
|
|
28
|
+
port: number;
|
|
29
|
+
user?: string;
|
|
30
|
+
pass?: string;
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Development services configuration.
|
|
35
|
+
*/
|
|
36
|
+
interface ServicesConfig {
|
|
37
|
+
/** PostgreSQL database (default: postgres:18-alpine) */
|
|
38
|
+
db?: boolean | ServiceImageConfig;
|
|
39
|
+
/** Redis cache (default: redis:8-alpine) */
|
|
40
|
+
cache?: boolean | ServiceImageConfig;
|
|
41
|
+
/** Mail service (mailpit for dev) */
|
|
42
|
+
mail?: boolean | MailServiceConfig;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Dokploy workspace deployment configuration.
|
|
46
|
+
*/
|
|
47
|
+
interface DokployWorkspaceConfig {
|
|
48
|
+
/** Dokploy API endpoint */
|
|
49
|
+
endpoint: string;
|
|
50
|
+
/** Project ID (1 workspace = 1 project) */
|
|
51
|
+
projectId: string;
|
|
52
|
+
/** Container registry for images */
|
|
53
|
+
registry?: string;
|
|
54
|
+
/** Registry ID in Dokploy */
|
|
55
|
+
registryId?: string;
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Deployment configuration for the workspace.
|
|
59
|
+
*/
|
|
60
|
+
interface DeployConfig {
|
|
61
|
+
/** Default deploy target for all apps */
|
|
62
|
+
default?: DeployTarget;
|
|
63
|
+
/** Dokploy-specific configuration */
|
|
64
|
+
dokploy?: DokployWorkspaceConfig;
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Models package configuration for shared schemas.
|
|
68
|
+
*/
|
|
69
|
+
interface ModelsConfig {
|
|
70
|
+
/** Path to models package (default: packages/models) */
|
|
71
|
+
path?: string;
|
|
72
|
+
/**
|
|
73
|
+
* Schema library to use.
|
|
74
|
+
* Currently only 'zod' is supported.
|
|
75
|
+
* Future: any StandardSchema-compatible library
|
|
76
|
+
*/
|
|
77
|
+
schema?: 'zod';
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* Shared packages configuration.
|
|
81
|
+
*/
|
|
82
|
+
interface SharedConfig {
|
|
83
|
+
/** Glob patterns for shared packages (default: ['packages/*']) */
|
|
84
|
+
packages?: string[];
|
|
85
|
+
/** Models package configuration */
|
|
86
|
+
models?: ModelsConfig;
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Secrets encryption configuration.
|
|
90
|
+
*/
|
|
91
|
+
interface SecretsConfig {
|
|
92
|
+
/** Enable encrypted secrets */
|
|
93
|
+
enabled?: boolean;
|
|
94
|
+
/** Encryption algorithm (default: aes-256-gcm) */
|
|
95
|
+
algorithm?: string;
|
|
96
|
+
/** Key derivation function (default: scrypt) */
|
|
97
|
+
kdf?: 'scrypt' | 'pbkdf2';
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Client generation configuration for frontend apps.
|
|
101
|
+
*/
|
|
102
|
+
interface ClientConfig {
|
|
103
|
+
/** Output directory for generated client (relative to app path) */
|
|
104
|
+
output?: string;
|
|
105
|
+
}
|
|
106
|
+
/**
|
|
107
|
+
* Base app configuration properties (shared between input and normalized).
|
|
108
|
+
*/
|
|
109
|
+
interface AppConfigBase {
|
|
110
|
+
/** App type (default: 'backend') */
|
|
111
|
+
type?: 'backend' | 'frontend';
|
|
112
|
+
/** Path relative to workspace root */
|
|
113
|
+
path: string;
|
|
114
|
+
/** Dev server port */
|
|
115
|
+
port: number;
|
|
116
|
+
/** Per-app deploy target override */
|
|
117
|
+
deploy?: DeployTarget;
|
|
118
|
+
/** Routes glob pattern */
|
|
119
|
+
routes?: Routes;
|
|
120
|
+
/** Functions glob pattern */
|
|
121
|
+
functions?: Routes;
|
|
122
|
+
/** Crons glob pattern */
|
|
123
|
+
crons?: Routes;
|
|
124
|
+
/** Subscribers glob pattern */
|
|
125
|
+
subscribers?: Routes;
|
|
126
|
+
/** Path to environment parser module */
|
|
127
|
+
envParser?: string;
|
|
128
|
+
/** Path to logger module */
|
|
129
|
+
logger?: string;
|
|
130
|
+
/** Provider configuration */
|
|
131
|
+
providers?: ProvidersConfig;
|
|
132
|
+
/** Server lifecycle hooks */
|
|
133
|
+
hooks?: HooksConfig;
|
|
134
|
+
/** Telescope configuration */
|
|
135
|
+
telescope?: string | boolean | TelescopeConfig;
|
|
136
|
+
/** Studio configuration */
|
|
137
|
+
studio?: string | boolean | StudioConfig;
|
|
138
|
+
/** OpenAPI configuration */
|
|
139
|
+
openapi?: boolean | OpenApiConfig;
|
|
140
|
+
/** Runtime (node or bun) */
|
|
141
|
+
runtime?: Runtime;
|
|
142
|
+
/** Environment file(s) to load */
|
|
143
|
+
env?: string | string[];
|
|
144
|
+
/** Frontend framework (currently only 'nextjs') */
|
|
145
|
+
framework?: 'nextjs';
|
|
146
|
+
/** Client generation configuration */
|
|
147
|
+
client?: ClientConfig;
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* App configuration input with type-safe dependencies.
|
|
151
|
+
* @template TAppNames - Union of valid app names in the workspace
|
|
152
|
+
*/
|
|
153
|
+
interface AppConfigInput<TAppNames extends string = string> extends AppConfigBase {
|
|
154
|
+
/** Dependencies on other apps in the workspace (type-safe) */
|
|
155
|
+
dependencies?: TAppNames[];
|
|
156
|
+
}
|
|
157
|
+
/**
|
|
158
|
+
* App configuration (legacy, for backwards compatibility).
|
|
159
|
+
* @deprecated Use AppConfigInput for new code
|
|
160
|
+
*/
|
|
161
|
+
interface AppConfig extends AppConfigBase {
|
|
162
|
+
/** Dependencies on other apps in the workspace */
|
|
163
|
+
dependencies?: string[];
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Base app input type for type inference.
|
|
167
|
+
*/
|
|
168
|
+
type AppInput = AppConfigBase & {
|
|
169
|
+
dependencies?: readonly string[];
|
|
170
|
+
};
|
|
171
|
+
/**
|
|
172
|
+
* Apps record type for workspace configuration.
|
|
173
|
+
*/
|
|
174
|
+
type AppsRecord = Record<string, AppInput>;
|
|
175
|
+
/**
|
|
176
|
+
* Constrain apps so dependencies only reference valid app names.
|
|
177
|
+
* Dependencies must be an array of valid app names from the workspace.
|
|
178
|
+
*/
|
|
179
|
+
type ConstrainedApps<TApps extends AppsRecord> = { [K in keyof TApps]: Omit<TApps[K], 'dependencies'> & {
|
|
180
|
+
dependencies?: readonly (keyof TApps & string)[];
|
|
181
|
+
} };
|
|
182
|
+
/**
|
|
183
|
+
* Full workspace input type with constrained dependencies.
|
|
184
|
+
*/
|
|
185
|
+
type WorkspaceInput<TApps extends AppsRecord> = {
|
|
186
|
+
name?: string;
|
|
187
|
+
apps: ConstrainedApps<TApps>;
|
|
188
|
+
shared?: SharedConfig;
|
|
189
|
+
deploy?: DeployConfig;
|
|
190
|
+
services?: ServicesConfig;
|
|
191
|
+
secrets?: SecretsConfig;
|
|
192
|
+
};
|
|
193
|
+
/**
|
|
194
|
+
* Extract app names from apps record.
|
|
195
|
+
*/
|
|
196
|
+
type InferAppNames<TApps extends AppsRecord> = keyof TApps & string;
|
|
197
|
+
/**
|
|
198
|
+
* Inferred workspace config with proper app name types.
|
|
199
|
+
*/
|
|
200
|
+
type InferredWorkspaceConfig<TApps extends AppsRecord> = {
|
|
201
|
+
name?: string;
|
|
202
|
+
apps: { [K in keyof TApps]: Omit<TApps[K], 'dependencies'> & {
|
|
203
|
+
dependencies?: InferAppNames<TApps>[];
|
|
204
|
+
} };
|
|
205
|
+
shared?: SharedConfig;
|
|
206
|
+
deploy?: DeployConfig;
|
|
207
|
+
services?: ServicesConfig;
|
|
208
|
+
secrets?: SecretsConfig;
|
|
209
|
+
};
|
|
210
|
+
/** @deprecated Use WorkspaceInput */
|
|
211
|
+
|
|
212
|
+
/**
|
|
213
|
+
* Workspace configuration for multi-app monorepos (legacy).
|
|
214
|
+
* @deprecated Use WorkspaceConfigInput with defineWorkspace for type inference
|
|
215
|
+
*/
|
|
216
|
+
interface WorkspaceConfig {
|
|
217
|
+
/** Workspace name (defaults to root package.json name) */
|
|
218
|
+
name?: string;
|
|
219
|
+
/** App definitions */
|
|
220
|
+
apps: Record<string, AppConfig>;
|
|
221
|
+
/** Shared packages configuration */
|
|
222
|
+
shared?: SharedConfig;
|
|
223
|
+
/** Default deployment configuration */
|
|
224
|
+
deploy?: DeployConfig;
|
|
225
|
+
/** Development services (db, cache, mail) */
|
|
226
|
+
services?: ServicesConfig;
|
|
227
|
+
/** Encrypted secrets configuration */
|
|
228
|
+
secrets?: SecretsConfig;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Normalized app configuration with resolved defaults.
|
|
232
|
+
*/
|
|
233
|
+
interface NormalizedAppConfig extends Omit<AppConfigBase, 'type'> {
|
|
234
|
+
type: 'backend' | 'frontend';
|
|
235
|
+
path: string;
|
|
236
|
+
port: number;
|
|
237
|
+
dependencies: string[];
|
|
238
|
+
/** Resolved deploy target (app.deploy > deploy.default > 'dokploy') */
|
|
239
|
+
resolvedDeployTarget: DeployTarget;
|
|
240
|
+
}
|
|
241
|
+
/**
|
|
242
|
+
* Normalized workspace configuration with resolved defaults.
|
|
243
|
+
*/
|
|
244
|
+
interface NormalizedWorkspace {
|
|
245
|
+
name: string;
|
|
246
|
+
root: string;
|
|
247
|
+
apps: Record<string, NormalizedAppConfig>;
|
|
248
|
+
services: ServicesConfig;
|
|
249
|
+
deploy: DeployConfig;
|
|
250
|
+
shared: SharedConfig;
|
|
251
|
+
secrets: SecretsConfig;
|
|
252
|
+
}
|
|
253
|
+
/**
|
|
254
|
+
* Result of loading and processing a configuration.
|
|
255
|
+
*/
|
|
256
|
+
interface LoadedConfig {
|
|
257
|
+
/** Whether this is a single-app or workspace config */
|
|
258
|
+
type: 'single' | 'workspace';
|
|
259
|
+
/** The raw configuration as loaded */
|
|
260
|
+
raw: GkmConfig | WorkspaceConfig;
|
|
261
|
+
/** Normalized workspace (always available) */
|
|
262
|
+
workspace: NormalizedWorkspace;
|
|
263
|
+
}
|
|
264
|
+
/**
|
|
265
|
+
* Type guard to check if a config is a WorkspaceConfig.
|
|
266
|
+
*/
|
|
267
|
+
declare function isWorkspaceConfig(config: GkmConfig | WorkspaceConfig): config is WorkspaceConfig;
|
|
268
|
+
//#endregion
|
|
269
|
+
//#region src/workspace/schema.d.ts
|
|
270
|
+
/**
|
|
271
|
+
* Supported deploy targets (Phase 1).
|
|
272
|
+
*/
|
|
273
|
+
declare const SUPPORTED_DEPLOY_TARGETS: readonly ["dokploy"];
|
|
274
|
+
/**
|
|
275
|
+
* Phase 2 deploy targets (not yet implemented).
|
|
276
|
+
*/
|
|
277
|
+
declare const PHASE_2_DEPLOY_TARGETS: readonly ["vercel", "cloudflare"];
|
|
278
|
+
/**
|
|
279
|
+
* Check if a deploy target is supported.
|
|
280
|
+
*/
|
|
281
|
+
declare function isDeployTargetSupported(target: string): boolean;
|
|
282
|
+
/**
|
|
283
|
+
* Check if a deploy target is planned for Phase 2.
|
|
284
|
+
*/
|
|
285
|
+
declare function isPhase2DeployTarget(target: string): boolean;
|
|
286
|
+
/**
|
|
287
|
+
* Get error message for unsupported deploy targets.
|
|
288
|
+
*/
|
|
289
|
+
declare function getDeployTargetError(target: string, appName?: string): string;
|
|
290
|
+
/**
|
|
291
|
+
* Workspace configuration schema.
|
|
292
|
+
*/
|
|
293
|
+
declare const WorkspaceConfigSchema: z.ZodObject<{
|
|
294
|
+
name: z.ZodOptional<z.ZodString>;
|
|
295
|
+
apps: z.ZodRecord<z.ZodString, z.ZodObject<{
|
|
296
|
+
type: z.ZodDefault<z.ZodOptional<z.ZodEnum<{
|
|
297
|
+
backend: "backend";
|
|
298
|
+
frontend: "frontend";
|
|
299
|
+
}>>>;
|
|
300
|
+
path: z.ZodString;
|
|
301
|
+
port: z.ZodNumber;
|
|
302
|
+
dependencies: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
303
|
+
deploy: z.ZodOptional<z.ZodEnum<{
|
|
304
|
+
dokploy: "dokploy";
|
|
305
|
+
vercel: "vercel";
|
|
306
|
+
cloudflare: "cloudflare";
|
|
307
|
+
}>>;
|
|
308
|
+
routes: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
309
|
+
functions: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
310
|
+
crons: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
311
|
+
subscribers: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
312
|
+
envParser: z.ZodOptional<z.ZodString>;
|
|
313
|
+
logger: z.ZodOptional<z.ZodString>;
|
|
314
|
+
hooks: z.ZodOptional<z.ZodObject<{
|
|
315
|
+
server: z.ZodOptional<z.ZodString>;
|
|
316
|
+
}, z.core.$strip>>;
|
|
317
|
+
telescope: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodBoolean, z.ZodObject<{
|
|
318
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
319
|
+
port: z.ZodOptional<z.ZodNumber>;
|
|
320
|
+
path: z.ZodOptional<z.ZodString>;
|
|
321
|
+
ignore: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
322
|
+
recordBody: z.ZodOptional<z.ZodBoolean>;
|
|
323
|
+
maxEntries: z.ZodOptional<z.ZodNumber>;
|
|
324
|
+
websocket: z.ZodOptional<z.ZodBoolean>;
|
|
325
|
+
}, z.core.$strip>]>>;
|
|
326
|
+
studio: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodBoolean, z.ZodObject<{
|
|
327
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
328
|
+
path: z.ZodOptional<z.ZodString>;
|
|
329
|
+
schema: z.ZodOptional<z.ZodString>;
|
|
330
|
+
}, z.core.$strip>]>>;
|
|
331
|
+
openapi: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
|
|
332
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
333
|
+
title: z.ZodOptional<z.ZodString>;
|
|
334
|
+
version: z.ZodOptional<z.ZodString>;
|
|
335
|
+
description: z.ZodOptional<z.ZodString>;
|
|
336
|
+
}, z.core.$strip>]>>;
|
|
337
|
+
runtime: z.ZodOptional<z.ZodEnum<{
|
|
338
|
+
node: "node";
|
|
339
|
+
bun: "bun";
|
|
340
|
+
}>>;
|
|
341
|
+
env: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodArray<z.ZodString>]>>;
|
|
342
|
+
framework: z.ZodOptional<z.ZodEnum<{
|
|
343
|
+
nextjs: "nextjs";
|
|
344
|
+
}>>;
|
|
345
|
+
client: z.ZodOptional<z.ZodObject<{
|
|
346
|
+
output: z.ZodOptional<z.ZodString>;
|
|
347
|
+
}, z.core.$strip>>;
|
|
348
|
+
}, z.core.$strip>>;
|
|
349
|
+
shared: z.ZodOptional<z.ZodObject<{
|
|
350
|
+
packages: z.ZodOptional<z.ZodArray<z.ZodString>>;
|
|
351
|
+
models: z.ZodOptional<z.ZodObject<{
|
|
352
|
+
path: z.ZodOptional<z.ZodString>;
|
|
353
|
+
schema: z.ZodOptional<z.ZodEnum<{
|
|
354
|
+
zod: "zod";
|
|
355
|
+
}>>;
|
|
356
|
+
}, z.core.$strip>>;
|
|
357
|
+
}, z.core.$strip>>;
|
|
358
|
+
deploy: z.ZodOptional<z.ZodObject<{
|
|
359
|
+
default: z.ZodOptional<z.ZodEnum<{
|
|
360
|
+
dokploy: "dokploy";
|
|
361
|
+
vercel: "vercel";
|
|
362
|
+
cloudflare: "cloudflare";
|
|
363
|
+
}>>;
|
|
364
|
+
dokploy: z.ZodOptional<z.ZodObject<{
|
|
365
|
+
endpoint: z.ZodURL;
|
|
366
|
+
projectId: z.ZodString;
|
|
367
|
+
registry: z.ZodOptional<z.ZodString>;
|
|
368
|
+
registryId: z.ZodOptional<z.ZodString>;
|
|
369
|
+
}, z.core.$strip>>;
|
|
370
|
+
}, z.core.$strip>>;
|
|
371
|
+
services: z.ZodOptional<z.ZodObject<{
|
|
372
|
+
db: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
|
|
373
|
+
version: z.ZodOptional<z.ZodString>;
|
|
374
|
+
image: z.ZodOptional<z.ZodString>;
|
|
375
|
+
}, z.core.$strip>]>>;
|
|
376
|
+
cache: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
|
|
377
|
+
version: z.ZodOptional<z.ZodString>;
|
|
378
|
+
image: z.ZodOptional<z.ZodString>;
|
|
379
|
+
}, z.core.$strip>]>>;
|
|
380
|
+
mail: z.ZodOptional<z.ZodUnion<readonly [z.ZodBoolean, z.ZodObject<{
|
|
381
|
+
version: z.ZodOptional<z.ZodString>;
|
|
382
|
+
image: z.ZodOptional<z.ZodString>;
|
|
383
|
+
smtp: z.ZodOptional<z.ZodObject<{
|
|
384
|
+
host: z.ZodString;
|
|
385
|
+
port: z.ZodNumber;
|
|
386
|
+
user: z.ZodOptional<z.ZodString>;
|
|
387
|
+
pass: z.ZodOptional<z.ZodString>;
|
|
388
|
+
}, z.core.$strip>>;
|
|
389
|
+
}, z.core.$strip>]>>;
|
|
390
|
+
}, z.core.$strip>>;
|
|
391
|
+
secrets: z.ZodOptional<z.ZodObject<{
|
|
392
|
+
enabled: z.ZodOptional<z.ZodBoolean>;
|
|
393
|
+
algorithm: z.ZodOptional<z.ZodString>;
|
|
394
|
+
kdf: z.ZodOptional<z.ZodEnum<{
|
|
395
|
+
scrypt: "scrypt";
|
|
396
|
+
pbkdf2: "pbkdf2";
|
|
397
|
+
}>>;
|
|
398
|
+
}, z.core.$strip>>;
|
|
399
|
+
}, z.core.$strip>;
|
|
400
|
+
/**
|
|
401
|
+
* Validate workspace configuration.
|
|
402
|
+
* Throws ZodError with detailed messages on validation failure.
|
|
403
|
+
*/
|
|
404
|
+
declare function validateWorkspaceConfig(config: unknown): z.infer<typeof WorkspaceConfigSchema>;
|
|
405
|
+
/**
|
|
406
|
+
* Safe validation that returns result instead of throwing.
|
|
407
|
+
*/
|
|
408
|
+
declare function safeValidateWorkspaceConfig(config: unknown): {
|
|
409
|
+
success: boolean;
|
|
410
|
+
data?: z.infer<typeof WorkspaceConfigSchema>;
|
|
411
|
+
error?: z.ZodError;
|
|
412
|
+
};
|
|
413
|
+
/**
|
|
414
|
+
* Format Zod errors into user-friendly messages.
|
|
415
|
+
*/
|
|
416
|
+
declare function formatValidationErrors(error: z.ZodError): string;
|
|
417
|
+
//#endregion
|
|
418
|
+
//#region src/workspace/index.d.ts
|
|
419
|
+
/**
|
|
420
|
+
* Define workspace configuration with full TypeScript support and type inference.
|
|
421
|
+
*
|
|
422
|
+
* Uses `const` type parameter to infer literal app names, providing:
|
|
423
|
+
* - Autocomplete for app names in dependencies
|
|
424
|
+
* - Type errors for invalid dependency references
|
|
425
|
+
* - Full type inference for the returned config
|
|
426
|
+
*
|
|
427
|
+
* @example
|
|
428
|
+
* ```ts
|
|
429
|
+
* // gkm.config.ts
|
|
430
|
+
* import { defineWorkspace } from '@geekmidas/cli';
|
|
431
|
+
*
|
|
432
|
+
* export default defineWorkspace({
|
|
433
|
+
* name: 'my-saas',
|
|
434
|
+
* apps: {
|
|
435
|
+
* api: {
|
|
436
|
+
* type: 'backend',
|
|
437
|
+
* path: 'apps/api',
|
|
438
|
+
* port: 3000,
|
|
439
|
+
* routes: './src/endpoints/**\/*.ts',
|
|
440
|
+
* envParser: './src/config/env',
|
|
441
|
+
* logger: './src/logger',
|
|
442
|
+
* },
|
|
443
|
+
* web: {
|
|
444
|
+
* type: 'frontend',
|
|
445
|
+
* framework: 'nextjs',
|
|
446
|
+
* path: 'apps/web',
|
|
447
|
+
* port: 3001,
|
|
448
|
+
* dependencies: ['api'], // <- autocomplete shows 'api' | 'web'
|
|
449
|
+
* },
|
|
450
|
+
* },
|
|
451
|
+
* services: {
|
|
452
|
+
* db: true,
|
|
453
|
+
* cache: true,
|
|
454
|
+
* },
|
|
455
|
+
* });
|
|
456
|
+
*
|
|
457
|
+
* // config.apps.api <- full type inference
|
|
458
|
+
* // config.apps.foo <- TypeScript error
|
|
459
|
+
* ```
|
|
460
|
+
*/
|
|
461
|
+
declare function defineWorkspace<const TApps extends AppsRecord>(config: WorkspaceInput<TApps>): InferredWorkspaceConfig<TApps>;
|
|
462
|
+
/**
|
|
463
|
+
* Normalize a workspace configuration with resolved defaults.
|
|
464
|
+
*/
|
|
465
|
+
declare function normalizeWorkspace(config: WorkspaceConfig, cwd: string): NormalizedWorkspace;
|
|
466
|
+
/**
|
|
467
|
+
* Wrap a single-app GkmConfig as a workspace.
|
|
468
|
+
* This allows existing single-app configs to work seamlessly.
|
|
469
|
+
*/
|
|
470
|
+
declare function wrapSingleAppAsWorkspace(config: GkmConfig, cwd: string): NormalizedWorkspace;
|
|
471
|
+
/**
|
|
472
|
+
* Process a loaded configuration (either single-app or workspace).
|
|
473
|
+
* Returns a normalized workspace in both cases.
|
|
474
|
+
*/
|
|
475
|
+
declare function processConfig(config: GkmConfig | WorkspaceConfig, cwd: string): LoadedConfig;
|
|
476
|
+
/**
|
|
477
|
+
* Get the GkmConfig for a specific app in a workspace.
|
|
478
|
+
* Useful for running existing single-app commands on a specific app.
|
|
479
|
+
*/
|
|
480
|
+
declare function getAppGkmConfig(workspace: NormalizedWorkspace, appName: string): GkmConfig | undefined;
|
|
481
|
+
/**
|
|
482
|
+
* Get topologically sorted app names based on dependencies.
|
|
483
|
+
* Apps with no dependencies come first, then apps that depend on them.
|
|
484
|
+
*/
|
|
485
|
+
declare function getAppBuildOrder(workspace: NormalizedWorkspace): string[];
|
|
486
|
+
/**
|
|
487
|
+
* Generate environment variables for app dependencies.
|
|
488
|
+
* Each dependency gets a {DEP_NAME}_URL variable.
|
|
489
|
+
*/
|
|
490
|
+
declare function getDependencyEnvVars(workspace: NormalizedWorkspace, appName: string, urlPrefix?: string): Record<string, string>;
|
|
491
|
+
//# sourceMappingURL=index.d.ts.map
|
|
492
|
+
|
|
493
|
+
//#endregion
|
|
494
|
+
export { AppConfig, AppConfigInput, AppInput, AppsRecord, ClientConfig, ConstrainedApps, DeployConfig, DeployTarget, DokployWorkspaceConfig, InferAppNames, InferredWorkspaceConfig, LoadedConfig, MailServiceConfig, ModelsConfig, NormalizedAppConfig, NormalizedWorkspace, PHASE_2_DEPLOY_TARGETS, SUPPORTED_DEPLOY_TARGETS, SecretsConfig, ServiceImageConfig, ServicesConfig, SharedConfig, WorkspaceConfig, WorkspaceConfigSchema, WorkspaceInput, defineWorkspace, formatValidationErrors, getAppBuildOrder, getAppGkmConfig, getDependencyEnvVars, getDeployTargetError, isDeployTargetSupported, isPhase2DeployTarget, isWorkspaceConfig, normalizeWorkspace, processConfig, safeValidateWorkspaceConfig, validateWorkspaceConfig, wrapSingleAppAsWorkspace };
|
|
495
|
+
//# sourceMappingURL=index-CWN-bgrO.d.mts.map
|