Files
2025-12-31 09:34:27 +01:00

5.9 KiB
Raw Blame History

GIT-004: Working Notes


Research Notes

GitHub App vs OAuth App

GitHub App (Recommended):

  • More granular permissions
  • Installation-based access (per-repo or org-wide)
  • Higher rate limits (5000 vs 5000, but per installation)
  • Better for org-wide deployment
  • Supports webhook subscriptions

OAuth App:

  • Simpler to implement
  • User-based access
  • Good for personal use
  • Lower setup complexity

Decision: Start with OAuth App for simplicity, can upgrade to GitHub App later for enterprise features.

Existing Code Patterns

// Current PAT storage pattern (GitStore)
// packages/noodl-editor/src/editor/src/views/panels/VersionControlPanel/
// components/GitProviderPopout/GitProviderPopout.tsx

await GitStore.set(provider, ProjectModel.instance.id, {
  username,
  password // This is actually the PAT
});
// Current Git provider detection
// packages/noodl-git/src/git.ts

public getProviderForRemote(remoteUrl: string): GitProvider {
  if (!remoteUrl) return 'none';
  else if (remoteUrl.includes('noodlapp.com')) return 'noodl';
  else if (remoteUrl.includes('github.com')) return 'github';
  else return 'unknown';
}

Rate Limiting Strategy

GitHub API limits:

  • Unauthenticated: 60 requests/hour
  • Authenticated (PAT/OAuth): 5000 requests/hour
  • GitHub App: 5000 requests/hour per installation

Caching strategy:

interface CacheEntry<T> {
  data: T;
  etag: string;
  timestamp: number;
}

// Use ETags for conditional requests
const headers = { 'If-None-Match': cachedEtag };
// 304 Not Modified = use cache, doesn't count against rate limit

Implementation Notes

OAuth Flow in Electron

// Rough implementation sketch
async function startOAuthFlow() {
  const state = crypto.randomUUID();
  const authUrl = `https://github.com/login/oauth/authorize?` +
    `client_id=${CLIENT_ID}&` +
    `redirect_uri=${REDIRECT_URI}&` +
    `scope=repo,read:user&` +
    `state=${state}`;
  
  // Open in external browser or BrowserWindow
  shell.openExternal(authUrl);
  
  // Listen for callback via deep link or local server
  // Exchange code for token
}

Component Metadata Schema

// Proposed schema for project.json
interface ComponentGitHubMetadata {
  linkedIssues: Array<{
    number: number;
    linkType: 'mentions' | 'implements' | 'fixes';
    linkedAt: string; // ISO date
    linkedBy?: string; // GitHub username
  }>;
  linkedPRs: Array<{
    number: number;
    linkedAt: string;
  }>;
}

// In component definition
{
  "name": "UserLoginForm",
  "graph": { ... },
  "github": {
    "linkedIssues": [
      { "number": 42, "linkType": "implements", "linkedAt": "2025-01-15T..." }
    ]
  }
}

Visual Indicator Ideas

Component with issues:
┌──────────────────┐
│ 🔴 UserLoginForm │  ← Red badge = has open issues
└──────────────────┘

Component with resolved:
┌──────────────────┐
│ ✅ PaymentForm   │  ← Green check = all issues closed
└──────────────────┘

Badge shows count:
┌──────────────────┐
│ 3⃣ DataTable    │  ← Number = issue count
└──────────────────┘

Questions to Resolve

  • Should we support multiple GitHub accounts?
  • How to handle private vs public repos differently?
  • Should component links sync back to GitHub as comments?
  • How to handle issue links when component is renamed?
  • Should we support GitHub Enterprise Server?

Decisions Log

Date Decision Rationale
2024-XX-XX Use OAuth App initially Simpler, can upgrade later
2024-XX-XX Store links in project.json Keeps with existing patterns
- - -

Session Notes

Session 1: [Date TBD]

Notes from implementation session


Session 2: [Date TBD]

Notes from implementation session


Useful Code Snippets

Octokit Basic Usage

import { Octokit } from '@octokit/rest';

const octokit = new Octokit({ auth: token });

// List issues
const { data: issues } = await octokit.issues.listForRepo({
  owner: 'The-Low-Code-Foundation',
  repo: 'OpenNoodl',
  state: 'open',
  per_page: 30
});

// Create issue
const { data: newIssue } = await octokit.issues.create({
  owner,
  repo,
  title: 'Bug in UserLoginForm',
  body: 'Description...',
  labels: ['bug']
});

React-Markdown Setup

import ReactMarkdown from 'react-markdown';
import remarkGfm from 'remark-gfm';

function IssueBody({ markdown }: { markdown: string }) {
  return (
    <ReactMarkdown 
      remarkPlugins={[remarkGfm]}
      components={{
        // Custom renderers for GitHub-specific elements
        a: ({ href, children }) => (
          <a href={href} target="_blank" rel="noopener">
            {children}
          </a>
        )
      }}
    >
      {markdown}
    </ReactMarkdown>
  );
}

Testing Repos

  • Use The-Low-Code-Foundation/OpenNoodl for real testing
  • Create a test repo with known issue/PR states
  • Test with repo that has 100+ issues for pagination

References from Codebase

Files to study:

  • packages/noodl-git/src/git.ts - Git operations patterns
  • packages/noodl-editor/src/editor/src/views/panels/VersionControlPanel/ - UI patterns
  • packages/noodl-editor/src/editor/src/models/projectmodel.ts - Metadata storage
  • packages/noodl-editor/src/editor/src/views/nodegrapheditor/ - Context menus