Skip to content

Commit 365ece4

Browse files
committed
detect backend automatically
1 parent 095f17c commit 365ece4

File tree

6 files changed

+70
-36
lines changed

6 files changed

+70
-36
lines changed

frontend/src/components/meh-comments/meh-comments.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {Component, Element, h, Prop, State} from '@stencil/core';
2-
import {formatRelativeTime, isAdmin, makeApiRequest, TranslationManager} from '../../utils/utils';
2+
import {formatRelativeTime, isAdmin, makeApiRequest, TranslationManager, detectBackendUrl} from '../../utils/utils';
33

44
@Component({
55
tag: 'meh-comments',
@@ -20,7 +20,7 @@ export class MehComments {
2020

2121
/**
2222
* The base URL for where the meh system is hosted
23-
* If not provided, defaults to same origin
23+
* If not provided, attempts to detect from script tag
2424
*/
2525
@Prop() backend: string = '';
2626

@@ -78,10 +78,8 @@ export class MehComments {
7878
this.post = window.location.pathname;
7979
}
8080

81-
// remove trailing slash from backend URL
82-
if (this.backend.endsWith('/')) {
83-
this.backend = this.backend.slice(0, -1);
84-
}
81+
// Process the backend URL (clean or detect)
82+
this.backend = detectBackendUrl(this.backend);
8583

8684
// Initialize the TranslationManager with default translations
8785
this.translator = new TranslationManager(this.defaultTranslations);

frontend/src/components/meh-count/meh-count.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {Component, Prop, h, State} from '@stencil/core';
2-
import {TranslationManager, makeApiRequest} from '../../utils/utils';
2+
import {TranslationManager, makeApiRequest, detectBackendUrl} from '../../utils/utils';
33

44
@Component({
55
tag: 'meh-count',
@@ -18,7 +18,7 @@ export class MehCount {
1818

1919
/**
2020
* The base URL for where the meh system is hosted
21-
* If not provided, defaults to same origin
21+
* If not provided, attempts to detect from script tag
2222
*/
2323
@Prop() backend: string = '';
2424

@@ -77,10 +77,8 @@ export class MehCount {
7777
this.post = window.location.pathname;
7878
}
7979

80-
// remove trailing slash from backend URL
81-
if (this.backend.endsWith('/')) {
82-
this.backend = this.backend.slice(0, -1);
83-
}
80+
// Process the backend URL (clean or detect)
81+
this.backend = detectBackendUrl(this.backend);
8482

8583
// Initialize the TranslationManager with default translations
8684
this.translator = new TranslationManager(this.defaultTranslations);

frontend/src/components/meh-form/meh-form.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {Component, Prop, h, State, Element} from '@stencil/core';
2-
import { TranslationManager, TOKEN_STORAGE_KEY, makeApiRequest } from '../../utils/utils';
2+
import { TranslationManager, TOKEN_STORAGE_KEY, makeApiRequest, detectBackendUrl } from '../../utils/utils';
33

44
@Component({
55
tag: 'meh-form',
@@ -21,7 +21,7 @@ export class MehForm {
2121

2222
/**
2323
* The base URL for where the meh system is hosted
24-
* If not provided, defaults to same origin
24+
* If not provided, attempts to detect from script tag
2525
*/
2626
@Prop() backend: string = '';
2727

@@ -95,10 +95,8 @@ export class MehForm {
9595
this.post = window.location.pathname;
9696
}
9797

98-
// remove trailing slash from backend URL
99-
if (this.backend.endsWith('/')) {
100-
this.backend = this.backend.slice(0, -1);
101-
}
98+
// Process the backend URL (clean or detect)
99+
this.backend = detectBackendUrl(this.backend);
102100

103101
// Initialize the TranslationManager with default translations
104102
this.translator = new TranslationManager(this.defaultTranslations);

frontend/src/components/meh-login/meh-login.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {Component, Prop, h, State} from '@stencil/core';
2-
import {TranslationManager, TOKEN_STORAGE_KEY, isAdmin, makeApiRequest} from '../../utils/utils';
2+
import {TranslationManager, TOKEN_STORAGE_KEY, isAdmin, makeApiRequest, detectBackendUrl} from '../../utils/utils';
33

44
@Component({
55
tag: 'meh-login',
@@ -13,7 +13,7 @@ import {TranslationManager, TOKEN_STORAGE_KEY, isAdmin, makeApiRequest} from '..
1313
export class MehLogin {
1414
/**
1515
* The base URL for where the meh system is hosted
16-
* If not provided, defaults to same origin
16+
* If not provided, attempts to detect from script tag
1717
*/
1818
@Prop() backend: string = '';
1919

@@ -68,10 +68,8 @@ export class MehLogin {
6868
}
6969

7070
async componentWillLoad() {
71-
// remove trailing slash from backend URL
72-
if (this.backend.endsWith('/')) {
73-
this.backend = this.backend.slice(0, -1);
74-
}
71+
// Process the backend URL (clean or detect)
72+
this.backend = detectBackendUrl(this.backend);
7573

7674
// Initialize the TranslationManager with default translations
7775
this.translator = new TranslationManager(this.defaultTranslations);

frontend/src/components/meh-mastodon/meh-mastodon.tsx

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import {Component, h, Prop, State} from '@stencil/core';
2-
import {TranslationManager, makeApiRequest} from '../../utils/utils';
2+
import {TranslationManager, makeApiRequest, detectBackendUrl} from '../../utils/utils';
33

44
@Component({
55
tag: 'meh-mastodon',
@@ -18,7 +18,7 @@ export class MehMastodon {
1818

1919
/**
2020
* The base URL for where the meh system is hosted
21-
* If not provided, defaults to same origin
21+
* If not provided, attempts to detect from script tag
2222
*/
2323
@Prop() backend: string = '';
2424

@@ -67,10 +67,8 @@ export class MehMastodon {
6767
this.post = window.location.pathname;
6868
}
6969

70-
// remove trailing slash from backend URL
71-
if (this.backend.endsWith('/')) {
72-
this.backend = this.backend.slice(0, -1);
73-
}
70+
// Process the backend URL (clean or detect)
71+
this.backend = detectBackendUrl(this.backend);
7472

7573
// Initialize the TranslationManager with default translations
7674
this.translator = new TranslationManager(this.defaultTranslations);

frontend/src/utils/utils.ts

Lines changed: 50 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,49 @@
11
import {jwtDecode, JwtPayload} from "jwt-decode"
22

3+
/**
4+
* Process the backend URL:
5+
* - If a URL is provided, clean it (remove trailing slash)
6+
* - If no URL is provided, attempt to detect it from the script tag
7+
*
8+
* @param backendUrl - The backend URL provided by the component, if any
9+
* @returns The processed backend URL
10+
*/
11+
export function detectBackendUrl(backendUrl: string = ''): string {
12+
// If a backend URL is provided, just clean it
13+
if (backendUrl) {
14+
// Remove trailing slash if present
15+
return backendUrl.endsWith('/') ? backendUrl.slice(0, -1) : backendUrl;
16+
}
17+
18+
// Otherwise, try to detect it from the script tag
19+
try {
20+
// Find the script tag that loaded meh.esm.js
21+
const scriptTags = document.querySelectorAll('script[src*="meh.esm.js"]');
22+
if (scriptTags.length === 0) return '';
23+
24+
// Get the src attribute of the first matching script tag
25+
const scriptSrc = scriptTags[0].getAttribute('src');
26+
if (!scriptSrc) return '';
27+
28+
// Extract the base path from the script src
29+
const urlObj = new URL(scriptSrc, window.location.href);
30+
const pathParts = urlObj.pathname.split('/');
31+
32+
// Remove the filename and 'meh' directory from the path
33+
pathParts.pop(); // Remove 'meh.esm.js'
34+
if (pathParts[pathParts.length - 1] === 'meh') {
35+
pathParts.pop(); // Remove 'meh' directory
36+
}
37+
38+
// Construct the backend URL with protocol, hostname, and port if present
39+
const port = urlObj.port ? `:${urlObj.port}` : '';
40+
return `${urlObj.protocol}//${urlObj.hostname}${port}${pathParts.join('/')}`;
41+
} catch (error) {
42+
console.error('Error detecting backend URL:', error);
43+
return '';
44+
}
45+
}
46+
347
// Define a custom interface that extends JwtPayload to include scopes
448
interface MehJwtPayload extends JwtPayload {
549
scopes?: string[];
@@ -57,15 +101,15 @@ export async function makeApiRequest<T = any>(
57101

58102
// Build the URL
59103
let url = `${backend}/api/${site}/${endpoint}`;
60-
104+
61105
// For GET requests, convert body to query parameters
62106
if (method === 'GET' && body !== undefined) {
63107
const params = new URLSearchParams();
64108
Object.entries(body).forEach(([key, value]) => {
65109
params.append(key, String(value));
66110
});
67111
url += `?${params.toString()}`;
68-
}
112+
}
69113
// For non-GET requests, add body as JSON
70114
else if (method !== 'GET' && body !== undefined) {
71115
requestOptions.body = JSON.stringify(body);
@@ -208,20 +252,20 @@ export class TranslationManager<T extends Record<string, string>> {
208252
get<K extends keyof T | string>(key: K): string {
209253
// Check if this is a template string with `key` format
210254
const match = String(key).match(/^`([^`]+)`(.*)$/);
211-
255+
212256
if (match) {
213257
// Template format found
214258
const [, templateKey, fallbackText] = match;
215-
259+
216260
// Check if key exists in translations
217261
if (templateKey in this.translations) {
218262
return this.translations[templateKey as keyof T] as string;
219263
}
220-
264+
221265
// Return fallback text (trimming leading space if present)
222266
return fallbackText.trim();
223267
}
224-
268+
225269
// Not a template format, treat as regular key
226270
return (this.translations[key as keyof T] as string) || String(key);
227271
}

0 commit comments

Comments
 (0)