space-react-client 0.1.0 → 0.2.1
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.
- package/dist/index.d.ts +16 -4
- package/dist/index.js +44 -41
- package/package.json +4 -3
package/dist/index.d.ts
CHANGED
|
@@ -40,10 +40,11 @@ declare class SpaceClient$1 {
|
|
|
40
40
|
readonly tokenService: TokenService$1;
|
|
41
41
|
private userId;
|
|
42
42
|
constructor(config: SpaceConfiguration);
|
|
43
|
+
disconnectWebSocket(): void;
|
|
43
44
|
/**
|
|
44
45
|
* Connects to the SPACE WebSocket and handles incoming events.
|
|
45
46
|
*/
|
|
46
|
-
|
|
47
|
+
connectWebSocket(): void;
|
|
47
48
|
/**
|
|
48
49
|
* Listen to SPACE and connection events.
|
|
49
50
|
* @param event The event key to listen for.
|
|
@@ -108,9 +109,8 @@ interface SpaceClientContext{
|
|
|
108
109
|
/**
|
|
109
110
|
* SpaceProvider initializes and provides the SpaceClient instance to children.
|
|
110
111
|
*/
|
|
111
|
-
declare const SpaceProvider: ({ config,
|
|
112
|
+
declare const SpaceProvider: ({ config, children, }: {
|
|
112
113
|
config: SpaceConfiguration;
|
|
113
|
-
loader?: React.ReactNode;
|
|
114
114
|
children: React.ReactNode;
|
|
115
115
|
}) => JSX.Element;
|
|
116
116
|
|
|
@@ -130,7 +130,19 @@ interface FeatureProps {
|
|
|
130
130
|
id: string;
|
|
131
131
|
children: React.ReactNode;
|
|
132
132
|
}
|
|
133
|
+
declare function On({ children }: {
|
|
134
|
+
children: React.ReactNode;
|
|
135
|
+
}): JSX.Element;
|
|
136
|
+
declare function Default({ children }: {
|
|
137
|
+
children: React.ReactNode;
|
|
138
|
+
}): JSX.Element;
|
|
139
|
+
declare function Loading({ children }: {
|
|
140
|
+
children: React.ReactNode;
|
|
141
|
+
}): JSX.Element;
|
|
142
|
+
declare function ErrorFallback({ children }: {
|
|
143
|
+
children: React.ReactNode;
|
|
144
|
+
}): JSX.Element;
|
|
133
145
|
declare const Feature: ({ id, children }: FeatureProps) => JSX.Element;
|
|
134
146
|
|
|
135
|
-
export { Feature, SpaceClient$1 as SpaceClient, SpaceProvider, TokenService$1 as TokenService, usePricingToken, useSpaceClient };
|
|
147
|
+
export { Default, ErrorFallback, Feature, Loading, On, SpaceClient$1 as SpaceClient, SpaceProvider, TokenService$1 as TokenService, usePricingToken, useSpaceClient };
|
|
136
148
|
export type { EventMessage, SpaceClientContext, SpaceConfiguration, SpaceEvents };
|
package/dist/index.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import React, { createContext, useMemo, useContext, useState
|
|
1
|
+
import { jsx, Fragment } from 'react/jsx-runtime';
|
|
2
|
+
import React, { createContext, useMemo, useEffect, useContext, useState } from 'react';
|
|
3
3
|
import { TinyEmitter } from 'tiny-emitter';
|
|
4
4
|
import axios from 'axios';
|
|
5
5
|
import { io } from 'socket.io-client';
|
|
@@ -105,6 +105,12 @@ class SpaceClient {
|
|
|
105
105
|
});
|
|
106
106
|
this.connectWebSocket();
|
|
107
107
|
}
|
|
108
|
+
disconnectWebSocket() {
|
|
109
|
+
if (this.pricingSocketNamespace.connected) {
|
|
110
|
+
this.pricingSocketNamespace.disconnect();
|
|
111
|
+
this.emitter.off(); // Remove all listeners
|
|
112
|
+
}
|
|
113
|
+
}
|
|
108
114
|
/**
|
|
109
115
|
* Connects to the SPACE WebSocket and handles incoming events.
|
|
110
116
|
*/
|
|
@@ -113,11 +119,11 @@ class SpaceClient {
|
|
|
113
119
|
console.log('Connected to SPACE');
|
|
114
120
|
this.emitter.emit('synchronized', 'WebSocket connection established');
|
|
115
121
|
});
|
|
116
|
-
this.pricingSocketNamespace.on('message', data => {
|
|
122
|
+
this.pricingSocketNamespace.on('message', (data) => {
|
|
117
123
|
const event = data.code.toLowerCase();
|
|
118
124
|
this.emitter.emit(event, data.details);
|
|
119
125
|
});
|
|
120
|
-
this.pricingSocketNamespace.on('connect_error', error => {
|
|
126
|
+
this.pricingSocketNamespace.on('connect_error', (error) => {
|
|
121
127
|
this.emitter.emit('error', error);
|
|
122
128
|
});
|
|
123
129
|
}
|
|
@@ -165,7 +171,8 @@ class SpaceClient {
|
|
|
165
171
|
throw new Error('User ID must be a non-empty string.');
|
|
166
172
|
}
|
|
167
173
|
this.userId = userId;
|
|
168
|
-
|
|
174
|
+
const userPricingToken = await this.generateUserPricingToken();
|
|
175
|
+
this.tokenService.updatePricingToken(userPricingToken);
|
|
169
176
|
}
|
|
170
177
|
/**
|
|
171
178
|
* Performs a request to SPACE to retrieve a new pricing token for the user with the given userId.
|
|
@@ -178,7 +185,7 @@ class SpaceClient {
|
|
|
178
185
|
throw new Error('User ID is not set. Please set the user ID with `setUserId(userId)` before trying to generate a pricing token.');
|
|
179
186
|
}
|
|
180
187
|
return this.axios
|
|
181
|
-
.post(`/features/${this.userId}`)
|
|
188
|
+
.post(`/features/${this.userId}/pricing-token`)
|
|
182
189
|
.then((response) => {
|
|
183
190
|
return response.data.pricingToken;
|
|
184
191
|
})
|
|
@@ -194,10 +201,11 @@ const SpaceContext = createContext(undefined);
|
|
|
194
201
|
/**
|
|
195
202
|
* SpaceProvider initializes and provides the SpaceClient instance to children.
|
|
196
203
|
*/
|
|
197
|
-
const SpaceProvider = ({ config,
|
|
204
|
+
const SpaceProvider = ({ config, children, }) => {
|
|
198
205
|
// Memorize the client to avoid unnecessary re-instantiation
|
|
199
206
|
const context = useMemo(() => {
|
|
200
|
-
const
|
|
207
|
+
const denyConnectionWithSpace = config.allowConnectionWithSpace === false;
|
|
208
|
+
const client = denyConnectionWithSpace ? undefined : new SpaceClient(config);
|
|
201
209
|
let tokenService;
|
|
202
210
|
if (!client) {
|
|
203
211
|
tokenService = new TokenService();
|
|
@@ -210,29 +218,13 @@ const SpaceProvider = ({ config, loader, children, }) => {
|
|
|
210
218
|
tokenService: tokenService,
|
|
211
219
|
};
|
|
212
220
|
}, [config.url, config.apiKey]);
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
}
|
|
219
|
-
const handleSync = () => setConnected(true);
|
|
220
|
-
context.client.on('synchronized', handleSync);
|
|
221
|
+
useEffect(() => {
|
|
222
|
+
return () => {
|
|
223
|
+
if (context.client && typeof context.client.disconnectWebSocket === 'function') {
|
|
224
|
+
context.client.disconnectWebSocket();
|
|
225
|
+
}
|
|
226
|
+
};
|
|
221
227
|
}, [context.client]);
|
|
222
|
-
if (!connected)
|
|
223
|
-
return (jsxs("div", { style: { display: 'flex', alignItems: 'center', justifyContent: 'center', minHeight: '100vh', width: '100%' }, children: [loader ?? (jsx("div", { style: {
|
|
224
|
-
border: '4px solid #e0e0e0',
|
|
225
|
-
borderTop: '4px solid #1976d2',
|
|
226
|
-
borderRadius: '50%',
|
|
227
|
-
width: 48,
|
|
228
|
-
height: 48,
|
|
229
|
-
animation: 'spin 1s linear infinite',
|
|
230
|
-
} })), jsx("style", { children: `
|
|
231
|
-
@keyframes spin {
|
|
232
|
-
0% { transform: rotate(0deg); }
|
|
233
|
-
100% { transform: rotate(360deg); }
|
|
234
|
-
}
|
|
235
|
-
` })] }));
|
|
236
228
|
return jsx(SpaceContext.Provider, { value: context, children: children });
|
|
237
229
|
};
|
|
238
230
|
|
|
@@ -266,10 +258,23 @@ function usePricingToken() {
|
|
|
266
258
|
return spaceContext.tokenService;
|
|
267
259
|
}
|
|
268
260
|
|
|
269
|
-
//
|
|
270
|
-
function
|
|
271
|
-
|
|
272
|
-
|
|
261
|
+
// Generic wrapper for feature children
|
|
262
|
+
function On({ children }) {
|
|
263
|
+
return jsx(Fragment, { children: children });
|
|
264
|
+
}
|
|
265
|
+
function Default({ children }) {
|
|
266
|
+
return jsx(Fragment, { children: children });
|
|
267
|
+
}
|
|
268
|
+
function Loading({ children }) {
|
|
269
|
+
return jsx(Fragment, { children: children });
|
|
270
|
+
}
|
|
271
|
+
function ErrorFallback({ children }) {
|
|
272
|
+
return jsx(Fragment, { children: children });
|
|
273
|
+
}
|
|
274
|
+
// Helper to get the children of a specific subcomponent type
|
|
275
|
+
function getChildrenOfType(children, type) {
|
|
276
|
+
const match = React.Children.toArray(children).find((child) => React.isValidElement(child) && child.type === type);
|
|
277
|
+
return match ? match.props.children : null;
|
|
273
278
|
}
|
|
274
279
|
const Feature = ({ id, children }) => {
|
|
275
280
|
const tokenService = usePricingToken();
|
|
@@ -279,12 +284,10 @@ const Feature = ({ id, children }) => {
|
|
|
279
284
|
const isValidId = useMemo(() => id.includes('-'), [id]);
|
|
280
285
|
useEffect(() => {
|
|
281
286
|
if (!isValidId) {
|
|
282
|
-
console.error(`Invalid feature ID: ‘${id}’. A valid feature ID must contain a hyphen (’-’) and follow the format: ‘{serviceName in lowercase}-{featureName as defined in the pricing}’.`);
|
|
283
287
|
setStatus('error');
|
|
284
288
|
return;
|
|
285
289
|
}
|
|
286
290
|
if (tokenService.getPricingToken() === null) {
|
|
287
|
-
console.error(`Pricing token is either not set or expired. Please ensure the token is initialized and not expired before using the Feature component.`);
|
|
288
291
|
setStatus('error');
|
|
289
292
|
return;
|
|
290
293
|
}
|
|
@@ -300,18 +303,18 @@ const Feature = ({ id, children }) => {
|
|
|
300
303
|
}
|
|
301
304
|
}, [id, isValidId]);
|
|
302
305
|
if (status === 'loading') {
|
|
303
|
-
return
|
|
306
|
+
return jsx(Fragment, { children: getChildrenOfType(children, Loading) });
|
|
304
307
|
}
|
|
305
308
|
if (status === 'error') {
|
|
306
|
-
return
|
|
309
|
+
return jsx(Fragment, { children: getChildrenOfType(children, ErrorFallback) });
|
|
307
310
|
}
|
|
308
311
|
if (status === 'success' && result === true) {
|
|
309
|
-
return
|
|
312
|
+
return jsx(Fragment, { children: getChildrenOfType(children, On) });
|
|
310
313
|
}
|
|
311
314
|
if (status === 'success' && result === false) {
|
|
312
|
-
return
|
|
315
|
+
return jsx(Fragment, { children: getChildrenOfType(children, Default) });
|
|
313
316
|
}
|
|
314
317
|
return jsx(Fragment, {});
|
|
315
318
|
};
|
|
316
319
|
|
|
317
|
-
export { Feature, SpaceProvider, usePricingToken, useSpaceClient };
|
|
320
|
+
export { Default, ErrorFallback, Feature, Loading, On, SpaceProvider, usePricingToken, useSpaceClient };
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "space-react-client",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.1
|
|
4
|
+
"version": "0.2.1",
|
|
5
5
|
"description": "",
|
|
6
6
|
"main": "dist/index.js",
|
|
7
7
|
"module": "dist/index.js",
|
|
@@ -28,13 +28,14 @@
|
|
|
28
28
|
"license": "ISC",
|
|
29
29
|
"packageManager": "pnpm@10.10.0",
|
|
30
30
|
"peerDependencies": {
|
|
31
|
-
"react": "^
|
|
31
|
+
"react": "^18.3.1",
|
|
32
|
+
"react-dom": "^18.3.1"
|
|
32
33
|
},
|
|
33
34
|
"devDependencies": {
|
|
34
35
|
"@rollup/plugin-alias": "^5.1.1",
|
|
35
36
|
"@rollup/plugin-typescript": "^12.1.2",
|
|
36
37
|
"@testing-library/react": "^16.3.0",
|
|
37
|
-
"@types/react": "^
|
|
38
|
+
"@types/react": "^18.3.1",
|
|
38
39
|
"@vitejs/plugin-react": "^4.5.0",
|
|
39
40
|
"eslint": "^9.28.0",
|
|
40
41
|
"eslint-config-prettier": "^10.1.5",
|