blanchon commited on
Commit
befd3bb
·
2 Parent(s): b5ad80c ccb03a3

Resolve merge conflicts

Browse files
demo/README.md CHANGED
@@ -59,6 +59,48 @@ demo/
59
  2. **LeRobot Arena Server** running on port 8000
60
  3. **Built JavaScript Client** (automatically installed as dependency)
61
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
62
  ## 🚀 Quick Start
63
 
64
  ### 1. Install Dependencies
 
59
  2. **LeRobot Arena Server** running on port 8000
60
  3. **Built JavaScript Client** (automatically installed as dependency)
61
 
62
+ ## ⚙️ Server Configuration
63
+
64
+ The demo automatically detects the correct server URL based on the environment:
65
+
66
+ - **Development mode**: `http://localhost:8000` (when running on localhost)
67
+ - **Production mode**: `https://blanchon-robottransportserver.hf.space/api` (when deployed)
68
+
69
+ ### Environment Variable Override
70
+
71
+ You can override the default server URL by setting the `PUBLIC_SERVER_URL` environment variable:
72
+
73
+ ```bash
74
+ # For development with custom server
75
+ export PUBLIC_SERVER_URL=http://localhost:8000
76
+
77
+ # For production with HuggingFace Space
78
+ export PUBLIC_SERVER_URL=https://blanchon-robottransportserver.hf.space/api
79
+
80
+ # For custom server deployment
81
+ export PUBLIC_SERVER_URL=https://your-custom-server.com/api
82
+ ```
83
+
84
+ ### Setting Environment Variables
85
+
86
+ #### Option 1: Create a `.env` file
87
+ ```bash
88
+ # In demo/.env
89
+ PUBLIC_SERVER_URL=http://localhost:8000
90
+ ```
91
+
92
+ #### Option 2: Runtime environment variable
93
+ ```bash
94
+ # Set via window object (for runtime configuration)
95
+ window.__SERVER_URL__ = 'http://localhost:8000';
96
+ ```
97
+
98
+ #### Option 3: Build-time environment variable
99
+ ```bash
100
+ # When building
101
+ PUBLIC_SERVER_URL=https://your-server.com/api bun run build
102
+ ```
103
+
104
  ## 🚀 Quick Start
105
 
106
  ### 1. Install Dependencies
demo/bun.lock CHANGED
@@ -4,7 +4,7 @@
4
  "": {
5
  "name": "demo",
6
  "dependencies": {
7
- "@robothub/transport-server-client": "https://gitpkg.now.sh/julien-blanchon/robothub/services/transport-server/client/js?main",
8
  },
9
  "devDependencies": {
10
  "@eslint/compat": "^1.2.5",
@@ -130,7 +130,7 @@
130
 
131
  "@polka/url": ["@polka/[email protected]", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],
132
 
133
- "@robothub/transport-server-client": ["@robothub/transport-server-client@https://gitpkg.now.sh/julien-blanchon/robothub/services/transport-server/client/js?main", { "dependencies": { "eventemitter3": "^5.0.1" }, "peerDependencies": { "typescript": ">=5.0.0" } }],
134
 
135
  "@rollup/rollup-android-arm-eabi": ["@rollup/[email protected]", "", { "os": "android", "cpu": "arm" }, "sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw=="],
136
 
@@ -212,6 +212,8 @@
212
 
213
  "@tailwindcss/vite": ["@tailwindcss/[email protected]", "", { "dependencies": { "@tailwindcss/node": "4.1.8", "@tailwindcss/oxide": "4.1.8", "tailwindcss": "4.1.8" }, "peerDependencies": { "vite": "^5.2.0 || ^6" } }, "sha512-CQ+I8yxNV5/6uGaJjiuymgw0kEQiNKRinYbZXPdx1fk5WgiyReG0VaUx/Xq6aVNSUNJFzxm6o8FNKS5aMaim5A=="],
214
 
 
 
215
  "@types/cookie": ["@types/[email protected]", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],
216
 
217
  "@types/estree": ["@types/[email protected]", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
@@ -260,6 +262,8 @@
260
 
261
  "braces": ["[email protected]", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
262
 
 
 
263
  "callsites": ["[email protected]", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
264
 
265
  "chalk": ["[email protected]", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
 
4
  "": {
5
  "name": "demo",
6
  "dependencies": {
7
+ "@robothub/transport-server-client": "file:../client/js",
8
  },
9
  "devDependencies": {
10
  "@eslint/compat": "^1.2.5",
 
130
 
131
  "@polka/url": ["@polka/[email protected]", "", {}, "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww=="],
132
 
133
+ "@robothub/transport-server-client": ["@robothub/transport-server-client@file:../client/js", { "dependencies": { "eventemitter3": "^5.0.1" }, "devDependencies": { "@types/bun": "^1.2.15", "typescript": "^5.3.3" }, "peerDependencies": { "typescript": ">=5.0.0" } }],
134
 
135
  "@rollup/rollup-android-arm-eabi": ["@rollup/[email protected]", "", { "os": "android", "cpu": "arm" }, "sha512-NELNvyEWZ6R9QMkiytB4/L4zSEaBC03KIXEghptLGLZWJ6VPrL63ooZQCOnlx36aQPGhzuOMwDerC1Eb2VmrLw=="],
136
 
 
212
 
213
  "@tailwindcss/vite": ["@tailwindcss/[email protected]", "", { "dependencies": { "@tailwindcss/node": "4.1.8", "@tailwindcss/oxide": "4.1.8", "tailwindcss": "4.1.8" }, "peerDependencies": { "vite": "^5.2.0 || ^6" } }, "sha512-CQ+I8yxNV5/6uGaJjiuymgw0kEQiNKRinYbZXPdx1fk5WgiyReG0VaUx/Xq6aVNSUNJFzxm6o8FNKS5aMaim5A=="],
214
 
215
+ "@types/bun": ["@types/[email protected]", "", { "dependencies": { "bun-types": "1.2.17" } }, "sha512-l/BYs/JYt+cXA/0+wUhulYJB6a6p//GTPiJ7nV+QHa8iiId4HZmnu/3J/SowP5g0rTiERY2kfGKXEK5Ehltx4Q=="],
216
+
217
  "@types/cookie": ["@types/[email protected]", "", {}, "sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA=="],
218
 
219
  "@types/estree": ["@types/[email protected]", "", {}, "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w=="],
 
262
 
263
  "braces": ["[email protected]", "", { "dependencies": { "fill-range": "^7.1.1" } }, "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA=="],
264
 
265
+ "bun-types": ["[email protected]", "", { "dependencies": { "@types/node": "*" } }, "sha512-ElC7ItwT3SCQwYZDYoAH+q6KT4Fxjl8DtZ6qDulUFBmXA8YB4xo+l54J9ZJN+k2pphfn9vk7kfubeSd5QfTVJQ=="],
266
+
267
  "callsites": ["[email protected]", "", {}, "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ=="],
268
 
269
  "chalk": ["[email protected]", "", { "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" } }, "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA=="],
demo/src/lib/index.ts CHANGED
@@ -1 +1,35 @@
1
  // place files you want to import through the `$lib` alias in this folder.
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
  // place files you want to import through the `$lib` alias in this folder.
2
+
3
+ /**
4
+ * Get the server URL based on environment variables and dev/prod mode
5
+ * Priority: ENV variable > dev mode (localhost:8000) > prod mode (HF Space)
6
+ */
7
+ export function getServerUrl(): string {
8
+ // Check for environment variable first
9
+ if (typeof window !== 'undefined') {
10
+ // Client-side: check for runtime environment variable
11
+ const envUrl = (window as any).__SERVER_URL__;
12
+ if (envUrl) {
13
+ return envUrl;
14
+ }
15
+ } else {
16
+ // Server-side: check for build-time environment variable
17
+ const envUrl = process.env.PUBLIC_SERVER_URL;
18
+ if (envUrl) {
19
+ return envUrl;
20
+ }
21
+ }
22
+
23
+ // Fall back to dev/prod detection
24
+ if (typeof window !== 'undefined') {
25
+ // Client-side: check if we're in development
26
+ const isDev = window.location.hostname === 'localhost' ||
27
+ window.location.hostname === '127.0.0.1' ||
28
+ window.location.hostname.startsWith('192.168.');
29
+
30
+ return isDev ? 'http://localhost:8000' : 'https://blanchon-robottransportserver.hf.space/api';
31
+ }
32
+
33
+ // Server-side fallback
34
+ return 'http://localhost:8000';
35
+ }
demo/src/lib/settings.svelte.ts ADDED
@@ -0,0 +1,9 @@
 
 
 
 
 
 
 
 
 
 
1
+ import { getServerUrl } from './index.js';
2
+
3
+ interface Settings {
4
+ transportServerUrl: string;
5
+ }
6
+
7
+ export const settings: Settings = $state({
8
+ transportServerUrl: getServerUrl()
9
+ });
demo/src/routes/+page.svelte CHANGED
@@ -3,6 +3,8 @@
3
  import { robotics } from '@robothub/transport-server-client';
4
  import type { robotics as roboticsTypes } from '@robothub/transport-server-client';
5
  import { goto } from '$app/navigation';
 
 
6
 
7
  // Server status
8
  let serverStatus = $state<'checking' | 'connected' | 'error'>('checking');
@@ -29,10 +31,8 @@
29
  debugInfo.connectionAttempts++;
30
 
31
  try {
32
- // Use relative URL so it works in both development and production
33
- const baseUrl = typeof window !== 'undefined' ? window.location.origin : 'http://localhost:7860';
34
- const apiUrl = `${baseUrl}/api`;
35
- const client = new robotics.RoboticsClientCore(apiUrl);
36
  const roomList = await client.listRooms('');
37
  rooms = roomList;
38
  serverInfo = { rooms: roomList.length, version: '1.0.0' };
 
3
  import { robotics } from '@robothub/transport-server-client';
4
  import type { robotics as roboticsTypes } from '@robothub/transport-server-client';
5
  import { goto } from '$app/navigation';
6
+ import { settings } from '$lib/settings.svelte.js';
7
+
8
 
9
  // Server status
10
  let serverStatus = $state<'checking' | 'connected' | 'error'>('checking');
 
31
  debugInfo.connectionAttempts++;
32
 
33
  try {
34
+ // Use the configured server URL
35
+ const client = new robotics.RoboticsClientCore(settings.transportServerUrl);
 
 
36
  const roomList = await client.listRooms('');
37
  rooms = roomList;
38
  serverInfo = { rooms: roomList.length, version: '1.0.0' };
demo/src/routes/[workspaceId]/+page.svelte CHANGED
@@ -1,7 +1,9 @@
1
  <script lang="ts">
 
2
  import { onMount } from 'svelte';
3
  import { robotics, video } from '@robothub/transport-server-client';
4
  import type { robotics as roboticsTypes, video as videoTypes } from '@robothub/transport-server-client';
 
5
 
6
  // Get data from load function
7
  let { data } = $props();
@@ -41,7 +43,11 @@
41
 
42
  // Load robotics rooms
43
  try {
 
44
  roboticsClient = new robotics.RoboticsClientCore('https://blanchon-robothub-transportserver.hf.space/api');
 
 
 
45
  roboticsRooms = await roboticsClient.listRooms(workspaceId);
46
  } catch (err) {
47
  roboticsError = 'Failed to load robotics rooms';
@@ -50,7 +56,11 @@
50
 
51
  // Load video rooms
52
  try {
 
53
  videoClient = new video.VideoClientCore('https://blanchon-robothub-transportserver.hf.space/api');
 
 
 
54
  videoRooms = await videoClient.listRooms(workspaceId);
55
  } catch (err) {
56
  videoError = 'Failed to load video rooms';
 
1
  <script lang="ts">
2
+ import { settings } from '$lib/settings.svelte.js';
3
  import { onMount } from 'svelte';
4
  import { robotics, video } from '@robothub/transport-server-client';
5
  import type { robotics as roboticsTypes, video as videoTypes } from '@robothub/transport-server-client';
6
+
7
 
8
  // Get data from load function
9
  let { data } = $props();
 
43
 
44
  // Load robotics rooms
45
  try {
46
+ <<<<<<< HEAD
47
  roboticsClient = new robotics.RoboticsClientCore('https://blanchon-robothub-transportserver.hf.space/api');
48
+ =======
49
+ roboticsClient = new robotics.RoboticsClientCore(settings.transportServerUrl);
50
+ >>>>>>> ccb03a313c3f3278e408a849294738a50b7ec4d0
51
  roboticsRooms = await roboticsClient.listRooms(workspaceId);
52
  } catch (err) {
53
  roboticsError = 'Failed to load robotics rooms';
 
56
 
57
  // Load video rooms
58
  try {
59
+ <<<<<<< HEAD
60
  videoClient = new video.VideoClientCore('https://blanchon-robothub-transportserver.hf.space/api');
61
+ =======
62
+ videoClient = new video.VideoClientCore(settings.transportServerUrl);
63
+ >>>>>>> ccb03a313c3f3278e408a849294738a50b7ec4d0
64
  videoRooms = await videoClient.listRooms(workspaceId);
65
  } catch (err) {
66
  videoError = 'Failed to load video rooms';
demo/src/routes/[workspaceId]/robotics/+page.svelte CHANGED
@@ -2,6 +2,7 @@
2
  import { onMount } from 'svelte';
3
  import { robotics } from '@robothub/transport-server-client';
4
  import type { robotics as roboticsTypes } from '@robothub/transport-server-client';
 
5
 
6
  // Get data from load function
7
  let { data } = $props();
@@ -42,7 +43,11 @@
42
  try {
43
  loading = true;
44
  error = '';
 
45
  client = new robotics.RoboticsClientCore('https://blanchon-robothub-transportserver.hf.space/api');
 
 
 
46
  rooms = await client.listRooms(workspaceId);
47
  debugInfo.responseTime = Date.now() - startTime;
48
  } catch (err) {
 
2
  import { onMount } from 'svelte';
3
  import { robotics } from '@robothub/transport-server-client';
4
  import type { robotics as roboticsTypes } from '@robothub/transport-server-client';
5
+
6
 
7
  // Get data from load function
8
  let { data } = $props();
 
43
  try {
44
  loading = true;
45
  error = '';
46
+ <<<<<<< HEAD
47
  client = new robotics.RoboticsClientCore('https://blanchon-robothub-transportserver.hf.space/api');
48
+ =======
49
+ client = new robotics.RoboticsClientCore(settings.transportServerUrl);
50
+ >>>>>>> ccb03a313c3f3278e408a849294738a50b7ec4d0
51
  rooms = await client.listRooms(workspaceId);
52
  debugInfo.responseTime = Date.now() - startTime;
53
  } catch (err) {
demo/src/routes/[workspaceId]/robotics/consumer/+page.svelte CHANGED
@@ -1,7 +1,9 @@
1
  <script lang="ts">
 
2
  import { onMount } from 'svelte';
3
  import { robotics } from '@robothub/transport-server-client';
4
  import type { robotics as roboticsTypes } from '@robothub/transport-server-client';
 
5
 
6
  // Get data from load function
7
  let { data } = $props();
@@ -70,7 +72,11 @@
70
  connecting = true;
71
  error = '';
72
 
 
73
  consumer = new robotics.RoboticsConsumer('https://blanchon-robothub-transportserver.hf.space/api');
 
 
 
74
 
75
  // Set up event handlers
76
  consumer.onConnected(() => {
 
1
  <script lang="ts">
2
+ import { settings } from '$lib/settings.svelte.js';
3
  import { onMount } from 'svelte';
4
  import { robotics } from '@robothub/transport-server-client';
5
  import type { robotics as roboticsTypes } from '@robothub/transport-server-client';
6
+
7
 
8
  // Get data from load function
9
  let { data } = $props();
 
72
  connecting = true;
73
  error = '';
74
 
75
+ <<<<<<< HEAD
76
  consumer = new robotics.RoboticsConsumer('https://blanchon-robothub-transportserver.hf.space/api');
77
+ =======
78
+ consumer = new robotics.RoboticsConsumer(settings.transportServerUrl);
79
+ >>>>>>> ccb03a313c3f3278e408a849294738a50b7ec4d0
80
 
81
  // Set up event handlers
82
  consumer.onConnected(() => {
demo/src/routes/[workspaceId]/robotics/producer/+page.svelte CHANGED
@@ -1,6 +1,8 @@
1
  <script lang="ts">
 
2
  import { onMount } from 'svelte';
3
  import { robotics } from '@robothub/transport-server-client';
 
4
 
5
  // Get data from load function
6
  let { data } = $props();
@@ -98,7 +100,11 @@
98
  connecting = true;
99
  error = '';
100
 
 
101
  producer = new robotics.RoboticsProducer('https://blanchon-robothub-transportserver.hf.space/api');
 
 
 
102
 
103
  producer.onConnected(() => {
104
  connected = true;
@@ -138,7 +144,11 @@
138
  connecting = true;
139
  error = '';
140
 
 
141
  producer = new robotics.RoboticsProducer('https://blanchon-robothub-transportserver.hf.space/api');
 
 
 
142
 
143
  producer.onConnected(() => {
144
  connected = true;
 
1
  <script lang="ts">
2
+ import { settings } from '$lib/settings.svelte.js';
3
  import { onMount } from 'svelte';
4
  import { robotics } from '@robothub/transport-server-client';
5
+
6
 
7
  // Get data from load function
8
  let { data } = $props();
 
100
  connecting = true;
101
  error = '';
102
 
103
+ <<<<<<< HEAD
104
  producer = new robotics.RoboticsProducer('https://blanchon-robothub-transportserver.hf.space/api');
105
+ =======
106
+ producer = new robotics.RoboticsProducer(settings.transportServerUrl);
107
+ >>>>>>> ccb03a313c3f3278e408a849294738a50b7ec4d0
108
 
109
  producer.onConnected(() => {
110
  connected = true;
 
144
  connecting = true;
145
  error = '';
146
 
147
+ <<<<<<< HEAD
148
  producer = new robotics.RoboticsProducer('https://blanchon-robothub-transportserver.hf.space/api');
149
+ =======
150
+ producer = new robotics.RoboticsProducer(settings.transportServerUrl);
151
+ >>>>>>> ccb03a313c3f3278e408a849294738a50b7ec4d0
152
 
153
  producer.onConnected(() => {
154
  connected = true;
demo/src/routes/[workspaceId]/video/+page.svelte CHANGED
@@ -1,7 +1,9 @@
1
  <script lang="ts">
 
2
  import { onMount } from 'svelte';
3
  import { video } from '@robothub/transport-server-client';
4
  import type { video as videoTypes } from '@robothub/transport-server-client';
 
5
 
6
  // Get data from load function
7
  let { data } = $props();
@@ -42,7 +44,11 @@
42
  try {
43
  loading = true;
44
  error = '';
 
45
  client = new video.VideoClientCore('https://blanchon-robothub-transportserver.hf.space/api');
 
 
 
46
  rooms = await client.listRooms(workspaceId);
47
  debugInfo.responseTime = Date.now() - startTime;
48
  } catch (err) {
 
1
  <script lang="ts">
2
+ import { settings } from '$lib/settings.svelte.js';
3
  import { onMount } from 'svelte';
4
  import { video } from '@robothub/transport-server-client';
5
  import type { video as videoTypes } from '@robothub/transport-server-client';
6
+
7
 
8
  // Get data from load function
9
  let { data } = $props();
 
44
  try {
45
  loading = true;
46
  error = '';
47
+ <<<<<<< HEAD
48
  client = new video.VideoClientCore('https://blanchon-robothub-transportserver.hf.space/api');
49
+ =======
50
+ client = new video.VideoClientCore(settings.transportServerUrl);
51
+ >>>>>>> ccb03a313c3f3278e408a849294738a50b7ec4d0
52
  rooms = await client.listRooms(workspaceId);
53
  debugInfo.responseTime = Date.now() - startTime;
54
  } catch (err) {
demo/src/routes/[workspaceId]/video/consumer/+page.svelte CHANGED
@@ -1,6 +1,8 @@
1
  <script lang="ts">
 
2
  import { onMount } from 'svelte';
3
  import { video } from '@robothub/transport-server-client';
 
4
 
5
  // Get data from load function
6
  let { data } = $props();
@@ -78,7 +80,11 @@
78
  connecting = true;
79
  error = '';
80
 
 
81
  consumer = new video.VideoConsumer('https://blanchon-robothub-transportserver.hf.space/api');
 
 
 
82
 
83
  // Set up event handlers
84
  consumer.onConnected(() => {
 
1
  <script lang="ts">
2
+ import { settings } from '$lib/settings.svelte.js';
3
  import { onMount } from 'svelte';
4
  import { video } from '@robothub/transport-server-client';
5
+
6
 
7
  // Get data from load function
8
  let { data } = $props();
 
80
  connecting = true;
81
  error = '';
82
 
83
+ <<<<<<< HEAD
84
  consumer = new video.VideoConsumer('https://blanchon-robothub-transportserver.hf.space/api');
85
+ =======
86
+ consumer = new video.VideoConsumer(settings.transportServerUrl);
87
+ >>>>>>> ccb03a313c3f3278e408a849294738a50b7ec4d0
88
 
89
  // Set up event handlers
90
  consumer.onConnected(() => {
demo/src/routes/[workspaceId]/video/producer/+page.svelte CHANGED
@@ -1,4 +1,5 @@
1
  <script lang="ts">
 
2
  import { onMount } from 'svelte';
3
  import { video } from '@robothub/transport-server-client';
4
 
 
1
  <script lang="ts">
2
+ import { settings } from '$lib/settings.svelte.js';
3
  import { onMount } from 'svelte';
4
  import { video } from '@robothub/transport-server-client';
5