@geekmidas/cli 0.27.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/dist/index.cjs +106 -53
- package/dist/index.cjs.map +1 -1
- package/dist/index.mjs +106 -53
- package/dist/index.mjs.map +1 -1
- package/package.json +3 -3
- package/src/init/generators/models.ts +2 -11
- package/src/init/generators/web.ts +86 -37
- package/src/init/index.ts +15 -0
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@geekmidas/cli",
|
|
3
|
-
"version": "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,10 +48,10 @@
|
|
|
48
48
|
"lodash.kebabcase": "^4.1.1",
|
|
49
49
|
"openapi-typescript": "^7.4.2",
|
|
50
50
|
"prompts": "~2.4.2",
|
|
51
|
-
"@geekmidas/constructs": "~0.6.0",
|
|
52
|
-
"@geekmidas/schema": "~0.1.0",
|
|
53
51
|
"@geekmidas/errors": "~0.1.0",
|
|
54
52
|
"@geekmidas/envkit": "~0.4.0",
|
|
53
|
+
"@geekmidas/constructs": "~0.6.0",
|
|
54
|
+
"@geekmidas/schema": "~0.1.0",
|
|
55
55
|
"@geekmidas/logger": "~0.4.0"
|
|
56
56
|
},
|
|
57
57
|
"devDependencies": {
|
|
@@ -20,18 +20,9 @@ export function generateModelsPackage(
|
|
|
20
20
|
private: true,
|
|
21
21
|
type: 'module',
|
|
22
22
|
exports: {
|
|
23
|
-
'
|
|
24
|
-
types: './dist/index.d.ts',
|
|
25
|
-
import: './dist/index.js',
|
|
26
|
-
},
|
|
27
|
-
'./*': {
|
|
28
|
-
types: './dist/*.d.ts',
|
|
29
|
-
import: './dist/*.js',
|
|
30
|
-
},
|
|
23
|
+
'./*': './src/*.ts',
|
|
31
24
|
},
|
|
32
25
|
scripts: {
|
|
33
|
-
build: 'tsc',
|
|
34
|
-
'build:watch': 'tsc --watch',
|
|
35
26
|
typecheck: 'tsc --noEmit',
|
|
36
27
|
},
|
|
37
28
|
dependencies: {
|
|
@@ -42,7 +33,7 @@ export function generateModelsPackage(
|
|
|
42
33
|
},
|
|
43
34
|
};
|
|
44
35
|
|
|
45
|
-
// tsconfig.json for models -
|
|
36
|
+
// tsconfig.json for models - extends root config
|
|
46
37
|
const tsConfig = {
|
|
47
38
|
extends: '../../tsconfig.json',
|
|
48
39
|
compilerOptions: {
|
|
@@ -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>
|
|
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
|
|
177
|
+
const pageTsx = `import { api } from '@/api';
|
|
108
178
|
|
|
109
179
|
export default async function Home() {
|
|
110
|
-
//
|
|
111
|
-
const
|
|
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
|
|
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
|
|
170
|
-
|
|
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,
|
package/src/init/index.ts
CHANGED
|
@@ -395,6 +395,21 @@ export async function initCommand(
|
|
|
395
395
|
}
|
|
396
396
|
}
|
|
397
397
|
|
|
398
|
+
// Initialize git repository
|
|
399
|
+
console.log('\nš¦ Initializing git repository...\n');
|
|
400
|
+
try {
|
|
401
|
+
execSync('git init', { cwd: targetDir, stdio: 'pipe' });
|
|
402
|
+
execSync('git branch -M main', { cwd: targetDir, stdio: 'pipe' });
|
|
403
|
+
execSync('git add .', { cwd: targetDir, stdio: 'pipe' });
|
|
404
|
+
execSync('git commit -m "š Project created with @geekmidas/toolbox"', {
|
|
405
|
+
cwd: targetDir,
|
|
406
|
+
stdio: 'pipe',
|
|
407
|
+
});
|
|
408
|
+
console.log(' Initialized git repository on branch main');
|
|
409
|
+
} catch {
|
|
410
|
+
console.log(' Could not initialize git repository (git may not be installed)');
|
|
411
|
+
}
|
|
412
|
+
|
|
398
413
|
// Print success message with next steps
|
|
399
414
|
printNextSteps(name, templateOptions, pkgManager);
|
|
400
415
|
}
|