Pre-launch — Gluecron is in final validation. Public signups and git hosting for non-owner users open after launch review.
CodeIssuesPull RequestsActionsSecurityInsightsSettings
✨ AI
More
Blame · Line-by-line history

import-helper.ts

Each line is annotated with the commit that last touched it. Click any SHA to jump to that commit and see the surrounding change.

import-helper.tsBlame67 lines · 1 contributor
80bed05Claude1/**
2 * Small helpers for the GitHub import flow (/import).
3 *
4 * Kept in its own file so we can stay inside the rule that says we may
5 * only edit src/routes/import.tsx and add a helper here. No DB or git
6 * process coupling — this is pure parsing/normalization.
7 */
8
9export interface ParsedGithubUrl {
10 owner: string;
11 repo: string;
12}
13
14/**
15 * Parse a GitHub URL into { owner, repo }. Accepts:
16 * - https://github.com/foo/bar
17 * - https://github.com/foo/bar.git
18 * - http://github.com/foo/bar/
19 * - git@github.com:foo/bar.git
20 * - github.com/foo/bar
21 * - foo/bar
22 *
23 * Returns null if the URL cannot be parsed.
24 */
25export function parseGithubUrl(raw: string): ParsedGithubUrl | null {
26 const input = (raw || "").trim();
27 if (!input) return null;
28
29 // SSH form: git@github.com:owner/repo(.git)?
30 const ssh = input.match(/^git@github\.com:([^/]+)\/([^/\s]+?)(?:\.git)?\/?$/i);
31 if (ssh) return { owner: ssh[1], repo: stripDotGit(ssh[2]) };
32
33 // HTTP(S) / bare host form
34 const http = input.match(
35 /^(?:https?:\/\/)?(?:www\.)?github\.com\/([^/\s]+)\/([^/\s?#]+?)(?:\.git)?\/?(?:[?#].*)?$/i
36 );
37 if (http) return { owner: http[1], repo: stripDotGit(http[2]) };
38
39 // owner/repo shorthand
40 const short = input.match(/^([^/\s]+)\/([^/\s]+?)(?:\.git)?$/);
41 if (short) return { owner: short[1], repo: stripDotGit(short[2]) };
42
43 return null;
44}
45
46function stripDotGit(name: string): string {
47 return name.replace(/\.git$/i, "");
48}
49
50/**
51 * Repository names on gluecron follow GitHub's rough rules: letters,
52 * digits, hyphens, underscores, dots. We normalize by replacing anything
53 * else with a hyphen so an imported repo is always addressable.
54 */
55export function sanitizeRepoName(name: string): string {
56 const cleaned = name.replace(/[^A-Za-z0-9._-]/g, "-").replace(/^-+|-+$/g, "");
57 return cleaned || "imported-repo";
58}
59
60/**
61 * Build the clone URL that `git clone --bare --mirror` will use. When a
62 * token is supplied we inject it so private repos are reachable.
63 */
64export function buildCloneUrl(cloneUrl: string, token: string | null): string {
65 if (!token) return cloneUrl;
66 return cloneUrl.replace("https://github.com/", `https://${token}@github.com/`);
67}