gmoonc 0.0.18 → 0.0.20

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
@@ -63,6 +63,16 @@ The logo is installed at `src/gmoonc/assets/gmoonc-logo.png`. You can replace it
63
63
 
64
64
  ## Changelog
65
65
 
66
+ ### 0.0.20
67
+ - Fix: Navigate import now always added to GMooncAppLayout.tsx when patching
68
+ - Fix: Improved Navigate import detection and addition logic
69
+
70
+ ### 0.0.19
71
+ - Fix: Added Navigate import to GMooncAppLayout.tsx template
72
+ - Fix: Corrected route protection order - isLoading checked before isAuthenticated
73
+ - Fix: Automatic update of all session context imports to use GMooncSupabaseSessionProvider
74
+ - Fix: All components now use Supabase provider instead of mock context
75
+
66
76
  ### 0.0.18
67
77
  - Fix: env.ts no longer throws when .env is missing - only logs warning
68
78
  - Fix: client.ts import corrected - hasSupabaseEnv imported from env.ts
package/dist/index.cjs CHANGED
@@ -388,8 +388,8 @@ function resolveImportToFile(importPath, fromDir) {
388
388
  const extensions = [".tsx", ".ts", ".jsx", ".js"];
389
389
  const indexFiles = ["index.tsx", "index.ts", "index.jsx", "index.js"];
390
390
  if ((0, import_fs8.existsSync)(basePath)) {
391
- const { statSync: statSync2 } = require("fs");
392
- const stats = statSync2(basePath);
391
+ const { statSync: statSync3 } = require("fs");
392
+ const stats = statSync3(basePath);
393
393
  if (stats.isFile()) {
394
394
  return basePath;
395
395
  }
@@ -405,16 +405,16 @@ function resolveImportToFile(importPath, fromDir) {
405
405
  for (const ext of extensions) {
406
406
  const fullPath = basePath + ext;
407
407
  if ((0, import_fs8.existsSync)(fullPath)) {
408
- const { statSync: statSync2 } = require("fs");
409
- const stats = statSync2(fullPath);
408
+ const { statSync: statSync3 } = require("fs");
409
+ const stats = statSync3(fullPath);
410
410
  if (stats.isFile()) {
411
411
  return fullPath;
412
412
  }
413
413
  }
414
414
  }
415
415
  if ((0, import_fs8.existsSync)(basePath)) {
416
- const { statSync: statSync2 } = require("fs");
417
- const stats = statSync2(basePath);
416
+ const { statSync: statSync3 } = require("fs");
417
+ const stats = statSync3(basePath);
418
418
  if (stats.isDirectory()) {
419
419
  for (const indexFile of indexFiles) {
420
420
  const indexPath = (0, import_path5.join)(basePath, indexFile);
@@ -1667,19 +1667,22 @@ function patchExistingCode(projectDir, gmooncDir) {
1667
1667
  /import\s+{\s*GMooncSessionProvider[^}]*}\s+from\s+['"][^'"]*session\/GMooncSessionContext['"]/g,
1668
1668
  "import { GMooncSupabaseSessionProvider, useGMooncSession } from '../supabase/auth/GMooncSupabaseSessionProvider'"
1669
1669
  );
1670
- if (!content.includes("from 'react-router-dom'") || !content.includes("Navigate")) {
1670
+ const usesNavigate = /<Navigate\s+to=/.test(content);
1671
+ const hasNavigateImport = /import\s+{[^}]*Navigate[^}]*}\s+from\s+['"]react-router-dom['"]/.test(content);
1672
+ if (usesNavigate && !hasNavigateImport) {
1671
1673
  content = content.replace(
1672
1674
  /import\s+{\s*([^}]*)\s*}\s+from\s+['"]react-router-dom['"]/,
1673
1675
  (match, imports) => {
1674
- if (!imports.includes("Navigate")) {
1675
- return `import { ${imports}, Navigate } from 'react-router-dom'`;
1676
+ if (/\bNavigate\b/.test(imports)) {
1677
+ return match;
1676
1678
  }
1677
- return match;
1679
+ const cleanImports = imports.trim().replace(/,\s*$/, "");
1680
+ return `import { ${cleanImports}, Navigate } from 'react-router-dom'`;
1678
1681
  }
1679
1682
  );
1680
1683
  }
1681
1684
  content = content.replace(/GMooncSessionProvider/g, "GMooncSupabaseSessionProvider");
1682
- if (!content.includes("!isLoading && !isAuthenticated")) {
1685
+ if (!content.includes("!isAuthenticated")) {
1683
1686
  content = content.replace(
1684
1687
  /const\s+{\s*roles,\s*logout\s*}\s+=\s+useGMooncSession\(\);/,
1685
1688
  "const { roles, logout, isLoading, isAuthenticated } = useGMooncSession();"
@@ -1688,12 +1691,35 @@ function patchExistingCode(projectDir, gmooncDir) {
1688
1691
  /(\s+}, \[navigate, getBasePath\]\);)\s+(\s+return\s+\()/,
1689
1692
  `$1
1690
1693
 
1694
+ // Show loading state while checking authentication (verificar primeiro)
1695
+ if (isLoading) {
1696
+ return (
1697
+ <div className="gmoonc-root">
1698
+ <div style={{
1699
+ display: 'flex',
1700
+ justifyContent: 'center',
1701
+ alignItems: 'center',
1702
+ height: '100vh',
1703
+ fontSize: 'var(--gmoonc-font-size-base, 16px)',
1704
+ color: 'var(--gmoonc-color-text, #333)'
1705
+ }}>
1706
+ Loading...
1707
+ </div>
1708
+ </div>
1709
+ );
1710
+ }
1711
+
1691
1712
  // Route protection: redirect to login if not authenticated
1692
- if (!isLoading && !isAuthenticated) {
1713
+ if (!isAuthenticated) {
1693
1714
  return <Navigate to="/login" replace />;
1694
1715
  }
1695
1716
 
1696
- // Show loading state while checking authentication
1717
+ $2`
1718
+ );
1719
+ } else {
1720
+ content = content.replace(
1721
+ /\/\/ Route protection: redirect to login if not authenticated\s+if\s+\(!isLoading\s+&&\s+!isAuthenticated\)\s+\{[\s\S]*?return\s+<Navigate[^>]+>;[\s\S]*?\}\s+(\/\/ Show loading state)/,
1722
+ `// Show loading state while checking authentication (verificar primeiro)
1697
1723
  if (isLoading) {
1698
1724
  return (
1699
1725
  <div className="gmoonc-root">
@@ -1711,18 +1737,74 @@ function patchExistingCode(projectDir, gmooncDir) {
1711
1737
  );
1712
1738
  }
1713
1739
 
1714
- $2`
1740
+ // Route protection: redirect to login if not authenticated
1741
+ if (!isAuthenticated) {
1742
+ return <Navigate to="/login" replace />;
1743
+ }
1744
+
1745
+ $1`
1715
1746
  );
1716
1747
  }
1717
1748
  writeFileSafe(layoutPath, content);
1718
1749
  logSuccess("Patched layout/GMooncAppLayout.tsx to use GMooncSupabaseSessionProvider and add route protection");
1719
1750
  }
1720
- logInfo("Auth pages will use Supabase via GMooncSupabaseSessionProvider");
1751
+ updateAllSessionImports(gmooncDir);
1752
+ }
1753
+ function updateAllSessionImports(gmooncDir) {
1754
+ const filesToUpdate = [];
1755
+ function findFiles(dir) {
1756
+ if (!(0, import_fs9.existsSync)(dir)) return;
1757
+ const entries = (0, import_fs9.readdirSync)(dir, { withFileTypes: true });
1758
+ for (const entry of entries) {
1759
+ const fullPath = (0, import_path6.join)(dir, entry.name);
1760
+ if (entry.name.includes(".bak-") || entry.name === "supabase") {
1761
+ continue;
1762
+ }
1763
+ if (entry.isDirectory()) {
1764
+ findFiles(fullPath);
1765
+ } else if (entry.isFile() && (entry.name.endsWith(".ts") || entry.name.endsWith(".tsx"))) {
1766
+ filesToUpdate.push(fullPath);
1767
+ }
1768
+ }
1769
+ }
1770
+ findFiles(gmooncDir);
1771
+ let updatedCount = 0;
1772
+ for (const filePath of filesToUpdate) {
1773
+ let content = (0, import_fs9.readFileSync)(filePath, "utf-8");
1774
+ let modified = false;
1775
+ const fileDir = (0, import_path6.dirname)(filePath);
1776
+ const supabaseProviderPath = (0, import_path6.join)(gmooncDir, "supabase", "auth", "GMooncSupabaseSessionProvider");
1777
+ let relativePath = (0, import_path6.relative)(fileDir, supabaseProviderPath).replace(/\\/g, "/");
1778
+ if (!relativePath.startsWith(".")) {
1779
+ relativePath = "./" + relativePath;
1780
+ }
1781
+ const oldImportPattern = /from\s+['"](\.\.?\/)+session\/GMooncSessionContext['"]/g;
1782
+ if (oldImportPattern.test(content)) {
1783
+ content = content.replace(
1784
+ /from\s+['"](\.\.?\/)+session\/GMooncSessionContext['"]/g,
1785
+ `from '${relativePath}'`
1786
+ );
1787
+ modified = true;
1788
+ }
1789
+ if (content.includes("GMooncSessionProvider") && !content.includes("GMooncSupabaseSessionProvider")) {
1790
+ content = content.replace(/GMooncSessionProvider/g, "GMooncSupabaseSessionProvider");
1791
+ modified = true;
1792
+ }
1793
+ if (modified) {
1794
+ writeFileSafe(filePath, content);
1795
+ updatedCount++;
1796
+ }
1797
+ }
1798
+ if (updatedCount > 0) {
1799
+ logSuccess(`Updated ${updatedCount} file(s) to use GMooncSupabaseSessionProvider`);
1800
+ } else {
1801
+ logInfo("All files already use GMooncSupabaseSessionProvider");
1802
+ }
1721
1803
  }
1722
1804
 
1723
1805
  // src/cli/index.ts
1724
1806
  var program = new import_commander.Command();
1725
- program.name("gmoonc").description("Goalmoon Ctrl (gmoonc): Install complete dashboard into your React project").version("0.0.18").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) => {
1807
+ program.name("gmoonc").description("Goalmoon Ctrl (gmoonc): Install complete dashboard into your React project").version("0.0.20").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) => {
1726
1808
  try {
1727
1809
  logInfo("\u{1F680} Starting gmoonc installer...");
1728
1810
  logInfo("\u{1F4E6} Installing complete dashboard into your React project\n");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "gmoonc",
3
- "version": "0.0.18",
3
+ "version": "0.0.20",
4
4
  "description": "Goalmoon Ctrl (gmoonc): Complete dashboard installer for React projects",
5
5
  "license": "MIT",
6
6
  "homepage": "https://gmoonc.com",
@@ -47,12 +47,7 @@ function GMooncAppLayoutInner() {
47
47
  navigate(normalizedBasePath);
48
48
  }, [navigate, getBasePath]);
49
49
 
50
- // Route protection: redirect to login if not authenticated
51
- if (!isLoading && !isAuthenticated) {
52
- return <Navigate to="/login" replace />;
53
- }
54
-
55
- // Show loading state while checking authentication
50
+ // Show loading state while checking authentication (verificar primeiro)
56
51
  if (isLoading) {
57
52
  return (
58
53
  <div className="gmoonc-root">
@@ -70,6 +65,11 @@ function GMooncAppLayoutInner() {
70
65
  );
71
66
  }
72
67
 
68
+ // Route protection: redirect to login if not authenticated
69
+ if (!isAuthenticated) {
70
+ return <Navigate to="/login" replace />;
71
+ }
72
+
73
73
  return (
74
74
  <div className="gmoonc-root">
75
75
  <GmooncShell