Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
559 changes: 293 additions & 266 deletions package-lock.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion packages/core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@websdr/core",
"version": "0.6.0",
"version": "0.6.1",
"description": "This is the core package for WebSDR",
"author": "Timur Davydov <dtv.comp@gmail.com>",
"license": "MIT",
Expand Down
8 changes: 8 additions & 0 deletions packages/frontend-core/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ const profile = await apiFetch<Profile>('/api/auth/profile');

If `setApiBase()` is not called, the helper tries `globalThis.__API_BASE__`, then `process.env.VITE_API_URL` / `process.env.API_URL`, then `import.meta.env.VITE_API_URL` / `import.meta.env.API_URL`, and finally falls back to `/`.

For WebSocket endpoints that share the same API base, use `apiWsUrl()`. It resolves the `/` fallback against `globalThis.location` and converts `http:` / `https:` to `ws:` / `wss:`.

```ts
import { apiWsUrl } from '@websdr/frontend-core/services';

const rpcUrl = apiWsUrl('/rpc');
```

You can also set the API base via a global variable (useful for `index.html` deployments):

```ts
Expand Down
4 changes: 2 additions & 2 deletions packages/frontend-core/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@websdr/frontend-core",
"version": "0.6.0",
"version": "0.6.1",
"description": "This is the core frontend package for WebSDR",
"author": "Timur Davydov <dtv.comp@gmail.com>",
"license": "MIT",
Expand Down Expand Up @@ -37,7 +37,7 @@
"postpack": "rm -f ./LICENSE"
},
"dependencies": {
"@websdr/core": "^0.6.0",
"@websdr/core": "^0.6.1",
"usb": "^2.17.0"
},
"devDependencies": {
Expand Down
26 changes: 26 additions & 0 deletions packages/frontend-core/src/services/api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,31 @@ export function apiUrl(path = ''): string {
return `${base.replace(/\/+$/, '')}/${path.replace(/^\/+/, '')}`;
}

export function apiWsUrl(path = '', port?: number): string {
const httpUrl = apiUrl(path);
const baseUrl = typeof globalThis.location === 'object'
? globalThis.location.href
: undefined;

if (!baseUrl && httpUrl.startsWith('/')) {
throw new Error('Cannot build a WebSocket API URL from a relative API base without globalThis.location');
}

const url = new URL(httpUrl, baseUrl);

if (url.protocol === 'https:') {
url.protocol = 'wss:';
} else if (url.protocol === 'http:') {
url.protocol = 'ws:';
}

if (port !== undefined) {
url.port = String(port);
}

return url.toString();
}

export async function apiFetch<T = any>(path: string, init?: RequestInit): Promise<T> {
const url = apiUrl(path);
const res = await fetch(url, { ...init, credentials: 'include' });
Expand Down Expand Up @@ -77,5 +102,6 @@ export default {
setApiBase,
getApiBase,
apiUrl,
apiWsUrl,
apiFetch,
};
4 changes: 2 additions & 2 deletions packages/frontend-core/src/services/index.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
export { setApiBase, getApiBase, apiUrl, apiFetch } from "./api";
export { login, logout, getProfile } from "./auth";
export { setApiBase, getApiBase, apiUrl, apiWsUrl, apiFetch } from "./api";
export { login, logout, getProfile } from "./auth";
45 changes: 44 additions & 1 deletion packages/frontend-core/src/tests/services/api.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest';
import { apiFetch, setApiBase } from '@/services/api';
import { apiFetch, apiWsUrl, setApiBase } from '@/services/api';

describe('apiFetch', () => {
let originalFetch: typeof fetch | undefined;
Expand Down Expand Up @@ -100,6 +100,49 @@ describe('apiFetch', () => {
});

});

describe('apiWsUrl', () => {
let originalLocation: Location | undefined;

beforeEach(() => {
originalLocation = globalThis.location;
setApiBase(undefined);
});

afterEach(() => {
if (originalLocation === undefined) {
delete (globalThis as { location?: Location }).location;
} else {
Object.defineProperty(globalThis, 'location', {
value: originalLocation,
configurable: true,
});
}
setApiBase(undefined);
});

it('builds a websocket URL from an absolute HTTPS API base', () => {
setApiBase('https://api.example.com');

expect(apiWsUrl('/rpc')).toBe('wss://api.example.com/rpc');
});

it('overrides the websocket URL port when provided', () => {
setApiBase('https://api.example.com');

expect(apiWsUrl('/rpc', 8080)).toBe('wss://api.example.com:8080/rpc');
});

it('builds a websocket URL from the current origin when API base falls back to "/"', () => {
Object.defineProperty(globalThis, 'location', {
value: new URL('https://app.example.com/current/page'),
configurable: true,
});

expect(apiWsUrl('/rpc')).toBe('wss://app.example.com/rpc');
});
});

// Tests for getEnvApiBase (indirectly via the public getApiBase)
describe('getEnvApiBase via getApiBase', () => {
let originalApiBaseGlobal: any;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,7 @@ export class WebUsbSourceSink extends WebUsbDeviceControlBase {
}

close() {
this.stopStream();
void this.closeDevice();
this._streamMeterData?.down();
}
Expand Down
4 changes: 2 additions & 2 deletions packages/nestjs-microservice/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@websdr/nestjs-microservice",
"version": "0.6.0",
"version": "0.6.1",
"description": "This is a NestJS microservice for WebSDR",
"author": "Timur Davydov <dtv.comp@gmail.com>",
"license": "MIT",
Expand Down Expand Up @@ -33,7 +33,7 @@
"postpack": "rm -f ./LICENSE"
},
"dependencies": {
"@websdr/core": "^0.6.0",
"@websdr/core": "^0.6.1",
"class-transformer": "^0.5.1",
"class-validator": "^0.15.1",
"passport-jwt": "^4.0.1",
Expand Down
6 changes: 3 additions & 3 deletions packages/vue3-components/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@websdr/vue3-components",
"version": "0.6.0",
"version": "0.6.1",
"description": "This is a Vue 3 components package for WebSDR",
"author": "Timur Davydov <dtv.comp@gmail.com>",
"license": "MIT",
Expand Down Expand Up @@ -37,8 +37,8 @@
"postpack": "rm -f ./LICENSE"
},
"dependencies": {
"@websdr/core": "^0.6.0",
"@websdr/frontend-core": "^0.6.0"
"@websdr/core": "^0.6.1",
"@websdr/frontend-core": "^0.6.1"
},
"devDependencies": {
"@vitejs/plugin-vue": "^6.0.7",
Expand Down
Loading