@maka/maka-cli 5.1.44 → 5.1.46

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 (42) hide show
  1. package/.claude/settings.local.json +3 -1
  2. package/bundle/typescript/package.json +1 -1
  3. package/bundle/typescript/src/commands/ai/mcp.sub.cmd.js +135 -7
  4. package/bundle/typescript/src/commands/ai/mcp.sub.cmd.js.map +1 -1
  5. package/bundle/typescript/src/commands/create.js +3 -3
  6. package/bundle/typescript/src/commands/create.js.map +1 -1
  7. package/bundle/typescript/src/commands/run/run.command.js +0 -5
  8. package/bundle/typescript/src/commands/run/run.command.js.map +1 -1
  9. package/bundle/typescript/src/generators/kits/auth/_index.d.ts +1 -0
  10. package/bundle/typescript/src/generators/kits/auth/_index.js +1 -0
  11. package/bundle/typescript/src/generators/kits/auth/_index.js.map +1 -1
  12. package/bundle/typescript/src/generators/kits/auth/auth0-meteor.auth.gen.d.ts +1 -0
  13. package/bundle/typescript/src/generators/kits/auth/auth0-meteor.auth.gen.js +704 -0
  14. package/bundle/typescript/src/generators/kits/auth/auth0-meteor.auth.gen.js.map +1 -0
  15. package/bundle/typescript/src/generators/kits/auth/basic-meteor.auth.gen.js +2 -2
  16. package/bundle/typescript/src/generators/kits/auth/basic-meteor.auth.gen.js.map +1 -1
  17. package/bundle/typescript/src/generators/kits/mui/_index.d.ts +1 -0
  18. package/bundle/typescript/src/generators/kits/mui/_index.js +1 -0
  19. package/bundle/typescript/src/generators/kits/mui/_index.js.map +1 -1
  20. package/bundle/typescript/src/generators/kits/mui/auth0.mui.gen.d.ts +2 -0
  21. package/bundle/typescript/src/generators/kits/mui/auth0.mui.gen.js +158 -0
  22. package/bundle/typescript/src/generators/kits/mui/auth0.mui.gen.js.map +1 -0
  23. package/bundle/typescript/src/generators/publish.js +2 -6
  24. package/bundle/typescript/src/generators/publish.js.map +1 -1
  25. package/bundle/typescript/src/templates/react/kit/auth/service/auth0-client.js.jsx +141 -0
  26. package/bundle/typescript/src/templates/react/kit/auth/service/auth0-client.js.tsx +141 -0
  27. package/bundle/typescript/src/templates/react/kit/auth/service/auth0-config.js.jsx +46 -0
  28. package/bundle/typescript/src/templates/react/kit/auth/service/auth0-config.js.tsx +54 -0
  29. package/bundle/typescript/src/templates/react/kit/auth/service/auth0-methods.js.jsx +152 -0
  30. package/bundle/typescript/src/templates/react/kit/auth/service/auth0-methods.js.tsx +152 -0
  31. package/bundle/typescript/src/templates/react/kit/auth/service/auth0-validator.js.jsx +143 -0
  32. package/bundle/typescript/src/templates/react/kit/auth/service/auth0-validator.js.tsx +158 -0
  33. package/bundle/typescript/src/templates/react/kit/mui/auth0/auth-callback.js.jsx +71 -0
  34. package/bundle/typescript/src/templates/react/kit/mui/auth0/auth-callback.js.tsx +71 -0
  35. package/bundle/typescript/src/templates/react/kit/mui/auth0/auth0-account-settings.js.jsx +123 -0
  36. package/bundle/typescript/src/templates/react/kit/mui/auth0/auth0-account-settings.js.tsx +123 -0
  37. package/bundle/typescript/src/templates/react/kit/mui/auth0/auth0-login-button.js.jsx +56 -0
  38. package/bundle/typescript/src/templates/react/kit/mui/auth0/auth0-login-button.js.tsx +74 -0
  39. package/bundle/typescript/src/tools/scaffold/scaffold.class.d.ts +2 -1
  40. package/bundle/typescript/src/tools/scaffold/scaffold.class.js +12 -6
  41. package/bundle/typescript/src/tools/scaffold/scaffold.class.js.map +1 -1
  42. package/package.json +1 -1
@@ -0,0 +1,71 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { useNavigate } from 'react-router-dom';
3
+ import { Box, CircularProgress, Typography, Alert } from '@mui/material';
4
+ import AuthService from '<%= authServicePath %>';
5
+
6
+ /**
7
+ * Auth0 Callback Component
8
+ *
9
+ * This component handles the OAuth callback from Auth0.
10
+ * It exchanges the authorization code for tokens and logs the user into Meteor.
11
+ */
12
+ export const AuthCallback = () => {
13
+ const navigate = useNavigate();
14
+ const [error, setError] = useState(null);
15
+
16
+ useEffect(() => {
17
+ const handleCallback = async () => {
18
+ try {
19
+ // Handle the Auth0 callback and login to Meteor
20
+ await AuthService.handleAuth0Callback();
21
+
22
+ // Redirect to home page after successful login
23
+ navigate('/', { replace: true });
24
+ } catch (err) {
25
+ console.error('Auth0 callback error:', err);
26
+ setError(err instanceof Error ? err.message : 'Authentication failed');
27
+
28
+ // Redirect to login page after a delay
29
+ setTimeout(() => {
30
+ navigate('/login', { replace: true });
31
+ }, 3000);
32
+ }
33
+ };
34
+
35
+ handleCallback();
36
+ }, [navigate]);
37
+
38
+ return (
39
+ <Box
40
+ sx={{
41
+ display: 'flex',
42
+ flexDirection: 'column',
43
+ alignItems: 'center',
44
+ justifyContent: 'center',
45
+ minHeight: '100vh',
46
+ gap: 2,
47
+ }}
48
+ >
49
+ {error ? (
50
+ <>
51
+ <Alert severity="error" sx={{ maxWidth: 600 }}>
52
+ {error}
53
+ </Alert>
54
+ <Typography variant="body2" color="text.secondary">
55
+ Redirecting to login page...
56
+ </Typography>
57
+ </>
58
+ ) : (
59
+ <>
60
+ <CircularProgress size={60} />
61
+ <Typography variant="h6" sx={{ mt: 2 }}>
62
+ Completing authentication...
63
+ </Typography>
64
+ <Typography variant="body2" color="text.secondary">
65
+ Please wait while we log you in.
66
+ </Typography>
67
+ </>
68
+ )}
69
+ </Box>
70
+ );
71
+ };
@@ -0,0 +1,71 @@
1
+ import React, { useEffect, useState } from 'react';
2
+ import { useNavigate } from 'react-router-dom';
3
+ import { Box, CircularProgress, Typography, Alert } from '@mui/material';
4
+ import AuthService from '<%= authServicePath %>';
5
+
6
+ /**
7
+ * Auth0 Callback Component
8
+ *
9
+ * This component handles the OAuth callback from Auth0.
10
+ * It exchanges the authorization code for tokens and logs the user into Meteor.
11
+ */
12
+ export const AuthCallback = () => {
13
+ const navigate = useNavigate();
14
+ const [error, setError] = useState<string | null>(null);
15
+
16
+ useEffect(() => {
17
+ const handleCallback = async () => {
18
+ try {
19
+ // Handle the Auth0 callback and login to Meteor
20
+ await AuthService.handleAuth0Callback();
21
+
22
+ // Redirect to home page after successful login
23
+ navigate('/', { replace: true });
24
+ } catch (err) {
25
+ console.error('Auth0 callback error:', err);
26
+ setError(err instanceof Error ? err.message : 'Authentication failed');
27
+
28
+ // Redirect to login page after a delay
29
+ setTimeout(() => {
30
+ navigate('/login', { replace: true });
31
+ }, 3000);
32
+ }
33
+ };
34
+
35
+ handleCallback();
36
+ }, [navigate]);
37
+
38
+ return (
39
+ <Box
40
+ sx={{
41
+ display: 'flex',
42
+ flexDirection: 'column',
43
+ alignItems: 'center',
44
+ justifyContent: 'center',
45
+ minHeight: '100vh',
46
+ gap: 2,
47
+ }}
48
+ >
49
+ {error ? (
50
+ <>
51
+ <Alert severity="error" sx={{ maxWidth: 600 }}>
52
+ {error}
53
+ </Alert>
54
+ <Typography variant="body2" color="text.secondary">
55
+ Redirecting to login page...
56
+ </Typography>
57
+ </>
58
+ ) : (
59
+ <>
60
+ <CircularProgress size={60} />
61
+ <Typography variant="h6" sx={{ mt: 2 }}>
62
+ Completing authentication...
63
+ </Typography>
64
+ <Typography variant="body2" color="text.secondary">
65
+ Please wait while we log you in.
66
+ </Typography>
67
+ </>
68
+ )}
69
+ </Box>
70
+ );
71
+ };
@@ -0,0 +1,123 @@
1
+ import React, { useContext, useState } from 'react';
2
+ import {
3
+ Box,
4
+ Card,
5
+ CardContent,
6
+ Typography,
7
+ Button,
8
+ Alert,
9
+ CircularProgress,
10
+ } from '@mui/material';
11
+ import { Meteor } from 'meteor/meteor';
12
+ import { AuthContext } from '<%= authContextPath %>';
13
+
14
+ /**
15
+ * Auth0 Account Settings Component
16
+ *
17
+ * Displays Auth0 account status and allows linking/unlinking
18
+ * Auth0 account to/from the current Meteor user.
19
+ */
20
+ export const Auth0AccountSettings = () => {
21
+ const auth = useContext(AuthContext);
22
+ const [loading, setLoading] = useState(false);
23
+ const [message, setMessage] = useState(null);
24
+
25
+ if (!auth?.currentUser) {
26
+ return null;
27
+ }
28
+
29
+ const user = Meteor.user();
30
+ const hasAuth0Account = Boolean(user?.services?.auth0);
31
+
32
+ const handleLinkAccount = async () => {
33
+ setLoading(true);
34
+ setMessage(null);
35
+
36
+ try {
37
+ const success = await auth.linkAuth0Account?.();
38
+ if (success) {
39
+ setMessage({ type: 'success', text: 'Auth0 account linked successfully!' });
40
+ }
41
+ } catch (error) {
42
+ setMessage({
43
+ type: 'error',
44
+ text: error instanceof Error ? error.message : 'Failed to link Auth0 account',
45
+ });
46
+ } finally {
47
+ setLoading(false);
48
+ }
49
+ };
50
+
51
+ const handleUnlinkAccount = async () => {
52
+ setLoading(true);
53
+ setMessage(null);
54
+
55
+ try {
56
+ const success = await auth.unlinkAuth0Account?.();
57
+ if (success) {
58
+ setMessage({ type: 'success', text: 'Auth0 account unlinked successfully!' });
59
+ }
60
+ } catch (error) {
61
+ setMessage({
62
+ type: 'error',
63
+ text: error instanceof Error ? error.message : 'Failed to unlink Auth0 account',
64
+ });
65
+ } finally {
66
+ setLoading(false);
67
+ }
68
+ };
69
+
70
+ return (
71
+ <Card>
72
+ <CardContent>
73
+ <Typography variant="h6" gutterBottom>
74
+ Auth0 Integration
75
+ </Typography>
76
+
77
+ {message && (
78
+ <Alert severity={message.type} sx={{ mb: 2 }}>
79
+ {message.text}
80
+ </Alert>
81
+ )}
82
+
83
+ {hasAuth0Account ? (
84
+ <Box>
85
+ <Alert severity="success" sx={{ mb: 2 }}>
86
+ Your account is linked with Auth0
87
+ </Alert>
88
+ <Typography variant="body2" color="text.secondary" gutterBottom>
89
+ Email: {user?.services?.auth0?.email || 'N/A'}
90
+ </Typography>
91
+ <Typography variant="body2" color="text.secondary" gutterBottom>
92
+ Name: {user?.services?.auth0?.name || 'N/A'}
93
+ </Typography>
94
+ <Button
95
+ variant="outlined"
96
+ color="error"
97
+ onClick={handleUnlinkAccount}
98
+ disabled={loading}
99
+ sx={{ mt: 2 }}
100
+ startIcon={loading ? <CircularProgress size={20} /> : undefined}
101
+ >
102
+ {loading ? 'Unlinking...' : 'Unlink Auth0 Account'}
103
+ </Button>
104
+ </Box>
105
+ ) : (
106
+ <Box>
107
+ <Alert severity="info" sx={{ mb: 2 }}>
108
+ Link your account with Auth0 for easier login
109
+ </Alert>
110
+ <Button
111
+ variant="contained"
112
+ onClick={handleLinkAccount}
113
+ disabled={loading}
114
+ startIcon={loading ? <CircularProgress size={20} /> : undefined}
115
+ >
116
+ {loading ? 'Linking...' : 'Link Auth0 Account'}
117
+ </Button>
118
+ </Box>
119
+ )}
120
+ </CardContent>
121
+ </Card>
122
+ );
123
+ };
@@ -0,0 +1,123 @@
1
+ import React, { useContext, useState } from 'react';
2
+ import {
3
+ Box,
4
+ Card,
5
+ CardContent,
6
+ Typography,
7
+ Button,
8
+ Alert,
9
+ CircularProgress,
10
+ } from '@mui/material';
11
+ import { Meteor } from 'meteor/meteor';
12
+ import { AuthContext } from '<%= authContextPath %>';
13
+
14
+ /**
15
+ * Auth0 Account Settings Component
16
+ *
17
+ * Displays Auth0 account status and allows linking/unlinking
18
+ * Auth0 account to/from the current Meteor user.
19
+ */
20
+ export const Auth0AccountSettings: React.FC = () => {
21
+ const auth = useContext(AuthContext);
22
+ const [loading, setLoading] = useState(false);
23
+ const [message, setMessage] = useState<{ type: 'success' | 'error'; text: string } | null>(null);
24
+
25
+ if (!auth?.currentUser) {
26
+ return null;
27
+ }
28
+
29
+ const user = Meteor.user();
30
+ const hasAuth0Account = Boolean(user?.services?.auth0);
31
+
32
+ const handleLinkAccount = async () => {
33
+ setLoading(true);
34
+ setMessage(null);
35
+
36
+ try {
37
+ const success = await auth.linkAuth0Account?.();
38
+ if (success) {
39
+ setMessage({ type: 'success', text: 'Auth0 account linked successfully!' });
40
+ }
41
+ } catch (error) {
42
+ setMessage({
43
+ type: 'error',
44
+ text: error instanceof Error ? error.message : 'Failed to link Auth0 account',
45
+ });
46
+ } finally {
47
+ setLoading(false);
48
+ }
49
+ };
50
+
51
+ const handleUnlinkAccount = async () => {
52
+ setLoading(true);
53
+ setMessage(null);
54
+
55
+ try {
56
+ const success = await auth.unlinkAuth0Account?.();
57
+ if (success) {
58
+ setMessage({ type: 'success', text: 'Auth0 account unlinked successfully!' });
59
+ }
60
+ } catch (error) {
61
+ setMessage({
62
+ type: 'error',
63
+ text: error instanceof Error ? error.message : 'Failed to unlink Auth0 account',
64
+ });
65
+ } finally {
66
+ setLoading(false);
67
+ }
68
+ };
69
+
70
+ return (
71
+ <Card>
72
+ <CardContent>
73
+ <Typography variant="h6" gutterBottom>
74
+ Auth0 Integration
75
+ </Typography>
76
+
77
+ {message && (
78
+ <Alert severity={message.type} sx={{ mb: 2 }}>
79
+ {message.text}
80
+ </Alert>
81
+ )}
82
+
83
+ {hasAuth0Account ? (
84
+ <Box>
85
+ <Alert severity="success" sx={{ mb: 2 }}>
86
+ Your account is linked with Auth0
87
+ </Alert>
88
+ <Typography variant="body2" color="text.secondary" gutterBottom>
89
+ Email: {user?.services?.auth0?.email || 'N/A'}
90
+ </Typography>
91
+ <Typography variant="body2" color="text.secondary" gutterBottom>
92
+ Name: {user?.services?.auth0?.name || 'N/A'}
93
+ </Typography>
94
+ <Button
95
+ variant="outlined"
96
+ color="error"
97
+ onClick={handleUnlinkAccount}
98
+ disabled={loading}
99
+ sx={{ mt: 2 }}
100
+ startIcon={loading ? <CircularProgress size={20} /> : undefined}
101
+ >
102
+ {loading ? 'Unlinking...' : 'Unlink Auth0 Account'}
103
+ </Button>
104
+ </Box>
105
+ ) : (
106
+ <Box>
107
+ <Alert severity="info" sx={{ mb: 2 }}>
108
+ Link your account with Auth0 for easier login
109
+ </Alert>
110
+ <Button
111
+ variant="contained"
112
+ onClick={handleLinkAccount}
113
+ disabled={loading}
114
+ startIcon={loading ? <CircularProgress size={20} /> : undefined}
115
+ >
116
+ {loading ? 'Linking...' : 'Link Auth0 Account'}
117
+ </Button>
118
+ </Box>
119
+ )}
120
+ </CardContent>
121
+ </Card>
122
+ );
123
+ };
@@ -0,0 +1,56 @@
1
+ import React, { useContext, useState } from 'react';
2
+ import { Button, CircularProgress } from '@mui/material';
3
+ import { AuthContext } from '<%= authContextPath %>';
4
+
5
+ /**
6
+ * Auth0 Login Button Component
7
+ *
8
+ * A reusable button component for Auth0 authentication.
9
+ * Supports both redirect and popup login flows.
10
+ */
11
+ export const Auth0LoginButton = ({
12
+ method = 'redirect',
13
+ onLoginSuccess,
14
+ onLoginError,
15
+ children = 'Login with Auth0',
16
+ ...buttonProps
17
+ }) => {
18
+ const auth = useContext(AuthContext);
19
+ const [loading, setLoading] = useState(false);
20
+
21
+ const handleLogin = async () => {
22
+ if (!auth) {
23
+ console.error('Auth context not available');
24
+ return;
25
+ }
26
+
27
+ setLoading(true);
28
+
29
+ try {
30
+ if (method === 'popup') {
31
+ await auth.loginWithAuth0Popup?.();
32
+ onLoginSuccess?.();
33
+ } else {
34
+ // Redirect method - user will leave the page
35
+ await auth.loginWithAuth0Redirect?.();
36
+ }
37
+ } catch (error) {
38
+ console.error('Auth0 login error:', error);
39
+ onLoginError?.(error);
40
+ } finally {
41
+ setLoading(false);
42
+ }
43
+ };
44
+
45
+ return (
46
+ <Button
47
+ variant="contained"
48
+ onClick={handleLogin}
49
+ disabled={loading || auth?.loading}
50
+ startIcon={loading ? <CircularProgress size={20} /> : undefined}
51
+ {...buttonProps}
52
+ >
53
+ {loading ? 'Logging in...' : children}
54
+ </Button>
55
+ );
56
+ };
@@ -0,0 +1,74 @@
1
+ import React, { useContext, useState } from 'react';
2
+ import { Button, ButtonProps, CircularProgress } from '@mui/material';
3
+ import { AuthContext } from '<%= authContextPath %>';
4
+
5
+ interface Auth0LoginButtonProps extends ButtonProps {
6
+ /**
7
+ * Login method to use: 'redirect' or 'popup'
8
+ * Default is 'redirect'
9
+ */
10
+ method?: 'redirect' | 'popup';
11
+
12
+ /**
13
+ * Optional callback after successful login (only for popup method)
14
+ */
15
+ onLoginSuccess?: () => void;
16
+
17
+ /**
18
+ * Optional callback on error
19
+ */
20
+ onLoginError?: (error: Error) => void;
21
+ }
22
+
23
+ /**
24
+ * Auth0 Login Button Component
25
+ *
26
+ * A reusable button component for Auth0 authentication.
27
+ * Supports both redirect and popup login flows.
28
+ */
29
+ export const Auth0LoginButton: React.FC<Auth0LoginButtonProps> = ({
30
+ method = 'redirect',
31
+ onLoginSuccess,
32
+ onLoginError,
33
+ children = 'Login with Auth0',
34
+ ...buttonProps
35
+ }) => {
36
+ const auth = useContext(AuthContext);
37
+ const [loading, setLoading] = useState(false);
38
+
39
+ const handleLogin = async () => {
40
+ if (!auth) {
41
+ console.error('Auth context not available');
42
+ return;
43
+ }
44
+
45
+ setLoading(true);
46
+
47
+ try {
48
+ if (method === 'popup') {
49
+ await auth.loginWithAuth0Popup?.();
50
+ onLoginSuccess?.();
51
+ } else {
52
+ // Redirect method - user will leave the page
53
+ await auth.loginWithAuth0Redirect?.();
54
+ }
55
+ } catch (error) {
56
+ console.error('Auth0 login error:', error);
57
+ onLoginError?.(error as Error);
58
+ } finally {
59
+ setLoading(false);
60
+ }
61
+ };
62
+
63
+ return (
64
+ <Button
65
+ variant="contained"
66
+ onClick={handleLogin}
67
+ disabled={loading || auth?.loading}
68
+ startIcon={loading ? <CircularProgress size={20} /> : undefined}
69
+ {...buttonProps}
70
+ >
71
+ {loading ? 'Logging in...' : children}
72
+ </Button>
73
+ );
74
+ };
@@ -108,7 +108,8 @@ export declare class Scaffold {
108
108
  copyTemplateDirectory({ srcPath, destPath, context, ignore, keep, framework, config }: ICopyTemplateDir): Promise<void>;
109
109
  /**
110
110
  * Inject content at the top of a file. If the file
111
- * doesn't exist yet, create it.
111
+ * doesn't exist yet, create it. If the content already exists,
112
+ * do not inject it again.
112
113
  */
113
114
  injectAtBeginningOfFile({ filePath, content, opts }: IInjectIntoFile): Promise<void>;
114
115
  /**
@@ -429,7 +429,8 @@ export class Scaffold {
429
429
  }
430
430
  /**
431
431
  * Inject content at the top of a file. If the file
432
- * doesn't exist yet, create it.
432
+ * doesn't exist yet, create it. If the content already exists,
433
+ * do not inject it again.
433
434
  */
434
435
  async injectAtBeginningOfFile({ filePath, content, opts }) {
435
436
  if (!filePath) {
@@ -442,11 +443,16 @@ export class Scaffold {
442
443
  data: content
443
444
  });
444
445
  }
445
- let fileContent = fs.readFileSync(filePath, 'utf8');
446
- fileContent = content + "\n" + fileContent;
447
- fs.writeFileSync(filePath, fileContent);
448
- if (opts?.verbose) {
449
- Log.header(`${treeSymbol} updated file ${path.relative(process.cwd(), filePath)}`);
446
+ else {
447
+ let fileContent = fs.readFileSync(filePath, 'utf8');
448
+ // Check if the content already exists in the file
449
+ if (!fileContent.includes(content)) {
450
+ fileContent = content + "\n" + fileContent;
451
+ fs.writeFileSync(filePath, fileContent);
452
+ }
453
+ if (opts?.verbose) {
454
+ Log.header(`${treeSymbol} updated file ${path.relative(process.cwd(), filePath)}`);
455
+ }
450
456
  }
451
457
  }
452
458
  catch (e) {