@geekmidas/cli 0.28.0 → 0.29.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@geekmidas/cli",
3
- "version": "0.28.0",
3
+ "version": "0.29.0",
4
4
  "description": "CLI tools for building Lambda handlers, server applications, and generating OpenAPI specs",
5
5
  "private": false,
6
6
  "type": "module",
@@ -48,11 +48,11 @@
48
48
  "lodash.kebabcase": "^4.1.1",
49
49
  "openapi-typescript": "^7.4.2",
50
50
  "prompts": "~2.4.2",
51
- "@geekmidas/logger": "~0.4.0",
52
51
  "@geekmidas/errors": "~0.1.0",
53
52
  "@geekmidas/envkit": "~0.4.0",
54
53
  "@geekmidas/constructs": "~0.6.0",
55
- "@geekmidas/schema": "~0.1.0"
54
+ "@geekmidas/schema": "~0.1.0",
55
+ "@geekmidas/logger": "~0.4.0"
56
56
  },
57
57
  "devDependencies": {
58
58
  "@types/lodash.kebabcase": "^4.1.9",
@@ -1,4 +1,5 @@
1
1
  import type { GeneratedFile, TemplateOptions } from '../templates/index.js';
2
+ import { GEEKMIDAS_VERSIONS } from '../versions.js';
2
3
 
3
4
  /**
4
5
  * Generate Next.js web app files for fullstack template
@@ -25,6 +26,8 @@ export function generateWebAppFiles(options: TemplateOptions): GeneratedFile[] {
25
26
  },
26
27
  dependencies: {
27
28
  [modelsPackage]: 'workspace:*',
29
+ '@geekmidas/client': GEEKMIDAS_VERSIONS['@geekmidas/client'],
30
+ '@tanstack/react-query': '~5.80.0',
28
31
  next: '~16.1.0',
29
32
  react: '~19.2.0',
30
33
  'react-dom': '~19.2.0',
@@ -82,8 +85,73 @@ export default nextConfig;
82
85
  exclude: ['node_modules'],
83
86
  };
84
87
 
88
+ // Providers with QueryClient
89
+ const providersTsx = `'use client';
90
+
91
+ import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
92
+ import { useState } from 'react';
93
+
94
+ export function Providers({ children }: { children: React.ReactNode }) {
95
+ const [queryClient] = useState(
96
+ () =>
97
+ new QueryClient({
98
+ defaultOptions: {
99
+ queries: {
100
+ staleTime: 60 * 1000,
101
+ },
102
+ },
103
+ }),
104
+ );
105
+
106
+ return (
107
+ <QueryClientProvider client={queryClient}>{children}</QueryClientProvider>
108
+ );
109
+ }
110
+ `;
111
+
112
+ // API client setup
113
+ const apiIndexTs = `import { TypedFetcher } from '@geekmidas/client/fetcher';
114
+ import { createEndpointHooks } from '@geekmidas/client/endpoint-hooks';
115
+
116
+ // TODO: Run 'gkm openapi' to generate typed paths from your API
117
+ // This is a placeholder that will be replaced by the generated openapi.ts
118
+ interface paths {
119
+ '/health': {
120
+ get: {
121
+ responses: {
122
+ 200: {
123
+ content: {
124
+ 'application/json': { status: string; timestamp: string };
125
+ };
126
+ };
127
+ };
128
+ };
129
+ };
130
+ '/users': {
131
+ get: {
132
+ responses: {
133
+ 200: {
134
+ content: {
135
+ 'application/json': { users: Array<{ id: string; name: string }> };
136
+ };
137
+ };
138
+ };
139
+ };
140
+ };
141
+ }
142
+
143
+ const baseURL = process.env.NEXT_PUBLIC_API_URL || 'http://localhost:3000';
144
+
145
+ const fetcher = new TypedFetcher<paths>({ baseURL });
146
+
147
+ const hooks = createEndpointHooks<paths>(fetcher.request.bind(fetcher));
148
+
149
+ export const api = Object.assign(fetcher.request.bind(fetcher), hooks);
150
+ `;
151
+
85
152
  // App layout
86
153
  const layoutTsx = `import type { Metadata } from 'next';
154
+ import { Providers } from './providers';
87
155
 
88
156
  export const metadata: Metadata = {
89
157
  title: '${options.name}',
@@ -97,37 +165,20 @@ export default function RootLayout({
97
165
  }) {
98
166
  return (
99
167
  <html lang="en">
100
- <body>{children}</body>
168
+ <body>
169
+ <Providers>{children}</Providers>
170
+ </body>
101
171
  </html>
102
172
  );
103
173
  }
104
174
  `;
105
175
 
106
176
  // Home page with API example
107
- const pageTsx = `import type { User } from '${modelsPackage}';
177
+ const pageTsx = `import { api } from '@/api';
108
178
 
109
179
  export default async function Home() {
110
- // Example: Fetch from API
111
- const apiUrl = process.env.API_URL || 'http://localhost:3000';
112
- let health = null;
113
-
114
- try {
115
- const response = await fetch(\`\${apiUrl}/health\`, {
116
- cache: 'no-store',
117
- });
118
- health = await response.json();
119
- } catch (error) {
120
- console.error('Failed to fetch health:', error);
121
- }
122
-
123
- // Example: Type-safe model usage
124
- const exampleUser: User = {
125
- id: '123e4567-e89b-12d3-a456-426614174000',
126
- email: 'user@example.com',
127
- name: 'Example User',
128
- createdAt: new Date(),
129
- updatedAt: new Date(),
130
- };
180
+ // Type-safe API call using the generated client
181
+ const health = await api('GET /health').catch(() => null);
131
182
 
132
183
  return (
133
184
  <main style={{ padding: '2rem', fontFamily: 'system-ui' }}>
@@ -140,21 +191,14 @@ export default async function Home() {
140
191
  {JSON.stringify(health, null, 2)}
141
192
  </pre>
142
193
  ) : (
143
- <p>Unable to connect to API at {apiUrl}</p>
194
+ <p>Unable to connect to API</p>
144
195
  )}
145
196
  </section>
146
197
 
147
- <section style={{ marginTop: '2rem' }}>
148
- <h2>Shared Models</h2>
149
- <p>This user object is typed from @${options.name}/models:</p>
150
- <pre style={{ background: '#f0f0f0', padding: '1rem', borderRadius: '8px' }}>
151
- {JSON.stringify(exampleUser, null, 2)}
152
- </pre>
153
- </section>
154
-
155
198
  <section style={{ marginTop: '2rem' }}>
156
199
  <h2>Next Steps</h2>
157
200
  <ul>
201
+ <li>Run <code>gkm openapi</code> to generate typed API client</li>
158
202
  <li>Edit <code>apps/web/src/app/page.tsx</code> to customize this page</li>
159
203
  <li>Add API routes in <code>apps/api/src/endpoints/</code></li>
160
204
  <li>Define shared schemas in <code>packages/models/src/</code></li>
@@ -166,11 +210,8 @@ export default async function Home() {
166
210
  `;
167
211
 
168
212
  // Environment file for web app
169
- const envLocal = `# API URL (injected automatically in workspace mode)
170
- API_URL=http://localhost:3000
171
-
172
- # Other environment variables
173
- # NEXT_PUBLIC_API_URL=http://localhost:3000
213
+ const envLocal = `# API URL for client-side requests
214
+ NEXT_PUBLIC_API_URL=http://localhost:3000
174
215
  `;
175
216
 
176
217
  // .gitignore for Next.js
@@ -197,10 +238,18 @@ node_modules/
197
238
  path: 'apps/web/src/app/layout.tsx',
198
239
  content: layoutTsx,
199
240
  },
241
+ {
242
+ path: 'apps/web/src/app/providers.tsx',
243
+ content: providersTsx,
244
+ },
200
245
  {
201
246
  path: 'apps/web/src/app/page.tsx',
202
247
  content: pageTsx,
203
248
  },
249
+ {
250
+ path: 'apps/web/src/api/index.ts',
251
+ content: apiIndexTs,
252
+ },
204
253
  {
205
254
  path: 'apps/web/.env.local',
206
255
  content: envLocal,