gmoonc 0.0.4 → 0.0.5

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/README.md CHANGED
@@ -16,10 +16,28 @@ Run the installer in your React project root:
16
16
  npx gmoonc
17
17
  ```
18
18
 
19
- Or with options:
19
+ Or skip confirmations (recommended):
20
20
 
21
21
  ```bash
22
- npx gmoonc --yes --base /app
22
+ npx gmoonc -y
23
+ ```
24
+
25
+ **Note for Windows/npm 11+:** If you encounter issues with `--yes`, use the short flag `-y` instead:
26
+
27
+ ```bash
28
+ npx gmoonc -y
29
+ ```
30
+
31
+ Or use the pass-through syntax:
32
+
33
+ ```bash
34
+ npx gmoonc -- --yes
35
+ ```
36
+
37
+ With custom base path:
38
+
39
+ ```bash
40
+ npx gmoonc -y --base /dashboard
23
41
  ```
24
42
 
25
43
  ## What it does
@@ -31,7 +49,7 @@ npx gmoonc --yes --base /app
31
49
 
32
50
  ## Options
33
51
 
34
- - `--yes` / `-y`: Skip confirmations and install automatically
52
+ - `-y`, `--yes`, `--auto`: Skip confirmations and install automatically (recommended: use `-y`)
35
53
  - `--base <path>`: Base path for dashboard routes (default: `/app`)
36
54
  - `--skip-router-patch`: Skip automatic router integration
37
55
  - `--dry-run`: Show what would be done without making changes
package/dist/index.cjs CHANGED
@@ -330,16 +330,16 @@ function convertImportToRelative(importLine, appRoutesPath, appPath) {
330
330
  return importLine;
331
331
  }
332
332
  const originalPath = pathMatch[1];
333
- if (originalPath.startsWith("./") || originalPath.startsWith("../")) {
334
- const appDir = appPath.substring(0, appPath.lastIndexOf("/"));
335
- const appRoutesDir = appRoutesPath.substring(0, appRoutesPath.lastIndexOf("/"));
336
- const resolvedPath = (0, import_path5.join)(appDir, originalPath);
337
- const relativePath = (0, import_path5.relative)(appRoutesDir, resolvedPath);
338
- const normalizedPath = relativePath.replace(/\\/g, "/");
339
- const finalPath = normalizedPath.startsWith(".") ? normalizedPath : "./" + normalizedPath;
340
- return importLine.replace(pathMatch[1], finalPath);
341
- }
342
- return importLine;
333
+ if (!originalPath.startsWith("./") && !originalPath.startsWith("../")) {
334
+ return importLine;
335
+ }
336
+ const appDir = appPath.substring(0, appPath.lastIndexOf("/"));
337
+ const resolvedPath = (0, import_path5.join)(appDir, originalPath);
338
+ const appRoutesDir = appRoutesPath.substring(0, appRoutesPath.lastIndexOf("/"));
339
+ const relativePath = (0, import_path5.relative)(appRoutesDir, resolvedPath);
340
+ const normalizedPath = relativePath.replace(/\\/g, "/");
341
+ const finalPath = normalizedPath.startsWith(".") ? normalizedPath : "./" + normalizedPath;
342
+ return importLine.replace(pathMatch[1], finalPath);
343
343
  }
344
344
  function generateAppRoutes(consumerDir, basePath, indexImport, notFoundImport, indexComponent, notFoundComponent, appPath, dryRun) {
345
345
  const appRoutesPath = (0, import_path5.join)(consumerDir, "src/gmoonc/router/AppRoutes.tsx");
@@ -352,7 +352,7 @@ function generateAppRoutes(consumerDir, basePath, indexImport, notFoundImport, i
352
352
  if (indexComponent) {
353
353
  routes.push(` { path: "/", element: <${indexComponent} /> }`);
354
354
  }
355
- routes.push(` ...createGmooncRoutes({ basePath: "${basePath}" })`);
355
+ routes.push(` ...createGmooncRoutes({ basePath })`);
356
356
  if (notFoundComponent) {
357
357
  routes.push(` { path: "*", element: <${notFoundComponent} /> }`);
358
358
  }
@@ -538,12 +538,15 @@ function patchBrowserRouter(consumerDir, basePath, dryRun) {
538
538
 
539
539
  // src/cli/index.ts
540
540
  var program = new import_commander.Command();
541
- program.name("gmoonc").description("Goalmoon Ctrl (gmoonc): Install complete dashboard into your React project").version("0.0.3").option("-y, --yes", "Skip confirmations and install automatically").option("--base <path>", "Base path for dashboard routes", "/app").option("--skip-router-patch", "Skip automatic router integration (only copy files and inject CSS)").option("--dry-run", "Show what would be done without making changes").action(async (options) => {
541
+ program.name("gmoonc").description("Goalmoon Ctrl (gmoonc): Install complete dashboard into your React project").version("0.0.5").option("-y, --yes, --auto", "Skip confirmations and install automatically").option("--base <path>", "Base path for dashboard routes", "/app").option("--skip-router-patch", "Skip automatic router integration (only copy files and inject CSS)").option("--dry-run", "Show what would be done without making changes").action(async (options) => {
542
542
  try {
543
+ logInfo("\u{1F680} Starting gmoonc installer...");
544
+ logInfo("\u{1F4E6} Installing complete dashboard into your React project\n");
543
545
  const projectDir = (0, import_process.cwd)();
544
546
  const basePath = options.base || "/app";
545
547
  const dryRun = options.dryRun || false;
546
548
  const skipRouterPatch = options.skipRouterPatch || false;
549
+ const autoInstall = options.yes || options.auto || false;
547
550
  const safeBasePath = basePath === "/" ? "/app" : basePath;
548
551
  logInfo("\u{1F50D} Detecting React project...");
549
552
  const project = detectProject(projectDir);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gmoonc",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "description": "Goalmoon Ctrl (gmoonc): Complete dashboard installer for React projects",
5
5
  "license": "MIT",
6
6
  "homepage": "https://gmoonc.com",
@@ -389,31 +389,42 @@ export function GmooncMenu({
389
389
  };
390
390
 
391
391
  // Render main item link/button
392
- const mainItemContent = item.path && renderLink ? (
392
+ // IMPORTANT: If item has submenu, always use button (never renderLink) to avoid navigation to non-existent routes
393
+ const mainItemContent = hasSubmenu ? (
394
+ // Item with submenu: always button (toggle only, no navigation)
395
+ <button
396
+ type="button"
397
+ className={`gmoonc-menu-link has-submenu ${isSubmenuOpen ? 'submenu-open' : ''} ${isItemActive ? 'active' : ''}`}
398
+ onClick={handleItemClick}
399
+ >
400
+ {item.icon && <span className="gmoonc-menu-icon">{item.icon}</span>}
401
+ <span className="gmoonc-menu-label">{item.label}</span>
402
+ <span className="gmoonc-submenu-arrow">
403
+ {isSubmenuOpen
404
+ ? (item.collapseIcon || null)
405
+ : (item.expandIcon || null)
406
+ }
407
+ </span>
408
+ </button>
409
+ ) : item.path && renderLink ? (
410
+ // Item without submenu and with path: use renderLink
393
411
  renderLink({
394
412
  path: item.path,
395
413
  label: item.label,
396
414
  isActive: isItemActive,
397
415
  onClick: handleItemClick,
398
- className: `gmoonc-menu-link ${hasSubmenu ? 'has-submenu' : ''} ${isSubmenuOpen ? 'submenu-open' : ''} ${isItemActive ? 'active' : ''}`
416
+ className: `gmoonc-menu-link ${isItemActive ? 'active' : ''}`
399
417
  })
400
418
  ) : (
419
+ // Item without submenu and without renderLink: use button
401
420
  <button
402
421
  type="button"
403
- className={`gmoonc-menu-link ${hasSubmenu ? 'has-submenu' : ''} ${isSubmenuOpen ? 'submenu-open' : ''} ${isItemActive ? 'active' : ''}`}
422
+ className={`gmoonc-menu-link ${isItemActive ? 'active' : ''}`}
404
423
  onClick={handleItemClick}
405
- disabled={!item.path && !hasSubmenu && !onNavigate}
424
+ disabled={!item.path && !onNavigate}
406
425
  >
407
426
  {item.icon && <span className="gmoonc-menu-icon">{item.icon}</span>}
408
427
  <span className="gmoonc-menu-label">{item.label}</span>
409
- {hasSubmenu && (
410
- <span className="gmoonc-submenu-arrow">
411
- {isSubmenuOpen
412
- ? (item.collapseIcon || null)
413
- : (item.expandIcon || null)
414
- }
415
- </span>
416
- )}
417
428
  </button>
418
429
  );
419
430
 
@@ -1,20 +1,21 @@
1
1
  import React from 'react';
2
2
  import { RouteObject } from 'react-router-dom';
3
- import { GmooncAppLayout } from '../../app/GMooncAppLayout';
4
- import { GMooncLoginPage } from '../../pages/auth/GMooncLoginPage';
5
- import { GMooncRegisterPage } from '../../pages/auth/GMooncRegisterPage';
6
- import { GMooncForgotPasswordPage } from '../../pages/auth/GMooncForgotPasswordPage';
7
- import { GMooncResetPasswordPage } from '../../pages/auth/GMooncResetPasswordPage';
8
- import { GMooncLogoutPage } from '../../pages/auth/GMooncLogoutPage';
9
- import { GMooncAppHomePage } from '../../pages/app/GMooncAppHomePage';
10
- import { GMooncPermissionsPage } from '../../pages/app/admin/GMooncPermissionsPage';
11
- import { GMooncAdminUsersPage } from '../../pages/app/admin/GMooncAdminUsersPage';
12
- import { GMooncAdminAuthorizationsPage } from '../../pages/app/admin/GMooncAdminAuthorizationsPage';
13
- import { GMooncAdminNotificationsPage } from '../../pages/app/admin/GMooncAdminNotificationsPage';
14
- import { GMooncTechnicalMessagesPage } from '../../pages/app/technical/GMooncTechnicalMessagesPage';
15
- import { GMooncCustomerMessagesPage } from '../../pages/app/customer/GMooncCustomerMessagesPage';
16
- import { GMooncOfficeAccountPage } from '../../pages/app/office/GMooncOfficeAccountPage';
17
- import { GMooncOfficeAboutPage } from '../../pages/app/office/GMooncOfficeAboutPage';
3
+ import { GmooncAppLayout } from '../layout/GMooncAppLayout';
4
+ import { GMooncLoginPage } from '../pages/auth/GMooncLoginPage';
5
+ import { GMooncRegisterPage } from '../pages/auth/GMooncRegisterPage';
6
+ import { GMooncForgotPasswordPage } from '../pages/auth/GMooncForgotPasswordPage';
7
+ import { GMooncResetPasswordPage } from '../pages/auth/GMooncResetPasswordPage';
8
+ import { GMooncLogoutPage } from '../pages/auth/GMooncLogoutPage';
9
+ import { GMooncAppHomePage } from '../pages/app/GMooncAppHomePage';
10
+ import { GMooncPermissionsPage } from '../pages/app/admin/GMooncPermissionsPage';
11
+ import { GMooncAdminUsersPage } from '../pages/app/admin/GMooncAdminUsersPage';
12
+ import { GMooncAdminAuthorizationsPage } from '../pages/app/admin/GMooncAdminAuthorizationsPage';
13
+ import { GMooncAdminNotificationsPage } from '../pages/app/admin/GMooncAdminNotificationsPage';
14
+ import { GMooncTechnicalMessagesPage } from '../pages/app/technical/GMooncTechnicalMessagesPage';
15
+ import { GMooncCustomerMessagesPage } from '../pages/app/customer/GMooncCustomerMessagesPage';
16
+ import { GMooncOfficeAccountPage } from '../pages/app/office/GMooncOfficeAccountPage';
17
+ import { GMooncOfficeAboutPage } from '../pages/app/office/GMooncOfficeAboutPage';
18
+ import { GMooncSessionProvider } from '../session/GMooncSessionContext';
18
19
 
19
20
  /**
20
21
  * Creates route objects for the gmoonc dashboard.
@@ -37,7 +38,11 @@ export function createGmooncRoutes(options?: { basePath?: string }): RouteObject
37
38
  // Auth routes (outside basePath, but still avoid "/" to be safe)
38
39
  {
39
40
  path: '/login',
40
- element: <GMooncLoginPage />
41
+ element: (
42
+ <GMooncSessionProvider>
43
+ <GMooncLoginPage />
44
+ </GMooncSessionProvider>
45
+ )
41
46
  },
42
47
  {
43
48
  path: '/register',
@@ -53,7 +58,11 @@ export function createGmooncRoutes(options?: { basePath?: string }): RouteObject
53
58
  },
54
59
  {
55
60
  path: '/logout',
56
- element: <GMooncLogoutPage />
61
+ element: (
62
+ <GMooncSessionProvider>
63
+ <GMooncLogoutPage />
64
+ </GMooncSessionProvider>
65
+ )
57
66
  },
58
67
  // Dashboard routes (always nested under basePath, never "/")
59
68
  {