Skip to content

Commit 67da2d6

Browse files
committed
feat: introduce JS SDK (not part of CI yet).
GitOrigin-RevId: 936312f5f913130f496089a17ce353810e520c86
1 parent 7caccd8 commit 67da2d6

File tree

13 files changed

+956
-692
lines changed

13 files changed

+956
-692
lines changed

sdk/js/README.md

Lines changed: 26 additions & 80 deletions
Original file line numberDiff line numberDiff line change
@@ -9,93 +9,39 @@ When you want the user to be able to record a session, you basically want to cal
99
- Start the recording (and, more specifically, all queries in the template)
1010
- Stop the recording
1111

12-
In order to be able to start a frontend recording, you need to install `rrweb` and `rrweb-snapshot`.
13-
14-
Currently, there is no SDK available for the frontend. Nevertheless, it is very easy to integrate the frontend
15-
with WireQuery using a few simple `fetch` commands and using `rrweb`.
16-
17-
## Start Recording
18-
19-
A recording can be started by calling the `recordings` endpoint from WireQuery.
20-
21-
```
22-
const res = await fetch("<WireQuery Host>/api/v1/recordings", {
23-
method: "POST",
24-
headers: {
25-
"Content-Type": "application/json",
26-
},
27-
body: JSON.stringify({
28-
templateId: <templateId>,
29-
apiKey: <apiKey>,
30-
args: {
31-
<template args>
32-
},
33-
}),
34-
})
35-
36-
const recording = await res.json()
37-
38-
```
39-
40-
Here, the `<templateId>` has to be set to the Template id mentioned earlier. The api key needs to be set
41-
to the api key of the template, which can be found by clicking on Details when on a Template page.
42-
The args need to contain the parameters of that template, such as the `accountId`. For example:
43-
44-
```
45-
const res = fetch("https://demo.wirequery.io/api/v1/recordings", {
46-
method: "POST",
47-
headers: {
48-
"Content-Type": "application/json",
49-
},
50-
body: JSON.stringify({
51-
templateId: 1,
52-
apiKey: 'api-key',
53-
args: {
54-
accountId
55-
},
56-
}),
57-
})
58-
59-
const recording = await res.json()
12+
## Installation
13+
Install the required libraries:
14+
```bash
15+
npm install rrweb rrweb-snapshot @wirequery/wirequery-js-core
6016
```
6117

6218
## Recording
19+
To start recording, create a RecorderClass and call `startRecoding`:
20+
```ts
21+
const wireQueryBackendPath = 'http://localhost:8080';
6322

64-
The actual recording needs to be taken care by `rrweb`. A guide on `rrweb` can be found on
65-
[GitHub](https://github.com/rrweb-io/rrweb/blob/master/guide.md), and an example can be found
66-
in the [Shop](https://github.com/wirequery/wirequery/tree/main/sdk/js/examples/shop) example.
23+
const url = '';
24+
const templateId = '';
25+
const apiKey = '';
6726

68-
## Finish Recording
27+
const recorder = new RecorderClass(url, templateId, apiKey)
6928

70-
Similarly, when a recording is finished, a call to WireQuery needs to be made as well to send and finalize the
71-
recording.
29+
// start recording
7230

73-
When the recording is finished, the following call needs to be made:
31+
recorder
32+
.startRecording({ accountId: '123' })
33+
.then(() => {
34+
// ...
35+
})
7436

7537
```
76-
fetch(`<WireQuery Host>/api/v1/recordings/${recording.id}/finish`, {
77-
method: "POST",
78-
headers: {
79-
"Content-Type": "application/json",
80-
},
81-
body: JSON.stringify({
82-
secret: recording.secret,
83-
recording: JSON.stringify(events),
84-
context: {},
85-
}),
86-
});
87-
```
88-
89-
Where `events` represent `rrweb` events and `<WireQuery Host>` is the host of WireQuery, such
90-
as `https://demo.wirequery.io`.
38+
To end recording, call `recorder.stopRecording()`:
39+
```js
40+
// end recording
41+
recorder.stopRecording()
42+
.then(() => {
43+
// ...
44+
})
9145

92-
An example of how `rrweb` can be used, can be found in the `sdk/js/examples/shop` in
93-
the [WireQuery](https://github.com/wirequery/wirequery) repository.
94-
95-
## Examples
96-
97-
The following examples demonstrate how WireQuery can be used within a Frontend application:
98-
99-
- [Shop](https://github.com/wirequery/wirequery/tree/main/sdk/js/examples/shop) - simulates a webshop.
100-
- [Products Service](https://github.com/wirequery/wirequery/tree/main/sdk/jvm/examples/spring-boot/products) - simulates a product catalogue.
101-
- [Basket](https://github.com/wirequery/wirequery/tree/main/sdk/jvm/examples/spring-boot/basket) - simulates an order basket. Connects to the products service.
46+
```
47+
The API Key is the API Key belonging to the specified template.

sdk/js/examples/shop/package-lock.json

Lines changed: 11 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

sdk/js/examples/shop/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
"lint": "next lint"
1010
},
1111
"dependencies": {
12+
"@wirequery/wirequery-js-core": "0.0.4",
1213
"@mantine/core": "^7.1.5",
1314
"@mantine/hooks": "^7.1.5",
1415
"@next/font": "13.5.5",

sdk/js/examples/shop/src/components/Recorder.tsx

Lines changed: 27 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -5,69 +5,38 @@
55
//
66
// SPDX-License-Identifier: MIT
77

8-
import { getRecordNetworkPlugin } from "@/replay/rrwebRecord";
9-
import { Affix, rem } from "@mantine/core";
10-
import { useState } from "react";
11-
import { getRecordConsolePlugin, record } from "rrweb";
8+
import {Affix, rem} from "@mantine/core";
9+
import {useState} from "react";
10+
import {Recorder as RecorderClass} from "@wirequery/wirequery-js-core";
1211

13-
const events: any = [];
1412
const wireQueryBackendPath = 'http://localhost:8080';
1513

16-
export const Recorder = () => {
17-
const [recording, setRecording] = useState<any | undefined>(undefined)
14+
const recorder = new RecorderClass(wireQueryBackendPath, 1, '1/f2e74d68-f70e-48bd-94dc-ce889f612d73')
1815

19-
const start = () => {
20-
const destructor = startRecording()
21-
return () => destructor?.();
22-
};
16+
export const Recorder = () => {
17+
const [recording, setRecording] = useState<any | undefined>(undefined)
2318

24-
const startRecording = () => {
25-
fetch(`${wireQueryBackendPath}/api/v1/recordings`, {
26-
method: "POST",
27-
headers: {
28-
"Content-Type": "application/json",
29-
},
30-
body: JSON.stringify({
31-
templateId: 1, // Debug Session by Account Id
32-
apiKey: '1/f2e74d68-f70e-48bd-94dc-ce889f612d73',
33-
args: {
34-
accountId: "123",
35-
},
36-
}),
37-
}).then((res) => res.json().then((json) => {
38-
(window as any).recordingCorrelationId = json.correlationId
39-
setRecording(json);
40-
}));
41-
return record({
42-
emit: (event) => {
43-
events.push(event);
44-
},
45-
plugins: [getRecordConsolePlugin(), getRecordNetworkPlugin({ recordHeaders: true })],
46-
});
47-
};
19+
const start = () => {
20+
recorder
21+
.startRecording({ accountId: '123' })
22+
.then(() => {
23+
setRecording(true) })
24+
};
4825

49-
const send = () => {
50-
if (recording) {
51-
setRecording(undefined);
52-
fetch(`${wireQueryBackendPath}/api/v1/recordings/${recording.id}/finish`, {
53-
method: "POST",
54-
headers: {
55-
"Content-Type": "application/json",
56-
},
57-
body: JSON.stringify({
58-
secret: recording.secret,
59-
recording: JSON.stringify(events),
60-
context: {},
61-
}),
62-
});
63-
}
64-
};
26+
const send = () => {
27+
if (recording) {
28+
recorder.stopRecording()
29+
.then(() => {
30+
setRecording(false)
31+
})
32+
}
33+
};
6534

66-
return (
67-
<Affix position={{ bottom: 0, right: rem(20) }}>
68-
{recording
69-
? <button onClick={send}>Done</button>
70-
: <button onClick={start}>Start Recording</button>}
71-
</Affix>
72-
);
35+
return (
36+
<Affix position={{bottom: 0, right: rem(20)}}>
37+
{recording
38+
? <button onClick={send}>Done</button>
39+
: <button onClick={start}>Start Recording</button>}
40+
</Affix>
41+
);
7342
};

0 commit comments

Comments
 (0)