@unitn-asa/deliveroo-js-sdk 1.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/README.MD +49 -0
- package/package.json +38 -0
- package/src/client/DjsClientSocket.js +312 -0
- package/src/client/DjsRestClient.js +432 -0
- package/src/client/connectUtil.js +51 -0
- package/src/client/index.js +21 -0
- package/src/server/DjsServer.js +136 -0
- package/src/server/DjsServerSocket.js +316 -0
- package/src/server/index.js +21 -0
- package/src/types/IOAgent.js +14 -0
- package/src/types/IOClockEvent.js +21 -0
- package/src/types/IOConfig.js +17 -0
- package/src/types/IOCrate.js +9 -0
- package/src/types/IOGameOptions.js +54 -0
- package/src/types/IOIdentity.js +12 -0
- package/src/types/IOInfo.js +11 -0
- package/src/types/IOParcel.js +11 -0
- package/src/types/IOSensing.js +15 -0
- package/src/types/IOSocketEvents.js +44 -0
- package/src/types/IOTile.js +28 -0
- package/src/types/parseClockEvent.js +17 -0
package/README.MD
ADDED
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# @unitn-asa/deliveroo-js-sdk
|
|
2
|
+
|
|
3
|
+
Shared SDK utilities and types for Deliveroo.js (client & server integration helpers).
|
|
4
|
+
|
|
5
|
+
This package exposes small helpers for interacting with the Deliveroo.js backend (HTTP API helpers, socket helpers and shared JSDoc typedefs) so frontend and other packages can import them from a single entry point.
|
|
6
|
+
|
|
7
|
+
## Key features
|
|
8
|
+
|
|
9
|
+
- Small HTTP helper functions for the Deliveroo REST API (tokens, configs, agents, parcels).
|
|
10
|
+
- Socket-related helpers and types for `Deliveroojs`.
|
|
11
|
+
- JSDoc typedefs that can be used by editors/TypeScript for type hints.
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
This package is part of the monorepo and is consumed via file: references in the workspace. If you publish it standalone, install normally with npm/yarn.
|
|
16
|
+
|
|
17
|
+
From the monorepo root (already linked via workspace):
|
|
18
|
+
|
|
19
|
+
```bash
|
|
20
|
+
# frontend or other package: npm install ../packages/@unitn-asa/deliveroo-js-sdk
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Usage (ESM)
|
|
24
|
+
|
|
25
|
+
Import the functions and types you need from the package root:
|
|
26
|
+
|
|
27
|
+
```js
|
|
28
|
+
import {
|
|
29
|
+
DeliveroojsRestClient,
|
|
30
|
+
DeliveroojsAsyncClient
|
|
31
|
+
} from '@unitn-asa/deliveroo-js-sdk';
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
## Types
|
|
35
|
+
|
|
36
|
+
The package contains JSDoc typedef files describing `IOAgent`, `IOParcel`, `IOConfig`, `IOGameOptions` and other structures used across the project. When authoring code that consumes this SDK you can import the types in JSDoc.
|
|
37
|
+
|
|
38
|
+
Example JSDoc import:
|
|
39
|
+
|
|
40
|
+
```js
|
|
41
|
+
/** @typedef {import('@unitn-asa/deliveroo-js-sdk/types/IOAgent.js').IOAgent} IOAgent */
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## License
|
|
45
|
+
|
|
46
|
+
ISC
|
|
47
|
+
|
|
48
|
+
---
|
|
49
|
+
_Maintainer: Marco Robol <marco.robol@unitn.it>_
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@unitn-asa/deliveroo-js-sdk",
|
|
3
|
+
"version": "1.2.1",
|
|
4
|
+
"description": "Software development kit for Deliveroo.js",
|
|
5
|
+
"author": "Marco Robol <marco.robol@unitn.it>",
|
|
6
|
+
"type": "module",
|
|
7
|
+
"license": "ISC",
|
|
8
|
+
"repository": {
|
|
9
|
+
"type": "git",
|
|
10
|
+
"url": "https://github.com/unitn-ASA/Deliveroo.js.git"
|
|
11
|
+
},
|
|
12
|
+
"exports": {
|
|
13
|
+
".": "./src/client/index.js",
|
|
14
|
+
"./types/*": "./src/types/*",
|
|
15
|
+
"./client": "./src/client/index.js",
|
|
16
|
+
"./client/*": "./src/client/*",
|
|
17
|
+
"./server": "./src/server/index.js",
|
|
18
|
+
"./server/*": "./src/server/*"
|
|
19
|
+
},
|
|
20
|
+
"files": [
|
|
21
|
+
"src/*",
|
|
22
|
+
"index.js"
|
|
23
|
+
],
|
|
24
|
+
"scripts": {
|
|
25
|
+
"test": "node test/DeliveroojsApiClient.test.js"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"args-parser": "^1.3.0"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"socket.io": "^4.7.2",
|
|
32
|
+
"socket.io-client": "^4.7.2"
|
|
33
|
+
},
|
|
34
|
+
"publishConfig": {
|
|
35
|
+
"access": "public"
|
|
36
|
+
},
|
|
37
|
+
"gitHead": "66b8c3ba9a75eb7c81e08a500fd3c216c5791f8c"
|
|
38
|
+
}
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
import { Socket } from 'socket.io-client';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* @typedef {import("../types/IOAgent.js").IOAgent} IOAgent
|
|
5
|
+
* @typedef {import("../types/IOParcel.js").IOParcel} IOParcel
|
|
6
|
+
* @typedef {import("../types/IOTile.js").IOTile} IOTile
|
|
7
|
+
* @typedef {import("../types/IOConfig.js").IOConfig} IOConfig
|
|
8
|
+
* @typedef {import("../types/IOInfo.js").IOInfo} IOInfo
|
|
9
|
+
*
|
|
10
|
+
* @typedef {import("../types/IOSocketEvents.js").IOSensing} IOSensing
|
|
11
|
+
* @typedef {import("../types/IOSocketEvents.js").IOClientEvents} IOClientEvents
|
|
12
|
+
* @typedef {import("../types/IOSocketEvents.js").IOServerEvents} IOServerEvents
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* @class
|
|
19
|
+
* @extends { Socket<IOServerEvents, IOClientEvents> }
|
|
20
|
+
*/
|
|
21
|
+
export class DjsClientSocket extends Socket {
|
|
22
|
+
|
|
23
|
+
/** @type { Promise < string > } */
|
|
24
|
+
token = new Promise( (res) => {
|
|
25
|
+
this.once( 'token', (token) => {
|
|
26
|
+
// console.log( 'New token for ' + NAME + ': ' + token )
|
|
27
|
+
res( token );
|
|
28
|
+
} );
|
|
29
|
+
} );
|
|
30
|
+
|
|
31
|
+
/** @type { Promise < IOAgent > } */
|
|
32
|
+
me = new Promise( (res) => {
|
|
33
|
+
this.once( 'you', (agent, info) => {
|
|
34
|
+
res( agent );
|
|
35
|
+
} );
|
|
36
|
+
} );
|
|
37
|
+
|
|
38
|
+
/** @type { Promise } */
|
|
39
|
+
config = new Promise( (res) => {
|
|
40
|
+
this.once( 'config', (config) => {
|
|
41
|
+
res( config );
|
|
42
|
+
} );
|
|
43
|
+
} );
|
|
44
|
+
|
|
45
|
+
/** @type { Promise < { width:number, height:number, tiles: IOTile [] } > } */
|
|
46
|
+
map = new Promise ( (res) => {
|
|
47
|
+
this.once( 'map', (width, height, tiles) => {
|
|
48
|
+
res( {width, height, tiles} );
|
|
49
|
+
} );
|
|
50
|
+
} );
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
* @param { function() : void } callback
|
|
56
|
+
*/
|
|
57
|
+
onConnect ( callback ) {
|
|
58
|
+
this.on( "connect", callback )
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
/**
|
|
62
|
+
* @param { function() : void } callback
|
|
63
|
+
*/
|
|
64
|
+
onDisconnect ( callback ) {
|
|
65
|
+
this.on( "disconnect", callback )
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/**
|
|
69
|
+
* @param { function(IOConfig) : void } callback
|
|
70
|
+
*/
|
|
71
|
+
onConfig ( callback ) {
|
|
72
|
+
this.on( "config", callback )
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* @param { function( number, number, IOTile[] ) : void } callback ( width, height, tiles )
|
|
77
|
+
*/
|
|
78
|
+
onMap ( callback ) {
|
|
79
|
+
this.on( "map", callback )
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* @param { function( IOTile, IOInfo ) : void } callback
|
|
84
|
+
*/
|
|
85
|
+
onTile ( callback ) {
|
|
86
|
+
this.on( "tile", callback )
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
// @param { serverEvents['controller'] } callback
|
|
90
|
+
/**
|
|
91
|
+
* @param { function( string, { id:string, name:string, teamId:string, teamName:string, score:number } ) : void } callback
|
|
92
|
+
*/
|
|
93
|
+
onAgentConnected ( callback ) {
|
|
94
|
+
this.on( "controller", callback )
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @param { function( IOAgent, IOInfo ) : void } callback
|
|
99
|
+
*/
|
|
100
|
+
onYou ( callback ) {
|
|
101
|
+
this.on( "you", callback )
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @param { function( IOAgent, IOInfo ) : void } callback
|
|
106
|
+
*/
|
|
107
|
+
onceYou ( callback ) {
|
|
108
|
+
this.once( "you", callback )
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
/**
|
|
112
|
+
* Listen to 'agents sensing' events
|
|
113
|
+
* @param { function( IOSensing [] ) : void } callback
|
|
114
|
+
*/
|
|
115
|
+
onAgentsSensing ( callback ) {
|
|
116
|
+
this.on( "agents sensing", callback )
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* Listen to 'parcels sensing' events
|
|
121
|
+
* @param { function( IOSensing [] ) : void } callback
|
|
122
|
+
*/
|
|
123
|
+
onParcelsSensing ( callback ) {
|
|
124
|
+
this.on( "parcels sensing", callback )
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Listen to 'crates sensing' events
|
|
129
|
+
* @param { function( IOSensing [] ) : void } callback
|
|
130
|
+
*/
|
|
131
|
+
onCratesSensing ( callback ) {
|
|
132
|
+
this.on( "crates sensing", callback )
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
/**
|
|
136
|
+
* @callback onMsgCallback
|
|
137
|
+
* @param { string } id
|
|
138
|
+
* @param { string } name
|
|
139
|
+
* @param { {} } msg
|
|
140
|
+
* @param { function( any ) : void } replyAcknowledgmentCallback ( reply )
|
|
141
|
+
*/
|
|
142
|
+
/**
|
|
143
|
+
* Listen to 'msg' events
|
|
144
|
+
* @param {onMsgCallback} callback (id, name, msg, replyAcknowledgmentCallback)
|
|
145
|
+
*/
|
|
146
|
+
onMsg ( callback ) {
|
|
147
|
+
this.on( "msg", callback )
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
/**
|
|
151
|
+
* @template T
|
|
152
|
+
* @typedef {T extends [...infer _, infer L] ? L : never} Last
|
|
153
|
+
*/
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
* @template T
|
|
157
|
+
* @typedef {T extends [...infer R, any] ? R : T} AllButLast
|
|
158
|
+
*/
|
|
159
|
+
|
|
160
|
+
/**
|
|
161
|
+
* @template {keyof IOClientEvents} K
|
|
162
|
+
* @param {K} event
|
|
163
|
+
* @param {AllButLast<Parameters<IOClientEvents[K]>>} args
|
|
164
|
+
* @returns {Promise<Last<Parameters<IOClientEvents[K]>>>}
|
|
165
|
+
*/
|
|
166
|
+
// @ts-ignore
|
|
167
|
+
async emitAndResolveOnAck ( event, ...args ) {
|
|
168
|
+
// @ts-ignore
|
|
169
|
+
return this.timeout( 1000 ).emitWithAck( event, ...args );
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
/**
|
|
173
|
+
* @param {string} toId
|
|
174
|
+
* @param {any} msg
|
|
175
|
+
* @returns { Promise < 'successful' > } status
|
|
176
|
+
*/
|
|
177
|
+
async emitSay ( toId, msg ) {
|
|
178
|
+
return new Promise( (success) => {
|
|
179
|
+
this.emit( 'say', toId, msg, async ( status ) => {
|
|
180
|
+
success( status );
|
|
181
|
+
} );
|
|
182
|
+
} );
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* @param {string} toId
|
|
187
|
+
* @param {any} msg
|
|
188
|
+
* @returns { Promise < { any } > } reply
|
|
189
|
+
*/
|
|
190
|
+
async emitAsk ( toId, msg ) {
|
|
191
|
+
return new Promise( (success) => {
|
|
192
|
+
this.emit( 'ask', toId, msg, async ( reply ) => {
|
|
193
|
+
success( reply );
|
|
194
|
+
} );
|
|
195
|
+
} );
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
async emitShout ( msg ) {
|
|
199
|
+
return new Promise( (success) => {
|
|
200
|
+
this.emit( 'shout', msg, async ( status ) => {
|
|
201
|
+
success( status );
|
|
202
|
+
} );
|
|
203
|
+
} );
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
/**
|
|
207
|
+
* When movement completes, it resolves to true.
|
|
208
|
+
* In case of failure when moving, it resolves to false
|
|
209
|
+
* @param { 'up' | 'right' | 'left' | 'down' | { x:number, y:number } } directionOrXy It can be either: 'up', 'right', 'left', 'down', or destination Xy
|
|
210
|
+
* @returns { Promise < { x:number, y:number } | false > }
|
|
211
|
+
*/
|
|
212
|
+
async emitMove ( directionOrXy ) {
|
|
213
|
+
return this.emitAndResolveOnAck( 'move', directionOrXy );
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
/**
|
|
217
|
+
* Pick up all parcels in the agent tile.
|
|
218
|
+
* When completed, resolves to the array of picked up parcels
|
|
219
|
+
* @returns { Promise < { id:string } [] > } array of picked up parcels
|
|
220
|
+
*/
|
|
221
|
+
async emitPickup ( ) {
|
|
222
|
+
return this.emitAndResolveOnAck( 'pickup' );
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
/**
|
|
226
|
+
* Put down parcels:
|
|
227
|
+
* - if array of ids is provided: putdown only specified parcels
|
|
228
|
+
* - if no list is provided: put down all parcels
|
|
229
|
+
* When completed, resolves to the list of dropped parcels
|
|
230
|
+
* @param { string [] } selected array of parcels id to drop
|
|
231
|
+
* @returns { Promise < { id:string } [] >}
|
|
232
|
+
*/
|
|
233
|
+
async emitPutdown ( selected = null ) {
|
|
234
|
+
return this.emitAndResolveOnAck( 'putdown', selected );
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
/**
|
|
238
|
+
* @param { any [] } message
|
|
239
|
+
*/
|
|
240
|
+
emitLog ( ...message ) {
|
|
241
|
+
this.emit( "log", ...message );
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Listen to 'log' events from server and those redirected here from others client
|
|
246
|
+
* @param { function ( { src:'server'|'client', ms:number, frame: number, socket:string, id:string, name:string }, ...any) : void } callback ( { src, ms, frame, socket, id, name }, ...msgArgs )
|
|
247
|
+
*/
|
|
248
|
+
onLog ( callback ) {
|
|
249
|
+
this.on( "log", callback )
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
/**
|
|
255
|
+
* Enhance a Socket.io-client Socket into a DjsSocket
|
|
256
|
+
* @param { Socket } socket
|
|
257
|
+
* @returns { DjsClientSocket }
|
|
258
|
+
*/
|
|
259
|
+
static enhance (socket) {
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Mixin function to copy methods from a class prototype to an object
|
|
263
|
+
*/
|
|
264
|
+
function applyMixin(target, MixinClass) {
|
|
265
|
+
|
|
266
|
+
let proto = MixinClass.prototype;
|
|
267
|
+
|
|
268
|
+
const descriptors = Object.getOwnPropertyDescriptors(proto);
|
|
269
|
+
delete descriptors.constructor;
|
|
270
|
+
|
|
271
|
+
Object.defineProperties(target, descriptors);
|
|
272
|
+
|
|
273
|
+
return target;
|
|
274
|
+
}
|
|
275
|
+
applyMixin(socket, DjsClientSocket);
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Original socket enhanced with ClientSocketEnhancer methods casted as EnhancedSocket
|
|
279
|
+
* @type { DjsClientSocket }
|
|
280
|
+
*/
|
|
281
|
+
// @ts-ignore
|
|
282
|
+
return socket;
|
|
283
|
+
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
|
|
287
|
+
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
|
|
292
|
+
// import io from 'socket.io-client';
|
|
293
|
+
// const host = 'http://localhost:8080';
|
|
294
|
+
// const opts = {
|
|
295
|
+
// autoConnect: false,
|
|
296
|
+
// withCredentials: false,
|
|
297
|
+
// extraHeaders: { 'x-token': 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJpZCI6ImQzMDhhYiIsIm5hbWUiOiJwYW9sbyIsInRlYW1JZCI6IjYwNzA4ZCIsInRlYW1OYW1lIjoiZGlzaSIsInJvbGUiOiJ1c2VyIiwiaWF0IjoxNzQ4MzUzNTU4fQ.pzZxyGjv0WPbyh45Grr_sYqzGU1EUH-XK7hZEcWX5Js' },
|
|
298
|
+
// // query: { name: 'marco' }
|
|
299
|
+
// };
|
|
300
|
+
// const socket = io( host, opts );
|
|
301
|
+
// const enhancedSocket = DjsClientSocket.enhance( socket );
|
|
302
|
+
// enhancedSocket.emitMove( 'up' ).then( ( result ) => {
|
|
303
|
+
// console.log( 'Move result:', result );
|
|
304
|
+
// } );
|
|
305
|
+
// enhancedSocket.emitShout( 'hellooooo!' );
|
|
306
|
+
// enhancedSocket.onceYou( ( agent, info ) => {
|
|
307
|
+
// console.log( 'enhanceClientSocket.js I am', agent, info );
|
|
308
|
+
// } );
|
|
309
|
+
// // enhancedSocket.emitAndResolveOnAck( 'putdown' ).then( ( ack ) => {
|
|
310
|
+
// // console.log( 'Acknowledged with', ack );
|
|
311
|
+
// // } );
|
|
312
|
+
// enhancedSocket.connect();
|