@geekmidas/cli 0.9.0 → 0.12.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.
Files changed (146) hide show
  1. package/README.md +525 -0
  2. package/dist/bundler-DRXCw_YR.mjs +70 -0
  3. package/dist/bundler-DRXCw_YR.mjs.map +1 -0
  4. package/dist/bundler-WsEvH_b2.cjs +71 -0
  5. package/dist/bundler-WsEvH_b2.cjs.map +1 -0
  6. package/dist/{config-CFls09Ey.cjs → config-AmInkU7k.cjs} +10 -8
  7. package/dist/config-AmInkU7k.cjs.map +1 -0
  8. package/dist/{config-Bq72aj8e.mjs → config-DYULeEv8.mjs} +6 -4
  9. package/dist/config-DYULeEv8.mjs.map +1 -0
  10. package/dist/config.cjs +1 -1
  11. package/dist/config.d.cts +2 -1
  12. package/dist/config.d.cts.map +1 -0
  13. package/dist/config.d.mts +2 -1
  14. package/dist/config.d.mts.map +1 -0
  15. package/dist/config.mjs +1 -1
  16. package/dist/encryption-C8H-38Yy.mjs +42 -0
  17. package/dist/encryption-C8H-38Yy.mjs.map +1 -0
  18. package/dist/encryption-Dyf_r1h-.cjs +44 -0
  19. package/dist/encryption-Dyf_r1h-.cjs.map +1 -0
  20. package/dist/index.cjs +2125 -184
  21. package/dist/index.cjs.map +1 -1
  22. package/dist/index.mjs +2143 -197
  23. package/dist/index.mjs.map +1 -1
  24. package/dist/{openapi--vOy9mo4.mjs → openapi-BfFlOBCG.mjs} +812 -49
  25. package/dist/openapi-BfFlOBCG.mjs.map +1 -0
  26. package/dist/{openapi-CHhTPief.cjs → openapi-Bt_1FDpT.cjs} +805 -42
  27. package/dist/openapi-Bt_1FDpT.cjs.map +1 -0
  28. package/dist/{openapi-react-query-o5iMi8tz.cjs → openapi-react-query-B-sNWHFU.cjs} +5 -5
  29. package/dist/openapi-react-query-B-sNWHFU.cjs.map +1 -0
  30. package/dist/{openapi-react-query-CcciaVu5.mjs → openapi-react-query-B6XTeGqS.mjs} +5 -5
  31. package/dist/openapi-react-query-B6XTeGqS.mjs.map +1 -0
  32. package/dist/openapi-react-query.cjs +1 -1
  33. package/dist/openapi-react-query.d.cts.map +1 -0
  34. package/dist/openapi-react-query.d.mts.map +1 -0
  35. package/dist/openapi-react-query.mjs +1 -1
  36. package/dist/openapi.cjs +2 -2
  37. package/dist/openapi.d.cts +1 -1
  38. package/dist/openapi.d.cts.map +1 -0
  39. package/dist/openapi.d.mts +1 -1
  40. package/dist/openapi.d.mts.map +1 -0
  41. package/dist/openapi.mjs +2 -2
  42. package/dist/storage-BUYQJgz7.cjs +4 -0
  43. package/dist/storage-BXoJvmv2.cjs +149 -0
  44. package/dist/storage-BXoJvmv2.cjs.map +1 -0
  45. package/dist/storage-C9PU_30f.mjs +101 -0
  46. package/dist/storage-C9PU_30f.mjs.map +1 -0
  47. package/dist/storage-DLJAYxzJ.mjs +3 -0
  48. package/dist/{types-b-vwGpqc.d.cts → types-BR0M2v_c.d.mts} +100 -1
  49. package/dist/types-BR0M2v_c.d.mts.map +1 -0
  50. package/dist/{types-DXgiA1sF.d.mts → types-BhkZc-vm.d.cts} +100 -1
  51. package/dist/types-BhkZc-vm.d.cts.map +1 -0
  52. package/examples/cron-example.ts +27 -27
  53. package/examples/env.ts +27 -27
  54. package/examples/function-example.ts +31 -31
  55. package/examples/gkm.config.json +20 -20
  56. package/examples/gkm.config.ts +8 -8
  57. package/examples/gkm.minimal.config.json +5 -5
  58. package/examples/gkm.production.config.json +25 -25
  59. package/examples/logger.ts +2 -2
  60. package/package.json +6 -6
  61. package/src/__tests__/EndpointGenerator.hooks.spec.ts +191 -191
  62. package/src/__tests__/config.spec.ts +55 -55
  63. package/src/__tests__/loadEnvFiles.spec.ts +93 -93
  64. package/src/__tests__/normalizeHooksConfig.spec.ts +58 -58
  65. package/src/__tests__/openapi-react-query.spec.ts +497 -497
  66. package/src/__tests__/openapi.spec.ts +428 -428
  67. package/src/__tests__/test-helpers.ts +77 -76
  68. package/src/auth/__tests__/credentials.spec.ts +204 -0
  69. package/src/auth/__tests__/index.spec.ts +168 -0
  70. package/src/auth/credentials.ts +187 -0
  71. package/src/auth/index.ts +226 -0
  72. package/src/build/__tests__/index-new.spec.ts +474 -474
  73. package/src/build/__tests__/manifests.spec.ts +333 -333
  74. package/src/build/bundler.ts +141 -0
  75. package/src/build/endpoint-analyzer.ts +236 -0
  76. package/src/build/handler-templates.ts +1253 -0
  77. package/src/build/index.ts +250 -179
  78. package/src/build/manifests.ts +52 -52
  79. package/src/build/providerResolver.ts +145 -145
  80. package/src/build/types.ts +64 -43
  81. package/src/config.ts +39 -37
  82. package/src/deploy/__tests__/docker.spec.ts +111 -0
  83. package/src/deploy/__tests__/dokploy.spec.ts +245 -0
  84. package/src/deploy/__tests__/init.spec.ts +662 -0
  85. package/src/deploy/docker.ts +128 -0
  86. package/src/deploy/dokploy.ts +204 -0
  87. package/src/deploy/index.ts +136 -0
  88. package/src/deploy/init.ts +484 -0
  89. package/src/deploy/types.ts +48 -0
  90. package/src/dev/__tests__/index.spec.ts +266 -266
  91. package/src/dev/index.ts +647 -593
  92. package/src/docker/__tests__/compose.spec.ts +531 -0
  93. package/src/docker/__tests__/templates.spec.ts +280 -0
  94. package/src/docker/compose.ts +273 -0
  95. package/src/docker/index.ts +230 -0
  96. package/src/docker/templates.ts +446 -0
  97. package/src/generators/CronGenerator.ts +72 -72
  98. package/src/generators/EndpointGenerator.ts +699 -398
  99. package/src/generators/FunctionGenerator.ts +84 -84
  100. package/src/generators/Generator.ts +72 -72
  101. package/src/generators/OpenApiTsGenerator.ts +589 -589
  102. package/src/generators/SubscriberGenerator.ts +124 -124
  103. package/src/generators/__tests__/CronGenerator.spec.ts +433 -433
  104. package/src/generators/__tests__/EndpointGenerator.spec.ts +532 -382
  105. package/src/generators/__tests__/FunctionGenerator.spec.ts +244 -244
  106. package/src/generators/__tests__/SubscriberGenerator.spec.ts +397 -382
  107. package/src/generators/index.ts +4 -4
  108. package/src/index.ts +628 -206
  109. package/src/init/__tests__/generators.spec.ts +334 -334
  110. package/src/init/__tests__/init.spec.ts +332 -332
  111. package/src/init/__tests__/utils.spec.ts +89 -89
  112. package/src/init/generators/config.ts +175 -175
  113. package/src/init/generators/docker.ts +41 -41
  114. package/src/init/generators/env.ts +72 -72
  115. package/src/init/generators/index.ts +1 -1
  116. package/src/init/generators/models.ts +64 -64
  117. package/src/init/generators/monorepo.ts +161 -161
  118. package/src/init/generators/package.ts +71 -71
  119. package/src/init/generators/source.ts +6 -6
  120. package/src/init/index.ts +203 -208
  121. package/src/init/templates/api.ts +115 -115
  122. package/src/init/templates/index.ts +75 -75
  123. package/src/init/templates/minimal.ts +98 -98
  124. package/src/init/templates/serverless.ts +89 -89
  125. package/src/init/templates/worker.ts +98 -98
  126. package/src/init/utils.ts +54 -56
  127. package/src/openapi-react-query.ts +194 -194
  128. package/src/openapi.ts +63 -63
  129. package/src/secrets/__tests__/encryption.spec.ts +226 -0
  130. package/src/secrets/__tests__/generator.spec.ts +319 -0
  131. package/src/secrets/__tests__/index.spec.ts +91 -0
  132. package/src/secrets/__tests__/storage.spec.ts +403 -0
  133. package/src/secrets/encryption.ts +91 -0
  134. package/src/secrets/generator.ts +164 -0
  135. package/src/secrets/index.ts +383 -0
  136. package/src/secrets/storage.ts +134 -0
  137. package/src/secrets/types.ts +53 -0
  138. package/src/types.ts +295 -176
  139. package/tsconfig.json +9 -0
  140. package/tsdown.config.ts +11 -8
  141. package/dist/config-Bq72aj8e.mjs.map +0 -1
  142. package/dist/config-CFls09Ey.cjs.map +0 -1
  143. package/dist/openapi--vOy9mo4.mjs.map +0 -1
  144. package/dist/openapi-CHhTPief.cjs.map +0 -1
  145. package/dist/openapi-react-query-CcciaVu5.mjs.map +0 -1
  146. package/dist/openapi-react-query-o5iMi8tz.cjs.map +0 -1
@@ -1,17 +1,17 @@
1
1
  import type {
2
- AWSApiGatewayConfig,
3
- AWSLambdaConfig,
4
- BuildOptions,
5
- GkmConfig,
6
- LegacyProvider,
7
- MainProvider,
8
- ProvidersConfig,
9
- ServerConfig,
2
+ AWSApiGatewayConfig,
3
+ AWSLambdaConfig,
4
+ BuildOptions,
5
+ GkmConfig,
6
+ LegacyProvider,
7
+ MainProvider,
8
+ ProvidersConfig,
9
+ ServerConfig,
10
10
  } from '../types';
11
11
 
12
12
  export interface ResolvedProviders {
13
- providers: LegacyProvider[];
14
- enableOpenApi: boolean;
13
+ providers: LegacyProvider[];
14
+ enableOpenApi: boolean;
15
15
  }
16
16
 
17
17
  /**
@@ -19,166 +19,166 @@ export interface ResolvedProviders {
19
19
  * to the internal legacy format for backward compatibility
20
20
  */
21
21
  export function resolveProviders(
22
- config: GkmConfig,
23
- options: BuildOptions,
22
+ config: GkmConfig,
23
+ options: BuildOptions,
24
24
  ): ResolvedProviders {
25
- const providers: LegacyProvider[] = [];
26
- let enableOpenApi = options.enableOpenApi || false;
27
-
28
- // Handle legacy providers option (deprecated)
29
- if (options.providers) {
30
- return {
31
- providers: options.providers,
32
- enableOpenApi,
33
- };
34
- }
35
-
36
- // Handle new provider option
37
- if (options.provider) {
38
- const resolvedProviders = resolveMainProvider(
39
- options.provider,
40
- config.providers,
41
- );
42
- providers.push(...resolvedProviders.providers);
43
- enableOpenApi = resolvedProviders.enableOpenApi || enableOpenApi;
44
- }
45
- // Default: build all configured providers
46
- else if (config.providers) {
47
- const resolvedProviders = resolveAllConfiguredProviders(config.providers);
48
- providers.push(...resolvedProviders.providers);
49
- enableOpenApi = resolvedProviders.enableOpenApi || enableOpenApi;
50
- }
51
- // Fallback: use default AWS configuration
52
- else {
53
- providers.push('aws-apigatewayv2', 'aws-lambda');
54
- }
55
-
56
- return {
57
- providers: [...new Set(providers)], // Remove duplicates
58
- enableOpenApi,
59
- };
25
+ const providers: LegacyProvider[] = [];
26
+ let enableOpenApi = options.enableOpenApi || false;
27
+
28
+ // Handle legacy providers option (deprecated)
29
+ if (options.providers) {
30
+ return {
31
+ providers: options.providers,
32
+ enableOpenApi,
33
+ };
34
+ }
35
+
36
+ // Handle new provider option
37
+ if (options.provider) {
38
+ const resolvedProviders = resolveMainProvider(
39
+ options.provider,
40
+ config.providers,
41
+ );
42
+ providers.push(...resolvedProviders.providers);
43
+ enableOpenApi = resolvedProviders.enableOpenApi || enableOpenApi;
44
+ }
45
+ // Default: build all configured providers
46
+ else if (config.providers) {
47
+ const resolvedProviders = resolveAllConfiguredProviders(config.providers);
48
+ providers.push(...resolvedProviders.providers);
49
+ enableOpenApi = resolvedProviders.enableOpenApi || enableOpenApi;
50
+ }
51
+ // Fallback: use default AWS configuration
52
+ else {
53
+ providers.push('aws-apigatewayv2', 'aws-lambda');
54
+ }
55
+
56
+ return {
57
+ providers: [...new Set(providers)], // Remove duplicates
58
+ enableOpenApi,
59
+ };
60
60
  }
61
61
 
62
62
  function resolveMainProvider(
63
- mainProvider: MainProvider,
64
- providersConfig?: ProvidersConfig,
63
+ mainProvider: MainProvider,
64
+ providersConfig?: ProvidersConfig,
65
65
  ): ResolvedProviders {
66
- const providers: LegacyProvider[] = [];
67
- let enableOpenApi = false;
68
-
69
- if (mainProvider === 'aws') {
70
- const awsConfig = providersConfig?.aws;
71
-
72
- // Resolve API Gateway providers
73
- if (awsConfig?.apiGateway) {
74
- if (isEnabled(awsConfig.apiGateway.v1)) {
75
- providers.push('aws-apigatewayv1');
76
- }
77
- if (isEnabled(awsConfig.apiGateway.v2)) {
78
- providers.push('aws-apigatewayv2');
79
- }
80
- } else {
81
- // Default: enable v2 if no specific config
82
- providers.push('aws-apigatewayv2');
83
- }
84
-
85
- // Resolve Lambda providers
86
- if (awsConfig?.lambda) {
87
- if (
88
- isEnabled(awsConfig.lambda.functions) ||
89
- isEnabled(awsConfig.lambda.crons)
90
- ) {
91
- providers.push('aws-lambda');
92
- }
93
- } else {
94
- // Default: enable lambda if no specific config
95
- providers.push('aws-lambda');
96
- }
97
- } else if (mainProvider === 'server') {
98
- providers.push('server');
99
- const serverConfig = providersConfig?.server;
100
-
101
- if (typeof serverConfig === 'object' && serverConfig?.enableOpenApi) {
102
- enableOpenApi = true;
103
- }
104
- }
105
-
106
- return { providers, enableOpenApi };
66
+ const providers: LegacyProvider[] = [];
67
+ let enableOpenApi = false;
68
+
69
+ if (mainProvider === 'aws') {
70
+ const awsConfig = providersConfig?.aws;
71
+
72
+ // Resolve API Gateway providers
73
+ if (awsConfig?.apiGateway) {
74
+ if (isEnabled(awsConfig.apiGateway.v1)) {
75
+ providers.push('aws-apigatewayv1');
76
+ }
77
+ if (isEnabled(awsConfig.apiGateway.v2)) {
78
+ providers.push('aws-apigatewayv2');
79
+ }
80
+ } else {
81
+ // Default: enable v2 if no specific config
82
+ providers.push('aws-apigatewayv2');
83
+ }
84
+
85
+ // Resolve Lambda providers
86
+ if (awsConfig?.lambda) {
87
+ if (
88
+ isEnabled(awsConfig.lambda.functions) ||
89
+ isEnabled(awsConfig.lambda.crons)
90
+ ) {
91
+ providers.push('aws-lambda');
92
+ }
93
+ } else {
94
+ // Default: enable lambda if no specific config
95
+ providers.push('aws-lambda');
96
+ }
97
+ } else if (mainProvider === 'server') {
98
+ providers.push('server');
99
+ const serverConfig = providersConfig?.server;
100
+
101
+ if (typeof serverConfig === 'object' && serverConfig?.enableOpenApi) {
102
+ enableOpenApi = true;
103
+ }
104
+ }
105
+
106
+ return { providers, enableOpenApi };
107
107
  }
108
108
 
109
109
  function resolveAllConfiguredProviders(
110
- providersConfig: ProvidersConfig,
110
+ providersConfig: ProvidersConfig,
111
111
  ): ResolvedProviders {
112
- const providers: LegacyProvider[] = [];
113
- let enableOpenApi = false;
114
-
115
- // AWS providers
116
- if (providersConfig.aws) {
117
- const awsProviders = resolveMainProvider('aws', providersConfig);
118
- providers.push(...awsProviders.providers);
119
- }
120
-
121
- // Server provider
122
- if (providersConfig.server && isEnabled(providersConfig.server)) {
123
- providers.push('server');
124
- if (
125
- typeof providersConfig.server === 'object' &&
126
- providersConfig.server.enableOpenApi
127
- ) {
128
- enableOpenApi = true;
129
- }
130
- }
131
-
132
- return { providers, enableOpenApi };
112
+ const providers: LegacyProvider[] = [];
113
+ let enableOpenApi = false;
114
+
115
+ // AWS providers
116
+ if (providersConfig.aws) {
117
+ const awsProviders = resolveMainProvider('aws', providersConfig);
118
+ providers.push(...awsProviders.providers);
119
+ }
120
+
121
+ // Server provider
122
+ if (providersConfig.server && isEnabled(providersConfig.server)) {
123
+ providers.push('server');
124
+ if (
125
+ typeof providersConfig.server === 'object' &&
126
+ providersConfig.server.enableOpenApi
127
+ ) {
128
+ enableOpenApi = true;
129
+ }
130
+ }
131
+
132
+ return { providers, enableOpenApi };
133
133
  }
134
134
 
135
135
  function isEnabled(
136
- config:
137
- | boolean
138
- | AWSApiGatewayConfig
139
- | AWSLambdaConfig
140
- | ServerConfig
141
- | undefined,
136
+ config:
137
+ | boolean
138
+ | AWSApiGatewayConfig
139
+ | AWSLambdaConfig
140
+ | ServerConfig
141
+ | undefined,
142
142
  ): boolean {
143
- if (config === undefined) return false;
144
- if (typeof config === 'boolean') return config;
145
- return config.enabled !== false; // Default to true if enabled is not explicitly false
143
+ if (config === undefined) return false;
144
+ if (typeof config === 'boolean') return config;
145
+ return config.enabled !== false; // Default to true if enabled is not explicitly false
146
146
  }
147
147
 
148
148
  /**
149
149
  * Gets configuration for a specific AWS service
150
150
  */
151
151
  export function getAWSServiceConfig<
152
- T extends AWSApiGatewayConfig | AWSLambdaConfig,
152
+ T extends AWSApiGatewayConfig | AWSLambdaConfig,
153
153
  >(
154
- config: GkmConfig,
155
- service: 'apiGateway' | 'lambda',
156
- subService?: 'v1' | 'v2' | 'functions' | 'crons',
154
+ config: GkmConfig,
155
+ service: 'apiGateway' | 'lambda',
156
+ subService?: 'v1' | 'v2' | 'functions' | 'crons',
157
157
  ): T | undefined {
158
- const awsConfig = config.providers?.aws;
159
- if (!awsConfig) return undefined;
160
-
161
- if (service === 'apiGateway' && awsConfig.apiGateway) {
162
- const apiConfig = subService
163
- ? awsConfig.apiGateway[subService as 'v1' | 'v2']
164
- : undefined;
165
- return typeof apiConfig === 'object' ? (apiConfig as T) : undefined;
166
- }
167
-
168
- if (service === 'lambda' && awsConfig.lambda) {
169
- const lambdaConfig = subService
170
- ? awsConfig.lambda[subService as 'functions' | 'crons']
171
- : undefined;
172
- return typeof lambdaConfig === 'object' ? (lambdaConfig as T) : undefined;
173
- }
174
-
175
- return undefined;
158
+ const awsConfig = config.providers?.aws;
159
+ if (!awsConfig) return undefined;
160
+
161
+ if (service === 'apiGateway' && awsConfig.apiGateway) {
162
+ const apiConfig = subService
163
+ ? awsConfig.apiGateway[subService as 'v1' | 'v2']
164
+ : undefined;
165
+ return typeof apiConfig === 'object' ? (apiConfig as T) : undefined;
166
+ }
167
+
168
+ if (service === 'lambda' && awsConfig.lambda) {
169
+ const lambdaConfig = subService
170
+ ? awsConfig.lambda[subService as 'functions' | 'crons']
171
+ : undefined;
172
+ return typeof lambdaConfig === 'object' ? (lambdaConfig as T) : undefined;
173
+ }
174
+
175
+ return undefined;
176
176
  }
177
177
 
178
178
  /**
179
179
  * Gets server configuration
180
180
  */
181
181
  export function getServerConfig(config: GkmConfig): ServerConfig | undefined {
182
- const serverConfig = config.providers?.server;
183
- return typeof serverConfig === 'object' ? serverConfig : undefined;
182
+ const serverConfig = config.providers?.server;
183
+ return typeof serverConfig === 'object' ? serverConfig : undefined;
184
184
  }
@@ -5,68 +5,89 @@ import type { Function } from '@geekmidas/constructs/functions';
5
5
  import type { CronInfo, FunctionInfo, RouteInfo } from '../types';
6
6
 
7
7
  export interface ProcessedEndpoint {
8
- file: string;
9
- exportName: string;
10
- endpoint: Endpoint<any, any, any, any, any, any>;
11
- routeInfo: RouteInfo;
8
+ file: string;
9
+ exportName: string;
10
+ endpoint: Endpoint<any, any, any, any, any, any>;
11
+ routeInfo: RouteInfo;
12
12
  }
13
13
 
14
14
  export interface ProcessedFunction {
15
- file: string;
16
- exportName: string;
17
- fn: Function<any, any, any, any, any>;
15
+ file: string;
16
+ exportName: string;
17
+ fn: Function<any, any, any, any, any>;
18
18
  }
19
19
 
20
20
  export interface ProcessedCron {
21
- file: string;
22
- exportName: string;
23
- cron: Cron<any, any, any, any>;
24
- schedule?: string;
21
+ file: string;
22
+ exportName: string;
23
+ cron: Cron<any, any, any, any>;
24
+ schedule?: string;
25
25
  }
26
26
 
27
27
  export interface NormalizedTelescopeConfig {
28
- enabled: boolean;
29
- /** Path to user's telescope module (if provided) */
30
- telescopePath?: string;
31
- /** Import pattern for telescope (e.g., '{ telescope }' or 'telescope') */
32
- telescopeImportPattern?: string;
33
- /** UI path for telescope dashboard */
34
- path: string;
35
- ignore: string[];
36
- recordBody: boolean;
37
- maxEntries: number;
38
- websocket: boolean;
28
+ enabled: boolean;
29
+ /** Path to user's telescope module (if provided) */
30
+ telescopePath?: string;
31
+ /** Import pattern for telescope (e.g., '{ telescope }' or 'telescope') */
32
+ telescopeImportPattern?: string;
33
+ /** UI path for telescope dashboard */
34
+ path: string;
35
+ ignore: string[];
36
+ recordBody: boolean;
37
+ maxEntries: number;
38
+ websocket: boolean;
39
39
  }
40
40
 
41
41
  export interface NormalizedStudioConfig {
42
- enabled: boolean;
43
- /** Path to user's studio module (if provided) */
44
- studioPath?: string;
45
- /** Import pattern for studio (e.g., '{ studio }' or 'studio') */
46
- studioImportPattern?: string;
47
- /** UI path for studio dashboard */
48
- path: string;
49
- /** Database schema to introspect */
50
- schema: string;
42
+ enabled: boolean;
43
+ /** Path to user's studio module (if provided) */
44
+ studioPath?: string;
45
+ /** Import pattern for studio (e.g., '{ studio }' or 'studio') */
46
+ studioImportPattern?: string;
47
+ /** UI path for studio dashboard */
48
+ path: string;
49
+ /** Database schema to introspect */
50
+ schema: string;
51
51
  }
52
52
 
53
53
  export interface NormalizedHooksConfig {
54
- /** Path to server hooks module */
55
- serverHooksPath: string;
54
+ /** Path to server hooks module */
55
+ serverHooksPath: string;
56
+ }
57
+
58
+ export interface NormalizedProductionConfig {
59
+ enabled: boolean;
60
+ bundle: boolean;
61
+ minify: boolean;
62
+ healthCheck: string;
63
+ gracefulShutdown: boolean;
64
+ external: string[];
65
+ subscribers: 'include' | 'exclude';
66
+ openapi: boolean;
67
+ /**
68
+ * Enable build-time optimized handler generation
69
+ * When true, generates specialized handlers based on endpoint tier:
70
+ * - minimal: Near-raw-Hono performance for simple endpoints
71
+ * - standard: Optimized handlers for auth/services
72
+ * - full: Uses HonoEndpoint.addRoutes for complex endpoints
73
+ */
74
+ optimizedHandlers: boolean;
56
75
  }
57
76
 
58
77
  export interface BuildContext {
59
- envParserPath: string;
60
- envParserImportPattern: string;
61
- loggerPath: string;
62
- loggerImportPattern: string;
63
- telescope?: NormalizedTelescopeConfig;
64
- studio?: NormalizedStudioConfig;
65
- hooks?: NormalizedHooksConfig;
78
+ envParserPath: string;
79
+ envParserImportPattern: string;
80
+ loggerPath: string;
81
+ loggerImportPattern: string;
82
+ telescope?: NormalizedTelescopeConfig;
83
+ studio?: NormalizedStudioConfig;
84
+ hooks?: NormalizedHooksConfig;
85
+ /** Production build configuration */
86
+ production?: NormalizedProductionConfig;
66
87
  }
67
88
 
68
89
  export interface ProviderBuildResult {
69
- routes: RouteInfo[];
70
- functions: FunctionInfo[];
71
- crons: CronInfo[];
90
+ routes: RouteInfo[];
91
+ functions: FunctionInfo[];
92
+ crons: CronInfo[];
72
93
  }
package/src/config.ts CHANGED
@@ -1,5 +1,5 @@
1
- import { existsSync } from 'fs';
2
- import { join } from 'path';
1
+ import { existsSync } from 'node:fs';
2
+ import { join } from 'node:path';
3
3
  import type { GkmConfig } from './types.ts';
4
4
 
5
5
  export type { GkmConfig } from './types.ts';
@@ -21,12 +21,12 @@ export type { GkmConfig } from './types.ts';
21
21
  * ```
22
22
  */
23
23
  export function defineConfig(config: GkmConfig): GkmConfig {
24
- return config;
24
+ return config;
25
25
  }
26
26
 
27
27
  export interface ParsedModuleConfig {
28
- path: string;
29
- importPattern: string;
28
+ path: string;
29
+ importPattern: string;
30
30
  }
31
31
 
32
32
  /**
@@ -47,45 +47,47 @@ export interface ParsedModuleConfig {
47
47
  * // { path: './src/config/env', importPattern: '{ myEnv as envParser }' }
48
48
  */
49
49
  export function parseModuleConfig(
50
- configString: string,
51
- defaultAlias: string,
50
+ configString: string,
51
+ defaultAlias: string,
52
52
  ): ParsedModuleConfig {
53
- const [path, exportName] = configString.split('#');
54
- const importPattern = !exportName
55
- ? defaultAlias
56
- : exportName === defaultAlias
57
- ? `{ ${defaultAlias} }`
58
- : `{ ${exportName} as ${defaultAlias} }`;
53
+ const parts = configString.split('#');
54
+ const path = parts[0] ?? configString;
55
+ const exportName = parts[1];
56
+ const importPattern = !exportName
57
+ ? defaultAlias
58
+ : exportName === defaultAlias
59
+ ? `{ ${defaultAlias} }`
60
+ : `{ ${exportName} as ${defaultAlias} }`;
59
61
 
60
- return { path, importPattern };
62
+ return { path, importPattern };
61
63
  }
62
64
 
63
65
  export async function loadConfig(
64
- cwd: string = process.cwd(),
66
+ cwd: string = process.cwd(),
65
67
  ): Promise<GkmConfig> {
66
- const files = ['gkm.config.json', 'gkm.config.ts', 'gkm.config.js'];
67
- let configPath = '';
68
+ const files = ['gkm.config.json', 'gkm.config.ts', 'gkm.config.js'];
69
+ let configPath = '';
68
70
 
69
- for (const file of files) {
70
- const path = join(cwd, file);
71
- if (existsSync(path)) {
72
- configPath = path;
73
- break;
74
- }
75
- }
71
+ for (const file of files) {
72
+ const path = join(cwd, file);
73
+ if (existsSync(path)) {
74
+ configPath = path;
75
+ break;
76
+ }
77
+ }
76
78
 
77
- if (!configPath) {
78
- throw new Error(
79
- 'Configuration file not found. Please create gkm.config.json, gkm.config.ts, or gkm.config.js in the project root.',
80
- );
81
- }
79
+ if (!configPath) {
80
+ throw new Error(
81
+ 'Configuration file not found. Please create gkm.config.json, gkm.config.ts, or gkm.config.js in the project root.',
82
+ );
83
+ }
82
84
 
83
- try {
84
- const config = await import(configPath);
85
- return config.default;
86
- } catch (error) {
87
- throw new Error(
88
- `Failed to load gkm.config.json: ${(error as Error).message}`,
89
- );
90
- }
85
+ try {
86
+ const config = await import(configPath);
87
+ return config.default;
88
+ } catch (error) {
89
+ throw new Error(
90
+ `Failed to load gkm.config.json: ${(error as Error).message}`,
91
+ );
92
+ }
91
93
  }
@@ -0,0 +1,111 @@
1
+ import { describe, expect, it } from 'vitest';
2
+ import type { GkmConfig } from '../../types';
3
+ import { getImageRef, resolveDockerConfig } from '../docker';
4
+
5
+ describe('getImageRef', () => {
6
+ it('should return image with registry prefix', () => {
7
+ const result = getImageRef('ghcr.io/myorg', 'myapp', 'v1.0.0');
8
+ expect(result).toBe('ghcr.io/myorg/myapp:v1.0.0');
9
+ });
10
+
11
+ it('should return image without registry when undefined', () => {
12
+ const result = getImageRef(undefined, 'myapp', 'v1.0.0');
13
+ expect(result).toBe('myapp:v1.0.0');
14
+ });
15
+
16
+ it('should handle different tag formats', () => {
17
+ expect(getImageRef('docker.io', 'app', 'latest')).toBe(
18
+ 'docker.io/app:latest',
19
+ );
20
+ expect(getImageRef('docker.io', 'app', 'sha-abc123')).toBe(
21
+ 'docker.io/app:sha-abc123',
22
+ );
23
+ expect(getImageRef('docker.io', 'app', '1.2.3-beta.1')).toBe(
24
+ 'docker.io/app:1.2.3-beta.1',
25
+ );
26
+ });
27
+
28
+ it('should handle registry with port', () => {
29
+ const result = getImageRef('localhost:5000', 'myapp', 'dev');
30
+ expect(result).toBe('localhost:5000/myapp:dev');
31
+ });
32
+
33
+ it('should handle nested registry paths', () => {
34
+ const result = getImageRef('gcr.io/my-project/images', 'api', 'prod');
35
+ expect(result).toBe('gcr.io/my-project/images/api:prod');
36
+ });
37
+ });
38
+
39
+ describe('resolveDockerConfig', () => {
40
+ it('should return empty config when docker not configured', () => {
41
+ const config: GkmConfig = {
42
+ routes: './src/endpoints',
43
+ envParser: './src/env',
44
+ logger: './src/logger',
45
+ };
46
+
47
+ const dockerConfig = resolveDockerConfig(config);
48
+
49
+ expect(dockerConfig.registry).toBeUndefined();
50
+ expect(dockerConfig.imageName).toBeUndefined();
51
+ });
52
+
53
+ it('should return registry from docker config', () => {
54
+ const config: GkmConfig = {
55
+ routes: './src/endpoints',
56
+ envParser: './src/env',
57
+ logger: './src/logger',
58
+ docker: {
59
+ registry: 'ghcr.io/myorg',
60
+ },
61
+ };
62
+
63
+ const dockerConfig = resolveDockerConfig(config);
64
+
65
+ expect(dockerConfig.registry).toBe('ghcr.io/myorg');
66
+ });
67
+
68
+ it('should return imageName from docker config', () => {
69
+ const config: GkmConfig = {
70
+ routes: './src/endpoints',
71
+ envParser: './src/env',
72
+ logger: './src/logger',
73
+ docker: {
74
+ imageName: 'my-api',
75
+ },
76
+ };
77
+
78
+ const dockerConfig = resolveDockerConfig(config);
79
+
80
+ expect(dockerConfig.imageName).toBe('my-api');
81
+ });
82
+
83
+ it('should return both registry and imageName', () => {
84
+ const config: GkmConfig = {
85
+ routes: './src/endpoints',
86
+ envParser: './src/env',
87
+ logger: './src/logger',
88
+ docker: {
89
+ registry: 'docker.io/company',
90
+ imageName: 'backend-api',
91
+ },
92
+ };
93
+
94
+ const dockerConfig = resolveDockerConfig(config);
95
+
96
+ expect(dockerConfig.registry).toBe('docker.io/company');
97
+ expect(dockerConfig.imageName).toBe('backend-api');
98
+ });
99
+
100
+ it('should handle empty docker object', () => {
101
+ const config: GkmConfig = {
102
+ routes: './src/endpoints',
103
+ docker: {},
104
+ };
105
+
106
+ const dockerConfig = resolveDockerConfig(config);
107
+
108
+ expect(dockerConfig.registry).toBeUndefined();
109
+ expect(dockerConfig.imageName).toBeUndefined();
110
+ });
111
+ });