@miradorlabs/parallax-web 1.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.
- package/.nvmrc +1 -0
- package/.prettierrc +8 -0
- package/README.md +217 -0
- package/SETUP.md +220 -0
- package/dist/index.d.ts +67 -0
- package/dist/index.esm.js +243 -0
- package/dist/index.esm.js.map +1 -0
- package/dist/index.umd.js +268 -0
- package/dist/index.umd.js.map +1 -0
- package/eslint.config.js +40 -0
- package/index.ts +2 -0
- package/jest.config.ts +26 -0
- package/package.json +53 -0
- package/rollup.config.mjs +86 -0
- package/src/grpc/index.ts +155 -0
- package/src/helpers/index.ts +13 -0
- package/src/parallax/index.ts +146 -0
- package/tests/parallax.test.ts +439 -0
- package/tsconfig.build.json +19 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import typescript from '@rollup/plugin-typescript';
|
|
2
|
+
import resolve from '@rollup/plugin-node-resolve';
|
|
3
|
+
import commonjs from '@rollup/plugin-commonjs';
|
|
4
|
+
import dts from 'rollup-plugin-dts';
|
|
5
|
+
|
|
6
|
+
export default [
|
|
7
|
+
// Bundle the JavaScript/TypeScript code for ES module
|
|
8
|
+
{
|
|
9
|
+
input: 'index.ts',
|
|
10
|
+
output: {
|
|
11
|
+
file: 'dist/index.esm.js',
|
|
12
|
+
format: 'es',
|
|
13
|
+
sourcemap: true,
|
|
14
|
+
},
|
|
15
|
+
plugins: [
|
|
16
|
+
resolve({
|
|
17
|
+
browser: true,
|
|
18
|
+
preferBuiltins: false,
|
|
19
|
+
}),
|
|
20
|
+
commonjs(),
|
|
21
|
+
typescript({
|
|
22
|
+
tsconfig: './tsconfig.build.json',
|
|
23
|
+
declaration: false,
|
|
24
|
+
sourceMap: true,
|
|
25
|
+
}),
|
|
26
|
+
],
|
|
27
|
+
external: [
|
|
28
|
+
'google-protobuf',
|
|
29
|
+
'mirador-gateway-parallax-web',
|
|
30
|
+
/^mirador-gateway-parallax-web\/.*/,
|
|
31
|
+
'rxjs',
|
|
32
|
+
/^rxjs\/.*/,
|
|
33
|
+
],
|
|
34
|
+
},
|
|
35
|
+
// Bundle the JavaScript/TypeScript code for UMD (browser global)
|
|
36
|
+
{
|
|
37
|
+
input: 'index.ts',
|
|
38
|
+
output: {
|
|
39
|
+
file: 'dist/index.umd.js',
|
|
40
|
+
format: 'umd',
|
|
41
|
+
name: 'ParallaxWeb',
|
|
42
|
+
sourcemap: true,
|
|
43
|
+
globals: {
|
|
44
|
+
'google-protobuf': 'googleProtobuf',
|
|
45
|
+
'mirador-gateway-parallax-web': 'miradorGatewayParallaxWeb',
|
|
46
|
+
'mirador-gateway-parallax-web/proto/gateway/parallax/v1/parallax_gateway': 'miradorGatewayParallaxWeb.parallaxGateway',
|
|
47
|
+
'rxjs': 'rxjs',
|
|
48
|
+
},
|
|
49
|
+
},
|
|
50
|
+
plugins: [
|
|
51
|
+
resolve({
|
|
52
|
+
browser: true,
|
|
53
|
+
preferBuiltins: false,
|
|
54
|
+
}),
|
|
55
|
+
commonjs(),
|
|
56
|
+
typescript({
|
|
57
|
+
tsconfig: './tsconfig.build.json',
|
|
58
|
+
declaration: false,
|
|
59
|
+
sourceMap: true,
|
|
60
|
+
}),
|
|
61
|
+
],
|
|
62
|
+
external: [
|
|
63
|
+
'google-protobuf',
|
|
64
|
+
'mirador-gateway-parallax-web',
|
|
65
|
+
/^mirador-gateway-parallax-web\/.*/,
|
|
66
|
+
'rxjs',
|
|
67
|
+
/^rxjs\/.*/,
|
|
68
|
+
],
|
|
69
|
+
},
|
|
70
|
+
// Bundle the TypeScript declarations
|
|
71
|
+
{
|
|
72
|
+
input: 'index.ts',
|
|
73
|
+
output: {
|
|
74
|
+
file: 'dist/index.d.ts',
|
|
75
|
+
format: 'es',
|
|
76
|
+
},
|
|
77
|
+
plugins: [dts()],
|
|
78
|
+
external: [
|
|
79
|
+
'google-protobuf',
|
|
80
|
+
'mirador-gateway-parallax-web',
|
|
81
|
+
/^mirador-gateway-parallax-web\/.*/,
|
|
82
|
+
'rxjs',
|
|
83
|
+
/^rxjs\/.*/,
|
|
84
|
+
],
|
|
85
|
+
},
|
|
86
|
+
];
|
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { Observable } from "rxjs";
|
|
2
|
+
|
|
3
|
+
interface Metadata {
|
|
4
|
+
[key: string]: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
interface Rpc {
|
|
8
|
+
request(
|
|
9
|
+
service: string,
|
|
10
|
+
method: string,
|
|
11
|
+
data: Uint8Array,
|
|
12
|
+
metadata?: Metadata
|
|
13
|
+
): Promise<Uint8Array>;
|
|
14
|
+
clientStreamingRequest(
|
|
15
|
+
service: string,
|
|
16
|
+
method: string,
|
|
17
|
+
data: Observable<Uint8Array>
|
|
18
|
+
): Promise<Uint8Array>;
|
|
19
|
+
serverStreamingRequest(
|
|
20
|
+
service: string,
|
|
21
|
+
method: string,
|
|
22
|
+
data: Uint8Array
|
|
23
|
+
): Observable<Uint8Array>;
|
|
24
|
+
bidirectionalStreamingRequest(
|
|
25
|
+
service: string,
|
|
26
|
+
method: string,
|
|
27
|
+
data: Observable<Uint8Array>
|
|
28
|
+
): Observable<Uint8Array>;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export class GrpcWebRpc implements Rpc {
|
|
32
|
+
private url: string;
|
|
33
|
+
private apiKey?: string;
|
|
34
|
+
|
|
35
|
+
constructor(url: string, apiKey?: string) {
|
|
36
|
+
this.url = url;
|
|
37
|
+
this.apiKey = apiKey;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async request(
|
|
41
|
+
service: string,
|
|
42
|
+
method: string,
|
|
43
|
+
data: Uint8Array,
|
|
44
|
+
metadata?: Metadata
|
|
45
|
+
): Promise<Uint8Array> {
|
|
46
|
+
console.log(`[gRPC-Web] Making request to ${this.url}/${service}/${method}`);
|
|
47
|
+
|
|
48
|
+
const headers: HeadersInit = {
|
|
49
|
+
'Content-Type': 'application/grpc-web+proto',
|
|
50
|
+
'X-Grpc-Web': '1',
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
// Add API key to headers if provided
|
|
54
|
+
if (this.apiKey) {
|
|
55
|
+
headers['x-api-key'] = this.apiKey;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// Add custom metadata
|
|
59
|
+
if (metadata) {
|
|
60
|
+
Object.entries(metadata).forEach(([key, value]) => {
|
|
61
|
+
headers[key] = value;
|
|
62
|
+
});
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
try {
|
|
66
|
+
const response = await fetch(`${this.url}/${service}/${method}`, {
|
|
67
|
+
method: 'POST',
|
|
68
|
+
headers,
|
|
69
|
+
body: data.buffer as ArrayBuffer,
|
|
70
|
+
});
|
|
71
|
+
|
|
72
|
+
if (!response.ok) {
|
|
73
|
+
const errorText = await response.text();
|
|
74
|
+
throw new Error(`gRPC-Web error: ${response.status} ${response.statusText} - ${errorText}`);
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
const arrayBuffer = await response.arrayBuffer();
|
|
78
|
+
console.log(`[gRPC-Web] Success from ${this.url}/${service}/${method}`);
|
|
79
|
+
return new Uint8Array(arrayBuffer);
|
|
80
|
+
} catch (error) {
|
|
81
|
+
console.error(
|
|
82
|
+
`[gRPC-Web] Error from ${this.url}/${service}/${method}:`,
|
|
83
|
+
error instanceof Error ? error.message : String(error)
|
|
84
|
+
);
|
|
85
|
+
throw error;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
clientStreamingRequest(): Promise<Uint8Array> {
|
|
90
|
+
throw new Error("Client streaming not yet implemented for gRPC-Web");
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
serverStreamingRequest(
|
|
94
|
+
service: string,
|
|
95
|
+
method: string,
|
|
96
|
+
data: Uint8Array
|
|
97
|
+
): Observable<Uint8Array> {
|
|
98
|
+
return new Observable((subscriber) => {
|
|
99
|
+
const headers: HeadersInit = {
|
|
100
|
+
'Content-Type': 'application/grpc-web+proto',
|
|
101
|
+
'X-Grpc-Web': '1',
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
// Add API key to headers if provided
|
|
105
|
+
if (this.apiKey) {
|
|
106
|
+
headers['x-api-key'] = this.apiKey;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
fetch(`${this.url}/${service}/${method}`, {
|
|
110
|
+
method: 'POST',
|
|
111
|
+
headers,
|
|
112
|
+
body: data.buffer as ArrayBuffer,
|
|
113
|
+
})
|
|
114
|
+
.then(async (response) => {
|
|
115
|
+
if (!response.ok) {
|
|
116
|
+
throw new Error(`gRPC-Web error: ${response.status} ${response.statusText}`);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
if (!response.body) {
|
|
120
|
+
throw new Error('Response body is null');
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
const reader = response.body.getReader();
|
|
124
|
+
|
|
125
|
+
try {
|
|
126
|
+
while (true) {
|
|
127
|
+
const { done, value } = await reader.read();
|
|
128
|
+
|
|
129
|
+
if (done) {
|
|
130
|
+
subscriber.complete();
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (value) {
|
|
135
|
+
subscriber.next(value);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
} catch (error) {
|
|
139
|
+
subscriber.error(error);
|
|
140
|
+
}
|
|
141
|
+
})
|
|
142
|
+
.catch((error) => {
|
|
143
|
+
subscriber.error(error);
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
return () => {
|
|
147
|
+
// Cleanup logic if needed
|
|
148
|
+
};
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
bidirectionalStreamingRequest(): Observable<Uint8Array> {
|
|
153
|
+
throw new Error("Bidirectional streaming not yet implemented for gRPC-Web");
|
|
154
|
+
}
|
|
155
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
// Helper serialization functions for browser environment
|
|
2
|
+
function serialize(value: Uint8Array): Uint8Array {
|
|
3
|
+
return value;
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
function deserialize(bytes: Uint8Array): Uint8Array {
|
|
7
|
+
return bytes;
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
export {
|
|
11
|
+
deserialize,
|
|
12
|
+
serialize
|
|
13
|
+
}
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
// Parallax SDK Web Client
|
|
2
|
+
import type {
|
|
3
|
+
CreateTraceRequest,
|
|
4
|
+
StartSpanRequest,
|
|
5
|
+
FinishSpanRequest,
|
|
6
|
+
AddSpanEventRequest,
|
|
7
|
+
AddSpanErrorRequest,
|
|
8
|
+
AddSpanHintRequest,
|
|
9
|
+
AddSpanAttributesRequest
|
|
10
|
+
} from "mirador-gateway-parallax-web/proto/gateway/parallax/v1/parallax_gateway";
|
|
11
|
+
import * as apiGateway from "mirador-gateway-parallax-web/proto/gateway/parallax/v1/parallax_gateway";
|
|
12
|
+
import { GrpcWebRpc } from "../grpc";
|
|
13
|
+
|
|
14
|
+
const GRPC_GATEWAY_API_URL = "https://gateway-parallax-dev.platform.svc.cluster.local:50053";
|
|
15
|
+
|
|
16
|
+
const debugIssue = (trace: string, error: Error) => {
|
|
17
|
+
// Handle our own debugging / logging here
|
|
18
|
+
console.error(`[ParallaxClient][${trace}] Error:`, error);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
class ParallaxClient {
|
|
22
|
+
public apiUrl: string = GRPC_GATEWAY_API_URL;
|
|
23
|
+
private apiGatewayRpc: GrpcWebRpc;
|
|
24
|
+
|
|
25
|
+
constructor(public apiKey?: string, apiUrl?: string) {
|
|
26
|
+
if (apiUrl) {
|
|
27
|
+
this.apiUrl = apiUrl;
|
|
28
|
+
}
|
|
29
|
+
this.apiGatewayRpc = new GrpcWebRpc(this.apiUrl, apiKey);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Create a new trace
|
|
34
|
+
* @param params Parameters to create a new trace
|
|
35
|
+
* @returns Response from the create trace operation
|
|
36
|
+
*/
|
|
37
|
+
async createTrace(params: CreateTraceRequest): Promise<apiGateway.CreateTraceResponse> {
|
|
38
|
+
try {
|
|
39
|
+
const apiGatewayClient = new apiGateway.ParallaxGatewayServiceClientImpl(
|
|
40
|
+
this.apiGatewayRpc
|
|
41
|
+
);
|
|
42
|
+
return await apiGatewayClient.CreateTrace(params);
|
|
43
|
+
} catch (_error) {
|
|
44
|
+
debugIssue("createTrace", new Error('Error creating trace'));
|
|
45
|
+
throw _error;
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Start a new span within a trace
|
|
51
|
+
* @param params Parameters to start a new span
|
|
52
|
+
*/
|
|
53
|
+
async startSpan(params: StartSpanRequest) {
|
|
54
|
+
try {
|
|
55
|
+
const apiGatewayClient = new apiGateway.ParallaxGatewayServiceClientImpl(
|
|
56
|
+
this.apiGatewayRpc
|
|
57
|
+
);
|
|
58
|
+
return await apiGatewayClient.StartSpan(params);
|
|
59
|
+
} catch (_error) {
|
|
60
|
+
debugIssue("startSpan", new Error('Error starting span'));
|
|
61
|
+
throw _error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Finish a span within a trace
|
|
67
|
+
* @param params Parameters to finish a span
|
|
68
|
+
*/
|
|
69
|
+
async finishSpan(params: FinishSpanRequest) {
|
|
70
|
+
try {
|
|
71
|
+
const apiGatewayClient = new apiGateway.ParallaxGatewayServiceClientImpl(
|
|
72
|
+
this.apiGatewayRpc
|
|
73
|
+
);
|
|
74
|
+
return await apiGatewayClient.FinishSpan(params);
|
|
75
|
+
} catch (_error) {
|
|
76
|
+
debugIssue("finishSpan", new Error('Error finishing span'));
|
|
77
|
+
throw _error;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* Add attributes to a span
|
|
83
|
+
* @param params Parameters to add attributes to a span
|
|
84
|
+
*/
|
|
85
|
+
async addSpanAttributes(params: AddSpanAttributesRequest) {
|
|
86
|
+
try {
|
|
87
|
+
const apiGatewayClient = new apiGateway.ParallaxGatewayServiceClientImpl(
|
|
88
|
+
this.apiGatewayRpc
|
|
89
|
+
);
|
|
90
|
+
return await apiGatewayClient.AddSpanAttributes(params);
|
|
91
|
+
} catch (_error) {
|
|
92
|
+
debugIssue("addSpanAttributes", new Error('Error adding span attributes'));
|
|
93
|
+
throw _error;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* Add an event to a span
|
|
99
|
+
* @param params Parameters to add an event to a span
|
|
100
|
+
*/
|
|
101
|
+
async addSpanEvent(params: AddSpanEventRequest) {
|
|
102
|
+
try {
|
|
103
|
+
const apiGatewayClient = new apiGateway.ParallaxGatewayServiceClientImpl(
|
|
104
|
+
this.apiGatewayRpc
|
|
105
|
+
);
|
|
106
|
+
return await apiGatewayClient.AddSpanEvent(params);
|
|
107
|
+
} catch (_error) {
|
|
108
|
+
debugIssue("addSpanEvent", new Error('Error adding span event'));
|
|
109
|
+
throw _error;
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Add an error to a span
|
|
115
|
+
* @param params Parameters to add an error to a span
|
|
116
|
+
*/
|
|
117
|
+
async addSpanError(params: AddSpanErrorRequest) {
|
|
118
|
+
try {
|
|
119
|
+
const apiGatewayClient = new apiGateway.ParallaxGatewayServiceClientImpl(
|
|
120
|
+
this.apiGatewayRpc
|
|
121
|
+
);
|
|
122
|
+
return await apiGatewayClient.AddSpanError(params);
|
|
123
|
+
} catch (_error) {
|
|
124
|
+
debugIssue("addSpanError", new Error('Error adding span error'));
|
|
125
|
+
throw _error;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Add a hint to a span
|
|
131
|
+
* @param params Parameters to add a hint to a span
|
|
132
|
+
*/
|
|
133
|
+
async addSpanHint(params: AddSpanHintRequest) {
|
|
134
|
+
try {
|
|
135
|
+
const apiGatewayClient = new apiGateway.ParallaxGatewayServiceClientImpl(
|
|
136
|
+
this.apiGatewayRpc
|
|
137
|
+
);
|
|
138
|
+
return await apiGatewayClient.AddSpanHint(params);
|
|
139
|
+
} catch (_error) {
|
|
140
|
+
debugIssue("addSpanHint", new Error('Error adding span hint'));
|
|
141
|
+
throw _error;
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
export { ParallaxClient };
|