@geekmidas/cli 1.10.8 → 1.10.10
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/CHANGELOG.md +12 -0
- package/dist/{bundler-NpfYPBUo.cjs → bundler-Bm3Az_sv.cjs} +2 -2
- package/dist/{bundler-NpfYPBUo.cjs.map → bundler-Bm3Az_sv.cjs.map} +1 -1
- package/dist/{bundler-DQYjKFPm.mjs → bundler-kk_XJTRp.mjs} +2 -2
- package/dist/{bundler-DQYjKFPm.mjs.map → bundler-kk_XJTRp.mjs.map} +1 -1
- package/dist/config.d.cts +2 -2
- package/dist/config.d.mts +2 -2
- package/dist/{fullstack-secrets-BctGaE4E.cjs → fullstack-secrets-BC9t9wWB.cjs} +27 -1
- package/dist/fullstack-secrets-BC9t9wWB.cjs.map +1 -0
- package/dist/{fullstack-secrets-ca0Kyrvt.mjs → fullstack-secrets-DmUOfLeX.mjs} +16 -2
- package/dist/fullstack-secrets-DmUOfLeX.mjs.map +1 -0
- package/dist/{index-9tjTQjFt.d.mts → index-BdJZKXCJ.d.cts} +4 -2
- package/dist/index-BdJZKXCJ.d.cts.map +1 -0
- package/dist/{index-VOKKO-lm.d.cts → index-DB9VbcCD.d.mts} +4 -2
- package/dist/index-DB9VbcCD.d.mts.map +1 -0
- package/dist/index.cjs +174 -49
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +174 -49
- package/dist/index.mjs.map +1 -1
- package/dist/openapi-BYxAWwok.cjs.map +1 -1
- package/dist/openapi-DenF-okj.mjs.map +1 -1
- package/dist/openapi.d.cts +1 -1
- package/dist/openapi.d.mts +1 -1
- package/dist/{reconcile-TEBsryVn.cjs → reconcile-BZ8j_-0z.cjs} +2 -2
- package/dist/{reconcile-TEBsryVn.cjs.map → reconcile-BZ8j_-0z.cjs.map} +1 -1
- package/dist/{reconcile-C5OyCA7V.mjs → reconcile-C0dsg-Gq.mjs} +2 -2
- package/dist/{reconcile-C5OyCA7V.mjs.map → reconcile-C0dsg-Gq.mjs.map} +1 -1
- package/dist/{storage-DmCbr6DI.mjs → storage-B7H2PPCS.mjs} +8 -1
- package/dist/{storage-DmCbr6DI.mjs.map → storage-B7H2PPCS.mjs.map} +1 -1
- package/dist/{storage-Dx_jZbq6.mjs → storage-C1FNm2EP.mjs} +1 -1
- package/dist/{storage-CoCNe0Pt.cjs → storage-Cs13jkJ9.cjs} +8 -1
- package/dist/{storage-CoCNe0Pt.cjs.map → storage-Cs13jkJ9.cjs.map} +1 -1
- package/dist/{storage-C7pmBq1u.cjs → storage-D6BGLgWf.cjs} +1 -1
- package/dist/{sync-6FoT41G3.mjs → sync-CyGe5f1I.mjs} +1 -1
- package/dist/{sync-CbeKrnQV.mjs → sync-CzXruMzP.mjs} +2 -2
- package/dist/{sync-CbeKrnQV.mjs.map → sync-CzXruMzP.mjs.map} +1 -1
- package/dist/sync-DLlwsrBs.cjs +4 -0
- package/dist/{sync-DdkKaHqP.cjs → sync-oCqELfeA.cjs} +2 -2
- package/dist/{sync-DdkKaHqP.cjs.map → sync-oCqELfeA.cjs.map} +1 -1
- package/dist/{types-C7QJJl9f.d.cts → types-D4MLWXSL.d.cts} +2 -2
- package/dist/{types-C7QJJl9f.d.cts.map → types-D4MLWXSL.d.cts.map} +1 -1
- package/dist/{types-Iqsq_FIG.d.mts → types-DwpLq_fp.d.mts} +2 -2
- package/dist/{types-Iqsq_FIG.d.mts.map → types-DwpLq_fp.d.mts.map} +1 -1
- package/dist/workspace/index.d.cts +2 -2
- package/dist/workspace/index.d.mts +2 -2
- package/dist/workspace-4SP3Gx4Y.cjs.map +1 -1
- package/dist/workspace-D4z4A4cq.mjs.map +1 -1
- package/package.json +3 -3
- package/src/dev/__tests__/index.spec.ts +73 -0
- package/src/dev/index.ts +42 -26
- package/src/docker/__tests__/compose.spec.ts +145 -1
- package/src/docker/compose.ts +97 -5
- package/src/init/index.ts +1 -0
- package/src/init/versions.ts +1 -1
- package/src/secrets/__tests__/generator.spec.ts +68 -0
- package/src/secrets/__tests__/storage.spec.ts +30 -0
- package/src/secrets/generator.ts +18 -0
- package/src/secrets/index.ts +9 -0
- package/src/secrets/storage.ts +7 -0
- package/src/secrets/types.ts +4 -0
- package/src/setup/__tests__/reconcile-secrets.spec.ts +59 -0
- package/src/setup/index.ts +52 -16
- package/src/types.ts +1 -1
- package/src/workspace/types.ts +2 -0
- package/dist/fullstack-secrets-BctGaE4E.cjs.map +0 -1
- package/dist/fullstack-secrets-ca0Kyrvt.mjs.map +0 -1
- package/dist/index-9tjTQjFt.d.mts.map +0 -1
- package/dist/index-VOKKO-lm.d.cts.map +0 -1
- package/dist/sync-RsnjXYwG.cjs +0 -4
package/dist/index.mjs
CHANGED
|
@@ -4,13 +4,13 @@ import { getAppBuildOrder, getDependencyEnvVars, getDeployTargetError, isDeployT
|
|
|
4
4
|
import { getAppNameFromCwd, loadAppConfig, loadConfig, loadWorkspaceAppInfo, loadWorkspaceConfig, parseModuleConfig } from "./config-jsRYHOHU.mjs";
|
|
5
5
|
import { getCredentialsPath, getDokployCredentials, getDokployRegistryId, getDokployToken, removeDokployCredentials, storeDokployCredentials, storeDokployRegistryId } from "./credentials-s1kLcIzK.mjs";
|
|
6
6
|
import { ConstructGenerator, EndpointGenerator, OPENAPI_OUTPUT_PATH, copyAllClients, copyClientToFrontends, generateOpenApi, getBackendOpenApiPath, isPartitionedRoutes, normalizeRoutes, openapiCommand, resolveOpenApiConfig } from "./openapi-DenF-okj.mjs";
|
|
7
|
-
import { getKeyPath, maskPassword, readStageSecrets, secretsExist, setCustomSecret, toEmbeddableSecrets, writeStageSecrets } from "./storage-
|
|
7
|
+
import { getKeyPath, maskPassword, readStageSecrets, secretsExist, setCustomSecret, toEmbeddableSecrets, writeStageSecrets } from "./storage-B7H2PPCS.mjs";
|
|
8
8
|
import { DokployApi } from "./dokploy-api-2ldYoN3i.mjs";
|
|
9
9
|
import { encryptSecrets } from "./encryption-BOH5M-f-.mjs";
|
|
10
10
|
import { CachedStateProvider } from "./CachedStateProvider-BDq5WqSy.mjs";
|
|
11
|
-
import { createStageSecrets, generateDbPassword, generateDbUrl, generateFullstackCustomSecrets, rotateServicePassword, writeDockerEnvFromSecrets } from "./fullstack-secrets-
|
|
11
|
+
import { createStageSecrets, generateConnectionUrls, generateDbPassword, generateDbUrl, generateFullstackCustomSecrets, generateServiceCredentials, rotateServicePassword, writeDockerEnvFromSecrets } from "./fullstack-secrets-DmUOfLeX.mjs";
|
|
12
12
|
import { generateReactQueryCommand } from "./openapi-react-query-C4UdILaI.mjs";
|
|
13
|
-
import { isSSMConfigured, pullSecrets, pushSecrets } from "./sync-
|
|
13
|
+
import { isSSMConfigured, pullSecrets, pushSecrets } from "./sync-CzXruMzP.mjs";
|
|
14
14
|
import { createRequire } from "node:module";
|
|
15
15
|
import { copyFileSync, existsSync, readFileSync, unlinkSync } from "node:fs";
|
|
16
16
|
import { basename, dirname, join, parse, relative, resolve } from "node:path";
|
|
@@ -35,7 +35,7 @@ import prompts from "prompts";
|
|
|
35
35
|
|
|
36
36
|
//#region package.json
|
|
37
37
|
var name = "@geekmidas/cli";
|
|
38
|
-
var version = "1.10.
|
|
38
|
+
var version = "1.10.9";
|
|
39
39
|
var description = "CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs";
|
|
40
40
|
var private$1 = false;
|
|
41
41
|
var type = "module";
|
|
@@ -767,25 +767,30 @@ async function resolveServicePorts(workspaceRoot) {
|
|
|
767
767
|
const savedState = await loadPortState(workspaceRoot);
|
|
768
768
|
const dockerEnv = {};
|
|
769
769
|
const ports = {};
|
|
770
|
+
const assignedPorts = /* @__PURE__ */ new Set();
|
|
770
771
|
logger$11.log("\n🔌 Resolving service ports...");
|
|
771
772
|
for (const mapping of mappings) {
|
|
772
773
|
const containerPort = getContainerHostPort(workspaceRoot, mapping.service, mapping.containerPort);
|
|
773
774
|
if (containerPort !== null) {
|
|
774
775
|
ports[mapping.envVar] = containerPort;
|
|
775
776
|
dockerEnv[mapping.envVar] = String(containerPort);
|
|
777
|
+
assignedPorts.add(containerPort);
|
|
776
778
|
logger$11.log(` 🔄 ${mapping.service}:${mapping.containerPort}: reusing existing container on port ${containerPort}`);
|
|
777
779
|
continue;
|
|
778
780
|
}
|
|
779
781
|
const savedPort = savedState[mapping.envVar];
|
|
780
|
-
if (savedPort && await isPortAvailable(savedPort)) {
|
|
782
|
+
if (savedPort && !assignedPorts.has(savedPort) && await isPortAvailable(savedPort)) {
|
|
781
783
|
ports[mapping.envVar] = savedPort;
|
|
782
784
|
dockerEnv[mapping.envVar] = String(savedPort);
|
|
785
|
+
assignedPorts.add(savedPort);
|
|
783
786
|
logger$11.log(` 💾 ${mapping.service}:${mapping.containerPort}: using saved port ${savedPort}`);
|
|
784
787
|
continue;
|
|
785
788
|
}
|
|
786
|
-
|
|
789
|
+
let resolvedPort = await findAvailablePort(mapping.defaultPort);
|
|
790
|
+
while (assignedPorts.has(resolvedPort)) resolvedPort = await findAvailablePort(resolvedPort + 1);
|
|
787
791
|
ports[mapping.envVar] = resolvedPort;
|
|
788
792
|
dockerEnv[mapping.envVar] = String(resolvedPort);
|
|
793
|
+
assignedPorts.add(resolvedPort);
|
|
789
794
|
if (resolvedPort !== mapping.defaultPort) logger$11.log(` ⚡ ${mapping.service}:${mapping.containerPort}: port ${mapping.defaultPort} occupied, using port ${resolvedPort}`);
|
|
790
795
|
else logger$11.log(` ✅ ${mapping.service}:${mapping.containerPort}: using default port ${resolvedPort}`);
|
|
791
796
|
}
|
|
@@ -1235,26 +1240,31 @@ function buildDockerComposeEnv(secretsEnv, portEnv) {
|
|
|
1235
1240
|
};
|
|
1236
1241
|
}
|
|
1237
1242
|
/**
|
|
1243
|
+
* Parse all service names from a docker-compose.yml file.
|
|
1244
|
+
* @internal Exported for testing
|
|
1245
|
+
*/
|
|
1246
|
+
function parseComposeServiceNames(composePath) {
|
|
1247
|
+
if (!existsSync(composePath)) return [];
|
|
1248
|
+
const content = readFileSync(composePath, "utf-8");
|
|
1249
|
+
const compose = parse$1(content);
|
|
1250
|
+
return Object.keys(compose?.services ?? {});
|
|
1251
|
+
}
|
|
1252
|
+
/**
|
|
1238
1253
|
* Start docker-compose services for the workspace.
|
|
1239
|
-
*
|
|
1240
|
-
*
|
|
1254
|
+
* Parses the docker-compose.yml to discover all services and starts
|
|
1255
|
+
* everything except app services (which are managed by turbo).
|
|
1256
|
+
* This ensures manually added services are always started.
|
|
1241
1257
|
* @internal Exported for testing
|
|
1242
1258
|
*/
|
|
1243
1259
|
async function startWorkspaceServices(workspace, portEnv, secretsEnv) {
|
|
1244
|
-
const
|
|
1245
|
-
if (!
|
|
1246
|
-
const
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
if (services.mail) servicesToStart.push("mailpit");
|
|
1260
|
+
const composeFile = join(workspace.root, "docker-compose.yml");
|
|
1261
|
+
if (!existsSync(composeFile)) return;
|
|
1262
|
+
const allServices = parseComposeServiceNames(composeFile);
|
|
1263
|
+
const appNames = new Set(Object.keys(workspace.apps));
|
|
1264
|
+
const servicesToStart = allServices.filter((name$1) => !appNames.has(name$1));
|
|
1250
1265
|
if (servicesToStart.length === 0) return;
|
|
1251
1266
|
logger$11.log(`🐳 Starting services: ${servicesToStart.join(", ")}`);
|
|
1252
1267
|
try {
|
|
1253
|
-
const composeFile = join(workspace.root, "docker-compose.yml");
|
|
1254
|
-
if (!existsSync(composeFile)) {
|
|
1255
|
-
logger$11.warn("⚠️ No docker-compose.yml found. Services will not be started.");
|
|
1256
|
-
return;
|
|
1257
|
-
}
|
|
1258
1268
|
execSync(`docker compose up -d ${servicesToStart.join(" ")}`, {
|
|
1259
1269
|
cwd: workspace.root,
|
|
1260
1270
|
stdio: "inherit",
|
|
@@ -2188,7 +2198,7 @@ async function buildForProvider(provider, context, rootOutputDir, endpointGenera
|
|
|
2188
2198
|
let masterKey;
|
|
2189
2199
|
if (context.production?.bundle && !skipBundle) {
|
|
2190
2200
|
logger$9.log(`\n📦 Bundling production server...`);
|
|
2191
|
-
const { bundleServer } = await import("./bundler-
|
|
2201
|
+
const { bundleServer } = await import("./bundler-kk_XJTRp.mjs");
|
|
2192
2202
|
const allConstructs = [
|
|
2193
2203
|
...endpoints.map((e) => e.construct),
|
|
2194
2204
|
...functions.map((f) => f.construct),
|
|
@@ -2850,13 +2860,15 @@ async function verifyDnsRecords(appHostnames, serverIp, state) {
|
|
|
2850
2860
|
const DEFAULT_SERVICE_IMAGES = {
|
|
2851
2861
|
postgres: "postgres",
|
|
2852
2862
|
redis: "redis",
|
|
2853
|
-
rabbitmq: "rabbitmq"
|
|
2863
|
+
rabbitmq: "rabbitmq",
|
|
2864
|
+
minio: "minio/minio"
|
|
2854
2865
|
};
|
|
2855
2866
|
/** Default Docker image versions for services */
|
|
2856
2867
|
const DEFAULT_SERVICE_VERSIONS = {
|
|
2857
2868
|
postgres: "18-alpine",
|
|
2858
2869
|
redis: "7-alpine",
|
|
2859
|
-
rabbitmq: "3-management-alpine"
|
|
2870
|
+
rabbitmq: "3-management-alpine",
|
|
2871
|
+
minio: "latest"
|
|
2860
2872
|
};
|
|
2861
2873
|
/** Get the default full image reference for a service */
|
|
2862
2874
|
function getDefaultImage(serviceName) {
|
|
@@ -2909,6 +2921,13 @@ services:
|
|
|
2909
2921
|
if (serviceMap.has("redis")) yaml += ` - REDIS_URL=\${REDIS_URL:-redis://redis:6379}
|
|
2910
2922
|
`;
|
|
2911
2923
|
if (serviceMap.has("rabbitmq")) yaml += ` - RABBITMQ_URL=\${RABBITMQ_URL:-amqp://rabbitmq:5672}
|
|
2924
|
+
`;
|
|
2925
|
+
if (serviceMap.has("minio")) yaml += ` - S3_ENDPOINT=\${S3_ENDPOINT:-http://minio:9000}
|
|
2926
|
+
- S3_ACCESS_KEY_ID=\${MINIO_ACCESS_KEY:-app}
|
|
2927
|
+
- S3_SECRET_ACCESS_KEY=\${MINIO_SECRET_KEY:-app}
|
|
2928
|
+
- S3_BUCKET=\${MINIO_BUCKET:-app}
|
|
2929
|
+
- S3_REGION=\${S3_REGION:-eu-west-1}
|
|
2930
|
+
- S3_FORCE_PATH_STYLE=true
|
|
2912
2931
|
`;
|
|
2913
2932
|
yaml += ` healthcheck:
|
|
2914
2933
|
test: ["CMD", "wget", "-q", "--spider", "http://localhost:${port}${healthCheckPath}"]
|
|
@@ -2982,6 +3001,29 @@ services:
|
|
|
2982
3001
|
retries: 5
|
|
2983
3002
|
networks:
|
|
2984
3003
|
- app-network
|
|
3004
|
+
`;
|
|
3005
|
+
const minioImage = serviceMap.get("minio");
|
|
3006
|
+
if (minioImage) yaml += `
|
|
3007
|
+
minio:
|
|
3008
|
+
image: ${minioImage}
|
|
3009
|
+
container_name: minio
|
|
3010
|
+
restart: unless-stopped
|
|
3011
|
+
entrypoint: sh
|
|
3012
|
+
command: -c 'mkdir -p /data/\${MINIO_BUCKET:-app} && /usr/bin/docker-entrypoint.sh server --console-address ":9001" /data'
|
|
3013
|
+
environment:
|
|
3014
|
+
MINIO_ROOT_USER: \${MINIO_ACCESS_KEY:-app}
|
|
3015
|
+
MINIO_ROOT_PASSWORD: \${MINIO_SECRET_KEY:-app}
|
|
3016
|
+
ports:
|
|
3017
|
+
- "9001:9001" # Console UI
|
|
3018
|
+
volumes:
|
|
3019
|
+
- minio_data:/data
|
|
3020
|
+
healthcheck:
|
|
3021
|
+
test: ["CMD", "mc", "ready", "local"]
|
|
3022
|
+
interval: 10s
|
|
3023
|
+
timeout: 5s
|
|
3024
|
+
retries: 5
|
|
3025
|
+
networks:
|
|
3026
|
+
- app-network
|
|
2985
3027
|
`;
|
|
2986
3028
|
yaml += `
|
|
2987
3029
|
volumes:
|
|
@@ -2991,6 +3033,8 @@ volumes:
|
|
|
2991
3033
|
if (serviceMap.has("redis")) yaml += ` redis_data:
|
|
2992
3034
|
`;
|
|
2993
3035
|
if (serviceMap.has("rabbitmq")) yaml += ` rabbitmq_data:
|
|
3036
|
+
`;
|
|
3037
|
+
if (serviceMap.has("minio")) yaml += ` minio_data:
|
|
2994
3038
|
`;
|
|
2995
3039
|
yaml += `
|
|
2996
3040
|
networks:
|
|
@@ -3046,8 +3090,10 @@ function generateWorkspaceCompose(workspace, options = {}) {
|
|
|
3046
3090
|
const hasPostgres = services.db !== void 0 && services.db !== false;
|
|
3047
3091
|
const hasRedis = services.cache !== void 0 && services.cache !== false;
|
|
3048
3092
|
const hasMail = services.mail !== void 0 && services.mail !== false;
|
|
3093
|
+
const hasMinio = services.storage !== void 0 && services.storage !== false;
|
|
3049
3094
|
const postgresImage = getInfraServiceImage("postgres", services.db);
|
|
3050
3095
|
const redisImage = getInfraServiceImage("redis", services.cache);
|
|
3096
|
+
const minioImage = getInfraServiceImage("minio", services.storage);
|
|
3051
3097
|
let yaml = `# Docker Compose for ${workspace.name} workspace
|
|
3052
3098
|
# Use "gkm dev" or "gkm test" to start services.
|
|
3053
3099
|
# Running "docker compose up" directly will not inject secrets or resolve ports.
|
|
@@ -3057,7 +3103,8 @@ services:
|
|
|
3057
3103
|
for (const [appName, app] of apps) yaml += generateAppService(appName, app, apps, {
|
|
3058
3104
|
registry,
|
|
3059
3105
|
hasPostgres,
|
|
3060
|
-
hasRedis
|
|
3106
|
+
hasRedis,
|
|
3107
|
+
hasMinio
|
|
3061
3108
|
});
|
|
3062
3109
|
if (hasPostgres) yaml += `
|
|
3063
3110
|
postgres:
|
|
@@ -3103,6 +3150,28 @@ services:
|
|
|
3103
3150
|
- "1025:1025" # SMTP
|
|
3104
3151
|
networks:
|
|
3105
3152
|
- workspace-network
|
|
3153
|
+
`;
|
|
3154
|
+
if (hasMinio) yaml += `
|
|
3155
|
+
minio:
|
|
3156
|
+
image: ${minioImage}
|
|
3157
|
+
container_name: ${workspace.name}-minio
|
|
3158
|
+
restart: unless-stopped
|
|
3159
|
+
entrypoint: sh
|
|
3160
|
+
command: -c 'mkdir -p /data/\${MINIO_BUCKET:-app} && /usr/bin/docker-entrypoint.sh server --console-address ":9001" /data'
|
|
3161
|
+
environment:
|
|
3162
|
+
MINIO_ROOT_USER: \${MINIO_ACCESS_KEY:-app}
|
|
3163
|
+
MINIO_ROOT_PASSWORD: \${MINIO_SECRET_KEY:-app}
|
|
3164
|
+
ports:
|
|
3165
|
+
- "9001:9001" # Console UI
|
|
3166
|
+
volumes:
|
|
3167
|
+
- minio_data:/data
|
|
3168
|
+
healthcheck:
|
|
3169
|
+
test: ["CMD", "mc", "ready", "local"]
|
|
3170
|
+
interval: 10s
|
|
3171
|
+
timeout: 5s
|
|
3172
|
+
retries: 5
|
|
3173
|
+
networks:
|
|
3174
|
+
- workspace-network
|
|
3106
3175
|
`;
|
|
3107
3176
|
yaml += `
|
|
3108
3177
|
volumes:
|
|
@@ -3110,6 +3179,8 @@ volumes:
|
|
|
3110
3179
|
if (hasPostgres) yaml += ` dbdata:
|
|
3111
3180
|
`;
|
|
3112
3181
|
if (hasRedis) yaml += ` redis_data:
|
|
3182
|
+
`;
|
|
3183
|
+
if (hasMinio) yaml += ` minio_data:
|
|
3113
3184
|
`;
|
|
3114
3185
|
yaml += `
|
|
3115
3186
|
networks:
|
|
@@ -3124,14 +3195,19 @@ networks:
|
|
|
3124
3195
|
function getInfraServiceImage(serviceName, config$1) {
|
|
3125
3196
|
const defaults = {
|
|
3126
3197
|
postgres: "postgres:18-alpine",
|
|
3127
|
-
redis: "redis:7-alpine"
|
|
3198
|
+
redis: "redis:7-alpine",
|
|
3199
|
+
minio: "minio/minio:latest"
|
|
3128
3200
|
};
|
|
3129
3201
|
if (!config$1 || config$1 === true) return defaults[serviceName];
|
|
3130
3202
|
if (typeof config$1 === "object") {
|
|
3131
3203
|
if (config$1.image) return config$1.image;
|
|
3132
3204
|
if (config$1.version) {
|
|
3133
|
-
const
|
|
3134
|
-
|
|
3205
|
+
const baseImages = {
|
|
3206
|
+
postgres: "postgres",
|
|
3207
|
+
redis: "redis",
|
|
3208
|
+
minio: "minio/minio"
|
|
3209
|
+
};
|
|
3210
|
+
return `${baseImages[serviceName]}:${config$1.version}`;
|
|
3135
3211
|
}
|
|
3136
3212
|
}
|
|
3137
3213
|
return defaults[serviceName];
|
|
@@ -3140,7 +3216,7 @@ function getInfraServiceImage(serviceName, config$1) {
|
|
|
3140
3216
|
* Generate a service definition for an app.
|
|
3141
3217
|
*/
|
|
3142
3218
|
function generateAppService(appName, app, allApps, options) {
|
|
3143
|
-
const { registry, hasPostgres, hasRedis } = options;
|
|
3219
|
+
const { registry, hasPostgres, hasRedis, hasMinio } = options;
|
|
3144
3220
|
const imageRef = registry ? `\${REGISTRY:-${registry}}/` : "";
|
|
3145
3221
|
const healthCheckPath = app.type === "frontend" ? "/" : "/health";
|
|
3146
3222
|
const healthCheckCmd = app.type === "frontend" ? `["CMD", "wget", "-q", "--spider", "http://localhost:${app.port}/"]` : `["CMD", "wget", "-q", "--spider", "http://localhost:${app.port}${healthCheckPath}"]`;
|
|
@@ -3167,6 +3243,13 @@ function generateAppService(appName, app, allApps, options) {
|
|
|
3167
3243
|
if (hasPostgres) yaml += ` - DATABASE_URL=\${DATABASE_URL:-postgresql://\${POSTGRES_USER:-postgres}:\${POSTGRES_PASSWORD:-postgres}@postgres:5432/\${POSTGRES_DB:-app}}
|
|
3168
3244
|
`;
|
|
3169
3245
|
if (hasRedis) yaml += ` - REDIS_URL=\${REDIS_URL:-redis://redis:6379}
|
|
3246
|
+
`;
|
|
3247
|
+
if (hasMinio) yaml += ` - S3_ENDPOINT=\${S3_ENDPOINT:-http://minio:9000}
|
|
3248
|
+
- S3_ACCESS_KEY_ID=\${MINIO_ACCESS_KEY:-app}
|
|
3249
|
+
- S3_SECRET_ACCESS_KEY=\${MINIO_SECRET_KEY:-app}
|
|
3250
|
+
- S3_BUCKET=\${MINIO_BUCKET:-app}
|
|
3251
|
+
- S3_REGION=\${S3_REGION:-eu-west-1}
|
|
3252
|
+
- S3_FORCE_PATH_STYLE=true
|
|
3170
3253
|
`;
|
|
3171
3254
|
}
|
|
3172
3255
|
yaml += ` healthcheck:
|
|
@@ -3179,6 +3262,7 @@ function generateAppService(appName, app, allApps, options) {
|
|
|
3179
3262
|
if (app.type === "backend") {
|
|
3180
3263
|
if (hasPostgres) dependencies$1.push("postgres");
|
|
3181
3264
|
if (hasRedis) dependencies$1.push("redis");
|
|
3265
|
+
if (hasMinio) dependencies$1.push("minio");
|
|
3182
3266
|
}
|
|
3183
3267
|
if (dependencies$1.length > 0) {
|
|
3184
3268
|
yaml += ` depends_on:
|
|
@@ -6223,7 +6307,7 @@ async function deployCommand(options) {
|
|
|
6223
6307
|
dokployConfig = setupResult.config;
|
|
6224
6308
|
finalRegistry = dokployConfig.registry ?? dockerConfig.registry;
|
|
6225
6309
|
if (setupResult.serviceUrls) {
|
|
6226
|
-
const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1, initStageSecrets } = await import("./storage-
|
|
6310
|
+
const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1, initStageSecrets } = await import("./storage-C1FNm2EP.mjs");
|
|
6227
6311
|
let secrets = await readStageSecrets$1(stage);
|
|
6228
6312
|
if (!secrets) {
|
|
6229
6313
|
logger$3.log(` Creating secrets file for stage "${stage}"...`);
|
|
@@ -6520,7 +6604,7 @@ const GEEKMIDAS_VERSIONS = {
|
|
|
6520
6604
|
"@geekmidas/storage": "~2.0.0",
|
|
6521
6605
|
"@geekmidas/studio": "~1.0.0",
|
|
6522
6606
|
"@geekmidas/telescope": "~1.0.0",
|
|
6523
|
-
"@geekmidas/testkit": "~1.0.
|
|
6607
|
+
"@geekmidas/testkit": "~1.0.5",
|
|
6524
6608
|
"@geekmidas/cli": CLI_VERSION
|
|
6525
6609
|
};
|
|
6526
6610
|
|
|
@@ -10888,6 +10972,7 @@ async function initCommand(projectName, options = {}) {
|
|
|
10888
10972
|
const secretServices = [];
|
|
10889
10973
|
if (services.db) secretServices.push("postgres");
|
|
10890
10974
|
if (services.cache) secretServices.push("redis");
|
|
10975
|
+
if (services.storage) secretServices.push("minio");
|
|
10891
10976
|
const devSecrets = createStageSecrets("development", secretServices, { projectName: name$1 });
|
|
10892
10977
|
const customSecrets = {
|
|
10893
10978
|
NODE_ENV: "development",
|
|
@@ -11046,6 +11131,7 @@ async function secretsInitCommand(options) {
|
|
|
11046
11131
|
if (secrets.urls.DATABASE_URL) logger$2.log(`\n DATABASE_URL: ${maskUrl(secrets.urls.DATABASE_URL)}`);
|
|
11047
11132
|
if (secrets.urls.REDIS_URL) logger$2.log(` REDIS_URL: ${maskUrl(secrets.urls.REDIS_URL)}`);
|
|
11048
11133
|
if (secrets.urls.RABBITMQ_URL) logger$2.log(` RABBITMQ_URL: ${maskUrl(secrets.urls.RABBITMQ_URL)}`);
|
|
11134
|
+
if (secrets.urls.S3_ENDPOINT) logger$2.log(` S3_ENDPOINT: ${secrets.urls.S3_ENDPOINT}`);
|
|
11049
11135
|
if (Object.keys(secrets.custom).length > 0) logger$2.log(`\n Custom secrets: ${Object.keys(secrets.custom).length}`);
|
|
11050
11136
|
logger$2.log(`\n Use "gkm secrets:show --stage ${stage}" to view secrets`);
|
|
11051
11137
|
logger$2.log(" Use \"gkm secrets:set <KEY> <VALUE> --stage " + stage + "\" to add custom secrets");
|
|
@@ -11107,11 +11193,13 @@ async function secretsShowCommand(options) {
|
|
|
11107
11193
|
logger$2.log(` password: ${reveal ? creds.password : maskPassword(creds.password)}`);
|
|
11108
11194
|
if (creds.database) logger$2.log(` database: ${creds.database}`);
|
|
11109
11195
|
if (creds.vhost) logger$2.log(` vhost: ${creds.vhost}`);
|
|
11196
|
+
if (creds.bucket) logger$2.log(` bucket: ${creds.bucket}`);
|
|
11110
11197
|
}
|
|
11111
11198
|
logger$2.log("\nConnection URLs:");
|
|
11112
11199
|
if (secrets.urls.DATABASE_URL) logger$2.log(` DATABASE_URL: ${reveal ? secrets.urls.DATABASE_URL : maskUrl(secrets.urls.DATABASE_URL)}`);
|
|
11113
11200
|
if (secrets.urls.REDIS_URL) logger$2.log(` REDIS_URL: ${reveal ? secrets.urls.REDIS_URL : maskUrl(secrets.urls.REDIS_URL)}`);
|
|
11114
11201
|
if (secrets.urls.RABBITMQ_URL) logger$2.log(` RABBITMQ_URL: ${reveal ? secrets.urls.RABBITMQ_URL : maskUrl(secrets.urls.RABBITMQ_URL)}`);
|
|
11202
|
+
if (secrets.urls.S3_ENDPOINT) logger$2.log(` S3_ENDPOINT: ${secrets.urls.S3_ENDPOINT}`);
|
|
11115
11203
|
const customKeys = Object.keys(secrets.custom);
|
|
11116
11204
|
if (customKeys.length > 0) {
|
|
11117
11205
|
logger$2.log("\nCustom Secrets:");
|
|
@@ -11292,20 +11380,56 @@ async function resolveSecrets(stage, workspace, options) {
|
|
|
11292
11380
|
* @internal Exported for testing
|
|
11293
11381
|
*/
|
|
11294
11382
|
function reconcileSecrets(secrets, workspace) {
|
|
11383
|
+
let changed = false;
|
|
11384
|
+
let result = { ...secrets };
|
|
11385
|
+
const serviceMap = [
|
|
11386
|
+
{
|
|
11387
|
+
key: "db",
|
|
11388
|
+
name: "postgres"
|
|
11389
|
+
},
|
|
11390
|
+
{
|
|
11391
|
+
key: "cache",
|
|
11392
|
+
name: "redis"
|
|
11393
|
+
},
|
|
11394
|
+
{
|
|
11395
|
+
key: "storage",
|
|
11396
|
+
name: "minio"
|
|
11397
|
+
}
|
|
11398
|
+
];
|
|
11399
|
+
for (const { key, name: name$1 } of serviceMap) if (workspace.services[key] && !result.services[name$1]) {
|
|
11400
|
+
const creds = generateServiceCredentials(name$1);
|
|
11401
|
+
result = {
|
|
11402
|
+
...result,
|
|
11403
|
+
services: {
|
|
11404
|
+
...result.services,
|
|
11405
|
+
[name$1]: creds
|
|
11406
|
+
}
|
|
11407
|
+
};
|
|
11408
|
+
result.urls = generateConnectionUrls(result.services);
|
|
11409
|
+
logger$1.log(` 🔄 Adding missing service credentials: ${name$1}`);
|
|
11410
|
+
changed = true;
|
|
11411
|
+
}
|
|
11295
11412
|
const isMultiApp = Object.keys(workspace.apps).length > 1;
|
|
11296
|
-
if (
|
|
11297
|
-
|
|
11298
|
-
|
|
11299
|
-
|
|
11300
|
-
|
|
11301
|
-
|
|
11302
|
-
|
|
11303
|
-
|
|
11304
|
-
|
|
11305
|
-
|
|
11306
|
-
|
|
11307
|
-
|
|
11413
|
+
if (isMultiApp) {
|
|
11414
|
+
const expected = generateFullstackCustomSecrets(workspace);
|
|
11415
|
+
const missing = {};
|
|
11416
|
+
for (const [key, value] of Object.entries(expected)) if (!(key in result.custom)) missing[key] = value;
|
|
11417
|
+
if (Object.keys(missing).length > 0) {
|
|
11418
|
+
logger$1.log(` 🔄 Adding missing secrets: ${Object.keys(missing).join(", ")}`);
|
|
11419
|
+
result = {
|
|
11420
|
+
...result,
|
|
11421
|
+
custom: {
|
|
11422
|
+
...result.custom,
|
|
11423
|
+
...missing
|
|
11424
|
+
}
|
|
11425
|
+
};
|
|
11426
|
+
changed = true;
|
|
11308
11427
|
}
|
|
11428
|
+
}
|
|
11429
|
+
if (!changed) return null;
|
|
11430
|
+
return {
|
|
11431
|
+
...result,
|
|
11432
|
+
updatedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
11309
11433
|
};
|
|
11310
11434
|
}
|
|
11311
11435
|
/**
|
|
@@ -11315,6 +11439,7 @@ async function generateFreshSecrets(stage, workspace, options) {
|
|
|
11315
11439
|
const serviceNames = [];
|
|
11316
11440
|
if (workspace.services.db) serviceNames.push("postgres");
|
|
11317
11441
|
if (workspace.services.cache) serviceNames.push("redis");
|
|
11442
|
+
if (workspace.services.storage) serviceNames.push("minio");
|
|
11318
11443
|
const secrets = createStageSecrets(stage, serviceNames, { projectName: workspace.name });
|
|
11319
11444
|
const isMultiApp = Object.keys(workspace.apps).length > 1;
|
|
11320
11445
|
if (isMultiApp) {
|
|
@@ -11858,9 +11983,9 @@ program.command("secrets:push").description("Push secrets to remote provider (SS
|
|
|
11858
11983
|
const globalOptions = program.opts();
|
|
11859
11984
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11860
11985
|
const { loadWorkspaceConfig: loadWorkspaceConfig$1 } = await import("./config.mjs");
|
|
11861
|
-
const { pushSecrets: pushSecrets$1 } = await import("./sync-
|
|
11862
|
-
const { reconcileMissingSecrets } = await import("./reconcile-
|
|
11863
|
-
const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1 } = await import("./storage-
|
|
11986
|
+
const { pushSecrets: pushSecrets$1 } = await import("./sync-CyGe5f1I.mjs");
|
|
11987
|
+
const { reconcileMissingSecrets } = await import("./reconcile-C0dsg-Gq.mjs");
|
|
11988
|
+
const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1 } = await import("./storage-C1FNm2EP.mjs");
|
|
11864
11989
|
const { workspace } = await loadWorkspaceConfig$1();
|
|
11865
11990
|
const secrets = await readStageSecrets$1(options.stage, workspace.root);
|
|
11866
11991
|
if (secrets) {
|
|
@@ -11883,9 +12008,9 @@ program.command("secrets:pull").description("Pull secrets from remote provider (
|
|
|
11883
12008
|
const globalOptions = program.opts();
|
|
11884
12009
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11885
12010
|
const { loadWorkspaceConfig: loadWorkspaceConfig$1 } = await import("./config.mjs");
|
|
11886
|
-
const { pullSecrets: pullSecrets$1 } = await import("./sync-
|
|
11887
|
-
const { writeStageSecrets: writeStageSecrets$1 } = await import("./storage-
|
|
11888
|
-
const { reconcileMissingSecrets } = await import("./reconcile-
|
|
12011
|
+
const { pullSecrets: pullSecrets$1 } = await import("./sync-CyGe5f1I.mjs");
|
|
12012
|
+
const { writeStageSecrets: writeStageSecrets$1 } = await import("./storage-C1FNm2EP.mjs");
|
|
12013
|
+
const { reconcileMissingSecrets } = await import("./reconcile-C0dsg-Gq.mjs");
|
|
11889
12014
|
const { workspace } = await loadWorkspaceConfig$1();
|
|
11890
12015
|
let secrets = await pullSecrets$1(options.stage, workspace);
|
|
11891
12016
|
if (!secrets) {
|
|
@@ -11910,8 +12035,8 @@ program.command("secrets:reconcile").description("Backfill missing custom secret
|
|
|
11910
12035
|
const globalOptions = program.opts();
|
|
11911
12036
|
if (globalOptions.cwd) process.chdir(globalOptions.cwd);
|
|
11912
12037
|
const { loadWorkspaceConfig: loadWorkspaceConfig$1 } = await import("./config.mjs");
|
|
11913
|
-
const { reconcileMissingSecrets } = await import("./reconcile-
|
|
11914
|
-
const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1 } = await import("./storage-
|
|
12038
|
+
const { reconcileMissingSecrets } = await import("./reconcile-C0dsg-Gq.mjs");
|
|
12039
|
+
const { readStageSecrets: readStageSecrets$1, writeStageSecrets: writeStageSecrets$1 } = await import("./storage-C1FNm2EP.mjs");
|
|
11915
12040
|
const { workspace } = await loadWorkspaceConfig$1();
|
|
11916
12041
|
const secrets = await readStageSecrets$1(options.stage, workspace.root);
|
|
11917
12042
|
if (!secrets) {
|