@geekmidas/cli 0.22.0 → 0.24.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/config-BogU0_oQ.mjs +189 -0
- package/dist/config-BogU0_oQ.mjs.map +1 -0
- package/dist/{config-CxrLu8ia.cjs → config-CTftATBX.cjs} +95 -9
- package/dist/config-CTftATBX.cjs.map +1 -0
- package/dist/config.cjs +3 -1
- package/dist/config.d.cts +36 -2
- package/dist/config.d.cts.map +1 -1
- package/dist/config.d.mts +36 -2
- package/dist/config.d.mts.map +1 -1
- package/dist/config.mjs +2 -2
- package/dist/index.cjs +72 -31
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +72 -31
- package/dist/index.mjs.map +1 -1
- package/dist/{openapi-DfpxS0xv.cjs → openapi-BrhkPKM7.cjs} +2 -2
- package/dist/{openapi-DfpxS0xv.cjs.map → openapi-BrhkPKM7.cjs.map} +1 -1
- package/dist/{openapi-CgqR6Jkw.mjs → openapi-DNbXfhXE.mjs} +2 -2
- package/dist/{openapi-CgqR6Jkw.mjs.map → openapi-DNbXfhXE.mjs.map} +1 -1
- package/dist/openapi.cjs +2 -2
- package/dist/openapi.mjs +2 -2
- package/package.json +5 -4
- package/src/__tests__/config.spec.ts +314 -2
- package/src/config.ts +151 -15
- package/src/dev/index.ts +78 -26
- package/src/init/generators/docker.ts +1 -1
- package/src/init/versions.ts +13 -2
- package/dist/config-BaYqrF3n.mjs +0 -115
- package/dist/config-BaYqrF3n.mjs.map +0 -1
- package/dist/config-CxrLu8ia.cjs.map +0 -1
package/src/dev/index.ts
CHANGED
|
@@ -14,7 +14,12 @@ import type {
|
|
|
14
14
|
NormalizedStudioConfig,
|
|
15
15
|
NormalizedTelescopeConfig,
|
|
16
16
|
} from '../build/types';
|
|
17
|
-
import {
|
|
17
|
+
import {
|
|
18
|
+
getAppNameFromCwd,
|
|
19
|
+
loadAppConfig,
|
|
20
|
+
loadWorkspaceConfig,
|
|
21
|
+
parseModuleConfig,
|
|
22
|
+
} from '../config';
|
|
18
23
|
import {
|
|
19
24
|
CronGenerator,
|
|
20
25
|
EndpointGenerator,
|
|
@@ -230,6 +235,7 @@ export function normalizeStudioConfig(
|
|
|
230
235
|
*/
|
|
231
236
|
export function normalizeHooksConfig(
|
|
232
237
|
config: GkmConfig['hooks'],
|
|
238
|
+
cwd: string = process.cwd(),
|
|
233
239
|
): NormalizedHooksConfig | undefined {
|
|
234
240
|
if (!config?.server) {
|
|
235
241
|
return undefined;
|
|
@@ -240,7 +246,7 @@ export function normalizeHooksConfig(
|
|
|
240
246
|
? config.server
|
|
241
247
|
: `${config.server}.ts`;
|
|
242
248
|
|
|
243
|
-
const resolvedPath = resolve(
|
|
249
|
+
const resolvedPath = resolve(cwd, serverPath);
|
|
244
250
|
|
|
245
251
|
return {
|
|
246
252
|
serverHooksPath: resolvedPath,
|
|
@@ -308,21 +314,47 @@ export async function devCommand(options: DevOptions): Promise<void> {
|
|
|
308
314
|
logger.log(`📦 Loaded env: ${defaultEnv.loaded.join(', ')}`);
|
|
309
315
|
}
|
|
310
316
|
|
|
311
|
-
//
|
|
312
|
-
const
|
|
317
|
+
// Check if we're in an app subdirectory
|
|
318
|
+
const appName = getAppNameFromCwd();
|
|
319
|
+
let config: GkmConfig;
|
|
320
|
+
let appRoot: string = process.cwd();
|
|
313
321
|
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
322
|
+
if (appName) {
|
|
323
|
+
// Try to load app-specific config from workspace
|
|
324
|
+
try {
|
|
325
|
+
const appConfig = await loadAppConfig();
|
|
326
|
+
config = appConfig.gkmConfig;
|
|
327
|
+
appRoot = appConfig.appRoot;
|
|
328
|
+
logger.log(`📦 Running app: ${appConfig.appName}`);
|
|
329
|
+
} catch {
|
|
330
|
+
// Not in a workspace or app not found in workspace - fall back to regular loading
|
|
331
|
+
const loadedConfig = await loadWorkspaceConfig();
|
|
332
|
+
|
|
333
|
+
// Route to workspace dev mode for multi-app workspaces
|
|
334
|
+
if (loadedConfig.type === 'workspace') {
|
|
335
|
+
logger.log('📦 Detected workspace configuration');
|
|
336
|
+
return workspaceDevCommand(loadedConfig.workspace, options);
|
|
337
|
+
}
|
|
338
|
+
|
|
339
|
+
config = loadedConfig.raw as GkmConfig;
|
|
340
|
+
}
|
|
341
|
+
} else {
|
|
342
|
+
// Try to load workspace config
|
|
343
|
+
const loadedConfig = await loadWorkspaceConfig();
|
|
344
|
+
|
|
345
|
+
// Route to workspace dev mode for multi-app workspaces
|
|
346
|
+
if (loadedConfig.type === 'workspace') {
|
|
347
|
+
logger.log('📦 Detected workspace configuration');
|
|
348
|
+
return workspaceDevCommand(loadedConfig.workspace, options);
|
|
349
|
+
}
|
|
319
350
|
|
|
320
|
-
|
|
321
|
-
|
|
351
|
+
// Single-app mode - use existing logic
|
|
352
|
+
config = loadedConfig.raw as GkmConfig;
|
|
353
|
+
}
|
|
322
354
|
|
|
323
355
|
// Load any additional env files specified in config
|
|
324
356
|
if (config.env) {
|
|
325
|
-
const { loaded, missing } = loadEnvFiles(config.env);
|
|
357
|
+
const { loaded, missing } = loadEnvFiles(config.env, appRoot);
|
|
326
358
|
if (loaded.length > 0) {
|
|
327
359
|
logger.log(`📦 Loaded env: ${loaded.join(', ')}`);
|
|
328
360
|
}
|
|
@@ -366,7 +398,7 @@ export async function devCommand(options: DevOptions): Promise<void> {
|
|
|
366
398
|
}
|
|
367
399
|
|
|
368
400
|
// Normalize hooks configuration
|
|
369
|
-
const hooks = normalizeHooksConfig(config.hooks);
|
|
401
|
+
const hooks = normalizeHooksConfig(config.hooks, appRoot);
|
|
370
402
|
if (hooks) {
|
|
371
403
|
logger.log(`🪝 Server hooks enabled from ${config.hooks?.server}`);
|
|
372
404
|
}
|
|
@@ -395,6 +427,7 @@ export async function devCommand(options: DevOptions): Promise<void> {
|
|
|
395
427
|
buildContext,
|
|
396
428
|
resolved.providers[0] as LegacyProvider,
|
|
397
429
|
enableOpenApi,
|
|
430
|
+
appRoot,
|
|
398
431
|
);
|
|
399
432
|
|
|
400
433
|
// Generate OpenAPI spec on startup
|
|
@@ -414,6 +447,7 @@ export async function devCommand(options: DevOptions): Promise<void> {
|
|
|
414
447
|
telescope,
|
|
415
448
|
studio,
|
|
416
449
|
runtime,
|
|
450
|
+
appRoot,
|
|
417
451
|
);
|
|
418
452
|
|
|
419
453
|
await devServer.start();
|
|
@@ -451,7 +485,7 @@ export async function devCommand(options: DevOptions): Promise<void> {
|
|
|
451
485
|
|
|
452
486
|
// Resolve glob patterns to actual files (chokidar 4.x doesn't support globs)
|
|
453
487
|
const resolvedFiles = await fg(normalizedPatterns, {
|
|
454
|
-
cwd:
|
|
488
|
+
cwd: appRoot,
|
|
455
489
|
absolute: false,
|
|
456
490
|
onlyFiles: true,
|
|
457
491
|
});
|
|
@@ -474,7 +508,7 @@ export async function devCommand(options: DevOptions): Promise<void> {
|
|
|
474
508
|
ignored: /(^|[/\\])\../, // ignore dotfiles
|
|
475
509
|
persistent: true,
|
|
476
510
|
ignoreInitial: true,
|
|
477
|
-
cwd:
|
|
511
|
+
cwd: appRoot,
|
|
478
512
|
});
|
|
479
513
|
|
|
480
514
|
watcher.on('ready', () => {
|
|
@@ -503,6 +537,7 @@ export async function devCommand(options: DevOptions): Promise<void> {
|
|
|
503
537
|
buildContext,
|
|
504
538
|
resolved.providers[0] as LegacyProvider,
|
|
505
539
|
enableOpenApi,
|
|
540
|
+
appRoot,
|
|
506
541
|
);
|
|
507
542
|
|
|
508
543
|
// Regenerate OpenAPI if enabled
|
|
@@ -903,6 +938,17 @@ async function workspaceDevCommand(
|
|
|
903
938
|
);
|
|
904
939
|
}
|
|
905
940
|
|
|
941
|
+
// Find the config file path for GKM_CONFIG_PATH
|
|
942
|
+
const configFiles = ['gkm.config.ts', 'gkm.config.js', 'gkm.config.json'];
|
|
943
|
+
let configPath = '';
|
|
944
|
+
for (const file of configFiles) {
|
|
945
|
+
const fullPath = join(workspace.root, file);
|
|
946
|
+
if (existsSync(fullPath)) {
|
|
947
|
+
configPath = fullPath;
|
|
948
|
+
break;
|
|
949
|
+
}
|
|
950
|
+
}
|
|
951
|
+
|
|
906
952
|
// Prepare environment variables
|
|
907
953
|
// Order matters: secrets first, then dependencies (dependencies can override)
|
|
908
954
|
const turboEnv: Record<string, string> = {
|
|
@@ -910,6 +956,8 @@ async function workspaceDevCommand(
|
|
|
910
956
|
...secretsEnv,
|
|
911
957
|
...dependencyEnv,
|
|
912
958
|
NODE_ENV: 'development',
|
|
959
|
+
// Inject config path so child processes can find the workspace config
|
|
960
|
+
...(configPath ? { GKM_CONFIG_PATH: configPath } : {}),
|
|
913
961
|
};
|
|
914
962
|
|
|
915
963
|
// Spawn turbo run dev
|
|
@@ -1095,6 +1143,7 @@ async function buildServer(
|
|
|
1095
1143
|
context: BuildContext,
|
|
1096
1144
|
provider: LegacyProvider,
|
|
1097
1145
|
enableOpenApi: boolean,
|
|
1146
|
+
appRoot: string = process.cwd(),
|
|
1098
1147
|
): Promise<void> {
|
|
1099
1148
|
// Initialize generators
|
|
1100
1149
|
const endpointGenerator = new EndpointGenerator();
|
|
@@ -1102,17 +1151,19 @@ async function buildServer(
|
|
|
1102
1151
|
const cronGenerator = new CronGenerator();
|
|
1103
1152
|
const subscriberGenerator = new SubscriberGenerator();
|
|
1104
1153
|
|
|
1105
|
-
// Load all constructs
|
|
1154
|
+
// Load all constructs (resolve paths relative to appRoot)
|
|
1106
1155
|
const [allEndpoints, allFunctions, allCrons, allSubscribers] =
|
|
1107
1156
|
await Promise.all([
|
|
1108
|
-
endpointGenerator.load(config.routes),
|
|
1109
|
-
config.functions ? functionGenerator.load(config.functions) : [],
|
|
1110
|
-
config.crons ? cronGenerator.load(config.crons) : [],
|
|
1111
|
-
config.subscribers
|
|
1157
|
+
endpointGenerator.load(config.routes, appRoot),
|
|
1158
|
+
config.functions ? functionGenerator.load(config.functions, appRoot) : [],
|
|
1159
|
+
config.crons ? cronGenerator.load(config.crons, appRoot) : [],
|
|
1160
|
+
config.subscribers
|
|
1161
|
+
? subscriberGenerator.load(config.subscribers, appRoot)
|
|
1162
|
+
: [],
|
|
1112
1163
|
]);
|
|
1113
1164
|
|
|
1114
|
-
// Ensure .gkm directory exists
|
|
1115
|
-
const outputDir = join(
|
|
1165
|
+
// Ensure .gkm directory exists in app root
|
|
1166
|
+
const outputDir = join(appRoot, '.gkm', provider);
|
|
1116
1167
|
await mkdir(outputDir, { recursive: true });
|
|
1117
1168
|
|
|
1118
1169
|
// Build for server provider
|
|
@@ -1137,9 +1188,10 @@ class DevServer {
|
|
|
1137
1188
|
private requestedPort: number,
|
|
1138
1189
|
private portExplicit: boolean,
|
|
1139
1190
|
private enableOpenApi: boolean,
|
|
1140
|
-
private telescope
|
|
1141
|
-
private studio
|
|
1191
|
+
private telescope: NormalizedTelescopeConfig | undefined,
|
|
1192
|
+
private studio: NormalizedStudioConfig | undefined,
|
|
1142
1193
|
private runtime: Runtime = 'node',
|
|
1194
|
+
private appRoot: string = process.cwd(),
|
|
1143
1195
|
) {
|
|
1144
1196
|
this.actualPort = requestedPort;
|
|
1145
1197
|
}
|
|
@@ -1172,7 +1224,7 @@ class DevServer {
|
|
|
1172
1224
|
}
|
|
1173
1225
|
|
|
1174
1226
|
const serverEntryPath = join(
|
|
1175
|
-
|
|
1227
|
+
this.appRoot,
|
|
1176
1228
|
'.gkm',
|
|
1177
1229
|
this.provider,
|
|
1178
1230
|
'server.ts',
|
|
@@ -1292,7 +1344,7 @@ class DevServer {
|
|
|
1292
1344
|
const { writeFile } = await import('node:fs/promises');
|
|
1293
1345
|
const { relative, dirname } = await import('node:path');
|
|
1294
1346
|
|
|
1295
|
-
const serverPath = join(
|
|
1347
|
+
const serverPath = join(this.appRoot, '.gkm', this.provider, 'server.ts');
|
|
1296
1348
|
|
|
1297
1349
|
const relativeAppPath = relative(
|
|
1298
1350
|
dirname(serverPath),
|
|
@@ -147,7 +147,7 @@ export function generateDockerFiles(
|
|
|
147
147
|
}
|
|
148
148
|
|
|
149
149
|
// Mailpit for email testing
|
|
150
|
-
if (options.services
|
|
150
|
+
if (options.services?.mail) {
|
|
151
151
|
services.push(` mailpit:
|
|
152
152
|
image: axllent/mailpit:latest
|
|
153
153
|
container_name: ${options.name}-mailpit
|
package/src/init/versions.ts
CHANGED
|
@@ -1,8 +1,19 @@
|
|
|
1
1
|
import { createRequire } from 'node:module';
|
|
2
2
|
|
|
3
3
|
const require = createRequire(import.meta.url);
|
|
4
|
-
|
|
5
|
-
|
|
4
|
+
|
|
5
|
+
// Load package.json - handles both bundled (flat dist/) and source (nested src/init/)
|
|
6
|
+
function loadPackageJson(): { version: string } {
|
|
7
|
+
try {
|
|
8
|
+
// Try flat dist path first (../package.json from dist/)
|
|
9
|
+
return require('../package.json');
|
|
10
|
+
} catch {
|
|
11
|
+
// Fall back to nested source path (../../package.json from src/init/)
|
|
12
|
+
return require('../../package.json');
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
const pkg = loadPackageJson();
|
|
6
17
|
|
|
7
18
|
/**
|
|
8
19
|
* CLI version from package.json (used for scaffolded projects)
|
package/dist/config-BaYqrF3n.mjs
DELETED
|
@@ -1,115 +0,0 @@
|
|
|
1
|
-
import { isWorkspaceConfig, processConfig } from "./workspace-CPLEZDZf.mjs";
|
|
2
|
-
import { existsSync } from "node:fs";
|
|
3
|
-
import { join } from "node:path";
|
|
4
|
-
|
|
5
|
-
//#region src/config.ts
|
|
6
|
-
/**
|
|
7
|
-
* Define GKM configuration with full TypeScript support.
|
|
8
|
-
* This is an identity function that provides type safety and autocomplete.
|
|
9
|
-
*
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* // gkm.config.ts
|
|
13
|
-
* import { defineConfig } from '@geekmidas/cli/config';
|
|
14
|
-
*
|
|
15
|
-
* export default defineConfig({
|
|
16
|
-
* routes: './src/endpoints/**\/*.ts',
|
|
17
|
-
* envParser: './src/config/env',
|
|
18
|
-
* logger: './src/config/logger',
|
|
19
|
-
* telescope: true,
|
|
20
|
-
* });
|
|
21
|
-
* ```
|
|
22
|
-
*/
|
|
23
|
-
function defineConfig(config) {
|
|
24
|
-
return config;
|
|
25
|
-
}
|
|
26
|
-
/**
|
|
27
|
-
* Parse a module config string into path and import pattern.
|
|
28
|
-
*
|
|
29
|
-
* @param configString - Config string in format "./path/to/module" or "./path/to/module#exportName"
|
|
30
|
-
* @param defaultAlias - The default alias name to use if no export name specified
|
|
31
|
-
* @returns Object with path and import pattern
|
|
32
|
-
*
|
|
33
|
-
* @example
|
|
34
|
-
* parseModuleConfig('./src/config/env', 'envParser')
|
|
35
|
-
* // { path: './src/config/env', importPattern: 'envParser' }
|
|
36
|
-
*
|
|
37
|
-
* parseModuleConfig('./src/config/env#envParser', 'envParser')
|
|
38
|
-
* // { path: './src/config/env', importPattern: '{ envParser }' }
|
|
39
|
-
*
|
|
40
|
-
* parseModuleConfig('./src/config/env#myEnv', 'envParser')
|
|
41
|
-
* // { path: './src/config/env', importPattern: '{ myEnv as envParser }' }
|
|
42
|
-
*/
|
|
43
|
-
function parseModuleConfig(configString, defaultAlias) {
|
|
44
|
-
const parts = configString.split("#");
|
|
45
|
-
const path = parts[0] ?? configString;
|
|
46
|
-
const exportName = parts[1];
|
|
47
|
-
const importPattern = !exportName ? defaultAlias : exportName === defaultAlias ? `{ ${defaultAlias} }` : `{ ${exportName} as ${defaultAlias} }`;
|
|
48
|
-
return {
|
|
49
|
-
path,
|
|
50
|
-
importPattern
|
|
51
|
-
};
|
|
52
|
-
}
|
|
53
|
-
/**
|
|
54
|
-
* Find and return the path to the config file.
|
|
55
|
-
*/
|
|
56
|
-
function findConfigPath(cwd) {
|
|
57
|
-
const files = [
|
|
58
|
-
"gkm.config.json",
|
|
59
|
-
"gkm.config.ts",
|
|
60
|
-
"gkm.config.js"
|
|
61
|
-
];
|
|
62
|
-
for (const file of files) {
|
|
63
|
-
const path = join(cwd, file);
|
|
64
|
-
if (existsSync(path)) return path;
|
|
65
|
-
}
|
|
66
|
-
throw new Error("Configuration file not found. Please create gkm.config.json, gkm.config.ts, or gkm.config.js in the project root.");
|
|
67
|
-
}
|
|
68
|
-
/**
|
|
69
|
-
* Load raw configuration from file.
|
|
70
|
-
*/
|
|
71
|
-
async function loadRawConfig(cwd) {
|
|
72
|
-
const configPath = findConfigPath(cwd);
|
|
73
|
-
try {
|
|
74
|
-
const config = await import(configPath);
|
|
75
|
-
return config.default;
|
|
76
|
-
} catch (error) {
|
|
77
|
-
throw new Error(`Failed to load config: ${error.message}`);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
80
|
-
/**
|
|
81
|
-
* Load configuration file (single-app format).
|
|
82
|
-
* For backwards compatibility with existing code.
|
|
83
|
-
*
|
|
84
|
-
* @deprecated Use loadWorkspaceConfig for new code
|
|
85
|
-
*/
|
|
86
|
-
async function loadConfig(cwd = process.cwd()) {
|
|
87
|
-
const config = await loadRawConfig(cwd);
|
|
88
|
-
if (isWorkspaceConfig(config)) throw new Error("Workspace configuration detected. Use loadWorkspaceConfig() instead.");
|
|
89
|
-
return config;
|
|
90
|
-
}
|
|
91
|
-
/**
|
|
92
|
-
* Load configuration file and process it as a workspace.
|
|
93
|
-
* Works with both single-app and workspace configurations.
|
|
94
|
-
*
|
|
95
|
-
* Single-app configs are automatically wrapped as a workspace with one app.
|
|
96
|
-
*
|
|
97
|
-
* @example
|
|
98
|
-
* ```ts
|
|
99
|
-
* const { type, workspace } = await loadWorkspaceConfig();
|
|
100
|
-
*
|
|
101
|
-
* if (type === 'workspace') {
|
|
102
|
-
* console.log('Multi-app workspace:', workspace.apps);
|
|
103
|
-
* } else {
|
|
104
|
-
* console.log('Single app wrapped as workspace');
|
|
105
|
-
* }
|
|
106
|
-
* ```
|
|
107
|
-
*/
|
|
108
|
-
async function loadWorkspaceConfig(cwd = process.cwd()) {
|
|
109
|
-
const config = await loadRawConfig(cwd);
|
|
110
|
-
return processConfig(config, cwd);
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
//#endregion
|
|
114
|
-
export { defineConfig, loadConfig, loadWorkspaceConfig, parseModuleConfig };
|
|
115
|
-
//# sourceMappingURL=config-BaYqrF3n.mjs.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config-BaYqrF3n.mjs","names":["config: GkmConfig","configString: string","defaultAlias: string","cwd: string"],"sources":["../src/config.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { GkmConfig } from './types.js';\nimport {\n\tisWorkspaceConfig,\n\ttype LoadedConfig,\n\tprocessConfig,\n\ttype WorkspaceConfig,\n} from './workspace/index.js';\n\nexport type { GkmConfig } from './types.js';\nexport type { LoadedConfig, WorkspaceConfig } from './workspace/index.js';\nexport { defineWorkspace } from './workspace/index.js';\n/**\n * Define GKM configuration with full TypeScript support.\n * This is an identity function that provides type safety and autocomplete.\n *\n * @example\n * ```ts\n * // gkm.config.ts\n * import { defineConfig } from '@geekmidas/cli/config';\n *\n * export default defineConfig({\n * routes: './src/endpoints/**\\/*.ts',\n * envParser: './src/config/env',\n * logger: './src/config/logger',\n * telescope: true,\n * });\n * ```\n */\nexport function defineConfig(config: GkmConfig): GkmConfig {\n\treturn config;\n}\n\nexport interface ParsedModuleConfig {\n\tpath: string;\n\timportPattern: string;\n}\n\n/**\n * Parse a module config string into path and import pattern.\n *\n * @param configString - Config string in format \"./path/to/module\" or \"./path/to/module#exportName\"\n * @param defaultAlias - The default alias name to use if no export name specified\n * @returns Object with path and import pattern\n *\n * @example\n * parseModuleConfig('./src/config/env', 'envParser')\n * // { path: './src/config/env', importPattern: 'envParser' }\n *\n * parseModuleConfig('./src/config/env#envParser', 'envParser')\n * // { path: './src/config/env', importPattern: '{ envParser }' }\n *\n * parseModuleConfig('./src/config/env#myEnv', 'envParser')\n * // { path: './src/config/env', importPattern: '{ myEnv as envParser }' }\n */\nexport function parseModuleConfig(\n\tconfigString: string,\n\tdefaultAlias: string,\n): ParsedModuleConfig {\n\tconst parts = configString.split('#');\n\tconst path = parts[0] ?? configString;\n\tconst exportName = parts[1];\n\tconst importPattern = !exportName\n\t\t? defaultAlias\n\t\t: exportName === defaultAlias\n\t\t\t? `{ ${defaultAlias} }`\n\t\t\t: `{ ${exportName} as ${defaultAlias} }`;\n\n\treturn { path, importPattern };\n}\n\n/**\n * Find and return the path to the config file.\n */\nfunction findConfigPath(cwd: string): string {\n\tconst files = ['gkm.config.json', 'gkm.config.ts', 'gkm.config.js'];\n\n\tfor (const file of files) {\n\t\tconst path = join(cwd, file);\n\t\tif (existsSync(path)) {\n\t\t\treturn path;\n\t\t}\n\t}\n\n\tthrow new Error(\n\t\t'Configuration file not found. Please create gkm.config.json, gkm.config.ts, or gkm.config.js in the project root.',\n\t);\n}\n\n/**\n * Load raw configuration from file.\n */\nasync function loadRawConfig(\n\tcwd: string,\n): Promise<GkmConfig | WorkspaceConfig> {\n\tconst configPath = findConfigPath(cwd);\n\n\ttry {\n\t\tconst config = await import(configPath);\n\t\treturn config.default;\n\t} catch (error) {\n\t\tthrow new Error(`Failed to load config: ${(error as Error).message}`);\n\t}\n}\n\n/**\n * Load configuration file (single-app format).\n * For backwards compatibility with existing code.\n *\n * @deprecated Use loadWorkspaceConfig for new code\n */\nexport async function loadConfig(\n\tcwd: string = process.cwd(),\n): Promise<GkmConfig> {\n\tconst config = await loadRawConfig(cwd);\n\n\t// If it's a workspace config, throw an error\n\tif (isWorkspaceConfig(config)) {\n\t\tthrow new Error(\n\t\t\t'Workspace configuration detected. Use loadWorkspaceConfig() instead.',\n\t\t);\n\t}\n\n\treturn config;\n}\n\n/**\n * Load configuration file and process it as a workspace.\n * Works with both single-app and workspace configurations.\n *\n * Single-app configs are automatically wrapped as a workspace with one app.\n *\n * @example\n * ```ts\n * const { type, workspace } = await loadWorkspaceConfig();\n *\n * if (type === 'workspace') {\n * console.log('Multi-app workspace:', workspace.apps);\n * } else {\n * console.log('Single app wrapped as workspace');\n * }\n * ```\n */\nexport async function loadWorkspaceConfig(\n\tcwd: string = process.cwd(),\n): Promise<LoadedConfig> {\n\tconst config = await loadRawConfig(cwd);\n\treturn processConfig(config, cwd);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;AA8BA,SAAgB,aAAaA,QAA8B;AAC1D,QAAO;AACP;;;;;;;;;;;;;;;;;;AAwBD,SAAgB,kBACfC,cACAC,cACqB;CACrB,MAAM,QAAQ,aAAa,MAAM,IAAI;CACrC,MAAM,OAAO,MAAM,MAAM;CACzB,MAAM,aAAa,MAAM;CACzB,MAAM,iBAAiB,aACpB,eACA,eAAe,gBACb,IAAI,aAAa,OACjB,IAAI,WAAW,MAAM,aAAa;AAEvC,QAAO;EAAE;EAAM;CAAe;AAC9B;;;;AAKD,SAAS,eAAeC,KAAqB;CAC5C,MAAM,QAAQ;EAAC;EAAmB;EAAiB;CAAgB;AAEnE,MAAK,MAAM,QAAQ,OAAO;EACzB,MAAM,OAAO,KAAK,KAAK,KAAK;AAC5B,MAAI,WAAW,KAAK,CACnB,QAAO;CAER;AAED,OAAM,IAAI,MACT;AAED;;;;AAKD,eAAe,cACdA,KACuC;CACvC,MAAM,aAAa,eAAe,IAAI;AAEtC,KAAI;EACH,MAAM,SAAS,MAAM,OAAO;AAC5B,SAAO,OAAO;CACd,SAAQ,OAAO;AACf,QAAM,IAAI,OAAO,yBAA0B,MAAgB,QAAQ;CACnE;AACD;;;;;;;AAQD,eAAsB,WACrBA,MAAc,QAAQ,KAAK,EACN;CACrB,MAAM,SAAS,MAAM,cAAc,IAAI;AAGvC,KAAI,kBAAkB,OAAO,CAC5B,OAAM,IAAI,MACT;AAIF,QAAO;AACP;;;;;;;;;;;;;;;;;;AAmBD,eAAsB,oBACrBA,MAAc,QAAQ,KAAK,EACH;CACxB,MAAM,SAAS,MAAM,cAAc,IAAI;AACvC,QAAO,cAAc,QAAQ,IAAI;AACjC"}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"config-CxrLu8ia.cjs","names":["config: GkmConfig","configString: string","defaultAlias: string","cwd: string"],"sources":["../src/config.ts"],"sourcesContent":["import { existsSync } from 'node:fs';\nimport { join } from 'node:path';\nimport type { GkmConfig } from './types.js';\nimport {\n\tisWorkspaceConfig,\n\ttype LoadedConfig,\n\tprocessConfig,\n\ttype WorkspaceConfig,\n} from './workspace/index.js';\n\nexport type { GkmConfig } from './types.js';\nexport type { LoadedConfig, WorkspaceConfig } from './workspace/index.js';\nexport { defineWorkspace } from './workspace/index.js';\n/**\n * Define GKM configuration with full TypeScript support.\n * This is an identity function that provides type safety and autocomplete.\n *\n * @example\n * ```ts\n * // gkm.config.ts\n * import { defineConfig } from '@geekmidas/cli/config';\n *\n * export default defineConfig({\n * routes: './src/endpoints/**\\/*.ts',\n * envParser: './src/config/env',\n * logger: './src/config/logger',\n * telescope: true,\n * });\n * ```\n */\nexport function defineConfig(config: GkmConfig): GkmConfig {\n\treturn config;\n}\n\nexport interface ParsedModuleConfig {\n\tpath: string;\n\timportPattern: string;\n}\n\n/**\n * Parse a module config string into path and import pattern.\n *\n * @param configString - Config string in format \"./path/to/module\" or \"./path/to/module#exportName\"\n * @param defaultAlias - The default alias name to use if no export name specified\n * @returns Object with path and import pattern\n *\n * @example\n * parseModuleConfig('./src/config/env', 'envParser')\n * // { path: './src/config/env', importPattern: 'envParser' }\n *\n * parseModuleConfig('./src/config/env#envParser', 'envParser')\n * // { path: './src/config/env', importPattern: '{ envParser }' }\n *\n * parseModuleConfig('./src/config/env#myEnv', 'envParser')\n * // { path: './src/config/env', importPattern: '{ myEnv as envParser }' }\n */\nexport function parseModuleConfig(\n\tconfigString: string,\n\tdefaultAlias: string,\n): ParsedModuleConfig {\n\tconst parts = configString.split('#');\n\tconst path = parts[0] ?? configString;\n\tconst exportName = parts[1];\n\tconst importPattern = !exportName\n\t\t? defaultAlias\n\t\t: exportName === defaultAlias\n\t\t\t? `{ ${defaultAlias} }`\n\t\t\t: `{ ${exportName} as ${defaultAlias} }`;\n\n\treturn { path, importPattern };\n}\n\n/**\n * Find and return the path to the config file.\n */\nfunction findConfigPath(cwd: string): string {\n\tconst files = ['gkm.config.json', 'gkm.config.ts', 'gkm.config.js'];\n\n\tfor (const file of files) {\n\t\tconst path = join(cwd, file);\n\t\tif (existsSync(path)) {\n\t\t\treturn path;\n\t\t}\n\t}\n\n\tthrow new Error(\n\t\t'Configuration file not found. Please create gkm.config.json, gkm.config.ts, or gkm.config.js in the project root.',\n\t);\n}\n\n/**\n * Load raw configuration from file.\n */\nasync function loadRawConfig(\n\tcwd: string,\n): Promise<GkmConfig | WorkspaceConfig> {\n\tconst configPath = findConfigPath(cwd);\n\n\ttry {\n\t\tconst config = await import(configPath);\n\t\treturn config.default;\n\t} catch (error) {\n\t\tthrow new Error(`Failed to load config: ${(error as Error).message}`);\n\t}\n}\n\n/**\n * Load configuration file (single-app format).\n * For backwards compatibility with existing code.\n *\n * @deprecated Use loadWorkspaceConfig for new code\n */\nexport async function loadConfig(\n\tcwd: string = process.cwd(),\n): Promise<GkmConfig> {\n\tconst config = await loadRawConfig(cwd);\n\n\t// If it's a workspace config, throw an error\n\tif (isWorkspaceConfig(config)) {\n\t\tthrow new Error(\n\t\t\t'Workspace configuration detected. Use loadWorkspaceConfig() instead.',\n\t\t);\n\t}\n\n\treturn config;\n}\n\n/**\n * Load configuration file and process it as a workspace.\n * Works with both single-app and workspace configurations.\n *\n * Single-app configs are automatically wrapped as a workspace with one app.\n *\n * @example\n * ```ts\n * const { type, workspace } = await loadWorkspaceConfig();\n *\n * if (type === 'workspace') {\n * console.log('Multi-app workspace:', workspace.apps);\n * } else {\n * console.log('Single app wrapped as workspace');\n * }\n * ```\n */\nexport async function loadWorkspaceConfig(\n\tcwd: string = process.cwd(),\n): Promise<LoadedConfig> {\n\tconst config = await loadRawConfig(cwd);\n\treturn processConfig(config, cwd);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;AA8BA,SAAgB,aAAaA,QAA8B;AAC1D,QAAO;AACP;;;;;;;;;;;;;;;;;;AAwBD,SAAgB,kBACfC,cACAC,cACqB;CACrB,MAAM,QAAQ,aAAa,MAAM,IAAI;CACrC,MAAM,OAAO,MAAM,MAAM;CACzB,MAAM,aAAa,MAAM;CACzB,MAAM,iBAAiB,aACpB,eACA,eAAe,gBACb,IAAI,aAAa,OACjB,IAAI,WAAW,MAAM,aAAa;AAEvC,QAAO;EAAE;EAAM;CAAe;AAC9B;;;;AAKD,SAAS,eAAeC,KAAqB;CAC5C,MAAM,QAAQ;EAAC;EAAmB;EAAiB;CAAgB;AAEnE,MAAK,MAAM,QAAQ,OAAO;EACzB,MAAM,OAAO,oBAAK,KAAK,KAAK;AAC5B,MAAI,wBAAW,KAAK,CACnB,QAAO;CAER;AAED,OAAM,IAAI,MACT;AAED;;;;AAKD,eAAe,cACdA,KACuC;CACvC,MAAM,aAAa,eAAe,IAAI;AAEtC,KAAI;EACH,MAAM,SAAS,MAAM,OAAO;AAC5B,SAAO,OAAO;CACd,SAAQ,OAAO;AACf,QAAM,IAAI,OAAO,yBAA0B,MAAgB,QAAQ;CACnE;AACD;;;;;;;AAQD,eAAsB,WACrBA,MAAc,QAAQ,KAAK,EACN;CACrB,MAAM,SAAS,MAAM,cAAc,IAAI;AAGvC,KAAI,oCAAkB,OAAO,CAC5B,OAAM,IAAI,MACT;AAIF,QAAO;AACP;;;;;;;;;;;;;;;;;;AAmBD,eAAsB,oBACrBA,MAAc,QAAQ,KAAK,EACH;CACxB,MAAM,SAAS,MAAM,cAAc,IAAI;AACvC,QAAO,gCAAc,QAAQ,IAAI;AACjC"}
|