camstreamerlib 4.0.32 → 4.0.33
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/README.md +9 -0
- package/cjs/browser.index.d.ts +2 -0
- package/cjs/browser.index.js +18 -0
- package/esm/browser.index.js +2 -0
- package/examples/README.md +43 -0
- package/examples/camstreamerlib.js +13201 -0
- package/examples/camswitcher-events.html +137 -0
- package/examples/planetracker-events.html +186 -0
- package/examples/utils/example.css +102 -0
- package/package.json +6 -3
- package/types/browser.index.d.ts +2 -0
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<title>CamStreamerLib — CamSwitcher events over Device Connect</title>
|
|
6
|
+
<link rel="stylesheet" href="./utils/example.css" />
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<h1>CamSwitcher events over Device Connect</h1>
|
|
10
|
+
|
|
11
|
+
<form id="config">
|
|
12
|
+
<label>
|
|
13
|
+
Device host
|
|
14
|
+
<input id="host" placeholder="ACCC8EA84F71.device-connect.net" />
|
|
15
|
+
</label>
|
|
16
|
+
<label>
|
|
17
|
+
Device access token
|
|
18
|
+
<input id="token" placeholder="paste the device access token" />
|
|
19
|
+
</label>
|
|
20
|
+
<button id="connect" type="submit">Connect</button>
|
|
21
|
+
<button id="disconnect" type="button" disabled>Disconnect</button>
|
|
22
|
+
</form>
|
|
23
|
+
|
|
24
|
+
<div id="status">Not connected.</div>
|
|
25
|
+
<div id="log"></div>
|
|
26
|
+
|
|
27
|
+
<script type="module">
|
|
28
|
+
import {
|
|
29
|
+
CamSwitcherAPI,
|
|
30
|
+
CamSwitcherEvents,
|
|
31
|
+
DeviceConnectClient,
|
|
32
|
+
DeviceConnectWsClient,
|
|
33
|
+
} from './camstreamerlib.js';
|
|
34
|
+
|
|
35
|
+
// Fill these in to have the form prefilled on load.
|
|
36
|
+
const DEVICE_HOST = '';
|
|
37
|
+
const DEVICE_ACCESS_TOKEN = '';
|
|
38
|
+
|
|
39
|
+
// Every event type emitted by CamSwitcher — see doc/ws/CamSwitcherEvents.md.
|
|
40
|
+
const EVENT_TYPES = [
|
|
41
|
+
'authorization',
|
|
42
|
+
'PlaylistSwitch',
|
|
43
|
+
'StreamAvailable',
|
|
44
|
+
'StreamSwitchAudio',
|
|
45
|
+
'StreamSwitchVideo',
|
|
46
|
+
'StreamSwitchVideoError',
|
|
47
|
+
'StreamSwitchAudioError',
|
|
48
|
+
'PlaylistQueueChange',
|
|
49
|
+
'ClipUpload',
|
|
50
|
+
'ClipRemove',
|
|
51
|
+
'SwitcherStart',
|
|
52
|
+
'SwitcherStop',
|
|
53
|
+
'MediaServerStarted',
|
|
54
|
+
];
|
|
55
|
+
const LISTENER_ID = 'example';
|
|
56
|
+
|
|
57
|
+
const els = {
|
|
58
|
+
form: document.getElementById('config'),
|
|
59
|
+
host: document.getElementById('host'),
|
|
60
|
+
token: document.getElementById('token'),
|
|
61
|
+
connect: document.getElementById('connect'),
|
|
62
|
+
disconnect: document.getElementById('disconnect'),
|
|
63
|
+
status: document.getElementById('status'),
|
|
64
|
+
log: document.getElementById('log'),
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
els.host.value = DEVICE_HOST;
|
|
68
|
+
els.token.value = DEVICE_ACCESS_TOKEN;
|
|
69
|
+
|
|
70
|
+
let wsClient = null;
|
|
71
|
+
let cswEvents = null;
|
|
72
|
+
|
|
73
|
+
const setStatus = (text, isError = false) => {
|
|
74
|
+
els.status.textContent = text;
|
|
75
|
+
els.status.className = isError ? 'err' : '';
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
const log = (type, payload, isInit = false) => {
|
|
79
|
+
const row = document.createElement('div');
|
|
80
|
+
row.className = 'row';
|
|
81
|
+
row.innerHTML =
|
|
82
|
+
`<span class="time">${new Date().toLocaleTimeString()}</span> ` +
|
|
83
|
+
`<span class="type">${type}</span>` +
|
|
84
|
+
(isInit ? ' <span class="init">[init]</span>' : '') +
|
|
85
|
+
` ${JSON.stringify(payload)}`;
|
|
86
|
+
els.log.append(row);
|
|
87
|
+
els.log.scrollTop = els.log.scrollHeight;
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
const connect = (host, token) => {
|
|
91
|
+
const csw = new CamSwitcherAPI(new DeviceConnectClient(token, host));
|
|
92
|
+
|
|
93
|
+
// The path getter is evaluated on every (re)connect; the token is appended by the client.
|
|
94
|
+
wsClient = new DeviceConnectWsClient(token, host, () => CamSwitcherAPI.getWsEventsPath());
|
|
95
|
+
cswEvents = new CamSwitcherEvents(wsClient, () => csw.wsAuthorization());
|
|
96
|
+
|
|
97
|
+
for (const type of EVENT_TYPES) {
|
|
98
|
+
cswEvents.addListener(type, (data, isInit) => log(data.type, data, isInit), LISTENER_ID);
|
|
99
|
+
}
|
|
100
|
+
cswEvents.addListener(
|
|
101
|
+
'authorization',
|
|
102
|
+
(data) => setStatus(`Authorization: ${data.state}`, data.state !== 'ok'),
|
|
103
|
+
'status'
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
wsClient.init();
|
|
107
|
+
setStatus(`Connecting to wss://${host}${CamSwitcherAPI.getWsEventsPath()} …`);
|
|
108
|
+
};
|
|
109
|
+
|
|
110
|
+
const disconnect = () => {
|
|
111
|
+
cswEvents?.destroy(); // also destroys the underlying ws client
|
|
112
|
+
cswEvents = null;
|
|
113
|
+
wsClient = null;
|
|
114
|
+
setStatus('Disconnected.');
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
els.form.addEventListener('submit', (e) => {
|
|
118
|
+
e.preventDefault();
|
|
119
|
+
const host = els.host.value.trim();
|
|
120
|
+
const token = els.token.value.trim();
|
|
121
|
+
if (!host || !token) {
|
|
122
|
+
setStatus('Device host and access token are required.', true);
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
connect(host, token);
|
|
126
|
+
els.connect.disabled = true;
|
|
127
|
+
els.disconnect.disabled = false;
|
|
128
|
+
});
|
|
129
|
+
|
|
130
|
+
els.disconnect.addEventListener('click', () => {
|
|
131
|
+
disconnect();
|
|
132
|
+
els.connect.disabled = false;
|
|
133
|
+
els.disconnect.disabled = true;
|
|
134
|
+
});
|
|
135
|
+
</script>
|
|
136
|
+
</body>
|
|
137
|
+
</html>
|
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
<!DOCTYPE html>
|
|
2
|
+
<html lang="en">
|
|
3
|
+
<head>
|
|
4
|
+
<meta charset="utf-8" />
|
|
5
|
+
<title>CamStreamerLib — PlaneTracker events over Device Connect</title>
|
|
6
|
+
<link rel="stylesheet" href="./utils/example.css" />
|
|
7
|
+
</head>
|
|
8
|
+
<body>
|
|
9
|
+
<h1>PlaneTracker events over Device Connect</h1>
|
|
10
|
+
|
|
11
|
+
<form id="config">
|
|
12
|
+
<label>
|
|
13
|
+
Device host
|
|
14
|
+
<input id="host" placeholder="ACCC8EA84F71.device-connect.net" />
|
|
15
|
+
</label>
|
|
16
|
+
<label>
|
|
17
|
+
Device access token
|
|
18
|
+
<input id="token" placeholder="paste the device access token" />
|
|
19
|
+
</label>
|
|
20
|
+
<label>
|
|
21
|
+
User ID
|
|
22
|
+
<input id="userId" class="short" />
|
|
23
|
+
</label>
|
|
24
|
+
<label>
|
|
25
|
+
User name
|
|
26
|
+
<input id="userName" class="short" />
|
|
27
|
+
</label>
|
|
28
|
+
<label>
|
|
29
|
+
User priority
|
|
30
|
+
<input id="userPriority" class="short" type="number" />
|
|
31
|
+
</label>
|
|
32
|
+
<label class="inline">
|
|
33
|
+
<input id="logHighFrequency" type="checkbox" />
|
|
34
|
+
Log CAMERA_POSITION / FLIGHT_LIST
|
|
35
|
+
</label>
|
|
36
|
+
<button id="connect" type="submit">Connect</button>
|
|
37
|
+
<button id="disconnect" type="button" disabled>Disconnect</button>
|
|
38
|
+
</form>
|
|
39
|
+
|
|
40
|
+
<div id="status">Not connected.</div>
|
|
41
|
+
<div id="summary">
|
|
42
|
+
<span id="cameraSummary">CAMERA_POSITION: —</span>
|
|
43
|
+
<span id="flightSummary">FLIGHT_LIST: —</span>
|
|
44
|
+
</div>
|
|
45
|
+
<div id="log"></div>
|
|
46
|
+
|
|
47
|
+
<script type="module">
|
|
48
|
+
import { PlaneTrackerAPI, PlaneTrackerEvents, DeviceConnectWsClient } from './camstreamerlib.js';
|
|
49
|
+
|
|
50
|
+
// Fill these in to have the form prefilled on load.
|
|
51
|
+
const DEVICE_HOST = '';
|
|
52
|
+
const DEVICE_ACCESS_TOKEN = '';
|
|
53
|
+
|
|
54
|
+
// The connecting user is announced to PlaneTracker on every (re)connect and is broadcast
|
|
55
|
+
// to other clients in CONNECTED_USERS — see doc/ws/PlaneTrackerEvents.md.
|
|
56
|
+
const API_USER = { userId: 'example', userName: 'Example', userPriority: 1 };
|
|
57
|
+
|
|
58
|
+
// Every event type emitted by PlaneTracker.
|
|
59
|
+
const EVENT_TYPES = [
|
|
60
|
+
'CAMERA_POSITION',
|
|
61
|
+
'TRACKING_START',
|
|
62
|
+
'TRACKING_STOP',
|
|
63
|
+
'FLIGHT_LIST',
|
|
64
|
+
'USER_ACTION',
|
|
65
|
+
'CONNECTED_USERS',
|
|
66
|
+
'FORCE_TRACKING_STATUS',
|
|
67
|
+
'API_LOCK_STATUS',
|
|
68
|
+
];
|
|
69
|
+
const HIGH_FREQUENCY_TYPES = ['CAMERA_POSITION', 'FLIGHT_LIST'];
|
|
70
|
+
const LISTENER_ID = 'example';
|
|
71
|
+
|
|
72
|
+
const els = {
|
|
73
|
+
form: document.getElementById('config'),
|
|
74
|
+
host: document.getElementById('host'),
|
|
75
|
+
token: document.getElementById('token'),
|
|
76
|
+
userId: document.getElementById('userId'),
|
|
77
|
+
userName: document.getElementById('userName'),
|
|
78
|
+
userPriority: document.getElementById('userPriority'),
|
|
79
|
+
logHighFrequency: document.getElementById('logHighFrequency'),
|
|
80
|
+
connect: document.getElementById('connect'),
|
|
81
|
+
disconnect: document.getElementById('disconnect'),
|
|
82
|
+
status: document.getElementById('status'),
|
|
83
|
+
cameraSummary: document.getElementById('cameraSummary'),
|
|
84
|
+
flightSummary: document.getElementById('flightSummary'),
|
|
85
|
+
log: document.getElementById('log'),
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
els.host.value = DEVICE_HOST;
|
|
89
|
+
els.token.value = DEVICE_ACCESS_TOKEN;
|
|
90
|
+
els.userId.value = API_USER.userId;
|
|
91
|
+
els.userName.value = API_USER.userName;
|
|
92
|
+
els.userPriority.value = API_USER.userPriority;
|
|
93
|
+
|
|
94
|
+
let wsClient = null;
|
|
95
|
+
let ptrEvents = null;
|
|
96
|
+
const counts = { CAMERA_POSITION: 0, FLIGHT_LIST: 0 };
|
|
97
|
+
|
|
98
|
+
const setStatus = (text, isError = false) => {
|
|
99
|
+
els.status.textContent = text;
|
|
100
|
+
els.status.className = isError ? 'err' : '';
|
|
101
|
+
};
|
|
102
|
+
|
|
103
|
+
const log = (type, payload, isInit) => {
|
|
104
|
+
const row = document.createElement('div');
|
|
105
|
+
row.className = 'row';
|
|
106
|
+
row.innerHTML =
|
|
107
|
+
`<span class="time">${new Date().toLocaleTimeString()}</span> ` +
|
|
108
|
+
`<span class="type">${type}</span>` +
|
|
109
|
+
(isInit ? ' <span class="init">[init]</span>' : '') +
|
|
110
|
+
` ${JSON.stringify(payload)}`;
|
|
111
|
+
els.log.append(row);
|
|
112
|
+
els.log.scrollTop = els.log.scrollHeight;
|
|
113
|
+
};
|
|
114
|
+
|
|
115
|
+
const onEvent = (data, isInit) => {
|
|
116
|
+
setStatus('Connected.');
|
|
117
|
+
if (!HIGH_FREQUENCY_TYPES.includes(data.type)) {
|
|
118
|
+
log(data.type, data, isInit);
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
counts[data.type] += 1;
|
|
123
|
+
if (data.type === 'CAMERA_POSITION') {
|
|
124
|
+
els.cameraSummary.textContent =
|
|
125
|
+
`CAMERA_POSITION (${counts.CAMERA_POSITION}): ` +
|
|
126
|
+
`lat ${data.lat.toFixed(5)}, lon ${data.lon.toFixed(5)}, ` +
|
|
127
|
+
`azimuth ${data.azimuth.toFixed(1)}°, elevation ${data.elevation.toFixed(1)}°, ` +
|
|
128
|
+
`fov ${data.fov.toFixed(1)}°`;
|
|
129
|
+
} else {
|
|
130
|
+
els.flightSummary.textContent = `FLIGHT_LIST (${counts.FLIGHT_LIST}): ${data.list.length} targets`;
|
|
131
|
+
}
|
|
132
|
+
if (els.logHighFrequency.checked) {
|
|
133
|
+
log(data.type, data, isInit);
|
|
134
|
+
}
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
const connect = (host, token, apiUser) => {
|
|
138
|
+
// The path getter is evaluated on every (re)connect; the token is appended by the client.
|
|
139
|
+
wsClient = new DeviceConnectWsClient(token, host, () => PlaneTrackerAPI.getWsEventsPath());
|
|
140
|
+
ptrEvents = new PlaneTrackerEvents(wsClient, apiUser);
|
|
141
|
+
|
|
142
|
+
for (const type of EVENT_TYPES) {
|
|
143
|
+
ptrEvents.addListener(type, onEvent, LISTENER_ID);
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
wsClient.init();
|
|
147
|
+
setStatus(`Connecting to wss://${host}${PlaneTrackerAPI.getWsEventsPath()} …`);
|
|
148
|
+
};
|
|
149
|
+
|
|
150
|
+
const disconnect = () => {
|
|
151
|
+
ptrEvents?.destroy(); // also destroys the underlying ws client
|
|
152
|
+
ptrEvents = null;
|
|
153
|
+
wsClient = null;
|
|
154
|
+
setStatus('Disconnected.');
|
|
155
|
+
};
|
|
156
|
+
|
|
157
|
+
els.form.addEventListener('submit', (e) => {
|
|
158
|
+
e.preventDefault();
|
|
159
|
+
const host = els.host.value.trim();
|
|
160
|
+
const token = els.token.value.trim();
|
|
161
|
+
const apiUser = {
|
|
162
|
+
userId: els.userId.value.trim(),
|
|
163
|
+
userName: els.userName.value.trim(),
|
|
164
|
+
userPriority: Number(els.userPriority.value),
|
|
165
|
+
};
|
|
166
|
+
if (!host || !token) {
|
|
167
|
+
setStatus('Device host and access token are required.', true);
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
if (!apiUser.userId || !apiUser.userName || !Number.isFinite(apiUser.userPriority)) {
|
|
171
|
+
setStatus('User ID, user name and a numeric user priority are required.', true);
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
connect(host, token, apiUser);
|
|
175
|
+
els.connect.disabled = true;
|
|
176
|
+
els.disconnect.disabled = false;
|
|
177
|
+
});
|
|
178
|
+
|
|
179
|
+
els.disconnect.addEventListener('click', () => {
|
|
180
|
+
disconnect();
|
|
181
|
+
els.connect.disabled = false;
|
|
182
|
+
els.disconnect.disabled = true;
|
|
183
|
+
});
|
|
184
|
+
</script>
|
|
185
|
+
</body>
|
|
186
|
+
</html>
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
body {
|
|
2
|
+
font-family: system-ui, sans-serif;
|
|
3
|
+
margin: 0;
|
|
4
|
+
padding: 24px;
|
|
5
|
+
background: #14181d;
|
|
6
|
+
color: #e6e6e6;
|
|
7
|
+
}
|
|
8
|
+
h1 {
|
|
9
|
+
font-size: 18px;
|
|
10
|
+
margin: 0 0 16px;
|
|
11
|
+
}
|
|
12
|
+
form {
|
|
13
|
+
display: flex;
|
|
14
|
+
flex-wrap: wrap;
|
|
15
|
+
gap: 12px;
|
|
16
|
+
align-items: flex-end;
|
|
17
|
+
margin-bottom: 16px;
|
|
18
|
+
}
|
|
19
|
+
label {
|
|
20
|
+
display: flex;
|
|
21
|
+
flex-direction: column;
|
|
22
|
+
gap: 4px;
|
|
23
|
+
font-size: 12px;
|
|
24
|
+
color: #9aa4af;
|
|
25
|
+
}
|
|
26
|
+
label.inline {
|
|
27
|
+
flex-direction: row;
|
|
28
|
+
align-items: center;
|
|
29
|
+
gap: 6px;
|
|
30
|
+
padding-bottom: 8px;
|
|
31
|
+
}
|
|
32
|
+
input {
|
|
33
|
+
min-width: 340px;
|
|
34
|
+
padding: 6px 8px;
|
|
35
|
+
border: 1px solid #3a434d;
|
|
36
|
+
border-radius: 4px;
|
|
37
|
+
background: #1c2229;
|
|
38
|
+
color: #e6e6e6;
|
|
39
|
+
font-family: monospace;
|
|
40
|
+
}
|
|
41
|
+
input.short {
|
|
42
|
+
min-width: 120px;
|
|
43
|
+
}
|
|
44
|
+
input[type='checkbox'] {
|
|
45
|
+
min-width: 0;
|
|
46
|
+
}
|
|
47
|
+
button {
|
|
48
|
+
padding: 7px 14px;
|
|
49
|
+
border: 0;
|
|
50
|
+
border-radius: 4px;
|
|
51
|
+
background: #2f7dd1;
|
|
52
|
+
color: #fff;
|
|
53
|
+
cursor: pointer;
|
|
54
|
+
}
|
|
55
|
+
button:disabled {
|
|
56
|
+
background: #3a434d;
|
|
57
|
+
cursor: not-allowed;
|
|
58
|
+
}
|
|
59
|
+
#status {
|
|
60
|
+
margin-bottom: 12px;
|
|
61
|
+
font-size: 13px;
|
|
62
|
+
}
|
|
63
|
+
#summary {
|
|
64
|
+
display: flex;
|
|
65
|
+
flex-wrap: wrap;
|
|
66
|
+
gap: 24px;
|
|
67
|
+
margin-bottom: 12px;
|
|
68
|
+
padding: 10px 12px;
|
|
69
|
+
border: 1px solid #2a323b;
|
|
70
|
+
border-radius: 4px;
|
|
71
|
+
background: #0f1317;
|
|
72
|
+
font-family: monospace;
|
|
73
|
+
font-size: 12px;
|
|
74
|
+
color: #9aa4af;
|
|
75
|
+
}
|
|
76
|
+
#log {
|
|
77
|
+
height: 60vh;
|
|
78
|
+
overflow: auto;
|
|
79
|
+
padding: 12px;
|
|
80
|
+
border: 1px solid #2a323b;
|
|
81
|
+
border-radius: 4px;
|
|
82
|
+
background: #0f1317;
|
|
83
|
+
font-family: monospace;
|
|
84
|
+
font-size: 12px;
|
|
85
|
+
white-space: pre-wrap;
|
|
86
|
+
}
|
|
87
|
+
.row {
|
|
88
|
+
padding: 2px 0;
|
|
89
|
+
border-bottom: 1px solid #1c2229;
|
|
90
|
+
}
|
|
91
|
+
.time {
|
|
92
|
+
color: #6b7681;
|
|
93
|
+
}
|
|
94
|
+
.type {
|
|
95
|
+
color: #7fd18a;
|
|
96
|
+
}
|
|
97
|
+
.init {
|
|
98
|
+
color: #d1b84f;
|
|
99
|
+
}
|
|
100
|
+
.err {
|
|
101
|
+
color: #e07b7b;
|
|
102
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "camstreamerlib",
|
|
3
|
-
"version": "4.0.
|
|
3
|
+
"version": "4.0.33",
|
|
4
4
|
"description": "Helper library for CamStreamer ACAP applications.",
|
|
5
5
|
"prettier": "@camstreamer/prettier-config",
|
|
6
6
|
"engine": {
|
|
@@ -24,6 +24,7 @@
|
|
|
24
24
|
"@types/ws": "^8.5.10",
|
|
25
25
|
"@typescript-eslint/eslint-plugin": "^6.8.0",
|
|
26
26
|
"@typescript-eslint/parser": "^6.8.0",
|
|
27
|
+
"esbuild": "^0.28.2",
|
|
27
28
|
"eslint": "^8.51.0",
|
|
28
29
|
"eslint-plugin-deprecation": "^2.0.0",
|
|
29
30
|
"eslint-plugin-unused-imports": "^3.0.0",
|
|
@@ -42,7 +43,8 @@
|
|
|
42
43
|
"build": "npm-run-all clean build:cjs build:esm copyPackage",
|
|
43
44
|
"build:cjs": "tsc --project tsconfig.cjs.json",
|
|
44
45
|
"build:esm": "tsc --project tsconfig.esm.json",
|
|
45
|
-
"
|
|
46
|
+
"build:browser": "esbuild src/browser.index.ts --bundle --format=esm --platform=browser --target=es2022 --outfile=examples/camstreamerlib.js",
|
|
47
|
+
"copyPackage": "cp -f LICENSE dist/ && cp -f README.md dist/ && cp -f package.json dist/ && cp -r -f examples dist/",
|
|
46
48
|
"publishPackage": "./publish.sh",
|
|
47
49
|
"lint": "eslint \"src/**/*.ts\"",
|
|
48
50
|
"lint:fix": "eslint \"src/**/*.ts\" --fix",
|
|
@@ -53,7 +55,8 @@
|
|
|
53
55
|
},
|
|
54
56
|
"files": [
|
|
55
57
|
"/**/*.js",
|
|
56
|
-
"/**/*.ts"
|
|
58
|
+
"/**/*.ts",
|
|
59
|
+
"/examples/**/*"
|
|
57
60
|
],
|
|
58
61
|
"main": "./cjs/index.js",
|
|
59
62
|
"module": "./esm/index.js",
|