@geekmidas/cli 0.42.0 → 0.44.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/README.md +221 -0
- package/dist/index.cjs +18 -9
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +18 -9
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
- package/src/build/__tests__/bundler.spec.ts +3 -3
- package/src/dev/__tests__/entry-integration.spec.ts +7 -6
- package/src/dev/index.ts +5 -1
- package/src/docker/__tests__/templates.spec.ts +123 -0
- package/src/docker/templates.ts +11 -6
- package/src/init/__tests__/generators.spec.ts +3 -2
- package/src/init/__tests__/init.spec.ts +2 -1
- package/src/init/generators/monorepo.ts +1 -0
- package/src/init/templates/minimal.ts +2 -0
- package/tsconfig.tsbuildinfo +1 -1
package/README.md
CHANGED
|
@@ -1109,6 +1109,227 @@ const logger = createTelescopeLogger(telescope, new ConsoleLogger());
|
|
|
1109
1109
|
|
|
1110
1110
|
See the [@geekmidas/telescope documentation](../telescope/README.md) for more details.
|
|
1111
1111
|
|
|
1112
|
+
## Workspace Configuration
|
|
1113
|
+
|
|
1114
|
+
For fullstack monorepo projects with multiple apps, use `defineWorkspace` instead of `defineConfig`:
|
|
1115
|
+
|
|
1116
|
+
```typescript
|
|
1117
|
+
// gkm.config.ts (at workspace root)
|
|
1118
|
+
import { defineWorkspace } from '@geekmidas/cli/config';
|
|
1119
|
+
|
|
1120
|
+
export default defineWorkspace({
|
|
1121
|
+
name: 'my-project',
|
|
1122
|
+
apps: {
|
|
1123
|
+
api: {
|
|
1124
|
+
type: 'backend',
|
|
1125
|
+
path: 'apps/api',
|
|
1126
|
+
port: 3000,
|
|
1127
|
+
routes: './src/endpoints/**/*.ts',
|
|
1128
|
+
envParser: './src/config/env#envParser',
|
|
1129
|
+
logger: './src/config/logger#logger',
|
|
1130
|
+
telescope: {
|
|
1131
|
+
enabled: true,
|
|
1132
|
+
path: '/__telescope',
|
|
1133
|
+
},
|
|
1134
|
+
openapi: {
|
|
1135
|
+
enabled: true,
|
|
1136
|
+
},
|
|
1137
|
+
},
|
|
1138
|
+
auth: {
|
|
1139
|
+
type: 'backend',
|
|
1140
|
+
path: 'apps/auth',
|
|
1141
|
+
port: 3002,
|
|
1142
|
+
entry: './src/index.ts', // Entry-based app (no routes)
|
|
1143
|
+
envParser: './src/config/env#envParser',
|
|
1144
|
+
logger: './src/config/logger#logger',
|
|
1145
|
+
},
|
|
1146
|
+
web: {
|
|
1147
|
+
type: 'frontend',
|
|
1148
|
+
framework: 'nextjs',
|
|
1149
|
+
path: 'apps/web',
|
|
1150
|
+
port: 3001,
|
|
1151
|
+
dependencies: ['api', 'auth'],
|
|
1152
|
+
client: {
|
|
1153
|
+
output: './src/api',
|
|
1154
|
+
},
|
|
1155
|
+
},
|
|
1156
|
+
},
|
|
1157
|
+
shared: {
|
|
1158
|
+
packages: ['packages/*'],
|
|
1159
|
+
models: {
|
|
1160
|
+
path: 'packages/models',
|
|
1161
|
+
schema: 'zod',
|
|
1162
|
+
},
|
|
1163
|
+
},
|
|
1164
|
+
services: {
|
|
1165
|
+
db: true,
|
|
1166
|
+
cache: true,
|
|
1167
|
+
mail: true,
|
|
1168
|
+
},
|
|
1169
|
+
deploy: {
|
|
1170
|
+
default: 'dokploy',
|
|
1171
|
+
},
|
|
1172
|
+
});
|
|
1173
|
+
```
|
|
1174
|
+
|
|
1175
|
+
### App Types
|
|
1176
|
+
|
|
1177
|
+
#### Routes-Based Backend Apps
|
|
1178
|
+
|
|
1179
|
+
Standard API apps using endpoint discovery:
|
|
1180
|
+
|
|
1181
|
+
```typescript
|
|
1182
|
+
api: {
|
|
1183
|
+
type: 'backend',
|
|
1184
|
+
path: 'apps/api',
|
|
1185
|
+
port: 3000,
|
|
1186
|
+
routes: './src/endpoints/**/*.ts', // Glob pattern for endpoints
|
|
1187
|
+
envParser: './src/config/env#envParser',
|
|
1188
|
+
logger: './src/config/logger#logger',
|
|
1189
|
+
}
|
|
1190
|
+
```
|
|
1191
|
+
|
|
1192
|
+
These apps use `gkm build --provider server` internally to generate a Hono server from discovered endpoints.
|
|
1193
|
+
|
|
1194
|
+
#### Entry-Based Backend Apps
|
|
1195
|
+
|
|
1196
|
+
Apps with a custom entry point (like authentication services using better-auth):
|
|
1197
|
+
|
|
1198
|
+
```typescript
|
|
1199
|
+
auth: {
|
|
1200
|
+
type: 'backend',
|
|
1201
|
+
path: 'apps/auth',
|
|
1202
|
+
port: 3002,
|
|
1203
|
+
entry: './src/index.ts', // Direct entry point
|
|
1204
|
+
envParser: './src/config/env#envParser',
|
|
1205
|
+
logger: './src/config/logger#logger',
|
|
1206
|
+
}
|
|
1207
|
+
```
|
|
1208
|
+
|
|
1209
|
+
Entry-based apps are bundled directly with esbuild into a standalone file. All dependencies are bundled, producing a single `index.mjs` file that runs without `node_modules`.
|
|
1210
|
+
|
|
1211
|
+
Example entry point for an auth service:
|
|
1212
|
+
|
|
1213
|
+
```typescript
|
|
1214
|
+
// apps/auth/src/index.ts
|
|
1215
|
+
import { Hono } from 'hono';
|
|
1216
|
+
import { serve } from '@hono/node-server';
|
|
1217
|
+
import { auth } from './auth.js';
|
|
1218
|
+
|
|
1219
|
+
const app = new Hono();
|
|
1220
|
+
|
|
1221
|
+
app.get('/health', (c) => c.json({ status: 'ok' }));
|
|
1222
|
+
app.on(['POST', 'GET'], '/api/auth/*', (c) => auth.handler(c.req.raw));
|
|
1223
|
+
|
|
1224
|
+
serve({ fetch: app.fetch, port: 3002 });
|
|
1225
|
+
```
|
|
1226
|
+
|
|
1227
|
+
#### Frontend Apps
|
|
1228
|
+
|
|
1229
|
+
Next.js or other frontend frameworks:
|
|
1230
|
+
|
|
1231
|
+
```typescript
|
|
1232
|
+
web: {
|
|
1233
|
+
type: 'frontend',
|
|
1234
|
+
framework: 'nextjs',
|
|
1235
|
+
path: 'apps/web',
|
|
1236
|
+
port: 3001,
|
|
1237
|
+
dependencies: ['api', 'auth'], // Apps this depends on
|
|
1238
|
+
client: {
|
|
1239
|
+
output: './src/api', // Where to generate API client
|
|
1240
|
+
},
|
|
1241
|
+
}
|
|
1242
|
+
```
|
|
1243
|
+
|
|
1244
|
+
### Workspace Docker Generation
|
|
1245
|
+
|
|
1246
|
+
When running `gkm docker` in a workspace, the CLI generates optimized Dockerfiles for each app:
|
|
1247
|
+
|
|
1248
|
+
```bash
|
|
1249
|
+
gkm docker
|
|
1250
|
+
```
|
|
1251
|
+
|
|
1252
|
+
**Generated files:**
|
|
1253
|
+
- `.gkm/docker/Dockerfile.api` - Routes-based backend (uses `gkm build`)
|
|
1254
|
+
- `.gkm/docker/Dockerfile.auth` - Entry-based backend (uses esbuild bundling)
|
|
1255
|
+
- `.gkm/docker/Dockerfile.web` - Next.js standalone output
|
|
1256
|
+
- `.gkm/docker/docker-compose.yml` - Full stack with all apps and services
|
|
1257
|
+
- `.dockerignore` - Optimized ignore patterns
|
|
1258
|
+
|
|
1259
|
+
**Dockerfile types by app:**
|
|
1260
|
+
|
|
1261
|
+
| App Type | Build Method | Output |
|
|
1262
|
+
|----------|--------------|--------|
|
|
1263
|
+
| `routes` backend | `gkm build --provider server` | `.gkm/server/dist/server.mjs` |
|
|
1264
|
+
| `entry` backend | `esbuild --bundle --packages=bundle` | `dist/index.mjs` |
|
|
1265
|
+
| `nextjs` frontend | `next build` (standalone) | `.next/standalone` |
|
|
1266
|
+
|
|
1267
|
+
**Entry-based bundling:**
|
|
1268
|
+
|
|
1269
|
+
Entry-based apps use esbuild with full dependency bundling:
|
|
1270
|
+
|
|
1271
|
+
```bash
|
|
1272
|
+
npx esbuild ./src/index.ts \
|
|
1273
|
+
--bundle \
|
|
1274
|
+
--platform=node \
|
|
1275
|
+
--target=node22 \
|
|
1276
|
+
--format=esm \
|
|
1277
|
+
--outfile=dist/index.mjs \
|
|
1278
|
+
--packages=bundle \
|
|
1279
|
+
--banner:js='import { createRequire } from "module"; const require = createRequire(import.meta.url);'
|
|
1280
|
+
```
|
|
1281
|
+
|
|
1282
|
+
The `--packages=bundle` flag bundles all dependencies (unlike tsdown's default behavior). The banner adds CommonJS compatibility for packages that use `require()` internally.
|
|
1283
|
+
|
|
1284
|
+
### Workspace Interface
|
|
1285
|
+
|
|
1286
|
+
```typescript
|
|
1287
|
+
interface WorkspaceConfig {
|
|
1288
|
+
name: string;
|
|
1289
|
+
apps: Record<string, AppConfig>;
|
|
1290
|
+
shared?: {
|
|
1291
|
+
packages?: string[];
|
|
1292
|
+
models?: {
|
|
1293
|
+
path: string;
|
|
1294
|
+
schema: 'zod' | 'valibot';
|
|
1295
|
+
};
|
|
1296
|
+
};
|
|
1297
|
+
services?: {
|
|
1298
|
+
db?: boolean;
|
|
1299
|
+
cache?: boolean;
|
|
1300
|
+
mail?: boolean;
|
|
1301
|
+
};
|
|
1302
|
+
deploy?: {
|
|
1303
|
+
default?: 'dokploy' | 'docker';
|
|
1304
|
+
};
|
|
1305
|
+
}
|
|
1306
|
+
|
|
1307
|
+
interface BackendAppConfig {
|
|
1308
|
+
type: 'backend';
|
|
1309
|
+
path: string;
|
|
1310
|
+
port: number;
|
|
1311
|
+
routes?: string; // Glob pattern for routes-based apps
|
|
1312
|
+
entry?: string; // Entry file for entry-based apps
|
|
1313
|
+
envParser: string;
|
|
1314
|
+
logger: string;
|
|
1315
|
+
telescope?: TelescopeConfig;
|
|
1316
|
+
openapi?: { enabled: boolean };
|
|
1317
|
+
}
|
|
1318
|
+
|
|
1319
|
+
interface FrontendAppConfig {
|
|
1320
|
+
type: 'frontend';
|
|
1321
|
+
framework: 'nextjs';
|
|
1322
|
+
path: string;
|
|
1323
|
+
port: number;
|
|
1324
|
+
dependencies?: string[]; // Other apps this depends on
|
|
1325
|
+
client?: {
|
|
1326
|
+
output: string; // Where to generate typed API client
|
|
1327
|
+
};
|
|
1328
|
+
}
|
|
1329
|
+
|
|
1330
|
+
type AppConfig = BackendAppConfig | FrontendAppConfig;
|
|
1331
|
+
```
|
|
1332
|
+
|
|
1112
1333
|
## Providers
|
|
1113
1334
|
|
|
1114
1335
|
### AWS API Gateway v1
|
package/dist/index.cjs
CHANGED
|
@@ -29,7 +29,7 @@ const node_module = require_chunk.__toESM(require("node:module"));
|
|
|
29
29
|
|
|
30
30
|
//#region package.json
|
|
31
31
|
var name = "@geekmidas/cli";
|
|
32
|
-
var version = "0.
|
|
32
|
+
var version = "0.44.0";
|
|
33
33
|
var description = "CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs";
|
|
34
34
|
var private$1 = false;
|
|
35
35
|
var type = "module";
|
|
@@ -1625,7 +1625,8 @@ async function prepareEntryCredentials(options) {
|
|
|
1625
1625
|
credentials.PORT = String(resolvedPort);
|
|
1626
1626
|
const secretsDir = (0, node_path.join)(secretsRoot, ".gkm");
|
|
1627
1627
|
await (0, node_fs_promises.mkdir)(secretsDir, { recursive: true });
|
|
1628
|
-
const
|
|
1628
|
+
const secretsFileName = appName ? `dev-secrets-${appName}.json` : "dev-secrets.json";
|
|
1629
|
+
const secretsJsonPath = (0, node_path.join)(secretsDir, secretsFileName);
|
|
1629
1630
|
await (0, node_fs_promises.writeFile)(secretsJsonPath, JSON.stringify(credentials, null, 2));
|
|
1630
1631
|
return {
|
|
1631
1632
|
credentials,
|
|
@@ -3224,7 +3225,7 @@ CMD ["node", "server.mjs"]
|
|
|
3224
3225
|
}
|
|
3225
3226
|
/**
|
|
3226
3227
|
* Generate a Dockerfile for apps with a custom entry point.
|
|
3227
|
-
* Uses
|
|
3228
|
+
* Uses esbuild to bundle the entry point into dist/index.mjs with all dependencies.
|
|
3228
3229
|
* This is used for apps that don't use gkm routes (e.g., Better Auth servers).
|
|
3229
3230
|
* @internal Exported for testing
|
|
3230
3231
|
*/
|
|
@@ -3287,17 +3288,22 @@ RUN if [ -n "$GKM_ENCRYPTED_CREDENTIALS" ]; then \
|
|
|
3287
3288
|
echo "$GKM_CREDENTIALS_IV" > ${appPath}/.gkm/credentials.iv; \
|
|
3288
3289
|
fi
|
|
3289
3290
|
|
|
3290
|
-
# Bundle entry point with
|
|
3291
|
+
# Bundle entry point with esbuild (outputs to dist/index.mjs)
|
|
3292
|
+
# Creates a fully standalone bundle with all dependencies included
|
|
3291
3293
|
# Use define to embed credentials if present
|
|
3292
3294
|
RUN cd ${appPath} && \
|
|
3293
3295
|
if [ -f .gkm/credentials.enc ]; then \
|
|
3294
3296
|
CREDS=$(cat .gkm/credentials.enc) && \
|
|
3295
3297
|
IV=$(cat .gkm/credentials.iv) && \
|
|
3296
|
-
npx
|
|
3297
|
-
--
|
|
3298
|
-
--
|
|
3298
|
+
npx esbuild ${entry} --bundle --platform=node --target=node22 --format=esm \
|
|
3299
|
+
--outfile=dist/index.mjs --packages=bundle \
|
|
3300
|
+
--banner:js='import { createRequire } from "module"; const require = createRequire(import.meta.url);' \
|
|
3301
|
+
--define:__GKM_ENCRYPTED_CREDENTIALS__="'\\"$CREDS\\"'" \
|
|
3302
|
+
--define:__GKM_CREDENTIALS_IV__="'\\"$IV\\"'"; \
|
|
3299
3303
|
else \
|
|
3300
|
-
npx
|
|
3304
|
+
npx esbuild ${entry} --bundle --platform=node --target=node22 --format=esm \
|
|
3305
|
+
--outfile=dist/index.mjs --packages=bundle \
|
|
3306
|
+
--banner:js='import { createRequire } from "module"; const require = createRequire(import.meta.url);'; \
|
|
3301
3307
|
fi
|
|
3302
3308
|
|
|
3303
3309
|
# Stage 4: Production
|
|
@@ -6244,6 +6250,7 @@ export default defineWorkspace({
|
|
|
6244
6250
|
type: 'backend',
|
|
6245
6251
|
path: 'apps/auth',
|
|
6246
6252
|
port: 3002,
|
|
6253
|
+
entry: './src/index.ts',
|
|
6247
6254
|
envParser: './src/config/env#envParser',
|
|
6248
6255
|
logger: './src/config/logger#logger',
|
|
6249
6256
|
},
|
|
@@ -6557,12 +6564,14 @@ const minimalTemplate = {
|
|
|
6557
6564
|
"@geekmidas/schema": GEEKMIDAS_VERSIONS["@geekmidas/schema"],
|
|
6558
6565
|
"@hono/node-server": "~1.14.1",
|
|
6559
6566
|
hono: "~4.8.2",
|
|
6560
|
-
pino: "~9.6.0"
|
|
6567
|
+
pino: "~9.6.0",
|
|
6568
|
+
zod: "~4.1.0"
|
|
6561
6569
|
},
|
|
6562
6570
|
devDependencies: {
|
|
6563
6571
|
"@biomejs/biome": "~2.3.0",
|
|
6564
6572
|
"@geekmidas/cli": GEEKMIDAS_VERSIONS["@geekmidas/cli"],
|
|
6565
6573
|
"@types/node": "~22.0.0",
|
|
6574
|
+
esbuild: "~0.27.0",
|
|
6566
6575
|
tsx: "~4.20.0",
|
|
6567
6576
|
turbo: "~2.3.0",
|
|
6568
6577
|
typescript: "~5.8.2",
|