1
- import { injectable } from 'inversify' ;
1
+ import { injectable , inject } from 'inversify' ;
2
2
import * as createPaths from './create-paths' ;
3
- import { posix , splitSketchPath } from './create-paths' ;
3
+ import { posix } from './create-paths' ;
4
4
import { AuthenticationClientService } from '../auth/authentication-client-service' ;
5
5
import { ArduinoPreferences } from '../arduino-preferences' ;
6
+ import { SketchCache } from '../widgets/cloud-sketchbook/cloud-sketch-cache' ;
6
7
7
8
export interface ResponseResultProvider {
8
9
( response : Response ) : Promise < any > ;
@@ -15,10 +16,11 @@ export namespace ResponseResultProvider {
15
16
16
17
type ResourceType = 'f' | 'd' ;
17
18
18
- export let sketchCache : Create . Sketch [ ] = [ ] ;
19
-
20
19
@injectable ( )
21
20
export class CreateApi {
21
+ @inject ( SketchCache )
22
+ protected readonly sketchCache : SketchCache ;
23
+
22
24
protected authenticationService : AuthenticationClientService ;
23
25
protected arduinoPreferences : ArduinoPreferences ;
24
26
@@ -32,48 +34,24 @@ export class CreateApi {
32
34
return this ;
33
35
}
34
36
35
- public sketchCompareByPath = ( param : string ) => {
36
- return ( sketch : Create . Sketch ) => {
37
- const [ , spath ] = splitSketchPath ( sketch . path ) ;
38
- return param === spath ;
39
- } ;
40
- } ;
41
-
42
- async findSketchInCache (
43
- compareFn : ( sketch : Create . Sketch ) => boolean ,
44
- trustCache = true
45
- ) : Promise < Create . Sketch | undefined > {
46
- const sketch = sketchCache . find ( ( sketch ) => compareFn ( sketch ) ) ;
47
- if ( trustCache ) {
48
- return Promise . resolve ( sketch ) ;
49
- }
50
- return await this . sketch ( { id : sketch ?. id } ) ;
37
+ public wipeCache ( ) : void {
38
+ this . sketchCache . init ( ) ;
51
39
}
52
40
53
41
getSketchSecretStat ( sketch : Create . Sketch ) : Create . Resource {
54
42
return {
55
43
href : `${ sketch . href } ${ posix . sep } ${ Create . arduino_secrets_file } ` ,
56
44
modified_at : sketch . modified_at ,
45
+ created_at : sketch . created_at ,
57
46
name : `${ Create . arduino_secrets_file } ` ,
58
47
path : `${ sketch . path } ${ posix . sep } ${ Create . arduino_secrets_file } ` ,
59
48
mimetype : 'text/x-c++src; charset=utf-8' ,
60
49
type : 'file' ,
61
- sketchId : sketch . id ,
62
50
} ;
63
51
}
64
52
65
- async sketch ( opt : {
66
- id ?: string ;
67
- path ?: string ;
68
- } ) : Promise < Create . Sketch | undefined > {
69
- let url ;
70
- if ( opt . id ) {
71
- url = new URL ( `${ this . domain ( ) } /sketches/byID/${ opt . id } ` ) ;
72
- } else if ( opt . path ) {
73
- url = new URL ( `${ this . domain ( ) } /sketches/byPath${ opt . path } ` ) ;
74
- } else {
75
- return ;
76
- }
53
+ async sketch ( id : string ) : Promise < Create . Sketch | undefined > {
54
+ const url = new URL ( `${ this . domain ( ) } /sketches/byID/${ id } ` ) ;
77
55
78
56
url . searchParams . set ( 'user_id' , 'me' ) ;
79
57
const headers = await this . headers ( ) ;
@@ -92,7 +70,7 @@ export class CreateApi {
92
70
method : 'GET' ,
93
71
headers,
94
72
} ) ;
95
- sketchCache = result . sketches ;
73
+ result . sketches . forEach ( ( sketch ) => this . sketchCache . addSketch ( sketch ) ) ;
96
74
return result . sketches ;
97
75
}
98
76
@@ -118,7 +96,7 @@ export class CreateApi {
118
96
119
97
async readDirectory (
120
98
posixPath : string ,
121
- options : { recursive ?: boolean ; match ?: string ; secrets ?: boolean } = { }
99
+ options : { recursive ?: boolean ; match ?: string } = { }
122
100
) : Promise < Create . Resource [ ] > {
123
101
const url = new URL (
124
102
`${ this . domain ( ) } /files/d/$HOME/sketches_v2${ posixPath } `
@@ -131,58 +109,21 @@ export class CreateApi {
131
109
}
132
110
const headers = await this . headers ( ) ;
133
111
134
- const sketchProm = options . secrets
135
- ? this . sketches ( )
136
- : Promise . resolve ( sketchCache ) ;
137
-
138
- return Promise . all ( [
139
- this . run < Create . RawResource [ ] > ( url , {
140
- method : 'GET' ,
141
- headers,
142
- } ) ,
143
- sketchProm ,
144
- ] )
145
- . then ( async ( [ result , sketches ] ) => {
146
- if ( options . secrets ) {
147
- // for every sketch with secrets, create a fake arduino_secrets.h
148
- result . forEach ( async ( res ) => {
149
- if ( res . type !== 'sketch' ) {
150
- return ;
151
- }
152
-
153
- const [ , spath ] = createPaths . splitSketchPath ( res . path ) ;
154
- const sketch = await this . findSketchInCache (
155
- this . sketchCompareByPath ( spath )
156
- ) ;
157
- if ( sketch && sketch . secrets && sketch . secrets . length > 0 ) {
158
- result . push ( this . getSketchSecretStat ( sketch ) ) ;
159
- }
160
- } ) ;
161
-
162
- if ( posixPath !== posix . sep ) {
163
- const sketch = await this . findSketchInCache (
164
- this . sketchCompareByPath ( posixPath )
165
- ) ;
166
- if ( sketch && sketch . secrets && sketch . secrets . length > 0 ) {
167
- result . push ( this . getSketchSecretStat ( sketch ) ) ;
168
- }
112
+ return this . run < Create . RawResource [ ] > ( url , {
113
+ method : 'GET' ,
114
+ headers,
115
+ } )
116
+ . then ( async ( result ) => {
117
+ // add arduino_secrets.h to the results, when reading a sketch main folder
118
+ if ( posixPath . length && posixPath !== posix . sep ) {
119
+ const sketch = this . sketchCache . getSketch ( posixPath ) ;
120
+
121
+ if ( sketch && sketch . secrets && sketch . secrets . length > 0 ) {
122
+ result . push ( this . getSketchSecretStat ( sketch ) ) ;
169
123
}
170
124
}
171
- const sketchesMap : Record < string , Create . Sketch > = sketches . reduce (
172
- ( prev , curr ) => {
173
- return { ...prev , [ curr . path ] : curr } ;
174
- } ,
175
- { }
176
- ) ;
177
125
178
- // add the sketch id and isPublic to the resource
179
- return result . map ( ( resource ) => {
180
- return {
181
- ...resource ,
182
- sketchId : sketchesMap [ resource . path ] ?. id || '' ,
183
- isPublic : sketchesMap [ resource . path ] ?. is_public || false ,
184
- } ;
185
- } ) ;
126
+ return result ;
186
127
} )
187
128
. catch ( ( reason ) => {
188
129
if ( reason ?. status === 404 ) return [ ] as Create . Resource [ ] ;
@@ -214,18 +155,16 @@ export class CreateApi {
214
155
215
156
let resources ;
216
157
if ( basename === Create . arduino_secrets_file ) {
217
- const sketch = await this . findSketchInCache (
218
- this . sketchCompareByPath ( parentPosixPath )
219
- ) ;
158
+ const sketch = this . sketchCache . getSketch ( parentPosixPath ) ;
220
159
resources = sketch ? [ this . getSketchSecretStat ( sketch ) ] : [ ] ;
221
160
} else {
222
161
resources = await this . readDirectory ( parentPosixPath , {
223
162
match : basename ,
224
163
} ) ;
225
164
}
226
-
227
- resources . sort ( ( left , right ) => left . path . length - right . path . length ) ;
228
- const resource = resources . find ( ( { name } ) => name === basename ) ;
165
+ const resource = resources . find (
166
+ ( { path } ) => createPaths . splitSketchPath ( path ) [ 1 ] === posixPath
167
+ ) ;
229
168
if ( ! resource ) {
230
169
throw new CreateError ( `Not found: ${ posixPath } .` , 404 ) ;
231
170
}
@@ -248,10 +187,7 @@ export class CreateApi {
248
187
return data ;
249
188
}
250
189
251
- const sketch = await this . findSketchInCache ( ( sketch ) => {
252
- const [ , spath ] = splitSketchPath ( sketch . path ) ;
253
- return spath === createPaths . parentPosix ( path ) ;
254
- } , true ) ;
190
+ const sketch = this . sketchCache . getSketch ( createPaths . parentPosix ( path ) ) ;
255
191
256
192
if (
257
193
sketch &&
@@ -273,14 +209,25 @@ export class CreateApi {
273
209
274
210
if ( basename === Create . arduino_secrets_file ) {
275
211
const parentPosixPath = createPaths . parentPosix ( posixPath ) ;
276
- const sketch = await this . findSketchInCache (
277
- this . sketchCompareByPath ( parentPosixPath ) ,
278
- false
279
- ) ;
212
+
213
+ //retrieve the sketch id from the cache
214
+ const cacheSketch = this . sketchCache . getSketch ( parentPosixPath ) ;
215
+ if ( ! cacheSketch ) {
216
+ throw new Error ( `Unable to find sketch ${ parentPosixPath } in cache` ) ;
217
+ }
218
+
219
+ // get a fresh copy of the sketch in order to guarantee fresh secrets
220
+ const sketch = await this . sketch ( cacheSketch . id ) ;
221
+ if ( ! sketch ) {
222
+ throw new Error (
223
+ `Unable to get a fresh copy of the sketch ${ cacheSketch . id } `
224
+ ) ;
225
+ }
226
+ this . sketchCache . addSketch ( sketch ) ;
280
227
281
228
let file = '' ;
282
229
if ( sketch && sketch . secrets ) {
283
- for ( const item of sketch ? .secrets ) {
230
+ for ( const item of sketch . secrets ) {
284
231
file += `#define ${ item . name } "${ item . value } "\r\n` ;
285
232
}
286
233
}
@@ -310,9 +257,9 @@ export class CreateApi {
310
257
311
258
if ( basename === Create . arduino_secrets_file ) {
312
259
const parentPosixPath = createPaths . parentPosix ( posixPath ) ;
313
- const sketch = await this . findSketchInCache (
314
- this . sketchCompareByPath ( parentPosixPath )
315
- ) ;
260
+
261
+ const sketch = this . sketchCache . getSketch ( parentPosixPath ) ;
262
+
316
263
if ( sketch ) {
317
264
const url = new URL ( `${ this . domain ( ) } /sketches/${ sketch . id } ` ) ;
318
265
const headers = await this . headers ( ) ;
@@ -357,8 +304,7 @@ export class CreateApi {
357
304
} ;
358
305
359
306
// replace the sketch in the cache, so other calls will not overwrite each other
360
- sketchCache = sketchCache . filter ( ( skt ) => skt . id !== sketch . id ) ;
361
- sketchCache . push ( { ...sketch , secrets } ) ;
307
+ this . sketchCache . addSketch ( sketch ) ;
362
308
363
309
const init = {
364
310
method : 'POST' ,
@@ -543,8 +489,9 @@ export namespace Create {
543
489
*/
544
490
readonly path : string ;
545
491
readonly type : ResourceType ;
546
- readonly sketchId : string ;
492
+ readonly sketchId ? : string ;
547
493
readonly modified_at : string ; // As an ISO-8601 formatted string: `YYYY-MM-DDTHH:mm:ss.sssZ`
494
+ readonly created_at : string ; // As an ISO-8601 formatted string: `YYYY-MM-DDTHH:mm:ss.sssZ`
548
495
readonly children ?: number ; // For 'sketch' and 'folder' types.
549
496
readonly size ?: number ; // For 'sketch' type only.
550
497
readonly isPublic ?: boolean ; // For 'sketch' type only.
0 commit comments