@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 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();