@geekmidas/cli 1.4.0 → 1.5.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/CHANGELOG.md +6 -0
- package/dist/{Route53Provider-xrWuBXih.cjs → Route53Provider-Bs7Arms9.cjs} +3 -2
- package/dist/Route53Provider-Bs7Arms9.cjs.map +1 -0
- package/dist/{Route53Provider-DOWmFnwN.mjs → Route53Provider-C8mS0zY6.mjs} +3 -2
- package/dist/Route53Provider-C8mS0zY6.mjs.map +1 -0
- package/dist/{config-C1bidhvG.mjs → config-DfCJ29PQ.mjs} +2 -2
- package/dist/{config-C1bidhvG.mjs.map → config-DfCJ29PQ.mjs.map} +1 -1
- package/dist/{config-C1dM7aZb.cjs → config-ZQM1vBoz.cjs} +2 -2
- package/dist/{config-C1dM7aZb.cjs.map → config-ZQM1vBoz.cjs.map} +1 -1
- package/dist/config.cjs +2 -2
- package/dist/config.d.cts +1 -1
- package/dist/config.d.mts +1 -1
- package/dist/config.mjs +2 -2
- package/dist/{index-DzmZ6SUW.d.cts → index-B58qjyBd.d.cts} +27 -1
- package/dist/index-B58qjyBd.d.cts.map +1 -0
- package/dist/{index-DvpWzLD7.d.mts → index-C0SpUT9Y.d.mts} +27 -1
- package/dist/index-C0SpUT9Y.d.mts.map +1 -0
- package/dist/index.cjs +105 -48
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +105 -48
- package/dist/index.mjs.map +1 -1
- package/dist/{openapi-9k6a6VA4.mjs → openapi-BcSjLfWq.mjs} +2 -2
- package/dist/{openapi-9k6a6VA4.mjs.map → openapi-BcSjLfWq.mjs.map} +1 -1
- package/dist/{openapi-Dcja4e1C.cjs → openapi-D6Hcfov0.cjs} +2 -2
- package/dist/{openapi-Dcja4e1C.cjs.map → openapi-D6Hcfov0.cjs.map} +1 -1
- package/dist/openapi.cjs +3 -3
- package/dist/openapi.mjs +3 -3
- package/dist/workspace/index.cjs +1 -1
- package/dist/workspace/index.d.cts +1 -1
- package/dist/workspace/index.d.mts +1 -1
- package/dist/workspace/index.mjs +1 -1
- package/dist/{workspace-CeFgIDC-.cjs → workspace-2Do2YcGZ.cjs} +5 -1
- package/dist/{workspace-CeFgIDC-.cjs.map → workspace-2Do2YcGZ.cjs.map} +1 -1
- package/dist/{workspace-Cb_I7oCJ.mjs → workspace-BW2iU37P.mjs} +5 -1
- package/dist/{workspace-Cb_I7oCJ.mjs.map → workspace-BW2iU37P.mjs.map} +1 -1
- package/package.json +4 -4
- package/src/deploy/__tests__/Route53Provider.spec.ts +23 -0
- package/src/deploy/__tests__/env-resolver.spec.ts +239 -0
- package/src/deploy/__tests__/sniffer.spec.ts +104 -93
- package/src/deploy/dns/Route53Provider.ts +4 -1
- package/src/deploy/env-resolver.ts +11 -1
- package/src/deploy/index.ts +72 -24
- package/src/deploy/sniffer.ts +39 -7
- package/src/init/generators/monorepo.ts +4 -0
- package/src/init/generators/web.ts +45 -2
- package/src/workspace/schema.ts +8 -0
- package/src/workspace/types.ts +23 -0
- package/dist/Route53Provider-DOWmFnwN.mjs.map +0 -1
- package/dist/Route53Provider-xrWuBXih.cjs.map +0 -1
- package/dist/index-DvpWzLD7.d.mts.map +0 -1
- package/dist/index-DzmZ6SUW.d.cts.map +0 -1
package/dist/index.cjs
CHANGED
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
#!/usr/bin/env -S npx tsx
|
|
2
2
|
const require_chunk = require('./chunk-CUT6urMc.cjs');
|
|
3
|
-
const require_workspace = require('./workspace-
|
|
4
|
-
const require_config = require('./config-
|
|
3
|
+
const require_workspace = require('./workspace-2Do2YcGZ.cjs');
|
|
4
|
+
const require_config = require('./config-ZQM1vBoz.cjs');
|
|
5
5
|
const require_credentials = require('./credentials-C8DWtnMY.cjs');
|
|
6
|
-
const require_openapi = require('./openapi-
|
|
6
|
+
const require_openapi = require('./openapi-D6Hcfov0.cjs');
|
|
7
7
|
const require_storage = require('./storage-CoCNe0Pt.cjs');
|
|
8
8
|
const require_dokploy_api = require('./dokploy-api-CQvhV6Hd.cjs');
|
|
9
9
|
const require_encryption = require('./encryption-BE0UOb8j.cjs');
|
|
@@ -32,7 +32,7 @@ const prompts = require_chunk.__toESM(require("prompts"));
|
|
|
32
32
|
|
|
33
33
|
//#region package.json
|
|
34
34
|
var name = "@geekmidas/cli";
|
|
35
|
-
var version = "1.
|
|
35
|
+
var version = "1.4.0";
|
|
36
36
|
var description = "CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs";
|
|
37
37
|
var private$1 = false;
|
|
38
38
|
var type = "module";
|
|
@@ -2203,7 +2203,7 @@ async function createDnsProvider(options) {
|
|
|
2203
2203
|
return new HostingerProvider();
|
|
2204
2204
|
}
|
|
2205
2205
|
if (provider === "route53") {
|
|
2206
|
-
const { Route53Provider } = await Promise.resolve().then(() => require("./Route53Provider-
|
|
2206
|
+
const { Route53Provider } = await Promise.resolve().then(() => require("./Route53Provider-Bs7Arms9.cjs"));
|
|
2207
2207
|
const route53Config = config;
|
|
2208
2208
|
return new Route53Provider({
|
|
2209
2209
|
region: route53Config.region,
|
|
@@ -4137,33 +4137,6 @@ function isMainFrontendApp(appName, app, allApps) {
|
|
|
4137
4137
|
for (const [name$1, a] of Object.entries(allApps)) if (a.type === "frontend") return name$1 === appName;
|
|
4138
4138
|
return false;
|
|
4139
4139
|
}
|
|
4140
|
-
/**
|
|
4141
|
-
* Generate public URL build args for a frontend app based on its dependencies.
|
|
4142
|
-
*
|
|
4143
|
-
* @param app - The frontend app configuration
|
|
4144
|
-
* @param deployedUrls - Map of app name to deployed public URL
|
|
4145
|
-
* @returns Array of build args like 'NEXT_PUBLIC_API_URL=https://api.example.com'
|
|
4146
|
-
*/
|
|
4147
|
-
function generatePublicUrlBuildArgs(app, deployedUrls) {
|
|
4148
|
-
const buildArgs = [];
|
|
4149
|
-
for (const dep of app.dependencies) {
|
|
4150
|
-
const publicUrl = deployedUrls[dep];
|
|
4151
|
-
if (publicUrl) {
|
|
4152
|
-
const envVarName = `NEXT_PUBLIC_${dep.toUpperCase()}_URL`;
|
|
4153
|
-
buildArgs.push(`${envVarName}=${publicUrl}`);
|
|
4154
|
-
}
|
|
4155
|
-
}
|
|
4156
|
-
return buildArgs;
|
|
4157
|
-
}
|
|
4158
|
-
/**
|
|
4159
|
-
* Get public URL arg names from app dependencies.
|
|
4160
|
-
*
|
|
4161
|
-
* @param app - The frontend app configuration
|
|
4162
|
-
* @returns Array of arg names like 'NEXT_PUBLIC_API_URL'
|
|
4163
|
-
*/
|
|
4164
|
-
function getPublicUrlArgNames(app) {
|
|
4165
|
-
return app.dependencies.map((dep) => `NEXT_PUBLIC_${dep.toUpperCase()}_URL`);
|
|
4166
|
-
}
|
|
4167
4140
|
|
|
4168
4141
|
//#endregion
|
|
4169
4142
|
//#region src/deploy/env-resolver.ts
|
|
@@ -4225,7 +4198,9 @@ function resolveEnvVar(varName, context) {
|
|
|
4225
4198
|
break;
|
|
4226
4199
|
}
|
|
4227
4200
|
if (context.dependencyUrls && varName.endsWith("_URL")) {
|
|
4228
|
-
|
|
4201
|
+
let depName;
|
|
4202
|
+
if (varName.startsWith("NEXT_PUBLIC_")) depName = varName.slice(12, -4).toLowerCase();
|
|
4203
|
+
else depName = varName.slice(0, -4).toLowerCase();
|
|
4229
4204
|
if (context.dependencyUrls[depName]) return context.dependencyUrls[depName];
|
|
4230
4205
|
}
|
|
4231
4206
|
if (context.userSecrets) {
|
|
@@ -4637,14 +4612,29 @@ function resolveSnifferFile(baseName) {
|
|
|
4637
4612
|
*/
|
|
4638
4613
|
async function sniffAppEnvironment(app, appName, workspacePath, options = {}) {
|
|
4639
4614
|
const { logWarnings = true } = options;
|
|
4640
|
-
if (app.type === "frontend")
|
|
4641
|
-
|
|
4642
|
-
|
|
4643
|
-
|
|
4644
|
-
|
|
4645
|
-
|
|
4646
|
-
|
|
4647
|
-
|
|
4615
|
+
if (app.type === "frontend") {
|
|
4616
|
+
const depVars = (app.dependencies ?? []).map((dep) => `NEXT_PUBLIC_${dep.toUpperCase()}_URL`);
|
|
4617
|
+
if (app.config) {
|
|
4618
|
+
const sniffedVars = [];
|
|
4619
|
+
const configPaths = [];
|
|
4620
|
+
if (app.config.client) configPaths.push(app.config.client);
|
|
4621
|
+
if (app.config.server) configPaths.push(app.config.server);
|
|
4622
|
+
for (const configPath of configPaths) {
|
|
4623
|
+
const result = await sniffEntryFile(configPath, app.path, workspacePath);
|
|
4624
|
+
if (logWarnings && result.error) console.warn(`[sniffer] ${appName}: Config file "${configPath}" threw error during sniffing (env vars still captured): ${result.error.message}`);
|
|
4625
|
+
sniffedVars.push(...result.envVars);
|
|
4626
|
+
}
|
|
4627
|
+
const allVars = [...new Set([...depVars, ...sniffedVars])];
|
|
4628
|
+
return {
|
|
4629
|
+
appName,
|
|
4630
|
+
requiredEnvVars: allVars
|
|
4631
|
+
};
|
|
4632
|
+
}
|
|
4633
|
+
return {
|
|
4634
|
+
appName,
|
|
4635
|
+
requiredEnvVars: depVars
|
|
4636
|
+
};
|
|
4637
|
+
}
|
|
4648
4638
|
if (app.entry) {
|
|
4649
4639
|
const result = await sniffEntryFile(app.entry, app.path, workspacePath);
|
|
4650
4640
|
if (logWarnings && result.error) console.warn(`[sniffer] ${appName}: Entry file threw error during sniffing (env vars still captured): ${result.error.message}`);
|
|
@@ -5710,8 +5700,33 @@ async function workspaceDeployCommand(workspace, options) {
|
|
|
5710
5700
|
else logger$1.log(` Found existing application: ${application.applicationId}`);
|
|
5711
5701
|
}
|
|
5712
5702
|
setApplicationId(state, appName, application.applicationId);
|
|
5713
|
-
const
|
|
5714
|
-
if (
|
|
5703
|
+
const dependencyUrls = {};
|
|
5704
|
+
if (app.dependencies) {
|
|
5705
|
+
for (const dep of app.dependencies) if (publicUrls[dep]) dependencyUrls[dep] = publicUrls[dep];
|
|
5706
|
+
}
|
|
5707
|
+
const isMainFrontend = isMainFrontendApp(appName, app, workspace.apps);
|
|
5708
|
+
const frontendHost = resolveHost(appName, app, stage, dokployConfig, isMainFrontend);
|
|
5709
|
+
const envContext = {
|
|
5710
|
+
app,
|
|
5711
|
+
appName,
|
|
5712
|
+
stage,
|
|
5713
|
+
state,
|
|
5714
|
+
appHostname: frontendHost,
|
|
5715
|
+
frontendUrls: [],
|
|
5716
|
+
userSecrets: stageSecrets ?? void 0,
|
|
5717
|
+
dependencyUrls
|
|
5718
|
+
};
|
|
5719
|
+
const sniffedVars = sniffedApps.get(appName)?.requiredEnvVars ?? [];
|
|
5720
|
+
const { valid, missing, resolved } = validateEnvVars(sniffedVars, envContext);
|
|
5721
|
+
if (!valid) throw new Error(formatMissingVarsError(appName, missing, stage));
|
|
5722
|
+
if (Object.keys(resolved).length > 0) logger$1.log(` Resolved ${Object.keys(resolved).length} env vars: ${Object.keys(resolved).join(", ")}`);
|
|
5723
|
+
const buildArgs = [];
|
|
5724
|
+
const publicUrlArgNames = [];
|
|
5725
|
+
for (const [key, value] of Object.entries(resolved)) if (key.startsWith("NEXT_PUBLIC_")) {
|
|
5726
|
+
buildArgs.push(`${key}=${value}`);
|
|
5727
|
+
publicUrlArgNames.push(key);
|
|
5728
|
+
}
|
|
5729
|
+
if (buildArgs.length > 0) logger$1.log(` Build args: ${publicUrlArgNames.join(", ")}`);
|
|
5715
5730
|
const imageName = `${workspace.name}-${appName}`;
|
|
5716
5731
|
const imageRef = registry ? `${registry}/${imageName}:${imageTag}` : `${imageName}:${imageTag}`;
|
|
5717
5732
|
logger$1.log(` Building Docker image: ${imageRef}`);
|
|
@@ -5725,19 +5740,18 @@ async function workspaceDeployCommand(workspace, options) {
|
|
|
5725
5740
|
appName
|
|
5726
5741
|
},
|
|
5727
5742
|
buildArgs,
|
|
5728
|
-
publicUrlArgs:
|
|
5743
|
+
publicUrlArgs: publicUrlArgNames
|
|
5729
5744
|
});
|
|
5730
5745
|
const envVars = [
|
|
5731
5746
|
`NODE_ENV=production`,
|
|
5732
5747
|
`PORT=${app.port}`,
|
|
5733
5748
|
`STAGE=${stage}`
|
|
5734
5749
|
];
|
|
5750
|
+
for (const [key, value] of Object.entries(resolved)) envVars.push(`${key}=${value}`);
|
|
5735
5751
|
await api.saveDockerProvider(application.applicationId, imageRef, { registryId });
|
|
5736
5752
|
await api.saveApplicationEnv(application.applicationId, envVars.join("\n"));
|
|
5737
5753
|
logger$1.log(` Deploying to Dokploy...`);
|
|
5738
5754
|
await api.deployApplication(application.applicationId);
|
|
5739
|
-
const isMainFrontend = isMainFrontendApp(appName, app, workspace.apps);
|
|
5740
|
-
const frontendHost = resolveHost(appName, app, stage, dokployConfig, isMainFrontend);
|
|
5741
5755
|
const existingFrontendDomains = await api.getDomainsByApplicationId(application.applicationId);
|
|
5742
5756
|
const existingFrontendDomain = existingFrontendDomains.find((d) => d.host === frontendHost);
|
|
5743
5757
|
if (existingFrontendDomain) {
|
|
@@ -7365,6 +7379,10 @@ export default defineWorkspace({
|
|
|
7365
7379
|
path: 'apps/web',
|
|
7366
7380
|
port: 3001,
|
|
7367
7381
|
dependencies: ['api', 'auth'],
|
|
7382
|
+
config: {
|
|
7383
|
+
client: './src/config/client.ts',
|
|
7384
|
+
server: './src/config/server.ts',
|
|
7385
|
+
},
|
|
7368
7386
|
client: {
|
|
7369
7387
|
output: './src/api',
|
|
7370
7388
|
},
|
|
@@ -9959,12 +9977,42 @@ export function getQueryClient() {
|
|
|
9959
9977
|
if (!browserQueryClient) browserQueryClient = makeQueryClient();
|
|
9960
9978
|
return browserQueryClient;
|
|
9961
9979
|
}
|
|
9980
|
+
`;
|
|
9981
|
+
const clientConfigTs = `import { EnvironmentParser } from '@geekmidas/envkit';
|
|
9982
|
+
|
|
9983
|
+
// Client config - only NEXT_PUBLIC_* vars (available in browser)
|
|
9984
|
+
// These values are inlined at build time by Next.js
|
|
9985
|
+
const envParser = new EnvironmentParser({
|
|
9986
|
+
NEXT_PUBLIC_API_URL: process.env.NEXT_PUBLIC_API_URL,
|
|
9987
|
+
NEXT_PUBLIC_AUTH_URL: process.env.NEXT_PUBLIC_AUTH_URL,
|
|
9988
|
+
});
|
|
9989
|
+
|
|
9990
|
+
export const clientConfig = envParser
|
|
9991
|
+
.create((get) => ({
|
|
9992
|
+
apiUrl: get('NEXT_PUBLIC_API_URL').string(),
|
|
9993
|
+
authUrl: get('NEXT_PUBLIC_AUTH_URL').string(),
|
|
9994
|
+
}))
|
|
9995
|
+
.parse();
|
|
9996
|
+
`;
|
|
9997
|
+
const serverConfigTs = `import { EnvironmentParser } from '@geekmidas/envkit';
|
|
9998
|
+
|
|
9999
|
+
// Server config - all env vars (server-side only, not exposed to browser)
|
|
10000
|
+
// Access these only in Server Components, Route Handlers, or Server Actions
|
|
10001
|
+
const envParser = new EnvironmentParser({ ...process.env });
|
|
10002
|
+
|
|
10003
|
+
export const serverConfig = envParser
|
|
10004
|
+
.create((get) => ({
|
|
10005
|
+
// Add server-only secrets here
|
|
10006
|
+
// Example: stripeSecretKey: get('STRIPE_SECRET_KEY').string(),
|
|
10007
|
+
}))
|
|
10008
|
+
.parse();
|
|
9962
10009
|
`;
|
|
9963
10010
|
const authClientTs = `import { createAuthClient } from 'better-auth/react';
|
|
9964
10011
|
import { magicLinkClient } from 'better-auth/client/plugins';
|
|
10012
|
+
import { clientConfig } from '~/config/client';
|
|
9965
10013
|
|
|
9966
10014
|
export const authClient = createAuthClient({
|
|
9967
|
-
baseURL:
|
|
10015
|
+
baseURL: clientConfig.authUrl,
|
|
9968
10016
|
plugins: [magicLinkClient()],
|
|
9969
10017
|
});
|
|
9970
10018
|
|
|
@@ -9985,9 +10033,10 @@ export function Providers({ children }: { children: React.ReactNode }) {
|
|
|
9985
10033
|
`;
|
|
9986
10034
|
const apiIndexTs = `import { createApi } from './openapi';
|
|
9987
10035
|
import { getQueryClient } from '~/lib/query-client';
|
|
10036
|
+
import { clientConfig } from '~/config/client';
|
|
9988
10037
|
|
|
9989
10038
|
export const api = createApi({
|
|
9990
|
-
baseURL:
|
|
10039
|
+
baseURL: clientConfig.apiUrl,
|
|
9991
10040
|
queryClient: getQueryClient(),
|
|
9992
10041
|
});
|
|
9993
10042
|
`;
|
|
@@ -10108,6 +10157,14 @@ node_modules/
|
|
|
10108
10157
|
path: "apps/web/src/app/page.tsx",
|
|
10109
10158
|
content: pageTsx
|
|
10110
10159
|
},
|
|
10160
|
+
{
|
|
10161
|
+
path: "apps/web/src/config/client.ts",
|
|
10162
|
+
content: clientConfigTs
|
|
10163
|
+
},
|
|
10164
|
+
{
|
|
10165
|
+
path: "apps/web/src/config/server.ts",
|
|
10166
|
+
content: serverConfigTs
|
|
10167
|
+
},
|
|
10111
10168
|
{
|
|
10112
10169
|
path: "apps/web/src/lib/query-client.ts",
|
|
10113
10170
|
content: queryClientTs
|