gent-cli 14.0.0 → 20.0.0

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.
@@ -0,0 +1,125 @@
1
+ /**
2
+ * ============================================================================
3
+ * Web URLs - Build links into the gent web app (frontend), not the API.
4
+ * ============================================================================
5
+ *
6
+ * The frontend is a SEPARATE deployment from the API. Never derive a web URL
7
+ * from `api.base_url` — resolve `web.base_url` (env GENT_WEB_URL > user config
8
+ * > built-in default) instead.
9
+ *
10
+ * CANONICAL ROUTE TREE
11
+ * The Next.js app currently ships two parallel repo route trees:
12
+ * /app/[ownerId]/[name] (older lineage)
13
+ * /dashboard/repository/[owner_id]/[repo_name] (frontend2 lineage)
14
+ *
15
+ * We target the /dashboard tree: it is where `/auth/login` sends users after
16
+ * sign-in (`router.replace(DASHBOARD_PATH.ROOT)`), it is what the dashboard
17
+ * sidebar links to, and its route params (`owner_id` / `repo_name`) match the
18
+ * values the CLI parses out of a remote URL.
19
+ *
20
+ * If that decision is reversed, change `repoPath()` below — it is the single
21
+ * place the shape is defined.
22
+ *
23
+ * BRANCH / COMMIT DEEP LINKS
24
+ * The frontend has NO addressable branch or commit target. Verified against
25
+ * `npx next build` (no /tree/[branch], no /commit/[sha] route in either tree)
26
+ * and against the page sources: the branch picker and the commit diff modal
27
+ * are both local `useState`, never reflected in the URL or a query param.
28
+ * So we do not invent a URL shape — callers surface `BRANCH_COMMIT_UNSUPPORTED`
29
+ * and fall back to the repo page.
30
+ * ============================================================================
31
+ */
32
+
33
+ const userConfig = require('./user-config');
34
+
35
+ /** Message shown when a caller asks for a branch/commit link we cannot build. */
36
+ const BRANCH_COMMIT_UNSUPPORTED =
37
+ 'The gent web app has no branch or commit page yet, so this link points at the repository instead.';
38
+
39
+ /**
40
+ * Resolve the web app base URL (env > user config > default), validated and
41
+ * without a trailing slash.
42
+ *
43
+ * Validation is deliberate: a scheme-less value like `gent.example.com` is a
44
+ * realistic typo, and without a check it silently yields a relative path that
45
+ * looks like a link but isn't one. Fail loudly here instead — this is the
46
+ * single normalization point, so callers can assume a clean http(s) base.
47
+ *
48
+ * @returns {Promise<string>}
49
+ * @throws {Error} if the configured value is not an http(s) URL
50
+ */
51
+ async function getWebBaseUrl() {
52
+ const { value, source } = await userConfig.getResolved('web.base_url');
53
+ const raw = String(value ?? '').trim();
54
+
55
+ let parsed = null;
56
+ try {
57
+ parsed = new URL(raw);
58
+ } catch {
59
+ parsed = null;
60
+ }
61
+
62
+ if (!parsed || !/^https?:$/.test(parsed.protocol)) {
63
+ throw new Error(
64
+ `Invalid web.base_url (${source}): '${raw}'. `
65
+ + 'Expected an http(s) URL, e.g. https://gent-nu2e.onrender.com. '
66
+ + 'Set it with `gent config set web.base_url <url>`.'
67
+ );
68
+ }
69
+
70
+ return stripTrailingSlash(parsed.href);
71
+ }
72
+
73
+ function stripTrailingSlash(url) {
74
+ return String(url || '').replace(/\/+$/, '');
75
+ }
76
+
77
+ /**
78
+ * Path (no host) of a repository page on the web app.
79
+ * Single source of truth for the repo route shape.
80
+ * @param {string|number} ownerId
81
+ * @param {string} repoName
82
+ * @returns {string}
83
+ */
84
+ function repoPath(ownerId, repoName) {
85
+ return `/dashboard/repository/${encodeURIComponent(ownerId)}/${encodeURIComponent(repoName)}`;
86
+ }
87
+
88
+ /**
89
+ * Absolute URL of a repository page.
90
+ * @param {string} baseUrl - Web app base URL
91
+ * @param {string|number} ownerId
92
+ * @param {string} repoName
93
+ * @returns {string}
94
+ */
95
+ function repoUrl(baseUrl, ownerId, repoName) {
96
+ return `${stripTrailingSlash(baseUrl)}${repoPath(ownerId, repoName)}`;
97
+ }
98
+
99
+ /**
100
+ * Build the best available link for the requested target.
101
+ *
102
+ * Because branch/commit pages don't exist, a branch or commit request resolves
103
+ * to the repo page and reports `unsupported` so the caller can warn.
104
+ *
105
+ * @param {string} baseUrl - Web app base URL
106
+ * @param {{ owner_id: string|number, repo_name: string }} info
107
+ * @param {{ branch?: string, commit?: string }} [target]
108
+ * @returns {{ url: string, unsupported: null|'branch'|'commit' }}
109
+ */
110
+ function buildRepoLink(baseUrl, info, target = {}) {
111
+ const url = repoUrl(baseUrl, info.owner_id, info.repo_name);
112
+ let unsupported = null;
113
+ if (target.commit) unsupported = 'commit';
114
+ else if (target.branch) unsupported = 'branch';
115
+ return { url, unsupported };
116
+ }
117
+
118
+ module.exports = {
119
+ BRANCH_COMMIT_UNSUPPORTED,
120
+ getWebBaseUrl,
121
+ repoPath,
122
+ repoUrl,
123
+ buildRepoLink,
124
+ stripTrailingSlash,
125
+ };