jsrepo 1.13.2 → 1.13.3
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/dist/index.js +51 -3473
- package/package.json +1 -1
package/dist/index.js
CHANGED
|
@@ -1,3475 +1,53 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
import { resolveCommand as resolveCommand2 } from "package-manager-detector/commands";
|
|
15
|
-
import { detect } from "package-manager-detector/detect";
|
|
16
|
-
import path7 from "pathe";
|
|
17
|
-
import * as v5 from "valibot";
|
|
18
|
-
|
|
19
|
-
// src/utils/ascii.ts
|
|
20
|
-
import color from "chalk";
|
|
21
|
-
var VERTICAL_LINE = color.gray("\u2502");
|
|
22
|
-
var HORIZONTAL_LINE = color.gray("\u2500");
|
|
23
|
-
var TOP_RIGHT_CORNER = color.gray("\u2510");
|
|
24
|
-
var BOTTOM_RIGHT_CORNER = color.gray("\u2518");
|
|
25
|
-
var JUNCTION_RIGHT = color.gray("\u251C");
|
|
26
|
-
var TOP_LEFT_CORNER = color.gray("\u250C");
|
|
27
|
-
var BOTTOM_LEFT_CORNER = color.gray("\u2514");
|
|
28
|
-
var WARN = color.bgRgb(245, 149, 66).white("WARN");
|
|
29
|
-
var INFO = color.bgBlueBright.white("INFO");
|
|
30
|
-
var JSREPO = color.hex("#f7df1e")("jsrepo");
|
|
31
|
-
|
|
32
|
-
// src/utils/blocks.ts
|
|
33
|
-
import fs4 from "node:fs";
|
|
34
|
-
import color5 from "chalk";
|
|
35
|
-
import path4 from "pathe";
|
|
36
|
-
|
|
37
|
-
// src/utils/blocks/types/result.ts
|
|
38
|
-
var Result = class {
|
|
39
|
-
_result;
|
|
40
|
-
constructor(result) {
|
|
41
|
-
this._result = result;
|
|
42
|
-
}
|
|
43
|
-
/** Allows you to run callbacks based on the result.
|
|
44
|
-
*
|
|
45
|
-
* @param success callback to be run when result is success
|
|
46
|
-
* @param failure callback to be run when result is failure
|
|
47
|
-
* @returns
|
|
48
|
-
*
|
|
49
|
-
* ## Usage
|
|
50
|
-
*
|
|
51
|
-
* ```ts
|
|
52
|
-
* result.match(
|
|
53
|
-
* (val) => val,
|
|
54
|
-
* () => {
|
|
55
|
-
* throw new Error('oops!')
|
|
56
|
-
* }
|
|
57
|
-
* );
|
|
58
|
-
* ```
|
|
59
|
-
*
|
|
60
|
-
* ## Examples
|
|
61
|
-
*
|
|
62
|
-
* ```ts
|
|
63
|
-
* const functionThatMightFail = (): Result<string, string> => Ok("Hello, World!");
|
|
64
|
-
*
|
|
65
|
-
* const result = functionThatMightFail();
|
|
66
|
-
*
|
|
67
|
-
* const val = result.match(
|
|
68
|
-
* (val) => val,
|
|
69
|
-
* () => {
|
|
70
|
-
* throw new Error('oops!')
|
|
71
|
-
* }
|
|
72
|
-
* );
|
|
73
|
-
*
|
|
74
|
-
* console.log(val); // "Hello, World!"
|
|
75
|
-
* ```
|
|
76
|
-
*/
|
|
77
|
-
match(success, failure) {
|
|
78
|
-
if (!this._result.ok) {
|
|
79
|
-
return failure(this._result.err);
|
|
80
|
-
}
|
|
81
|
-
return success(this._result.val);
|
|
82
|
-
}
|
|
83
|
-
/** Maps `Result<T, E>` to `Result<A, E>` using the passed mapping function
|
|
84
|
-
*
|
|
85
|
-
* @param fn Mapping function
|
|
86
|
-
* @returns
|
|
87
|
-
*
|
|
88
|
-
* ## Usage
|
|
89
|
-
*
|
|
90
|
-
* ```ts
|
|
91
|
-
* result.map((val) => val.length);
|
|
92
|
-
* ```
|
|
93
|
-
*
|
|
94
|
-
* ## Examples
|
|
95
|
-
*
|
|
96
|
-
* ```ts
|
|
97
|
-
* const functionThatMightFail = (): Result<string, string> => Ok("Hello, World!");
|
|
98
|
-
*
|
|
99
|
-
* const result = functionThatMightFail();
|
|
100
|
-
*
|
|
101
|
-
* const hello = result.map((val) => val.slice(0, 5));
|
|
102
|
-
*
|
|
103
|
-
* console.log(hello.unwrap()); // "Hello"
|
|
104
|
-
* ```
|
|
105
|
-
*/
|
|
106
|
-
map(fn) {
|
|
107
|
-
return this.match(
|
|
108
|
-
(val) => Ok(fn(val)),
|
|
109
|
-
(err) => Err(err)
|
|
110
|
-
);
|
|
111
|
-
}
|
|
112
|
-
/** In the `Ok` case returns the mapped value using the function else returns `defaultVal`
|
|
113
|
-
*
|
|
114
|
-
* @param defaultVal Value to be returned when `Err`
|
|
115
|
-
* @param fn Mapping function to map in case of `Ok`
|
|
116
|
-
* @returns
|
|
117
|
-
*
|
|
118
|
-
* ## Usage
|
|
119
|
-
*
|
|
120
|
-
* ```ts
|
|
121
|
-
* result.mapOr(1, (val) => val.length);
|
|
122
|
-
* ```
|
|
123
|
-
*
|
|
124
|
-
* ## Examples
|
|
125
|
-
*
|
|
126
|
-
* ### When `Ok`
|
|
127
|
-
*
|
|
128
|
-
* ```ts
|
|
129
|
-
* const functionThatMightFail = (): Result<string, string> => Ok("foo");
|
|
130
|
-
*
|
|
131
|
-
* const result = functionThatMightFail();
|
|
132
|
-
*
|
|
133
|
-
* const length = result.mapOr(1, (val) => val.length);
|
|
134
|
-
*
|
|
135
|
-
* console.log(length); // 3
|
|
136
|
-
* ```
|
|
137
|
-
*
|
|
138
|
-
* ### When `Err`
|
|
139
|
-
*
|
|
140
|
-
* ```ts
|
|
141
|
-
* const functionThatMightFail = (): Result<string, string> => Err("oops!");
|
|
142
|
-
*
|
|
143
|
-
* const result = functionThatMightFail();
|
|
144
|
-
*
|
|
145
|
-
* const length = result.mapOr(1, (val) => val.length);
|
|
146
|
-
*
|
|
147
|
-
* console.log(length); // 1
|
|
148
|
-
* ```
|
|
149
|
-
*/
|
|
150
|
-
mapOr(defaultVal, fn) {
|
|
151
|
-
return this.match(
|
|
152
|
-
(val) => fn(val),
|
|
153
|
-
(_) => defaultVal
|
|
154
|
-
);
|
|
155
|
-
}
|
|
156
|
-
/** In the `Ok` case returns the mapped value using `fn` else returns value of `def`
|
|
157
|
-
*
|
|
158
|
-
* @param def Mapping function called when `Err`
|
|
159
|
-
* @param fn Mapping function called when `Ok`
|
|
160
|
-
* @returns
|
|
161
|
-
*
|
|
162
|
-
* ## Usage
|
|
163
|
-
*
|
|
164
|
-
* ```ts
|
|
165
|
-
* result.mapOrElse(() => 1, (val) => val.length);
|
|
166
|
-
* ```
|
|
167
|
-
*
|
|
168
|
-
* ## Examples
|
|
169
|
-
*
|
|
170
|
-
* ### When `Ok`
|
|
171
|
-
*
|
|
172
|
-
* ```ts
|
|
173
|
-
* const functionThatMightFail = (): Result<string, string> => Ok("foo");
|
|
174
|
-
*
|
|
175
|
-
* const result = functionThatMightFail();
|
|
176
|
-
*
|
|
177
|
-
* const length = result.mapOrElse(() => 1, (val) => val.length);
|
|
178
|
-
*
|
|
179
|
-
* console.log(length); // 3
|
|
180
|
-
* ```
|
|
181
|
-
*
|
|
182
|
-
* ### When `Err`
|
|
183
|
-
*
|
|
184
|
-
* ```ts
|
|
185
|
-
* const functionThatMightFail = (): Result<string, string> => Err("oops!");
|
|
186
|
-
*
|
|
187
|
-
* const result = functionThatMightFail();
|
|
188
|
-
*
|
|
189
|
-
* const length = result.mapOr(() => 1, (val) => val.length);
|
|
190
|
-
*
|
|
191
|
-
* console.log(length); // 1
|
|
192
|
-
* ```
|
|
193
|
-
*/
|
|
194
|
-
mapOrElse(def, fn) {
|
|
195
|
-
return this.match(
|
|
196
|
-
(val) => fn(val),
|
|
197
|
-
(err) => def(err)
|
|
198
|
-
);
|
|
199
|
-
}
|
|
200
|
-
/** Maps `Result<T, E>` to `Result<T, A>` using the passed mapping function
|
|
201
|
-
*
|
|
202
|
-
* @param fn Mapping function
|
|
203
|
-
* @returns
|
|
204
|
-
*
|
|
205
|
-
* ## Usage
|
|
206
|
-
*
|
|
207
|
-
* ```ts
|
|
208
|
-
* result.mapErr((err) => getCodeMsg(err));
|
|
209
|
-
* ```
|
|
210
|
-
*
|
|
211
|
-
* ## Examples
|
|
212
|
-
*
|
|
213
|
-
* ```ts
|
|
214
|
-
* const functionThatMightFail = (): Result<string, string> => Err(10);
|
|
215
|
-
*
|
|
216
|
-
* const result = functionThatMightFail();
|
|
217
|
-
*
|
|
218
|
-
* const message = result.mapErr(() => "Error");
|
|
219
|
-
*
|
|
220
|
-
* console.log(message); // "Error"
|
|
221
|
-
* ```
|
|
222
|
-
*/
|
|
223
|
-
mapErr(fn) {
|
|
224
|
-
return this.match(
|
|
225
|
-
(val) => Ok(val),
|
|
226
|
-
(err) => Err(fn(err))
|
|
227
|
-
);
|
|
228
|
-
}
|
|
229
|
-
/** In the `Err` case returns the mapped value using the function else returns `defaultVal`
|
|
230
|
-
*
|
|
231
|
-
* @param defaultVal Value to be returned when `Ok`
|
|
232
|
-
* @param fn Mapping function to map in case of `Err`
|
|
233
|
-
* @returns
|
|
234
|
-
*
|
|
235
|
-
* ## Usage
|
|
236
|
-
*
|
|
237
|
-
* ```ts
|
|
238
|
-
* result.mapErrOr("Should've been error", (err) => getCodeMsg(err));
|
|
239
|
-
* ```
|
|
240
|
-
*
|
|
241
|
-
* ## Examples
|
|
242
|
-
*
|
|
243
|
-
* ### When `Ok`
|
|
244
|
-
*
|
|
245
|
-
* ```ts
|
|
246
|
-
* const functionThatMightFail = (): Result<string, string> => Ok("foo");
|
|
247
|
-
*
|
|
248
|
-
* const result = functionThatMightFail();
|
|
249
|
-
*
|
|
250
|
-
* const message = result.mapErrOr("Should've been error", () => "Error");
|
|
251
|
-
*
|
|
252
|
-
* console.log(message); // "Should've been error"
|
|
253
|
-
* ```
|
|
254
|
-
*
|
|
255
|
-
* ### When `Err`
|
|
256
|
-
*
|
|
257
|
-
* ```ts
|
|
258
|
-
* const functionThatMightFail = (): Result<string, string> => Err(10);
|
|
259
|
-
*
|
|
260
|
-
* const result = functionThatMightFail();
|
|
261
|
-
*
|
|
262
|
-
* const message = result.mapErrOr("Should've been error", () => "Error");
|
|
263
|
-
*
|
|
264
|
-
* console.log(message); // "Error"
|
|
265
|
-
* ```
|
|
266
|
-
*/
|
|
267
|
-
mapErrOr(defaultVal, fn) {
|
|
268
|
-
return this.match(
|
|
269
|
-
(_) => defaultVal,
|
|
270
|
-
(err) => fn(err)
|
|
271
|
-
);
|
|
272
|
-
}
|
|
273
|
-
/** In the `Err` case returns the mapped value using the function else returns value of `def`
|
|
274
|
-
*
|
|
275
|
-
* @param def Mapping function called when `Ok`
|
|
276
|
-
* @param fn Mapping function called when `Err`
|
|
277
|
-
* @returns
|
|
278
|
-
*
|
|
279
|
-
* ## Usage
|
|
280
|
-
*
|
|
281
|
-
* ```ts
|
|
282
|
-
* result.mapErrOrElse(() => "Value", (_) => "Error!");
|
|
283
|
-
* ```
|
|
284
|
-
*
|
|
285
|
-
* ## Examples
|
|
286
|
-
*
|
|
287
|
-
* ### When `Ok`
|
|
288
|
-
*
|
|
289
|
-
* ```ts
|
|
290
|
-
* const functionThatMightFail = (): Result<string, string> => Ok("foo");
|
|
291
|
-
*
|
|
292
|
-
* const result = functionThatMightFail();
|
|
293
|
-
*
|
|
294
|
-
* const length = result.mapErrOrElse(() => 1, (val) => val.length);
|
|
295
|
-
*
|
|
296
|
-
* console.log(length); // 1
|
|
297
|
-
* ```
|
|
298
|
-
*
|
|
299
|
-
* ### When `Err`
|
|
300
|
-
*
|
|
301
|
-
* ```ts
|
|
302
|
-
* const functionThatMightFail = (): Result<string, string> => Err("oops!");
|
|
303
|
-
*
|
|
304
|
-
* const result = functionThatMightFail();
|
|
305
|
-
*
|
|
306
|
-
* const length = result.mapOr(() => 1, (val) => val.length);
|
|
307
|
-
*
|
|
308
|
-
* console.log(length); // 4
|
|
309
|
-
* ```
|
|
310
|
-
*/
|
|
311
|
-
mapErrOrElse(def, fn) {
|
|
312
|
-
return this.match(
|
|
313
|
-
(val) => def(val),
|
|
314
|
-
(err) => fn(err)
|
|
315
|
-
);
|
|
316
|
-
}
|
|
317
|
-
/** Returns true if result is `Ok`
|
|
318
|
-
*
|
|
319
|
-
* @returns
|
|
320
|
-
*
|
|
321
|
-
* ## Usage
|
|
322
|
-
*
|
|
323
|
-
* ```ts
|
|
324
|
-
* result.isOk();
|
|
325
|
-
* ```
|
|
326
|
-
*/
|
|
327
|
-
isOk() {
|
|
328
|
-
return this.match(
|
|
329
|
-
() => true,
|
|
330
|
-
() => false
|
|
331
|
-
);
|
|
332
|
-
}
|
|
333
|
-
/** Returns true if result is `Err`
|
|
334
|
-
*
|
|
335
|
-
* @returns
|
|
336
|
-
*
|
|
337
|
-
* ## Usage
|
|
338
|
-
*
|
|
339
|
-
* ```ts
|
|
340
|
-
* result.isErr();
|
|
341
|
-
* ```
|
|
342
|
-
*/
|
|
343
|
-
isErr() {
|
|
344
|
-
return this.match(
|
|
345
|
-
() => false,
|
|
346
|
-
() => true
|
|
347
|
-
);
|
|
348
|
-
}
|
|
349
|
-
/** Tries to return value if value is `Err` throws generic error message.
|
|
350
|
-
*
|
|
351
|
-
* @returns
|
|
352
|
-
*
|
|
353
|
-
* ## Usage
|
|
354
|
-
*
|
|
355
|
-
* ```ts
|
|
356
|
-
* result.unwrap();
|
|
357
|
-
* ```
|
|
358
|
-
*
|
|
359
|
-
* ## Examples
|
|
360
|
-
*
|
|
361
|
-
* ### When `Ok`
|
|
362
|
-
*
|
|
363
|
-
* ```ts
|
|
364
|
-
* const functionThatMightFail = (): Result<string, string> => Ok("Hello!");
|
|
365
|
-
*
|
|
366
|
-
* const result = functionThatMightFail();
|
|
367
|
-
*
|
|
368
|
-
* console.log(result.unwrap()); // "Hello!"
|
|
369
|
-
* ```
|
|
370
|
-
*
|
|
371
|
-
* ### When `Err`
|
|
372
|
-
*
|
|
373
|
-
* ```ts
|
|
374
|
-
* const functionThatMightFail = (): Result<string, string> => Err("oops!");
|
|
375
|
-
*
|
|
376
|
-
* const result = functionThatMightFail();
|
|
377
|
-
*
|
|
378
|
-
* result.unwrap(); // Error: Attempted to call `.unwrap()` on a non `Ok` value.
|
|
379
|
-
* ```
|
|
380
|
-
*/
|
|
381
|
-
unwrap() {
|
|
382
|
-
return this.match(
|
|
383
|
-
(val) => val,
|
|
384
|
-
() => {
|
|
385
|
-
throw new Error("Attempted to call `.unwrap()` on a non `Ok` value.");
|
|
386
|
-
}
|
|
387
|
-
);
|
|
388
|
-
}
|
|
389
|
-
/** Tries to return err if value is `Ok` throws generic error message.
|
|
390
|
-
*
|
|
391
|
-
* @returns
|
|
392
|
-
*
|
|
393
|
-
* ## Usage
|
|
394
|
-
*
|
|
395
|
-
* ```ts
|
|
396
|
-
* result.unwrapErr();
|
|
397
|
-
* ```
|
|
398
|
-
*
|
|
399
|
-
* ## Examples
|
|
400
|
-
*
|
|
401
|
-
* ### When `Ok`
|
|
402
|
-
*
|
|
403
|
-
* ```ts
|
|
404
|
-
* const functionThatMightFail = (): Result<string, string> => Ok("Hello!");
|
|
405
|
-
*
|
|
406
|
-
* const result = functionThatMightFail();
|
|
407
|
-
*
|
|
408
|
-
* result.unwrapErr(); // Error: Attempted to call `.unwrapErr()` on a non `Err` value.
|
|
409
|
-
* ```
|
|
410
|
-
*
|
|
411
|
-
* ### When `Err`
|
|
412
|
-
*
|
|
413
|
-
* ```ts
|
|
414
|
-
* const functionThatMightFail = (): Result<string, string> => Err("oops!");
|
|
415
|
-
*
|
|
416
|
-
* const result = functionThatMightFail();
|
|
417
|
-
*
|
|
418
|
-
* console.log(result.unwrapErr()); // "oops!"
|
|
419
|
-
* ```
|
|
420
|
-
*/
|
|
421
|
-
unwrapErr() {
|
|
422
|
-
return this.match(
|
|
423
|
-
() => {
|
|
424
|
-
throw new Error("Attempted to call `.unwrapErr()` on a non `Err` value.");
|
|
425
|
-
},
|
|
426
|
-
(err) => err
|
|
427
|
-
);
|
|
428
|
-
}
|
|
429
|
-
/** Tries to unwrap the value if value is `Err` returns `defaultVal`
|
|
430
|
-
*
|
|
431
|
-
* @param defaultVal Value to be returned if `Err`
|
|
432
|
-
* @returns
|
|
433
|
-
*
|
|
434
|
-
* ## Usage
|
|
435
|
-
*
|
|
436
|
-
* ```ts
|
|
437
|
-
* result.unwrapOr(7);
|
|
438
|
-
* ```
|
|
439
|
-
*
|
|
440
|
-
* ## Examples
|
|
441
|
-
*
|
|
442
|
-
* ### When `Ok`
|
|
443
|
-
*
|
|
444
|
-
* ```ts
|
|
445
|
-
* const functionThatMightFail = (): Result<string, string> => Ok("Hello!");
|
|
446
|
-
*
|
|
447
|
-
* const result = functionThatMightFail();
|
|
448
|
-
*
|
|
449
|
-
* console.log(result.unwrapOr("Yellow!")); // "Hello!"
|
|
450
|
-
* ```
|
|
451
|
-
*
|
|
452
|
-
* ### When `Err`
|
|
453
|
-
*
|
|
454
|
-
* ```ts
|
|
455
|
-
* const functionThatMightFail = (): Result<string, string> => Err("oops!");
|
|
456
|
-
*
|
|
457
|
-
* const result = functionThatMightFail();
|
|
458
|
-
*
|
|
459
|
-
* console.log(result.unwrapOr("Yellow!")); // "Yellow!"
|
|
460
|
-
* ```
|
|
461
|
-
*/
|
|
462
|
-
unwrapOr(defaultVal) {
|
|
463
|
-
return this.match(
|
|
464
|
-
(val) => val,
|
|
465
|
-
(_) => defaultVal
|
|
466
|
-
);
|
|
467
|
-
}
|
|
468
|
-
/** Tries to unwrap the error if vale is `Ok` returns `defaultVal`
|
|
469
|
-
*
|
|
470
|
-
* @param defaultVal
|
|
471
|
-
* @returns
|
|
472
|
-
*
|
|
473
|
-
* ## Usage
|
|
474
|
-
*
|
|
475
|
-
* ```ts
|
|
476
|
-
* result.unwrapErrOr("Error");
|
|
477
|
-
* ```
|
|
478
|
-
*
|
|
479
|
-
* ## Examples
|
|
480
|
-
*
|
|
481
|
-
* ### When `Ok`
|
|
482
|
-
*
|
|
483
|
-
* ```ts
|
|
484
|
-
* const functionThatMightFail = (): Result<string, string> => Ok("Hello!");
|
|
485
|
-
*
|
|
486
|
-
* const result = functionThatMightFail();
|
|
487
|
-
*
|
|
488
|
-
* console.log(result.unwrapErrOr("Yellow!")); // "Yellow!"
|
|
489
|
-
* ```
|
|
490
|
-
*
|
|
491
|
-
* ### When `Err`
|
|
492
|
-
*
|
|
493
|
-
* ```ts
|
|
494
|
-
* const functionThatMightFail = (): Result<string, string> => Err("oops!");
|
|
495
|
-
*
|
|
496
|
-
* const result = functionThatMightFail();
|
|
497
|
-
*
|
|
498
|
-
* console.log(result.unwrapErrOr("Yellow!")); // "oops!"
|
|
499
|
-
* ```
|
|
500
|
-
*/
|
|
501
|
-
unwrapErrOr(defaultVal) {
|
|
502
|
-
return this.match(
|
|
503
|
-
() => defaultVal,
|
|
504
|
-
(err) => err
|
|
505
|
-
);
|
|
506
|
-
}
|
|
507
|
-
/** Tries to return the value if value is `Err` calls `fn`
|
|
508
|
-
*
|
|
509
|
-
* @param fn Function called if `Err`
|
|
510
|
-
*
|
|
511
|
-
* ## Usage
|
|
512
|
-
*
|
|
513
|
-
* ```ts
|
|
514
|
-
* result.unwrapOrElse(() => "Hello!");
|
|
515
|
-
* ```
|
|
516
|
-
*
|
|
517
|
-
* ## Examples
|
|
518
|
-
*
|
|
519
|
-
* ### When `Ok`
|
|
520
|
-
*
|
|
521
|
-
* ```ts
|
|
522
|
-
* const functionThatMightFail = (): Result<string, string> => Ok("Hello!");
|
|
523
|
-
*
|
|
524
|
-
* const result = functionThatMightFail();
|
|
525
|
-
*
|
|
526
|
-
* console.log(result.unwrapOrElse(() => "oops!")); // "Hello!"
|
|
527
|
-
* ```
|
|
528
|
-
*
|
|
529
|
-
* ### When `Err`
|
|
530
|
-
*
|
|
531
|
-
* ```ts
|
|
532
|
-
* const functionThatMightFail = (): Result<string, string> => Err("oops!");
|
|
533
|
-
*
|
|
534
|
-
* const result = functionThatMightFail();
|
|
535
|
-
*
|
|
536
|
-
* console.log(result.unwrapOrElse(() => "Hello!")); // "Hello!"
|
|
537
|
-
* ```
|
|
538
|
-
*
|
|
539
|
-
*/
|
|
540
|
-
unwrapOrElse(fn) {
|
|
541
|
-
return this.match(
|
|
542
|
-
(val) => val,
|
|
543
|
-
(err) => fn(err)
|
|
544
|
-
);
|
|
545
|
-
}
|
|
546
|
-
/** Tries to return the error if value is `Ok` calls `fn`
|
|
547
|
-
*
|
|
548
|
-
* @param fn Function called if `Ok`
|
|
549
|
-
*
|
|
550
|
-
* ## Usage
|
|
551
|
-
*
|
|
552
|
-
* ```ts
|
|
553
|
-
* result.unwrapErrOrElse(() => "Error!");
|
|
554
|
-
* ```
|
|
555
|
-
*
|
|
556
|
-
* ## Examples
|
|
557
|
-
*
|
|
558
|
-
* ### When `Ok`
|
|
559
|
-
*
|
|
560
|
-
* ```ts
|
|
561
|
-
* const functionThatMightFail = (): Result<string, string> => Ok("Hello!");
|
|
562
|
-
*
|
|
563
|
-
* const result = functionThatMightFail();
|
|
564
|
-
*
|
|
565
|
-
* console.log(result.unwrapErrOrElse(() => "oops!")); // "oops!"
|
|
566
|
-
* ```
|
|
567
|
-
*
|
|
568
|
-
* ### When `Err`
|
|
569
|
-
*
|
|
570
|
-
* ```ts
|
|
571
|
-
* const functionThatMightFail = (): Result<string, string> => Err("oops!");
|
|
572
|
-
*
|
|
573
|
-
* const result = functionThatMightFail();
|
|
574
|
-
*
|
|
575
|
-
* console.log(result.unwrapErrOrElse(() => "Hello!")); // "oops!"
|
|
576
|
-
* ```
|
|
577
|
-
*
|
|
578
|
-
*/
|
|
579
|
-
unwrapErrOrElse(fn) {
|
|
580
|
-
return this.match(
|
|
581
|
-
(val) => fn(val),
|
|
582
|
-
(err) => err
|
|
583
|
-
);
|
|
584
|
-
}
|
|
585
|
-
/** Tries to return value if value is `Err` throws custom error message.
|
|
586
|
-
*
|
|
587
|
-
* @param message Message to show when value is `Err`
|
|
588
|
-
* @returns
|
|
589
|
-
*
|
|
590
|
-
* ## Usage
|
|
591
|
-
*
|
|
592
|
-
* ```ts
|
|
593
|
-
* result.expect("Custom message");
|
|
594
|
-
* ```
|
|
595
|
-
*
|
|
596
|
-
* ## Examples
|
|
597
|
-
*
|
|
598
|
-
* ### When `Ok`
|
|
599
|
-
*
|
|
600
|
-
* ```ts
|
|
601
|
-
* const functionThatMightFail = (): Result<string, string> => Ok("Hello!");
|
|
602
|
-
*
|
|
603
|
-
* const result = functionThatMightFail();
|
|
604
|
-
*
|
|
605
|
-
* console.log(result.expect("I failed!")); // "Hello!"
|
|
606
|
-
* ```
|
|
607
|
-
*
|
|
608
|
-
* ### When `Err`
|
|
609
|
-
*
|
|
610
|
-
* ```ts
|
|
611
|
-
* const functionThatMightFail = (): Result<string, string> => Err("oops!");
|
|
612
|
-
*
|
|
613
|
-
* const result = functionThatMightFail();
|
|
614
|
-
*
|
|
615
|
-
* result.expect("I failed!"); // Error: I failed!
|
|
616
|
-
* ```
|
|
617
|
-
*/
|
|
618
|
-
expect(message) {
|
|
619
|
-
return this.match(
|
|
620
|
-
(val) => val,
|
|
621
|
-
() => {
|
|
622
|
-
throw new Error(message);
|
|
623
|
-
}
|
|
624
|
-
);
|
|
625
|
-
}
|
|
626
|
-
/** Tries to return error value if value is `Ok` throws custom error message
|
|
627
|
-
*
|
|
628
|
-
* @param message
|
|
629
|
-
* @returns
|
|
630
|
-
*
|
|
631
|
-
* ## Usage
|
|
632
|
-
*
|
|
633
|
-
* ```ts
|
|
634
|
-
* result.expectErr("Custom message");
|
|
635
|
-
* ```
|
|
636
|
-
*
|
|
637
|
-
* ## Examples
|
|
638
|
-
*
|
|
639
|
-
* ### When `Ok`
|
|
640
|
-
*
|
|
641
|
-
* ```ts
|
|
642
|
-
* const functionThatMightFail = (): Result<string, string> => Ok("Hello!");
|
|
643
|
-
*
|
|
644
|
-
* const result = functionThatMightFail();
|
|
645
|
-
*
|
|
646
|
-
* console.log(result.expectErr("I failed!")); // Error: I failed!
|
|
647
|
-
* ```
|
|
648
|
-
*
|
|
649
|
-
* ### When `Err`
|
|
650
|
-
*
|
|
651
|
-
* ```ts
|
|
652
|
-
* const functionThatMightFail = (): Result<string, string> => Err("oops!");
|
|
653
|
-
*
|
|
654
|
-
* const result = functionThatMightFail();
|
|
655
|
-
*
|
|
656
|
-
* console.log(result.expectErr("I failed!")); // "oops!"
|
|
657
|
-
* ```
|
|
658
|
-
*/
|
|
659
|
-
expectErr(message) {
|
|
660
|
-
return this.match(
|
|
661
|
-
() => {
|
|
662
|
-
throw new Error(message);
|
|
663
|
-
},
|
|
664
|
-
(err) => err
|
|
665
|
-
);
|
|
666
|
-
}
|
|
667
|
-
};
|
|
668
|
-
var Ok = (val) => {
|
|
669
|
-
return new Result({ ok: true, val });
|
|
670
|
-
};
|
|
671
|
-
var Err = (err) => {
|
|
672
|
-
return new Result({ ok: false, err });
|
|
673
|
-
};
|
|
674
|
-
|
|
675
|
-
// src/utils/blocks/utils/map-to-array.ts
|
|
676
|
-
var mapToArray = (map, fn) => {
|
|
677
|
-
const items = [];
|
|
678
|
-
for (const [key, value] of map) {
|
|
679
|
-
items.push(fn(key, value));
|
|
680
|
-
}
|
|
681
|
-
return items;
|
|
682
|
-
};
|
|
683
|
-
|
|
684
|
-
// src/utils/git-providers.ts
|
|
685
|
-
import color4 from "chalk";
|
|
686
|
-
import fetch from "node-fetch";
|
|
687
|
-
import { Octokit } from "octokit";
|
|
688
|
-
import * as v3 from "valibot";
|
|
689
|
-
|
|
690
|
-
// src/utils/build.ts
|
|
691
|
-
import fs3 from "node:fs";
|
|
692
|
-
import color3 from "chalk";
|
|
693
|
-
import { program } from "commander";
|
|
694
|
-
import path3 from "pathe";
|
|
695
|
-
import * as v2 from "valibot";
|
|
696
|
-
|
|
697
|
-
// src/utils/language-support.ts
|
|
698
|
-
import fs2 from "node:fs";
|
|
699
|
-
import { builtinModules } from "node:module";
|
|
700
|
-
import { Biome, Distribution } from "@biomejs/js-api";
|
|
701
|
-
import * as v from "@vue/compiler-sfc";
|
|
702
|
-
import color2 from "chalk";
|
|
703
|
-
import { walk } from "estree-walker";
|
|
704
|
-
import path2 from "pathe";
|
|
705
|
-
import * as prettier from "prettier";
|
|
706
|
-
import * as sv from "svelte/compiler";
|
|
707
|
-
import { Project } from "ts-morph";
|
|
708
|
-
import validatePackageName from "validate-npm-package-name";
|
|
709
|
-
|
|
710
|
-
// src/utils/blocks/utils/lines.ts
|
|
711
|
-
import os from "node:os";
|
|
712
|
-
|
|
713
|
-
// src/utils/blocks/utils/strip-ansi.ts
|
|
714
|
-
import ansiRegex from "ansi-regex";
|
|
715
|
-
var stripAsni = (str) => str.replace(ansiRegex(), "");
|
|
716
|
-
|
|
717
|
-
// src/utils/blocks/utils/pad.ts
|
|
718
|
-
var leftPadMin = (str, length, padWith = " ") => {
|
|
719
|
-
if (stripAsni(str).length > length)
|
|
720
|
-
throw new Error("String length is greater than the length provided.");
|
|
721
|
-
return padWith.repeat(length - stripAsni(str).length) + str;
|
|
722
|
-
};
|
|
723
|
-
var rightPad = (str, space, padWith = " ") => {
|
|
724
|
-
return str + padWith.repeat(space);
|
|
725
|
-
};
|
|
726
|
-
var rightPadMin = (str, length, padWith = " ") => {
|
|
727
|
-
if (stripAsni(str).length > length)
|
|
728
|
-
throw new Error("String length is greater than the length provided.");
|
|
729
|
-
return str + padWith.repeat(length - stripAsni(str).length);
|
|
730
|
-
};
|
|
731
|
-
|
|
732
|
-
// src/utils/blocks/utils/lines.ts
|
|
733
|
-
var NEW_LINE_REGEX = /\n|\r\n/g;
|
|
734
|
-
var get = (str) => str.split(NEW_LINE_REGEX);
|
|
735
|
-
var join = (lines, { lineNumbers = false, prefix } = {}) => {
|
|
736
|
-
let transformed = lines;
|
|
737
|
-
if (lineNumbers) {
|
|
738
|
-
const length = lines.length.toString().length + 1;
|
|
739
|
-
transformed = transformed.map((line, i) => `${leftPadMin(`${i + 1}`, length)} ${line}`);
|
|
740
|
-
}
|
|
741
|
-
if (prefix !== void 0) {
|
|
742
|
-
transformed = transformed.map((line, i) => `${prefix(i, lines.length)}${line}`);
|
|
743
|
-
}
|
|
744
|
-
return transformed.join(os.EOL);
|
|
745
|
-
};
|
|
746
|
-
|
|
747
|
-
// src/utils/package.ts
|
|
748
|
-
import fs from "node:fs";
|
|
749
|
-
import path from "pathe";
|
|
750
|
-
var findNearestPackageJson = (startDir, until) => {
|
|
751
|
-
const packagePath = path.join(startDir, "package.json");
|
|
752
|
-
if (fs.existsSync(packagePath)) return packagePath;
|
|
753
|
-
if (startDir === until) return void 0;
|
|
754
|
-
const segments = startDir.split(/[\/\\]/);
|
|
755
|
-
return findNearestPackageJson(segments.slice(0, segments.length - 1).join("/"), until);
|
|
756
|
-
};
|
|
757
|
-
var getPackage = (path14) => {
|
|
758
|
-
if (!fs.existsSync(path14)) return Err(`${path14} doesn't exist`);
|
|
759
|
-
const contents = fs.readFileSync(path14).toString();
|
|
760
|
-
return Ok(JSON.parse(contents));
|
|
761
|
-
};
|
|
762
|
-
var returnShouldInstall = (dependencies, devDependencies, { cwd }) => {
|
|
763
|
-
const tempDeps = dependencies;
|
|
764
|
-
const tempDevDeps = devDependencies;
|
|
765
|
-
const packageResult = getPackage(path.join(cwd, "package.json"));
|
|
766
|
-
if (!packageResult.isErr()) {
|
|
767
|
-
const pkg = packageResult.unwrap();
|
|
768
|
-
if (pkg.dependencies) {
|
|
769
|
-
for (const dep of tempDeps) {
|
|
770
|
-
const [name2, version2] = dep.split("@");
|
|
771
|
-
const foundDep = pkg.dependencies[name2];
|
|
772
|
-
if (version2 === void 0 && foundDep) continue;
|
|
773
|
-
if (foundDep && foundDep === version2) {
|
|
774
|
-
tempDeps.delete(dep);
|
|
775
|
-
}
|
|
776
|
-
}
|
|
777
|
-
}
|
|
778
|
-
if (pkg.devDependencies) {
|
|
779
|
-
for (const dep of tempDevDeps) {
|
|
780
|
-
const [name2, version2] = dep.split("@");
|
|
781
|
-
const foundDep = pkg.devDependencies[name2];
|
|
782
|
-
if (version2 === void 0 && foundDep) continue;
|
|
783
|
-
if (foundDep && foundDep === version2) {
|
|
784
|
-
tempDevDeps.delete(dep);
|
|
785
|
-
}
|
|
786
|
-
}
|
|
787
|
-
}
|
|
788
|
-
}
|
|
789
|
-
return { dependencies: tempDeps, devDependencies: tempDevDeps };
|
|
790
|
-
};
|
|
791
|
-
|
|
792
|
-
// src/utils/parse-package-name.ts
|
|
793
|
-
var RE_SCOPED = /^(@[^\/]+\/[^@\/]+)(?:@([^\/]+))?(\/.*)?$/;
|
|
794
|
-
var RE_NON_SCOPED = /^([^@\/]+)(?:@([^\/]+))?(\/.*)?$/;
|
|
795
|
-
var parsePackageName = (input) => {
|
|
796
|
-
const m = RE_SCOPED.exec(input) || RE_NON_SCOPED.exec(input);
|
|
797
|
-
if (!m) return Err(`invalid package name: ${input}`);
|
|
798
|
-
return Ok({
|
|
799
|
-
name: m[1] || "",
|
|
800
|
-
version: m[2] || "latest",
|
|
801
|
-
path: m[3] || ""
|
|
802
|
-
});
|
|
803
|
-
};
|
|
804
|
-
|
|
805
|
-
// src/utils/language-support.ts
|
|
806
|
-
var typescript = {
|
|
807
|
-
matches: (fileName) => fileName.endsWith(".ts") || fileName.endsWith(".js") || fileName.endsWith(".tsx") || fileName.endsWith(".jsx"),
|
|
808
|
-
resolveDependencies: ({ filePath, isSubDir, excludeDeps }) => {
|
|
809
|
-
const project = new Project();
|
|
810
|
-
const blockFile = project.addSourceFileAtPath(filePath);
|
|
811
|
-
const imports = blockFile.getImportDeclarations();
|
|
812
|
-
const relativeImports = imports.filter(
|
|
813
|
-
(declaration) => declaration.getModuleSpecifierValue().startsWith(".")
|
|
814
|
-
);
|
|
815
|
-
const localDeps = /* @__PURE__ */ new Set();
|
|
816
|
-
for (const relativeImport of relativeImports) {
|
|
817
|
-
const mod = relativeImport.getModuleSpecifierValue();
|
|
818
|
-
const localDep = resolveLocalImport(mod, isSubDir, { filePath });
|
|
819
|
-
if (localDep.isErr()) return Err(localDep.unwrapErr());
|
|
820
|
-
if (localDep.unwrap()) localDeps.add(localDep.unwrap());
|
|
821
|
-
}
|
|
822
|
-
const deps = imports.filter((declaration) => !declaration.getModuleSpecifierValue().startsWith(".")).map((declaration) => declaration.getModuleSpecifierValue());
|
|
823
|
-
const { devDependencies, dependencies } = resolveRemoteDeps(
|
|
824
|
-
Array.from(deps),
|
|
825
|
-
filePath,
|
|
826
|
-
excludeDeps
|
|
827
|
-
);
|
|
828
|
-
return Ok({
|
|
829
|
-
local: Array.from(localDeps),
|
|
830
|
-
dependencies,
|
|
831
|
-
devDependencies
|
|
832
|
-
});
|
|
833
|
-
},
|
|
834
|
-
comment: (content) => `/*
|
|
835
|
-
${join(get(content), { prefix: () => " " })}
|
|
836
|
-
*/`,
|
|
837
|
-
format: async (code, { formatter, filePath, prettierOptions, biomeOptions }) => {
|
|
838
|
-
if (!formatter) return code;
|
|
839
|
-
if (formatter === "prettier") {
|
|
840
|
-
return await prettier.format(code, { filepath: filePath, ...prettierOptions });
|
|
841
|
-
}
|
|
842
|
-
const biome = await Biome.create({
|
|
843
|
-
distribution: Distribution.NODE
|
|
844
|
-
});
|
|
845
|
-
if (biomeOptions) {
|
|
846
|
-
biome.applyConfiguration(biomeOptions);
|
|
847
|
-
}
|
|
848
|
-
return biome.formatContent(code, { filePath }).content;
|
|
849
|
-
}
|
|
850
|
-
};
|
|
851
|
-
var svelte = {
|
|
852
|
-
matches: (fileName) => fileName.endsWith(".svelte"),
|
|
853
|
-
resolveDependencies: ({ filePath, isSubDir, excludeDeps }) => {
|
|
854
|
-
const sourceCode = fs2.readFileSync(filePath).toString();
|
|
855
|
-
const root = sv.parse(sourceCode, { modern: true, filename: filePath });
|
|
856
|
-
if (!root.instance) return Ok({ dependencies: [], devDependencies: [], local: [] });
|
|
857
|
-
const localDeps = /* @__PURE__ */ new Set();
|
|
858
|
-
const deps = /* @__PURE__ */ new Set();
|
|
859
|
-
walk(root.instance, {
|
|
860
|
-
enter: (node) => {
|
|
861
|
-
if (node.type === "ImportDeclaration") {
|
|
862
|
-
if (typeof node.source.value === "string") {
|
|
863
|
-
if (node.source.value.startsWith(".")) {
|
|
864
|
-
const localDep = resolveLocalImport(node.source.value, isSubDir, {
|
|
865
|
-
filePath
|
|
866
|
-
});
|
|
867
|
-
if (localDep.isErr()) return Err(localDep.unwrapErr());
|
|
868
|
-
if (localDep.unwrap()) localDeps.add(localDep.unwrap());
|
|
869
|
-
} else {
|
|
870
|
-
deps.add(node.source.value);
|
|
871
|
-
}
|
|
872
|
-
}
|
|
873
|
-
}
|
|
874
|
-
}
|
|
875
|
-
});
|
|
876
|
-
const { devDependencies, dependencies } = resolveRemoteDeps(Array.from(deps), filePath, [
|
|
877
|
-
"svelte",
|
|
878
|
-
...excludeDeps
|
|
879
|
-
]);
|
|
880
|
-
return Ok({
|
|
881
|
-
dependencies,
|
|
882
|
-
devDependencies,
|
|
883
|
-
local: Array.from(localDeps)
|
|
884
|
-
});
|
|
885
|
-
},
|
|
886
|
-
comment: (content) => `<!--
|
|
887
|
-
${join(get(content), { prefix: () => " " })}
|
|
888
|
-
-->`,
|
|
889
|
-
format: async (code, { formatter, filePath, prettierOptions }) => {
|
|
890
|
-
if (!formatter) return code;
|
|
891
|
-
if (formatter === "prettier" && prettierOptions && prettierOptions.plugins?.find((plugin) => plugin === "prettier-plugin-svelte")) {
|
|
892
|
-
return await prettier.format(code, { filepath: filePath, ...prettierOptions });
|
|
893
|
-
}
|
|
894
|
-
return code;
|
|
895
|
-
}
|
|
896
|
-
};
|
|
897
|
-
var vue = {
|
|
898
|
-
matches: (fileName) => fileName.endsWith(".vue"),
|
|
899
|
-
resolveDependencies: ({ filePath, isSubDir, excludeDeps }) => {
|
|
900
|
-
const sourceCode = fs2.readFileSync(filePath).toString();
|
|
901
|
-
const parsed = v.parse(sourceCode, { filename: filePath });
|
|
902
|
-
if (!parsed.descriptor.script?.content && !parsed.descriptor.scriptSetup?.content)
|
|
903
|
-
return Ok({ dependencies: [], devDependencies: [], local: [] });
|
|
904
|
-
const localDeps = /* @__PURE__ */ new Set();
|
|
905
|
-
const deps = /* @__PURE__ */ new Set();
|
|
906
|
-
let compiled;
|
|
907
|
-
try {
|
|
908
|
-
compiled = v.compileScript(parsed.descriptor, { id: "shut-it" });
|
|
909
|
-
} catch (err) {
|
|
910
|
-
return Err(`Compile error: ${err}`);
|
|
911
|
-
}
|
|
912
|
-
if (!compiled.imports) return Ok({ dependencies: [], devDependencies: [], local: [] });
|
|
913
|
-
const imports = Object.values(compiled.imports);
|
|
914
|
-
for (const imp of imports) {
|
|
915
|
-
if (imp.source.startsWith(".")) {
|
|
916
|
-
const localDep = resolveLocalImport(imp.source, isSubDir, {
|
|
917
|
-
filePath
|
|
918
|
-
});
|
|
919
|
-
if (localDep.isErr()) return Err(localDep.unwrapErr());
|
|
920
|
-
if (localDep.unwrap()) localDeps.add(localDep.unwrap());
|
|
921
|
-
} else {
|
|
922
|
-
deps.add(imp.source);
|
|
923
|
-
}
|
|
924
|
-
}
|
|
925
|
-
const { devDependencies, dependencies } = resolveRemoteDeps(Array.from(deps), filePath, [
|
|
926
|
-
"vue",
|
|
927
|
-
...excludeDeps
|
|
928
|
-
]);
|
|
929
|
-
return Ok({
|
|
930
|
-
dependencies,
|
|
931
|
-
devDependencies,
|
|
932
|
-
local: Array.from(localDeps)
|
|
933
|
-
});
|
|
934
|
-
},
|
|
935
|
-
comment: (content) => `<!--
|
|
936
|
-
${join(get(content), { prefix: () => " " })}
|
|
937
|
-
-->`,
|
|
938
|
-
format: async (code, { formatter, prettierOptions }) => {
|
|
939
|
-
if (!formatter) return code;
|
|
940
|
-
if (formatter === "prettier") {
|
|
941
|
-
return await prettier.format(code, { parser: "vue", ...prettierOptions });
|
|
942
|
-
}
|
|
943
|
-
return code;
|
|
944
|
-
}
|
|
945
|
-
};
|
|
946
|
-
var yaml = {
|
|
947
|
-
matches: (fileName) => fileName.endsWith(".yml") || fileName.endsWith(".yaml"),
|
|
948
|
-
resolveDependencies: () => Ok({ dependencies: [], local: [], devDependencies: [] }),
|
|
949
|
-
comment: (content) => join(get(content), { prefix: () => "# " }),
|
|
950
|
-
format: async (code, { formatter, prettierOptions }) => {
|
|
951
|
-
if (!formatter) return code;
|
|
952
|
-
if (formatter === "prettier") {
|
|
953
|
-
return await prettier.format(code, { parser: "yaml", ...prettierOptions });
|
|
954
|
-
}
|
|
955
|
-
return code;
|
|
956
|
-
}
|
|
957
|
-
};
|
|
958
|
-
var resolveLocalImport = (mod, isSubDir, { filePath }) => {
|
|
959
|
-
if (isSubDir && (mod.startsWith("./") || mod === ".")) return Ok(void 0);
|
|
960
|
-
const categoryDir = isSubDir ? path2.join(filePath, "../../") : path2.join(filePath, "../");
|
|
961
|
-
const modPath = path2.join(path2.join(filePath, "../"), mod);
|
|
962
|
-
const fullDir = path2.join(categoryDir, "../");
|
|
963
|
-
if (modPath.startsWith(fullDir)) {
|
|
964
|
-
let [category, block] = modPath.slice(fullDir.length).split("/");
|
|
965
|
-
if (block.includes(".")) {
|
|
966
|
-
block = block.slice(0, block.length - path2.parse(block).ext.length);
|
|
967
|
-
}
|
|
968
|
-
return Ok(`${category}/${block}`);
|
|
969
|
-
}
|
|
970
|
-
return Err(
|
|
971
|
-
`${filePath}:
|
|
972
|
-
${mod} references code not contained in ${categoryDir} and cannot be resolved.`
|
|
973
|
-
);
|
|
974
|
-
};
|
|
975
|
-
var resolveRemoteDeps = (deps, filePath, doNotInstall = []) => {
|
|
976
|
-
const exemptDeps = new Set(doNotInstall);
|
|
977
|
-
const filteredDeps = deps.filter(
|
|
978
|
-
(dep) => !builtinModules.includes(dep) && !dep.startsWith("node:")
|
|
979
|
-
);
|
|
980
|
-
const pkgPath = findNearestPackageJson(path2.dirname(filePath), "");
|
|
981
|
-
const dependencies = /* @__PURE__ */ new Set();
|
|
982
|
-
const devDependencies = /* @__PURE__ */ new Set();
|
|
983
|
-
if (pkgPath) {
|
|
984
|
-
const { devDependencies: packageDevDependencies, dependencies: packageDependencies } = JSON.parse(fs2.readFileSync(pkgPath, "utf-8"));
|
|
985
|
-
for (const dep of filteredDeps) {
|
|
986
|
-
const parsed = parsePackageName(dep);
|
|
987
|
-
if (parsed.isErr()) {
|
|
988
|
-
console.warn(
|
|
989
|
-
`${WARN} Skipped adding import \`${color2.cyan(dep)}\`. Reason: Couldn't parse package name`
|
|
990
|
-
);
|
|
991
|
-
continue;
|
|
992
|
-
}
|
|
993
|
-
const depInfo = parsed.unwrap();
|
|
994
|
-
if (!validatePackageName(depInfo.name).validForNewPackages) {
|
|
995
|
-
console.warn(
|
|
996
|
-
`${WARN} Skipped adding import \`${color2.cyan(dep)}\`. Reason: Not a valid package name`
|
|
997
|
-
);
|
|
998
|
-
continue;
|
|
999
|
-
}
|
|
1000
|
-
if (exemptDeps.has(depInfo.name)) continue;
|
|
1001
|
-
let version2 = void 0;
|
|
1002
|
-
if (packageDependencies !== void 0) {
|
|
1003
|
-
version2 = packageDependencies[depInfo.name];
|
|
1004
|
-
}
|
|
1005
|
-
if (version2 !== void 0) {
|
|
1006
|
-
dependencies.add(`${depInfo.name}@${version2}`);
|
|
1007
|
-
continue;
|
|
1008
|
-
}
|
|
1009
|
-
if (packageDevDependencies !== void 0) {
|
|
1010
|
-
version2 = packageDevDependencies[depInfo.name];
|
|
1011
|
-
}
|
|
1012
|
-
if (version2 !== void 0) {
|
|
1013
|
-
devDependencies.add(`${depInfo.name}@${version2}`);
|
|
1014
|
-
continue;
|
|
1015
|
-
}
|
|
1016
|
-
dependencies.add(depInfo.name);
|
|
1017
|
-
}
|
|
1018
|
-
}
|
|
1019
|
-
return {
|
|
1020
|
-
dependencies: Array.from(dependencies),
|
|
1021
|
-
devDependencies: Array.from(devDependencies)
|
|
1022
|
-
};
|
|
1023
|
-
};
|
|
1024
|
-
var languages = [typescript, svelte, vue, yaml];
|
|
1025
|
-
|
|
1026
|
-
// src/utils/build.ts
|
|
1027
|
-
var blockSchema = v2.object({
|
|
1028
|
-
name: v2.string(),
|
|
1029
|
-
category: v2.string(),
|
|
1030
|
-
localDependencies: v2.array(v2.string()),
|
|
1031
|
-
dependencies: v2.array(v2.string()),
|
|
1032
|
-
devDependencies: v2.array(v2.string()),
|
|
1033
|
-
tests: v2.boolean(),
|
|
1034
|
-
/** Where to find the block relative to root */
|
|
1035
|
-
directory: v2.string(),
|
|
1036
|
-
subdirectory: v2.boolean(),
|
|
1037
|
-
files: v2.array(v2.string())
|
|
1038
|
-
});
|
|
1039
|
-
var categorySchema = v2.object({
|
|
1040
|
-
name: v2.string(),
|
|
1041
|
-
blocks: v2.array(blockSchema)
|
|
1042
|
-
});
|
|
1043
|
-
var TEST_SUFFIXES = [".test.ts", "_test.ts", ".test.js", "_test.js"];
|
|
1044
|
-
var isTestFile = (file) => TEST_SUFFIXES.find((suffix) => file.endsWith(suffix)) !== void 0;
|
|
1045
|
-
var buildBlocksDirectory = (blocksPath, { cwd, excludeDeps, includeBlocks, includeCategories, errorOnWarn }) => {
|
|
1046
|
-
let paths;
|
|
1047
|
-
try {
|
|
1048
|
-
paths = fs3.readdirSync(blocksPath);
|
|
1049
|
-
} catch {
|
|
1050
|
-
program.error(color3.red(`Couldn't read the ${color3.bold(blocksPath)} directory.`));
|
|
1051
|
-
}
|
|
1052
|
-
const categories = [];
|
|
1053
|
-
for (const categoryPath of paths) {
|
|
1054
|
-
const categoryDir = path3.join(blocksPath, categoryPath);
|
|
1055
|
-
if (fs3.statSync(categoryDir).isFile()) continue;
|
|
1056
|
-
const categoryName = path3.basename(categoryPath);
|
|
1057
|
-
if (includeCategories.length > 0 && includeCategories.find((val) => val.trim() === categoryName.trim()) === void 0)
|
|
1058
|
-
continue;
|
|
1059
|
-
const category = {
|
|
1060
|
-
name: categoryName,
|
|
1061
|
-
blocks: []
|
|
1062
|
-
};
|
|
1063
|
-
const files = fs3.readdirSync(categoryDir);
|
|
1064
|
-
for (const file of files) {
|
|
1065
|
-
const blockDir = path3.join(categoryDir, file);
|
|
1066
|
-
if (fs3.statSync(blockDir).isFile()) {
|
|
1067
|
-
if (isTestFile(file)) continue;
|
|
1068
|
-
const name2 = path3.parse(path3.basename(file)).name;
|
|
1069
|
-
if (includeBlocks.length > 0 && includeBlocks.find((val) => val.trim() === name2.trim()) === void 0)
|
|
1070
|
-
continue;
|
|
1071
|
-
const lang = languages.find((resolver) => resolver.matches(file));
|
|
1072
|
-
if (!lang) {
|
|
1073
|
-
const error = "files are not currently supported!";
|
|
1074
|
-
if (errorOnWarn) {
|
|
1075
|
-
program.error(
|
|
1076
|
-
color3.red(
|
|
1077
|
-
`Couldn't add \`${color3.bold(blockDir)}\` \`*${color3.bold(
|
|
1078
|
-
path3.parse(file).ext
|
|
1079
|
-
)}\` ${error}`
|
|
1080
|
-
)
|
|
1081
|
-
);
|
|
1082
|
-
} else {
|
|
1083
|
-
console.warn(
|
|
1084
|
-
`${VERTICAL_LINE} ${WARN} Skipped \`${color3.bold(blockDir)}\` \`*${color3.bold(
|
|
1085
|
-
path3.parse(file).ext
|
|
1086
|
-
)}\` ${error}`
|
|
1087
|
-
);
|
|
1088
|
-
}
|
|
1089
|
-
continue;
|
|
1090
|
-
}
|
|
1091
|
-
const testsPath = files.find(
|
|
1092
|
-
(f) => TEST_SUFFIXES.find((suffix) => f === `${name2}${suffix}`)
|
|
1093
|
-
);
|
|
1094
|
-
const { dependencies, devDependencies, local } = lang.resolveDependencies({
|
|
1095
|
-
filePath: blockDir,
|
|
1096
|
-
isSubDir: false,
|
|
1097
|
-
excludeDeps,
|
|
1098
|
-
cwd
|
|
1099
|
-
}).match(
|
|
1100
|
-
(val) => val,
|
|
1101
|
-
(err) => {
|
|
1102
|
-
program.error(color3.red(err));
|
|
1103
|
-
}
|
|
1104
|
-
);
|
|
1105
|
-
const block = {
|
|
1106
|
-
name: name2,
|
|
1107
|
-
directory: path3.relative(cwd, categoryDir),
|
|
1108
|
-
category: categoryName,
|
|
1109
|
-
tests: testsPath !== void 0,
|
|
1110
|
-
subdirectory: false,
|
|
1111
|
-
files: [file],
|
|
1112
|
-
localDependencies: local,
|
|
1113
|
-
dependencies,
|
|
1114
|
-
devDependencies
|
|
1115
|
-
};
|
|
1116
|
-
if (testsPath !== void 0) {
|
|
1117
|
-
block.files.push(testsPath);
|
|
1118
|
-
}
|
|
1119
|
-
category.blocks.push(block);
|
|
1120
|
-
} else {
|
|
1121
|
-
const blockName = file;
|
|
1122
|
-
if (includeBlocks.length > 0 && includeBlocks.find((val) => val.trim() === blockName.trim()) === void 0)
|
|
1123
|
-
continue;
|
|
1124
|
-
const blockFiles = fs3.readdirSync(blockDir);
|
|
1125
|
-
const hasTests = blockFiles.findIndex((f) => isTestFile(f)) !== -1;
|
|
1126
|
-
const localDepsSet = /* @__PURE__ */ new Set();
|
|
1127
|
-
const depsSet = /* @__PURE__ */ new Set();
|
|
1128
|
-
const devDepsSet = /* @__PURE__ */ new Set();
|
|
1129
|
-
for (const f of blockFiles) {
|
|
1130
|
-
if (isTestFile(f)) continue;
|
|
1131
|
-
if (fs3.statSync(path3.join(blockDir, f)).isDirectory()) {
|
|
1132
|
-
const error = "subdirectories are not currently supported!";
|
|
1133
|
-
if (errorOnWarn) {
|
|
1134
|
-
program.error(
|
|
1135
|
-
color3.red(
|
|
1136
|
-
`Couldn't add \`${color3.bold(path3.join(blockDir, f))}\` ${error}`
|
|
1137
|
-
)
|
|
1138
|
-
);
|
|
1139
|
-
} else {
|
|
1140
|
-
console.warn(
|
|
1141
|
-
`${VERTICAL_LINE} ${WARN} Skipped \`${color3.bold(path3.join(blockDir, f))}\` ${error}`
|
|
1142
|
-
);
|
|
1143
|
-
}
|
|
1144
|
-
continue;
|
|
1145
|
-
}
|
|
1146
|
-
const lang = languages.find((resolver) => resolver.matches(f));
|
|
1147
|
-
if (!lang) {
|
|
1148
|
-
const error = "files are not currently supported!";
|
|
1149
|
-
if (errorOnWarn) {
|
|
1150
|
-
program.error(
|
|
1151
|
-
color3.red(
|
|
1152
|
-
`Couldn't add \`${color3.bold(path3.join(blockDir, f))}\` \`*${color3.bold(
|
|
1153
|
-
path3.parse(f).ext
|
|
1154
|
-
)}\` ${error}`
|
|
1155
|
-
)
|
|
1156
|
-
);
|
|
1157
|
-
} else {
|
|
1158
|
-
console.warn(
|
|
1159
|
-
`${VERTICAL_LINE} ${WARN} Skipped \`${path3.join(blockDir, f)}\` \`*${color3.bold(
|
|
1160
|
-
path3.parse(f).ext
|
|
1161
|
-
)}\` ${error}`
|
|
1162
|
-
);
|
|
1163
|
-
}
|
|
1164
|
-
continue;
|
|
1165
|
-
}
|
|
1166
|
-
const { local, dependencies, devDependencies } = lang.resolveDependencies({
|
|
1167
|
-
filePath: path3.join(blockDir, f),
|
|
1168
|
-
isSubDir: true,
|
|
1169
|
-
excludeDeps,
|
|
1170
|
-
cwd
|
|
1171
|
-
}).match(
|
|
1172
|
-
(val) => val,
|
|
1173
|
-
(err) => {
|
|
1174
|
-
program.error(color3.red(err));
|
|
1175
|
-
}
|
|
1176
|
-
);
|
|
1177
|
-
for (const dep of local) {
|
|
1178
|
-
localDepsSet.add(dep);
|
|
1179
|
-
}
|
|
1180
|
-
for (const dep of dependencies) {
|
|
1181
|
-
depsSet.add(dep);
|
|
1182
|
-
}
|
|
1183
|
-
for (const dep of devDependencies) {
|
|
1184
|
-
devDepsSet.add(dep);
|
|
1185
|
-
}
|
|
1186
|
-
}
|
|
1187
|
-
const block = {
|
|
1188
|
-
name: blockName,
|
|
1189
|
-
directory: path3.relative(cwd, blockDir),
|
|
1190
|
-
category: categoryName,
|
|
1191
|
-
tests: hasTests,
|
|
1192
|
-
subdirectory: true,
|
|
1193
|
-
files: [...blockFiles],
|
|
1194
|
-
localDependencies: Array.from(localDepsSet.keys()),
|
|
1195
|
-
dependencies: Array.from(depsSet.keys()),
|
|
1196
|
-
devDependencies: Array.from(devDepsSet.keys())
|
|
1197
|
-
};
|
|
1198
|
-
category.blocks.push(block);
|
|
1199
|
-
}
|
|
1200
|
-
}
|
|
1201
|
-
categories.push(category);
|
|
1202
|
-
}
|
|
1203
|
-
return categories;
|
|
1204
|
-
};
|
|
1205
|
-
|
|
1206
|
-
// src/utils/context.ts
|
|
1207
|
-
var OUTPUT_FILE = "jsrepo-manifest.json";
|
|
1208
|
-
|
|
1209
|
-
// src/utils/persisted.ts
|
|
1210
|
-
import Conf from "conf";
|
|
1211
|
-
var get2 = () => {
|
|
1212
|
-
return new Conf({ projectName: "jsrepo" });
|
|
1213
|
-
};
|
|
1214
|
-
|
|
1215
|
-
// src/utils/git-providers.ts
|
|
1216
|
-
var rawErrorMessage = (info, filePath, defaultBranch) => {
|
|
1217
|
-
return Err(
|
|
1218
|
-
`There was an error fetching the \`${color4.bold(filePath)}\` from ${color4.bold(info.url)}.
|
|
1219
|
-
|
|
1220
|
-
${color4.bold("This may be for one of the following reasons:")}
|
|
1221
|
-
1. The \`${color4.bold(filePath)}\` or containing repository doesn't exist
|
|
1222
|
-
2. Your repository path is incorrect (wrong branch, wrong tag) default branches other than \`${color4.bold(defaultBranch)}\` must be specified \`${color4.bold("github/<owner>/<name>/tree/<branch>")}\`
|
|
2
|
+
import Ne from'node:fs';import {fileURLToPath}from'node:url';import {Command,program,Option,Argument}from'commander';import J from'pathe';import {outro,spinner,confirm,isCancel,cancel,multiselect,text,select,password,intro}from'@clack/prompts';import I from'chalk';import {resolveCommand}from'package-manager-detector/commands';import {detect}from'package-manager-detector/detect';import*as B from'valibot';import xt from'node-fetch';import {Octokit}from'octokit';import {builtinModules}from'node:module';import {Biome,Distribution}from'@biomejs/js-api';import*as st from'@vue/compiler-sfc';import {walk}from'estree-walker';import*as Xe from'prettier';import*as Qt from'svelte/compiler';import {Project}from'ts-morph';import Fr from'validate-npm-package-name';import Ir from'node:os';import xr from'ansi-regex';import Mr from'conf';import {execa}from'execa';import {detect as detect$1,resolveCommand as resolveCommand$1}from'package-manager-detector';import {diffLines,diffChars}from'diff';var N=I.gray("\u2502"),yt=I.gray("\u2500"),Ut=I.gray("\u2510"),zt=I.gray("\u2518"),vt=I.gray("\u251C");I.gray("\u250C");I.gray("\u2514");var ie=I.bgRgb(245,149,66).white("WARN"),Le=I.bgBlueBright.white("INFO"),fe=I.hex("#f7df1e")("jsrepo");var nt=class{_result;constructor(e){this._result=e;}match(e,r){return this._result.ok?e(this._result.val):r(this._result.err)}map(e){return this.match(r=>O(e(r)),r=>P(r))}mapOr(e,r){return this.match(o=>r(o),o=>e)}mapOrElse(e,r){return this.match(o=>r(o),o=>e(o))}mapErr(e){return this.match(r=>O(r),r=>P(e(r)))}mapErrOr(e,r){return this.match(o=>e,o=>r(o))}mapErrOrElse(e,r){return this.match(o=>e(o),o=>r(o))}isOk(){return this.match(()=>!0,()=>!1)}isErr(){return this.match(()=>!1,()=>!0)}unwrap(){return this.match(e=>e,()=>{throw new Error("Attempted to call `.unwrap()` on a non `Ok` value.")})}unwrapErr(){return this.match(()=>{throw new Error("Attempted to call `.unwrapErr()` on a non `Err` value.")},e=>e)}unwrapOr(e){return this.match(r=>r,r=>e)}unwrapErrOr(e){return this.match(()=>e,r=>r)}unwrapOrElse(e){return this.match(r=>r,r=>e(r))}unwrapErrOrElse(e){return this.match(r=>e(r),r=>r)}expect(e){return this.match(r=>r,()=>{throw new Error(e)})}expectErr(e){return this.match(()=>{throw new Error(e)},r=>r)}},O=t=>new nt({ok:!0,val:t}),P=t=>new nt({ok:!1,err:t});var Gt=(t,e)=>{let r=[];for(let[o,n]of t)r.push(e(o,n));return r};var xe=t=>t.replace(xr(),"");var qe=(t,e,r=" ")=>{if(xe(t).length>e)throw new Error("String length is greater than the length provided.");return r.repeat(e-xe(t).length)+t},Ht=(t,e,r=" ")=>t+r.repeat(e),Kt=(t,e,r=" ")=>{if(xe(t).length>e)throw new Error("String length is greater than the length provided.");return t+r.repeat(e-xe(t).length)};var Er=/\n|\r\n/g,se=t=>t.split(Er),Q=(t,{lineNumbers:e=!1,prefix:r}={})=>{let o=t;if(e){let n=t.length.toString().length+1;o=o.map((i,s)=>`${qe(`${s+1}`,n)} ${i}`);}return r!==void 0&&(o=o.map((n,i)=>`${r(i,t.length)}${n}`)),o.join(Ir.EOL)};var $t=(t,e)=>{let r=J.join(t,"package.json");if(Ne.existsSync(r))return r;if(t===e)return;let o=t.split(/[\/\\]/);return $t(o.slice(0,o.length-1).join("/"),e)},Sr=t=>{if(!Ne.existsSync(t))return P(`${t} doesn't exist`);let e=Ne.readFileSync(t).toString();return O(JSON.parse(e))},it=(t,e,{cwd:r})=>{let o=t,n=e,i=Sr(J.join(r,"package.json"));if(!i.isErr()){let s=i.unwrap();if(s.dependencies)for(let a of o){let[d,h]=a.split("@"),f=s.dependencies[d];h===void 0&&f||f&&f===h&&o.delete(a);}if(s.devDependencies)for(let a of n){let[d,h]=a.split("@"),f=s.devDependencies[d];h===void 0&&f||f&&f===h&&n.delete(a);}}return {dependencies:o,devDependencies:n}};var jr=/^(@[^\/]+\/[^@\/]+)(?:@([^\/]+))?(\/.*)?$/,Tr=/^([^@\/]+)(?:@([^\/]+))?(\/.*)?$/,Xt=t=>{let e=jr.exec(t)||Tr.exec(t);return e?O({name:e[1]||"",version:e[2]||"latest",path:e[3]||""}):P(`invalid package name: ${t}`)};var Br={matches:t=>t.endsWith(".ts")||t.endsWith(".js")||t.endsWith(".tsx")||t.endsWith(".jsx"),resolveDependencies:({filePath:t,isSubDir:e,excludeDeps:r})=>{let i=new Project().addSourceFileAtPath(t).getImportDeclarations(),s=i.filter($=>$.getModuleSpecifierValue().startsWith(".")),a=new Set;for(let $ of s){let v=$.getModuleSpecifierValue(),m=kt(v,e,{filePath:t});if(m.isErr())return P(m.unwrapErr());m.unwrap()&&a.add(m.unwrap());}let d=i.filter($=>!$.getModuleSpecifierValue().startsWith(".")).map($=>$.getModuleSpecifierValue()),{devDependencies:h,dependencies:f}=Rt(Array.from(d),t,r);return O({local:Array.from(a),dependencies:f,devDependencies:h})},comment:t=>`/*
|
|
3
|
+
${Q(se(t),{prefix:()=>" "})}
|
|
4
|
+
*/`,format:async(t,{formatter:e,filePath:r,prettierOptions:o,biomeOptions:n})=>{if(!e)return t;if(e==="prettier")return await Xe.format(t,{filepath:r,...o});let i=await Biome.create({distribution:Distribution.NODE});return n&&i.applyConfiguration(n),i.formatContent(t,{filePath:r}).content}},Lr={matches:t=>t.endsWith(".svelte"),resolveDependencies:({filePath:t,isSubDir:e,excludeDeps:r})=>{let o=Ne.readFileSync(t).toString(),n=Qt.parse(o,{modern:!0,filename:t});if(!n.instance)return O({dependencies:[],devDependencies:[],local:[]});let i=new Set,s=new Set;walk(n.instance,{enter:h=>{if(h.type==="ImportDeclaration"&&typeof h.source.value=="string")if(h.source.value.startsWith(".")){let f=kt(h.source.value,e,{filePath:t});if(f.isErr())return P(f.unwrapErr());f.unwrap()&&i.add(f.unwrap());}else s.add(h.source.value);}});let{devDependencies:a,dependencies:d}=Rt(Array.from(s),t,["svelte",...r]);return O({dependencies:d,devDependencies:a,local:Array.from(i)})},comment:t=>`<!--
|
|
5
|
+
${Q(se(t),{prefix:()=>" "})}
|
|
6
|
+
-->`,format:async(t,{formatter:e,filePath:r,prettierOptions:o})=>e&&e==="prettier"&&o&&o.plugins?.find(n=>n==="prettier-plugin-svelte")?await Xe.format(t,{filepath:r,...o}):t},_r={matches:t=>t.endsWith(".vue"),resolveDependencies:({filePath:t,isSubDir:e,excludeDeps:r})=>{let o=Ne.readFileSync(t).toString(),n=st.parse(o,{filename:t});if(!n.descriptor.script?.content&&!n.descriptor.scriptSetup?.content)return O({dependencies:[],devDependencies:[],local:[]});let i=new Set,s=new Set,a;try{a=st.compileScript(n.descriptor,{id:"shut-it"});}catch($){return P(`Compile error: ${$}`)}if(!a.imports)return O({dependencies:[],devDependencies:[],local:[]});let d=Object.values(a.imports);for(let $ of d)if($.source.startsWith(".")){let v=kt($.source,e,{filePath:t});if(v.isErr())return P(v.unwrapErr());v.unwrap()&&i.add(v.unwrap());}else s.add($.source);let{devDependencies:h,dependencies:f}=Rt(Array.from(s),t,["vue",...r]);return O({dependencies:f,devDependencies:h,local:Array.from(i)})},comment:t=>`<!--
|
|
7
|
+
${Q(se(t),{prefix:()=>" "})}
|
|
8
|
+
-->`,format:async(t,{formatter:e,prettierOptions:r})=>e&&e==="prettier"?await Xe.format(t,{parser:"vue",...r}):t},Wr={matches:t=>t.endsWith(".yml")||t.endsWith(".yaml"),resolveDependencies:()=>O({dependencies:[],local:[],devDependencies:[]}),comment:t=>Q(se(t),{prefix:()=>"# "}),format:async(t,{formatter:e,prettierOptions:r})=>e&&e==="prettier"?await Xe.format(t,{parser:"yaml",...r}):t},kt=(t,e,{filePath:r})=>{if(e&&(t.startsWith("./")||t==="."))return O(void 0);let o=e?J.join(r,"../../"):J.join(r,"../"),n=J.join(J.join(r,"../"),t),i=J.join(o,"../");if(n.startsWith(i)){let[s,a]=n.slice(i.length).split("/");return a.includes(".")&&(a=a.slice(0,a.length-J.parse(a).ext.length)),O(`${s}/${a}`)}return P(`${r}:
|
|
9
|
+
${t} references code not contained in ${o} and cannot be resolved.`)},Rt=(t,e,r=[])=>{let o=new Set(r),n=t.filter(d=>!builtinModules.includes(d)&&!d.startsWith("node:")),i=$t(J.dirname(e),""),s=new Set,a=new Set;if(i){let{devDependencies:d,dependencies:h}=JSON.parse(Ne.readFileSync(i,"utf-8"));for(let f of n){let $=Xt(f);if($.isErr()){console.warn(`${ie} Skipped adding import \`${I.cyan(f)}\`. Reason: Couldn't parse package name`);continue}let v=$.unwrap();if(!Fr(v.name).validForNewPackages){console.warn(`${ie} Skipped adding import \`${I.cyan(f)}\`. Reason: Not a valid package name`);continue}if(o.has(v.name))continue;let m;if(h!==void 0&&(m=h[v.name]),m!==void 0){s.add(`${v.name}@${m}`);continue}if(d!==void 0&&(m=d[v.name]),m!==void 0){a.add(`${v.name}@${m}`);continue}s.add(v.name);}}return {dependencies:Array.from(s),devDependencies:Array.from(a)}},he=[Br,Lr,_r,Wr];var Vr=B.object({name:B.string(),category:B.string(),localDependencies:B.array(B.string()),dependencies:B.array(B.string()),devDependencies:B.array(B.string()),tests:B.boolean(),directory:B.string(),subdirectory:B.boolean(),files:B.array(B.string())}),at=B.object({name:B.string(),blocks:B.array(Vr)}),er=[".test.ts","_test.ts",".test.js","_test.js"],ae=t=>er.find(e=>t.endsWith(e))!==void 0,tr=(t,{cwd:e,excludeDeps:r,includeBlocks:o,includeCategories:n,errorOnWarn:i})=>{let s;try{s=Ne.readdirSync(t);}catch{program.error(I.red(`Couldn't read the ${I.bold(t)} directory.`));}let a=[];for(let d of s){let h=J.join(t,d);if(Ne.statSync(h).isFile())continue;let f=J.basename(d);if(n.length>0&&n.find(m=>m.trim()===f.trim())===void 0)continue;let $={name:f,blocks:[]},v=Ne.readdirSync(h);for(let m of v){let b=J.join(h,m);if(Ne.statSync(b).isFile()){if(ae(m))continue;let S=J.parse(J.basename(m)).name;if(o.length>0&&o.find(c=>c.trim()===S.trim())===void 0)continue;let j=he.find(c=>c.matches(m));if(!j){let c="files are not currently supported!";i?program.error(I.red(`Couldn't add \`${I.bold(b)}\` \`*${I.bold(J.parse(m).ext)}\` ${c}`)):console.warn(`${N} ${ie} Skipped \`${I.bold(b)}\` \`*${I.bold(J.parse(m).ext)}\` ${c}`);continue}let T=v.find(c=>er.find(y=>c===`${S}${y}`)),{dependencies:w,devDependencies:g,local:l}=j.resolveDependencies({filePath:b,isSubDir:!1,excludeDeps:r,cwd:e}).match(c=>c,c=>{program.error(I.red(c));}),p={name:S,directory:J.relative(e,h),category:f,tests:T!==void 0,subdirectory:!1,files:[m],localDependencies:l,dependencies:w,devDependencies:g};T!==void 0&&p.files.push(T),$.blocks.push(p);}else {let S=m;if(o.length>0&&o.find(c=>c.trim()===S.trim())===void 0)continue;let j=Ne.readdirSync(b),T=j.findIndex(c=>ae(c))!==-1,w=new Set,g=new Set,l=new Set;for(let c of j){if(ae(c))continue;if(Ne.statSync(J.join(b,c)).isDirectory()){let k="subdirectories are not currently supported!";i?program.error(I.red(`Couldn't add \`${I.bold(J.join(b,c))}\` ${k}`)):console.warn(`${N} ${ie} Skipped \`${I.bold(J.join(b,c))}\` ${k}`);continue}let y=he.find(k=>k.matches(c));if(!y){let k="files are not currently supported!";i?program.error(I.red(`Couldn't add \`${I.bold(J.join(b,c))}\` \`*${I.bold(J.parse(c).ext)}\` ${k}`)):console.warn(`${N} ${ie} Skipped \`${J.join(b,c)}\` \`*${I.bold(J.parse(c).ext)}\` ${k}`);continue}let{local:R,dependencies:u,devDependencies:C}=y.resolveDependencies({filePath:J.join(b,c),isSubDir:!0,excludeDeps:r,cwd:e}).match(k=>k,k=>{program.error(I.red(k));});for(let k of R)w.add(k);for(let k of u)g.add(k);for(let k of C)l.add(k);}let p={name:S,directory:J.relative(e,b),category:f,tests:T,subdirectory:!0,files:[...j],localDependencies:Array.from(w.keys()),dependencies:Array.from(g.keys()),devDependencies:Array.from(l.keys())};$.blocks.push(p);}}a.push($);}return a};var ce="jsrepo-manifest.json";var ye=()=>new Mr({projectName:"jsrepo"});var Ve=(t,e,r)=>P(`There was an error fetching the \`${I.bold(e)}\` from ${I.bold(t.url)}.
|
|
10
|
+
|
|
11
|
+
${I.bold("This may be for one of the following reasons:")}
|
|
12
|
+
1. The \`${I.bold(e)}\` or containing repository doesn't exist
|
|
13
|
+
2. Your repository path is incorrect (wrong branch, wrong tag) default branches other than \`${I.bold(r)}\` must be specified \`${I.bold("github/<owner>/<name>/tree/<branch>")}\`
|
|
1223
14
|
3. You are using an expired access token or a token that doesn't have access to this repository
|
|
1224
|
-
`
|
|
1225
|
-
|
|
1226
|
-
};
|
|
1227
|
-
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
},
|
|
1237
|
-
|
|
1238
|
-
|
|
1239
|
-
|
|
1240
|
-
|
|
1241
|
-
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1246
|
-
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1251
|
-
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1257
|
-
|
|
1258
|
-
|
|
1259
|
-
|
|
1260
|
-
|
|
1261
|
-
|
|
1262
|
-
|
|
1263
|
-
},
|
|
1264
|
-
info: async (repoPath) => {
|
|
1265
|
-
if (typeof repoPath !== "string") return repoPath;
|
|
1266
|
-
const repo = repoPath.replaceAll(/(https:\/\/github.com\/)|(github\/)/g, "");
|
|
1267
|
-
const [owner, repoName, ...rest] = repo.split("/");
|
|
1268
|
-
let ref = github.defaultBranch();
|
|
1269
|
-
const token = get2().get(`${github.name()}-token`);
|
|
1270
|
-
const octokit = new Octokit({ auth: token });
|
|
1271
|
-
if (rest[0] === "tree") {
|
|
1272
|
-
ref = rest[1];
|
|
1273
|
-
} else {
|
|
1274
|
-
try {
|
|
1275
|
-
const { data: repo2 } = await octokit.rest.repos.get({ owner, repo: repoName });
|
|
1276
|
-
ref = repo2.default_branch;
|
|
1277
|
-
} catch {
|
|
1278
|
-
}
|
|
1279
|
-
}
|
|
1280
|
-
let refs = "heads";
|
|
1281
|
-
if (ref !== github.defaultBranch()) {
|
|
1282
|
-
try {
|
|
1283
|
-
const { data: tags } = await octokit.rest.git.listMatchingRefs({
|
|
1284
|
-
owner,
|
|
1285
|
-
repo: repoName,
|
|
1286
|
-
ref: "tags"
|
|
1287
|
-
});
|
|
1288
|
-
if (tags.some((tag) => tag.ref === `refs/tags/${ref}`)) {
|
|
1289
|
-
refs = "tags";
|
|
1290
|
-
}
|
|
1291
|
-
} catch {
|
|
1292
|
-
refs = "heads";
|
|
1293
|
-
}
|
|
1294
|
-
}
|
|
1295
|
-
return {
|
|
1296
|
-
refs,
|
|
1297
|
-
url: repoPath,
|
|
1298
|
-
name: github.name(),
|
|
1299
|
-
repoName,
|
|
1300
|
-
owner,
|
|
1301
|
-
ref,
|
|
1302
|
-
provider: github
|
|
1303
|
-
};
|
|
1304
|
-
},
|
|
1305
|
-
matches: (repoPath) => repoPath.toLowerCase().startsWith("https://github.com") || repoPath.toLowerCase().startsWith("github")
|
|
1306
|
-
};
|
|
1307
|
-
var gitlab = {
|
|
1308
|
-
name: () => "gitlab",
|
|
1309
|
-
defaultBranch: () => "main",
|
|
1310
|
-
resolveRaw: async (repoPath, resourcePath) => {
|
|
1311
|
-
const info = await gitlab.info(repoPath);
|
|
1312
|
-
return new URL(
|
|
1313
|
-
`${encodeURIComponent(resourcePath)}/raw?ref=${info.ref}`,
|
|
1314
|
-
`https://gitlab.com/api/v4/projects/${encodeURIComponent(`${info.owner}/${info.repoName}`)}/repository/files/`
|
|
1315
|
-
);
|
|
1316
|
-
},
|
|
1317
|
-
fetchRaw: async (repoPath, resourcePath, { verbose } = {}) => {
|
|
1318
|
-
const info = await github.info(repoPath);
|
|
1319
|
-
const url = await gitlab.resolveRaw(info, resourcePath);
|
|
1320
|
-
verbose?.(`Trying to fetch from ${url}`);
|
|
1321
|
-
try {
|
|
1322
|
-
const token = get2().get(`${gitlab.name()}-token`);
|
|
1323
|
-
const headers = new Headers();
|
|
1324
|
-
if (token !== void 0) {
|
|
1325
|
-
headers.append("PRIVATE-TOKEN", `${token}`);
|
|
1326
|
-
}
|
|
1327
|
-
const response = await fetch(url, { headers });
|
|
1328
|
-
verbose?.(`Got a response from ${url} ${response.status} ${response.statusText}`);
|
|
1329
|
-
if (!response.ok) {
|
|
1330
|
-
return rawErrorMessage(info, resourcePath, gitlab.defaultBranch());
|
|
1331
|
-
}
|
|
1332
|
-
return Ok(await response.text());
|
|
1333
|
-
} catch {
|
|
1334
|
-
return rawErrorMessage(info, resourcePath, gitlab.defaultBranch());
|
|
1335
|
-
}
|
|
1336
|
-
},
|
|
1337
|
-
fetchManifest: async (repoPath) => {
|
|
1338
|
-
const manifest = await gitlab.fetchRaw(repoPath, OUTPUT_FILE);
|
|
1339
|
-
if (manifest.isErr()) return Err(manifest.unwrapErr());
|
|
1340
|
-
const categories = v3.parse(v3.array(categorySchema), JSON.parse(manifest.unwrap()));
|
|
1341
|
-
return Ok(categories);
|
|
1342
|
-
},
|
|
1343
|
-
info: async (repoPath) => {
|
|
1344
|
-
if (typeof repoPath !== "string") return repoPath;
|
|
1345
|
-
const repo = repoPath.replaceAll(/(https:\/\/gitlab.com\/)|(gitlab\/)/g, "");
|
|
1346
|
-
const [owner, repoName, ...rest] = repo.split("/");
|
|
1347
|
-
let ref = gitlab.defaultBranch();
|
|
1348
|
-
let refs = "heads";
|
|
1349
|
-
if (rest[0] === "-" && rest[1] === "tree") {
|
|
1350
|
-
if (rest[2].includes("?")) {
|
|
1351
|
-
const [tempRef, last] = rest[2].split("?");
|
|
1352
|
-
ref = tempRef;
|
|
1353
|
-
if (last.startsWith("ref_type=")) {
|
|
1354
|
-
if (last.slice(10) === "tags") {
|
|
1355
|
-
refs = "tags";
|
|
1356
|
-
}
|
|
1357
|
-
}
|
|
1358
|
-
} else {
|
|
1359
|
-
ref = rest[2];
|
|
1360
|
-
}
|
|
1361
|
-
}
|
|
1362
|
-
return {
|
|
1363
|
-
refs,
|
|
1364
|
-
url: repoPath,
|
|
1365
|
-
name: gitlab.name(),
|
|
1366
|
-
repoName,
|
|
1367
|
-
owner,
|
|
1368
|
-
ref,
|
|
1369
|
-
provider: gitlab
|
|
1370
|
-
};
|
|
1371
|
-
},
|
|
1372
|
-
matches: (repoPath) => repoPath.toLowerCase().startsWith("https://gitlab.com") || repoPath.toLowerCase().startsWith("gitlab")
|
|
1373
|
-
};
|
|
1374
|
-
var bitbucket = {
|
|
1375
|
-
name: () => "bitbucket",
|
|
1376
|
-
defaultBranch: () => "master",
|
|
1377
|
-
resolveRaw: async (repoPath, resourcePath) => {
|
|
1378
|
-
const info = await bitbucket.info(repoPath);
|
|
1379
|
-
return new URL(
|
|
1380
|
-
resourcePath,
|
|
1381
|
-
`https://api.bitbucket.org/2.0/repositories/${info.owner}/${info.repoName}/src/${info.ref}/`
|
|
1382
|
-
);
|
|
1383
|
-
},
|
|
1384
|
-
fetchRaw: async (repoPath, resourcePath, { verbose } = {}) => {
|
|
1385
|
-
const info = await bitbucket.info(repoPath);
|
|
1386
|
-
const url = await bitbucket.resolveRaw(info, resourcePath);
|
|
1387
|
-
verbose?.(`Trying to fetch from ${url}`);
|
|
1388
|
-
try {
|
|
1389
|
-
const token = get2().get(`${bitbucket.name()}-token`);
|
|
1390
|
-
const headers = new Headers();
|
|
1391
|
-
if (token !== void 0) {
|
|
1392
|
-
headers.append("Authorization", `Bearer ${token}`);
|
|
1393
|
-
}
|
|
1394
|
-
const response = await fetch(url, { headers });
|
|
1395
|
-
verbose?.(`Got a response from ${url} ${response.status} ${response.statusText}`);
|
|
1396
|
-
if (!response.ok) {
|
|
1397
|
-
return rawErrorMessage(info, resourcePath, bitbucket.defaultBranch());
|
|
1398
|
-
}
|
|
1399
|
-
return Ok(await response.text());
|
|
1400
|
-
} catch {
|
|
1401
|
-
return rawErrorMessage(info, resourcePath, bitbucket.defaultBranch());
|
|
1402
|
-
}
|
|
1403
|
-
},
|
|
1404
|
-
fetchManifest: async (repoPath) => {
|
|
1405
|
-
const manifest = await bitbucket.fetchRaw(repoPath, OUTPUT_FILE);
|
|
1406
|
-
if (manifest.isErr()) return Err(manifest.unwrapErr());
|
|
1407
|
-
const categories = v3.parse(v3.array(categorySchema), JSON.parse(manifest.unwrap()));
|
|
1408
|
-
return Ok(categories);
|
|
1409
|
-
},
|
|
1410
|
-
info: async (repoPath) => {
|
|
1411
|
-
if (typeof repoPath !== "string") return repoPath;
|
|
1412
|
-
const repo = repoPath.replaceAll(/(https:\/\/bitbucket.org\/)|(bitbucket\/)/g, "");
|
|
1413
|
-
const [owner, repoName, ...rest] = repo.split("/");
|
|
1414
|
-
const refs = "heads";
|
|
1415
|
-
let ref = bitbucket.defaultBranch();
|
|
1416
|
-
if (rest[0] === "src") {
|
|
1417
|
-
ref = rest[1];
|
|
1418
|
-
}
|
|
1419
|
-
return {
|
|
1420
|
-
refs,
|
|
1421
|
-
url: repoPath,
|
|
1422
|
-
name: bitbucket.name(),
|
|
1423
|
-
repoName,
|
|
1424
|
-
owner,
|
|
1425
|
-
ref,
|
|
1426
|
-
provider: bitbucket
|
|
1427
|
-
};
|
|
1428
|
-
},
|
|
1429
|
-
matches: (repoPath) => repoPath.toLowerCase().startsWith("https://bitbucket.org") || repoPath.toLowerCase().startsWith("bitbucket")
|
|
1430
|
-
};
|
|
1431
|
-
var providers = [github, gitlab, bitbucket];
|
|
1432
|
-
var getProviderInfo = async (repo) => {
|
|
1433
|
-
const provider = providers.find((provider2) => provider2.matches(repo));
|
|
1434
|
-
if (provider) {
|
|
1435
|
-
return Ok(await provider.info(repo));
|
|
1436
|
-
}
|
|
1437
|
-
return Err(
|
|
1438
|
-
`Only ${providers.map((p, i) => `${i === providers.length - 1 ? "and" : ""}${color4.cyan(p.name())}`).join(", ")} repositories are supported at this time!`
|
|
1439
|
-
);
|
|
1440
|
-
};
|
|
1441
|
-
var fetchBlocks = async (...repos) => {
|
|
1442
|
-
const blocksMap = /* @__PURE__ */ new Map();
|
|
1443
|
-
for (const repo of repos) {
|
|
1444
|
-
const getProviderResult = await getProviderInfo(repo);
|
|
1445
|
-
if (getProviderResult.isErr()) return Err({ message: getProviderResult.unwrapErr(), repo });
|
|
1446
|
-
const providerInfo = getProviderResult.unwrap();
|
|
1447
|
-
const getManifestResult = await providerInfo.provider.fetchManifest(providerInfo);
|
|
1448
|
-
if (getManifestResult.isErr()) return Err({ message: getManifestResult.unwrapErr(), repo });
|
|
1449
|
-
const categories = getManifestResult.unwrap();
|
|
1450
|
-
for (const category of categories) {
|
|
1451
|
-
for (const block of category.blocks) {
|
|
1452
|
-
blocksMap.set(
|
|
1453
|
-
`${providerInfo.name}/${providerInfo.owner}/${providerInfo.repoName}/${category.name}/${block.name}`,
|
|
1454
|
-
{
|
|
1455
|
-
...block,
|
|
1456
|
-
sourceRepo: providerInfo
|
|
1457
|
-
}
|
|
1458
|
-
);
|
|
1459
|
-
}
|
|
1460
|
-
}
|
|
1461
|
-
}
|
|
1462
|
-
return Ok(blocksMap);
|
|
1463
|
-
};
|
|
1464
|
-
|
|
1465
|
-
// src/utils/blocks.ts
|
|
1466
|
-
var resolveTree = async (blockSpecifiers, blocksMap, repoPaths) => {
|
|
1467
|
-
const blocks = /* @__PURE__ */ new Map();
|
|
1468
|
-
for (const blockSpecifier of blockSpecifiers) {
|
|
1469
|
-
let block = void 0;
|
|
1470
|
-
if (!providers.find((p) => blockSpecifier.startsWith(p.name()))) {
|
|
1471
|
-
if (repoPaths.length === 0) {
|
|
1472
|
-
return Err(
|
|
1473
|
-
color5.red(
|
|
1474
|
-
`If your config doesn't repos then you must provide the repo in the block specifier ex: \`${color5.bold(
|
|
1475
|
-
`github/<owner>/<name>/${blockSpecifier}`
|
|
1476
|
-
)}\`!`
|
|
1477
|
-
)
|
|
1478
|
-
);
|
|
1479
|
-
}
|
|
1480
|
-
for (const repo of repoPaths) {
|
|
1481
|
-
const providerInfo = (await getProviderInfo(repo)).unwrap();
|
|
1482
|
-
const tempBlock = blocksMap.get(
|
|
1483
|
-
`${providerInfo.name}/${providerInfo.owner}/${providerInfo.repoName}/${blockSpecifier}`
|
|
1484
|
-
);
|
|
1485
|
-
if (tempBlock === void 0) continue;
|
|
1486
|
-
block = tempBlock;
|
|
1487
|
-
break;
|
|
1488
|
-
}
|
|
1489
|
-
} else {
|
|
1490
|
-
const [providerName, owner, repoName, ...rest] = blockSpecifier.split("/");
|
|
1491
|
-
block = blocksMap.get(
|
|
1492
|
-
`${providerName}/${owner}/${repoName}/${rest.slice(rest.length - 2).join("/")}`
|
|
1493
|
-
);
|
|
1494
|
-
}
|
|
1495
|
-
if (!block) {
|
|
1496
|
-
return Err(`Invalid block! ${color5.bold(blockSpecifier)} does not exist!`);
|
|
1497
|
-
}
|
|
1498
|
-
const specifier = `${block.category}/${block.name}`;
|
|
1499
|
-
blocks.set(specifier, { name: block.name, subDependency: false, block });
|
|
1500
|
-
if (block.localDependencies && block.localDependencies.length > 0) {
|
|
1501
|
-
const subDeps = await resolveTree(
|
|
1502
|
-
block.localDependencies.filter((dep) => !blocks.has(dep)),
|
|
1503
|
-
blocksMap,
|
|
1504
|
-
repoPaths
|
|
1505
|
-
);
|
|
1506
|
-
if (subDeps.isErr()) return Err(subDeps.unwrapErr());
|
|
1507
|
-
for (const dep of subDeps.unwrap()) {
|
|
1508
|
-
blocks.set(dep.name, dep);
|
|
1509
|
-
}
|
|
1510
|
-
}
|
|
1511
|
-
}
|
|
1512
|
-
return Ok(mapToArray(blocks, (_, val) => val));
|
|
1513
|
-
};
|
|
1514
|
-
var getInstalled = (blocks, config, cwd) => {
|
|
1515
|
-
const installedBlocks = [];
|
|
1516
|
-
for (const [_, block] of blocks) {
|
|
1517
|
-
const baseDir = path4.join(cwd, config.path, block.category);
|
|
1518
|
-
let blockPath = path4.join(baseDir, block.files[0]);
|
|
1519
|
-
if (block.subdirectory) {
|
|
1520
|
-
blockPath = path4.join(baseDir, block.name);
|
|
1521
|
-
}
|
|
1522
|
-
if (fs4.existsSync(blockPath))
|
|
1523
|
-
installedBlocks.push({
|
|
1524
|
-
specifier: `${block.category}/${block.name}`,
|
|
1525
|
-
path: blockPath,
|
|
1526
|
-
block
|
|
1527
|
-
});
|
|
1528
|
-
}
|
|
1529
|
-
return installedBlocks;
|
|
1530
|
-
};
|
|
1531
|
-
|
|
1532
|
-
// src/utils/config.ts
|
|
1533
|
-
import fs5 from "node:fs";
|
|
1534
|
-
import path5 from "pathe";
|
|
1535
|
-
import * as v4 from "valibot";
|
|
1536
|
-
var CONFIG_NAME = "jsrepo.json";
|
|
1537
|
-
var formatterSchema = v4.union([v4.literal("prettier"), v4.literal("biome")]);
|
|
1538
|
-
var schema = v4.object({
|
|
1539
|
-
$schema: v4.string(),
|
|
1540
|
-
repos: v4.optional(v4.array(v4.string()), []),
|
|
1541
|
-
includeTests: v4.boolean(),
|
|
1542
|
-
path: v4.pipe(v4.string(), v4.minLength(1)),
|
|
1543
|
-
watermark: v4.optional(v4.boolean(), true),
|
|
1544
|
-
formatter: v4.optional(formatterSchema)
|
|
1545
|
-
});
|
|
1546
|
-
var getConfig = (cwd) => {
|
|
1547
|
-
if (!fs5.existsSync(path5.join(cwd, CONFIG_NAME))) {
|
|
1548
|
-
return Err("Could not find your configuration file! Please run `init`.");
|
|
1549
|
-
}
|
|
1550
|
-
const config = v4.safeParse(
|
|
1551
|
-
schema,
|
|
1552
|
-
JSON.parse(fs5.readFileSync(path5.join(cwd, CONFIG_NAME)).toString())
|
|
1553
|
-
);
|
|
1554
|
-
if (!config.success) {
|
|
1555
|
-
return Err(`There was an error reading your \`${CONFIG_NAME}\` file!`);
|
|
1556
|
-
}
|
|
1557
|
-
return Ok(config.output);
|
|
1558
|
-
};
|
|
1559
|
-
|
|
1560
|
-
// src/utils/dependencies.ts
|
|
1561
|
-
import color6 from "chalk";
|
|
1562
|
-
import { execa } from "execa";
|
|
1563
|
-
import { resolveCommand } from "package-manager-detector";
|
|
1564
|
-
var installDependencies = async ({
|
|
1565
|
-
pm,
|
|
1566
|
-
deps,
|
|
1567
|
-
dev,
|
|
1568
|
-
cwd
|
|
1569
|
-
}) => {
|
|
1570
|
-
let add2;
|
|
1571
|
-
if (dev) {
|
|
1572
|
-
add2 = resolveCommand(pm, "install", [...deps, "-D"]);
|
|
1573
|
-
} else {
|
|
1574
|
-
add2 = resolveCommand(pm, "install", [...deps]);
|
|
1575
|
-
}
|
|
1576
|
-
if (add2 == null) return Err(color6.red(`Could not resolve add command for '${pm}'.`));
|
|
1577
|
-
try {
|
|
1578
|
-
await execa(add2.command, [...add2.args], { cwd });
|
|
1579
|
-
return Ok(deps);
|
|
1580
|
-
} catch {
|
|
1581
|
-
return Err(
|
|
1582
|
-
color6.red(
|
|
1583
|
-
`Failed to install ${color6.bold(deps.join(", "))}! Failed while running '${color6.bold(
|
|
1584
|
-
`${add2.command} ${add2.args.join(" ")}`
|
|
1585
|
-
)}'`
|
|
1586
|
-
)
|
|
1587
|
-
);
|
|
1588
|
-
}
|
|
1589
|
-
};
|
|
1590
|
-
|
|
1591
|
-
// src/utils/format.ts
|
|
1592
|
-
import fs6 from "node:fs";
|
|
1593
|
-
import path6 from "pathe";
|
|
1594
|
-
import * as prettier2 from "prettier";
|
|
1595
|
-
var loadFormatterConfig = async ({
|
|
1596
|
-
formatter,
|
|
1597
|
-
cwd
|
|
1598
|
-
}) => {
|
|
1599
|
-
let prettierOptions = null;
|
|
1600
|
-
if (formatter === "prettier") {
|
|
1601
|
-
prettierOptions = await prettier2.resolveConfig(path6.join(cwd, ".prettierrc"));
|
|
1602
|
-
}
|
|
1603
|
-
let biomeOptions = null;
|
|
1604
|
-
if (formatter === "biome") {
|
|
1605
|
-
const configPath = path6.join(cwd, "biome.json");
|
|
1606
|
-
if (fs6.existsSync(configPath)) {
|
|
1607
|
-
biomeOptions = JSON.parse(fs6.readFileSync(configPath).toString());
|
|
1608
|
-
}
|
|
1609
|
-
}
|
|
1610
|
-
return {
|
|
1611
|
-
biomeOptions,
|
|
1612
|
-
prettierOptions
|
|
1613
|
-
};
|
|
1614
|
-
};
|
|
1615
|
-
|
|
1616
|
-
// src/utils/get-watermark.ts
|
|
1617
|
-
var getWatermark = (version2, repoUrl) => {
|
|
1618
|
-
return `jsrepo ${version2}
|
|
1619
|
-
Installed from ${repoUrl}
|
|
1620
|
-
${(/* @__PURE__ */ new Date()).toLocaleDateString().replaceAll("/", "-")}`;
|
|
1621
|
-
};
|
|
1622
|
-
|
|
1623
|
-
// src/utils/prompts.ts
|
|
1624
|
-
import { intro, spinner } from "@clack/prompts";
|
|
1625
|
-
import color7 from "chalk";
|
|
1626
|
-
var runTasks = async (tasks, { verbose = void 0 }) => {
|
|
1627
|
-
const loading = spinner();
|
|
1628
|
-
for (const task of tasks) {
|
|
1629
|
-
if (verbose) {
|
|
1630
|
-
verbose(task.loadingMessage);
|
|
1631
|
-
} else {
|
|
1632
|
-
loading.start(task.loadingMessage);
|
|
1633
|
-
}
|
|
1634
|
-
try {
|
|
1635
|
-
await task.run();
|
|
1636
|
-
} catch (err) {
|
|
1637
|
-
loading.stop(`Error while ${task.loadingMessage}`);
|
|
1638
|
-
console.error(err);
|
|
1639
|
-
}
|
|
1640
|
-
if (verbose) {
|
|
1641
|
-
verbose(task.completedMessage);
|
|
1642
|
-
} else {
|
|
1643
|
-
loading.stop(task.completedMessage);
|
|
1644
|
-
}
|
|
1645
|
-
}
|
|
1646
|
-
};
|
|
1647
|
-
var nextSteps = (steps) => {
|
|
1648
|
-
let max = 20;
|
|
1649
|
-
steps.map((val) => {
|
|
1650
|
-
const reset = rightPad(stripAsni(val), 4);
|
|
1651
|
-
if (reset.length > max) max = reset.length;
|
|
1652
|
-
});
|
|
1653
|
-
const NEXT_STEPS = "Next Steps";
|
|
1654
|
-
let result = `${VERTICAL_LINE}
|
|
1655
|
-
`;
|
|
1656
|
-
result += `${JUNCTION_RIGHT} ${NEXT_STEPS} ${HORIZONTAL_LINE.repeat(
|
|
1657
|
-
max - NEXT_STEPS.length - 1
|
|
1658
|
-
)}${TOP_RIGHT_CORNER}
|
|
1659
|
-
`;
|
|
1660
|
-
result += `${VERTICAL_LINE} ${" ".repeat(max)} ${VERTICAL_LINE}
|
|
1661
|
-
`;
|
|
1662
|
-
steps.map((step) => {
|
|
1663
|
-
result += `${VERTICAL_LINE} ${rightPadMin(step, max - 1)} ${VERTICAL_LINE}
|
|
1664
|
-
`;
|
|
1665
|
-
});
|
|
1666
|
-
result += `${VERTICAL_LINE} ${" ".repeat(max)} ${VERTICAL_LINE}
|
|
1667
|
-
`;
|
|
1668
|
-
result += `${JUNCTION_RIGHT}${HORIZONTAL_LINE.repeat(max + 2)}${BOTTOM_RIGHT_CORNER}
|
|
1669
|
-
`;
|
|
1670
|
-
return result;
|
|
1671
|
-
};
|
|
1672
|
-
var _intro = (version2) => intro(`${color7.bgHex("#f7df1e").black(" jsrepo ")}${color7.gray(` v${version2} `)}`);
|
|
1673
|
-
|
|
1674
|
-
// src/commands/add.ts
|
|
1675
|
-
var schema2 = v5.object({
|
|
1676
|
-
repo: v5.optional(v5.string()),
|
|
1677
|
-
allow: v5.boolean(),
|
|
1678
|
-
yes: v5.boolean(),
|
|
1679
|
-
verbose: v5.boolean(),
|
|
1680
|
-
cwd: v5.string()
|
|
1681
|
-
});
|
|
1682
|
-
var add = new Command("add").argument(
|
|
1683
|
-
"[blocks...]",
|
|
1684
|
-
"Names of the blocks you want to add to your project. ex: (utils/math, github/ieedan/std/utils/math)"
|
|
1685
|
-
).option("--repo <repo>", "Repository to download the blocks from.").option("-A, --allow", "Allow jsrepo to download code from the provided repo.", false).option("-y, --yes", "Skip confirmation prompt.", false).option("--verbose", "Include debug logs.", false).option("--cwd <path>", "The current working directory.", process.cwd()).action(async (blockNames, opts) => {
|
|
1686
|
-
const options = v5.parse(schema2, opts);
|
|
1687
|
-
_intro(context.package.version);
|
|
1688
|
-
await _add(blockNames, options);
|
|
1689
|
-
outro(color8.green("All done!"));
|
|
1690
|
-
});
|
|
1691
|
-
var _add = async (blockNames, options) => {
|
|
1692
|
-
const verbose = (msg) => {
|
|
1693
|
-
if (options.verbose) {
|
|
1694
|
-
console.info(`${INFO} ${msg}`);
|
|
1695
|
-
}
|
|
1696
|
-
};
|
|
1697
|
-
verbose(`Attempting to add ${JSON.stringify(blockNames)}`);
|
|
1698
|
-
const loading = spinner2();
|
|
1699
|
-
const configResult = getConfig(options.cwd);
|
|
1700
|
-
const noConfig = configResult.isErr();
|
|
1701
|
-
let config;
|
|
1702
|
-
if (configResult.isErr()) {
|
|
1703
|
-
const response = await confirm({
|
|
1704
|
-
message: `You don't have ${JSREPO} initialized in your project. Do you want to continue?`,
|
|
1705
|
-
initialValue: false
|
|
1706
|
-
});
|
|
1707
|
-
if (isCancel(response) || !response) {
|
|
1708
|
-
cancel("Canceled!");
|
|
1709
|
-
process.exit(0);
|
|
1710
|
-
}
|
|
1711
|
-
config = {
|
|
1712
|
-
$schema: "",
|
|
1713
|
-
includeTests: false,
|
|
1714
|
-
watermark: true,
|
|
1715
|
-
path: "./src/blocks",
|
|
1716
|
-
repos: []
|
|
1717
|
-
};
|
|
1718
|
-
} else {
|
|
1719
|
-
config = configResult.unwrap();
|
|
1720
|
-
}
|
|
1721
|
-
let repoPaths = config.repos;
|
|
1722
|
-
if (options.repo) repoPaths = [options.repo];
|
|
1723
|
-
for (const blockSpecifier of blockNames) {
|
|
1724
|
-
if (!providers.find((p) => blockSpecifier.startsWith(p.name()))) continue;
|
|
1725
|
-
const [providerName, owner, repoName, ...rest] = blockSpecifier.split("/");
|
|
1726
|
-
let repo;
|
|
1727
|
-
if (rest.length > 2) {
|
|
1728
|
-
repo = `${providerName}/${owner}/${repoName}/${rest.slice(0, rest.length - 2).join("/")}`;
|
|
1729
|
-
} else {
|
|
1730
|
-
repo = `${providerName}/${owner}/${repoName}`;
|
|
1731
|
-
}
|
|
1732
|
-
if (!repoPaths.find((repoPath) => repoPath === repo)) {
|
|
1733
|
-
if (!options.allow) {
|
|
1734
|
-
const result = await confirm({
|
|
1735
|
-
message: `Allow ${JSREPO} to download and run code from ${color8.cyan(repo)}?`,
|
|
1736
|
-
initialValue: true
|
|
1737
|
-
});
|
|
1738
|
-
if (isCancel(result) || !result) {
|
|
1739
|
-
cancel("Canceled!");
|
|
1740
|
-
process.exit(0);
|
|
1741
|
-
}
|
|
1742
|
-
}
|
|
1743
|
-
repoPaths.push(repo);
|
|
1744
|
-
}
|
|
1745
|
-
}
|
|
1746
|
-
if (!options.allow && options.repo) {
|
|
1747
|
-
const result = await confirm({
|
|
1748
|
-
message: `Allow ${JSREPO} to download and run code from ${color8.cyan(options.repo)}?`,
|
|
1749
|
-
initialValue: true
|
|
1750
|
-
});
|
|
1751
|
-
if (isCancel(result) || !result) {
|
|
1752
|
-
cancel("Canceled!");
|
|
1753
|
-
process.exit(0);
|
|
1754
|
-
}
|
|
1755
|
-
}
|
|
1756
|
-
if (repoPaths.length === 0) {
|
|
1757
|
-
if (noConfig) {
|
|
1758
|
-
program2.error(
|
|
1759
|
-
color8.red(
|
|
1760
|
-
`Fully quality blocks ex: (github/ieedan/std/utils/math) or provide the \`${color8.bold(
|
|
1761
|
-
"--repo"
|
|
1762
|
-
)}\` flag to specify a registry.`
|
|
1763
|
-
)
|
|
1764
|
-
);
|
|
1765
|
-
}
|
|
1766
|
-
program2.error(
|
|
1767
|
-
color8.red(
|
|
1768
|
-
`There were no repos present in your config and you didn't provide the \`${color8.bold(
|
|
1769
|
-
"--repo"
|
|
1770
|
-
)}\` flag with a repo.`
|
|
1771
|
-
)
|
|
1772
|
-
);
|
|
1773
|
-
}
|
|
1774
|
-
verbose(`Fetching blocks from ${color8.cyan(repoPaths.join(", "))}`);
|
|
1775
|
-
if (!options.verbose) loading.start(`Fetching blocks from ${color8.cyan(repoPaths.join(", "))}`);
|
|
1776
|
-
const blocksMap = (await fetchBlocks(...repoPaths)).match(
|
|
1777
|
-
(val) => val,
|
|
1778
|
-
({ repo, message }) => {
|
|
1779
|
-
loading.stop(`Failed fetching blocks from ${color8.cyan(repo)}`);
|
|
1780
|
-
program2.error(color8.red(message));
|
|
1781
|
-
}
|
|
1782
|
-
);
|
|
1783
|
-
if (!options.verbose) loading.stop(`Retrieved blocks from ${color8.cyan(repoPaths.join(", "))}`);
|
|
1784
|
-
verbose(`Retrieved blocks from ${color8.cyan(repoPaths.join(", "))}`);
|
|
1785
|
-
const installedBlocks = getInstalled(blocksMap, config, options.cwd).map(
|
|
1786
|
-
(val) => val.specifier
|
|
1787
|
-
);
|
|
1788
|
-
let installingBlockNames = blockNames;
|
|
1789
|
-
if (installingBlockNames.length === 0) {
|
|
1790
|
-
const promptResult = await multiselect({
|
|
1791
|
-
message: "Select which blocks to add.",
|
|
1792
|
-
options: Array.from(blocksMap.entries()).map(([key, value]) => {
|
|
1793
|
-
const shortName = `${value.category}/${value.name}`;
|
|
1794
|
-
const blockExists = installedBlocks.findIndex((block) => block === shortName) !== -1;
|
|
1795
|
-
let label;
|
|
1796
|
-
if (repoPaths.length > 1) {
|
|
1797
|
-
label = `${color8.cyan(
|
|
1798
|
-
`${value.sourceRepo.name}/${value.sourceRepo.owner}/${value.sourceRepo.repoName}/${value.category}`
|
|
1799
|
-
)}/${value.name}`;
|
|
1800
|
-
} else {
|
|
1801
|
-
label = `${color8.cyan(value.category)}/${value.name}`;
|
|
1802
|
-
}
|
|
1803
|
-
return {
|
|
1804
|
-
label: blockExists ? color8.gray(label) : label,
|
|
1805
|
-
value: key,
|
|
1806
|
-
// show hint for `Installed` if block is already installed
|
|
1807
|
-
hint: blockExists ? "Installed" : void 0
|
|
1808
|
-
};
|
|
1809
|
-
}),
|
|
1810
|
-
required: true
|
|
1811
|
-
});
|
|
1812
|
-
if (isCancel(promptResult)) {
|
|
1813
|
-
cancel("Canceled!");
|
|
1814
|
-
process.exit(0);
|
|
1815
|
-
}
|
|
1816
|
-
installingBlockNames = promptResult;
|
|
1817
|
-
}
|
|
1818
|
-
verbose(`Installing blocks ${color8.cyan(installingBlockNames.join(", "))}`);
|
|
1819
|
-
if (options.verbose) console.log("Blocks map: ", blocksMap);
|
|
1820
|
-
const installingBlocks = (await resolveTree(installingBlockNames, blocksMap, repoPaths)).match(
|
|
1821
|
-
(val) => val,
|
|
1822
|
-
(err) => program2.error(err)
|
|
1823
|
-
);
|
|
1824
|
-
const pm = (await detect({ cwd: options.cwd }))?.agent ?? "npm";
|
|
1825
|
-
const tasks = [];
|
|
1826
|
-
let devDeps = /* @__PURE__ */ new Set();
|
|
1827
|
-
let deps = /* @__PURE__ */ new Set();
|
|
1828
|
-
if (noConfig) {
|
|
1829
|
-
const blocksPath = await text({
|
|
1830
|
-
message: "Where would you like to add the blocks?",
|
|
1831
|
-
initialValue: config.path,
|
|
1832
|
-
defaultValue: config.path,
|
|
1833
|
-
placeholder: config.path,
|
|
1834
|
-
validate(value) {
|
|
1835
|
-
if (value.trim() === "") return "Please provide a value";
|
|
1836
|
-
}
|
|
1837
|
-
});
|
|
1838
|
-
if (isCancel(blocksPath)) {
|
|
1839
|
-
cancel("Canceled!");
|
|
1840
|
-
process.exit(0);
|
|
1841
|
-
}
|
|
1842
|
-
config.path = blocksPath;
|
|
1843
|
-
if (!options.yes) {
|
|
1844
|
-
const includeTests = await confirm({
|
|
1845
|
-
message: "Include tests?",
|
|
1846
|
-
initialValue: config.includeTests
|
|
1847
|
-
});
|
|
1848
|
-
if (isCancel(includeTests)) {
|
|
1849
|
-
cancel("Canceled!");
|
|
1850
|
-
process.exit(0);
|
|
1851
|
-
}
|
|
1852
|
-
config.includeTests = includeTests;
|
|
1853
|
-
const addWatermark = await confirm({
|
|
1854
|
-
message: "Add watermark?",
|
|
1855
|
-
initialValue: config.watermark
|
|
1856
|
-
});
|
|
1857
|
-
if (isCancel(addWatermark)) {
|
|
1858
|
-
cancel("Canceled!");
|
|
1859
|
-
process.exit(0);
|
|
1860
|
-
}
|
|
1861
|
-
config.watermark = addWatermark;
|
|
1862
|
-
}
|
|
1863
|
-
}
|
|
1864
|
-
const { prettierOptions, biomeOptions } = await loadFormatterConfig({
|
|
1865
|
-
formatter: config.formatter,
|
|
1866
|
-
cwd: options.cwd
|
|
1867
|
-
});
|
|
1868
|
-
for (const { block } of installingBlocks) {
|
|
1869
|
-
const fullSpecifier = `${block.sourceRepo.url}/${block.category}/${block.name}`;
|
|
1870
|
-
const shortSpecifier = `${block.category}/${block.name}`;
|
|
1871
|
-
const watermark = getWatermark(context.package.version, block.sourceRepo.url);
|
|
1872
|
-
const providerInfo = block.sourceRepo;
|
|
1873
|
-
verbose(`Setting up ${fullSpecifier}`);
|
|
1874
|
-
const directory = path7.join(options.cwd, config.path, block.category);
|
|
1875
|
-
const blockExists = !block.subdirectory && fs7.existsSync(path7.join(directory, block.files[0])) || block.subdirectory && fs7.existsSync(path7.join(directory, block.name));
|
|
1876
|
-
if (blockExists && !options.yes) {
|
|
1877
|
-
const result = await confirm({
|
|
1878
|
-
message: `${color8.cyan(shortSpecifier)} already exists in your project would you like to overwrite it?`,
|
|
1879
|
-
initialValue: false
|
|
1880
|
-
});
|
|
1881
|
-
if (isCancel(result) || !result) {
|
|
1882
|
-
cancel("Canceled!");
|
|
1883
|
-
process.exit(0);
|
|
1884
|
-
}
|
|
1885
|
-
}
|
|
1886
|
-
tasks.push({
|
|
1887
|
-
loadingMessage: `Adding ${fullSpecifier}`,
|
|
1888
|
-
completedMessage: `Added ${fullSpecifier}`,
|
|
1889
|
-
run: async () => {
|
|
1890
|
-
verbose(`Creating directory ${color8.bold(directory)}`);
|
|
1891
|
-
fs7.mkdirSync(directory, { recursive: true });
|
|
1892
|
-
verbose(`Created directory ${color8.bold(directory)}`);
|
|
1893
|
-
const files = [];
|
|
1894
|
-
const getSourceFile = async (filePath) => {
|
|
1895
|
-
const content = await providerInfo.provider.fetchRaw(providerInfo, filePath, {
|
|
1896
|
-
verbose
|
|
1897
|
-
});
|
|
1898
|
-
if (content.isErr()) {
|
|
1899
|
-
loading.stop(color8.red(`Error fetching ${color8.bold(filePath)}`));
|
|
1900
|
-
program2.error(
|
|
1901
|
-
color8.red(`There was an error trying to get ${fullSpecifier}`)
|
|
1902
|
-
);
|
|
1903
|
-
}
|
|
1904
|
-
return content.unwrap();
|
|
1905
|
-
};
|
|
1906
|
-
for (const sourceFile of block.files) {
|
|
1907
|
-
if (!config.includeTests && isTestFile(sourceFile)) continue;
|
|
1908
|
-
const sourcePath = path7.join(block.directory, sourceFile);
|
|
1909
|
-
let destPath;
|
|
1910
|
-
if (block.subdirectory) {
|
|
1911
|
-
destPath = path7.join(directory, block.name, sourceFile);
|
|
1912
|
-
} else {
|
|
1913
|
-
destPath = path7.join(directory, sourceFile);
|
|
1914
|
-
}
|
|
1915
|
-
verbose(`Adding ${color8.bold(sourcePath)}`);
|
|
1916
|
-
const content = await getSourceFile(sourcePath);
|
|
1917
|
-
const pathFolder = destPath.slice(0, destPath.length - sourceFile.length);
|
|
1918
|
-
verbose(`Creating directory ${color8.bold(pathFolder)}`);
|
|
1919
|
-
fs7.mkdirSync(pathFolder, {
|
|
1920
|
-
recursive: true
|
|
1921
|
-
});
|
|
1922
|
-
verbose(`Created directory ${color8.bold(pathFolder)}`);
|
|
1923
|
-
files.push({ content, destPath });
|
|
1924
|
-
verbose(`Got ${color8.bold(sourcePath)}`);
|
|
1925
|
-
}
|
|
1926
|
-
for (const file of files) {
|
|
1927
|
-
const lang = languages.find((lang2) => lang2.matches(file.destPath));
|
|
1928
|
-
let content = file.content;
|
|
1929
|
-
if (lang) {
|
|
1930
|
-
if (config.watermark) {
|
|
1931
|
-
const comment = lang.comment(watermark);
|
|
1932
|
-
content = `${comment}
|
|
1933
|
-
|
|
1934
|
-
${content}`;
|
|
1935
|
-
}
|
|
1936
|
-
verbose(`Formatting ${color8.bold(file.destPath)}`);
|
|
1937
|
-
content = await lang.format(content, {
|
|
1938
|
-
filePath: file.destPath,
|
|
1939
|
-
formatter: config.formatter,
|
|
1940
|
-
prettierOptions,
|
|
1941
|
-
biomeOptions
|
|
1942
|
-
});
|
|
1943
|
-
}
|
|
1944
|
-
verbose(`Writing to ${color8.bold(file.destPath)}`);
|
|
1945
|
-
fs7.writeFileSync(file.destPath, content);
|
|
1946
|
-
}
|
|
1947
|
-
if (config.includeTests && block.tests) {
|
|
1948
|
-
verbose("Trying to include tests");
|
|
1949
|
-
const { devDependencies } = JSON.parse(
|
|
1950
|
-
fs7.readFileSync(path7.join(options.cwd, "package.json")).toString()
|
|
1951
|
-
);
|
|
1952
|
-
if (devDependencies === void 0 || devDependencies.vitest === void 0) {
|
|
1953
|
-
devDeps.add("vitest");
|
|
1954
|
-
}
|
|
1955
|
-
}
|
|
1956
|
-
for (const dep of block.devDependencies) {
|
|
1957
|
-
devDeps.add(dep);
|
|
1958
|
-
}
|
|
1959
|
-
for (const dep of block.dependencies) {
|
|
1960
|
-
deps.add(dep);
|
|
1961
|
-
}
|
|
1962
|
-
}
|
|
1963
|
-
});
|
|
1964
|
-
}
|
|
1965
|
-
await runTasks(tasks, { verbose: options.verbose ? verbose : void 0 });
|
|
1966
|
-
const requiredDependencies = returnShouldInstall(deps, devDeps, { cwd: options.cwd });
|
|
1967
|
-
deps = requiredDependencies.dependencies;
|
|
1968
|
-
devDeps = requiredDependencies.devDependencies;
|
|
1969
|
-
const hasDependencies = deps.size > 0 || devDeps.size > 0;
|
|
1970
|
-
if (hasDependencies) {
|
|
1971
|
-
let install = options.yes;
|
|
1972
|
-
if (!options.yes) {
|
|
1973
|
-
const result = await confirm({
|
|
1974
|
-
message: "Would you like to install dependencies?",
|
|
1975
|
-
initialValue: true
|
|
1976
|
-
});
|
|
1977
|
-
if (isCancel(result)) {
|
|
1978
|
-
cancel("Canceled!");
|
|
1979
|
-
process.exit(0);
|
|
1980
|
-
}
|
|
1981
|
-
install = result;
|
|
1982
|
-
}
|
|
1983
|
-
if (install) {
|
|
1984
|
-
if (deps.size > 0) {
|
|
1985
|
-
if (!options.verbose)
|
|
1986
|
-
loading.start(`Installing dependencies with ${color8.cyan(pm)}`);
|
|
1987
|
-
(await installDependencies({
|
|
1988
|
-
pm,
|
|
1989
|
-
deps: Array.from(deps),
|
|
1990
|
-
dev: false,
|
|
1991
|
-
cwd: options.cwd
|
|
1992
|
-
})).match(
|
|
1993
|
-
(installed) => {
|
|
1994
|
-
if (!options.verbose)
|
|
1995
|
-
loading.stop(`Installed ${color8.cyan(installed.join(", "))}`);
|
|
1996
|
-
},
|
|
1997
|
-
(err) => {
|
|
1998
|
-
if (!options.verbose) loading.stop("Failed to install dependencies");
|
|
1999
|
-
program2.error(err);
|
|
2000
|
-
}
|
|
2001
|
-
);
|
|
2002
|
-
}
|
|
2003
|
-
if (devDeps.size > 0) {
|
|
2004
|
-
if (!options.verbose)
|
|
2005
|
-
loading.start(`Installing dependencies with ${color8.cyan(pm)}`);
|
|
2006
|
-
(await installDependencies({
|
|
2007
|
-
pm,
|
|
2008
|
-
deps: Array.from(devDeps),
|
|
2009
|
-
dev: true,
|
|
2010
|
-
cwd: options.cwd
|
|
2011
|
-
})).match(
|
|
2012
|
-
(installed) => {
|
|
2013
|
-
if (!options.verbose)
|
|
2014
|
-
loading.stop(`Installed ${color8.cyan(installed.join(", "))}`);
|
|
2015
|
-
},
|
|
2016
|
-
(err) => {
|
|
2017
|
-
if (!options.verbose) loading.stop("Failed to install dev dependencies");
|
|
2018
|
-
program2.error(err);
|
|
2019
|
-
}
|
|
2020
|
-
);
|
|
2021
|
-
}
|
|
2022
|
-
}
|
|
2023
|
-
let steps = [];
|
|
2024
|
-
if (!install) {
|
|
2025
|
-
if (deps.size > 0) {
|
|
2026
|
-
const cmd = resolveCommand2(pm, "install", [...deps]);
|
|
2027
|
-
steps.push(
|
|
2028
|
-
`Install dependencies \`${color8.cyan(`${cmd?.command} ${cmd?.args.join(" ")}`)}\``
|
|
2029
|
-
);
|
|
2030
|
-
}
|
|
2031
|
-
if (devDeps.size > 0) {
|
|
2032
|
-
const cmd = resolveCommand2(pm, "install", [...devDeps, "-D"]);
|
|
2033
|
-
steps.push(
|
|
2034
|
-
`Install dev dependencies \`${color8.cyan(`${cmd?.command} ${cmd?.args.join(" ")}`)}\``
|
|
2035
|
-
);
|
|
2036
|
-
}
|
|
2037
|
-
}
|
|
2038
|
-
steps = steps.map((step, i) => `${i + 1}. ${step}`);
|
|
2039
|
-
if (!install) {
|
|
2040
|
-
steps.push("");
|
|
2041
|
-
}
|
|
2042
|
-
steps.push(`Import the blocks from \`${color8.cyan(config.path)}\``);
|
|
2043
|
-
const next = nextSteps(steps);
|
|
2044
|
-
process.stdout.write(next);
|
|
2045
|
-
}
|
|
2046
|
-
};
|
|
2047
|
-
|
|
2048
|
-
// src/commands/auth.ts
|
|
2049
|
-
import { cancel as cancel2, confirm as confirm2, isCancel as isCancel2, outro as outro2, password, select } from "@clack/prompts";
|
|
2050
|
-
import color9 from "chalk";
|
|
2051
|
-
import { Command as Command2, Option } from "commander";
|
|
2052
|
-
import * as v6 from "valibot";
|
|
2053
|
-
var schema3 = v6.object({
|
|
2054
|
-
token: v6.optional(v6.string()),
|
|
2055
|
-
provider: v6.optional(v6.string()),
|
|
2056
|
-
logout: v6.boolean(),
|
|
2057
|
-
cwd: v6.string()
|
|
2058
|
-
});
|
|
2059
|
-
var auth = new Command2("auth").description("Provide a token for access to private repositories.").option("--token <token>", "The token to use for authenticating to your provider.").addOption(
|
|
2060
|
-
new Option("--provider <name>", "The provider this token belongs to.").choices(
|
|
2061
|
-
providers.map((provider) => provider.name())
|
|
2062
|
-
)
|
|
2063
|
-
).option("--logout", "Erase tokens from each provider from storage.", false).option("--cwd <path>", "The current working directory.", process.cwd()).action(async (opts) => {
|
|
2064
|
-
const options = v6.parse(schema3, opts);
|
|
2065
|
-
_intro(context.package.version);
|
|
2066
|
-
await _auth(options);
|
|
2067
|
-
outro2(color9.green("All done!"));
|
|
2068
|
-
});
|
|
2069
|
-
var _auth = async (options) => {
|
|
2070
|
-
const storage = get2();
|
|
2071
|
-
if (options.logout) {
|
|
2072
|
-
for (const provider of providers) {
|
|
2073
|
-
const tokenKey = `${provider.name()}-token`;
|
|
2074
|
-
if (storage.get(tokenKey) === void 0) {
|
|
2075
|
-
process.stdout.write(`${VERTICAL_LINE}
|
|
2076
|
-
`);
|
|
2077
|
-
process.stdout.write(
|
|
2078
|
-
color9.gray(
|
|
2079
|
-
`${VERTICAL_LINE} Already logged out of ${provider.name()}.
|
|
2080
|
-
`
|
|
2081
|
-
)
|
|
2082
|
-
);
|
|
2083
|
-
continue;
|
|
2084
|
-
}
|
|
2085
|
-
const response = await confirm2({
|
|
2086
|
-
message: `Remove ${provider.name()} token?`,
|
|
2087
|
-
initialValue: true
|
|
2088
|
-
});
|
|
2089
|
-
if (isCancel2(response)) {
|
|
2090
|
-
cancel2("Canceled!");
|
|
2091
|
-
process.exit(0);
|
|
2092
|
-
}
|
|
2093
|
-
if (!response) continue;
|
|
2094
|
-
storage.delete(tokenKey);
|
|
2095
|
-
}
|
|
2096
|
-
return;
|
|
2097
|
-
}
|
|
2098
|
-
if (providers.length > 1) {
|
|
2099
|
-
const response = await select({
|
|
2100
|
-
message: "Which provider is this token for?",
|
|
2101
|
-
options: providers.map((provider) => ({
|
|
2102
|
-
label: provider.name(),
|
|
2103
|
-
value: provider.name()
|
|
2104
|
-
})),
|
|
2105
|
-
initialValue: providers[0].name()
|
|
2106
|
-
});
|
|
2107
|
-
if (isCancel2(response)) {
|
|
2108
|
-
cancel2("Canceled!");
|
|
2109
|
-
process.exit(0);
|
|
2110
|
-
}
|
|
2111
|
-
options.provider = response;
|
|
2112
|
-
} else {
|
|
2113
|
-
options.provider = providers[0].name();
|
|
2114
|
-
}
|
|
2115
|
-
if (options.token === void 0) {
|
|
2116
|
-
const response = await password({
|
|
2117
|
-
message: "Paste your token",
|
|
2118
|
-
validate(value) {
|
|
2119
|
-
if (value.trim() === "") return "Please provide a value";
|
|
2120
|
-
}
|
|
2121
|
-
});
|
|
2122
|
-
if (isCancel2(response) || !response) {
|
|
2123
|
-
cancel2("Canceled!");
|
|
2124
|
-
process.exit(0);
|
|
2125
|
-
}
|
|
2126
|
-
options.token = response;
|
|
2127
|
-
}
|
|
2128
|
-
storage.set(`${options.provider}-token`, options.token);
|
|
2129
|
-
};
|
|
2130
|
-
|
|
2131
|
-
// src/commands/build.ts
|
|
2132
|
-
import fs8 from "node:fs";
|
|
2133
|
-
import { outro as outro3, spinner as spinner3 } from "@clack/prompts";
|
|
2134
|
-
import color10 from "chalk";
|
|
2135
|
-
import { Command as Command3, program as program3 } from "commander";
|
|
2136
|
-
import path8 from "pathe";
|
|
2137
|
-
import * as v7 from "valibot";
|
|
2138
|
-
var schema4 = v7.object({
|
|
2139
|
-
dirs: v7.array(v7.string()),
|
|
2140
|
-
includeBlocks: v7.array(v7.string()),
|
|
2141
|
-
includeCategories: v7.array(v7.string()),
|
|
2142
|
-
excludeDeps: v7.array(v7.string()),
|
|
2143
|
-
output: v7.boolean(),
|
|
2144
|
-
errorOnWarn: v7.boolean(),
|
|
2145
|
-
verbose: v7.boolean(),
|
|
2146
|
-
cwd: v7.string()
|
|
2147
|
-
});
|
|
2148
|
-
var build = new Command3("build").description(`Builds the provided --dirs in the project root into a \`${OUTPUT_FILE}\` file.`).option("--dirs [dirs...]", "The directories containing the blocks.", ["./blocks"]).option("--include-blocks [blockNames...]", "Include only the blocks with these names.", []).option(
|
|
2149
|
-
"--include-categories [categoryNames...]",
|
|
2150
|
-
"Include only the categories with these names.",
|
|
2151
|
-
[]
|
|
2152
|
-
).option("--exclude-deps [deps...]", "Dependencies that should not be added.", []).option("--no-output", `Do not output a \`${OUTPUT_FILE}\` file.`).option(
|
|
2153
|
-
"--error-on-warn",
|
|
2154
|
-
"If there is a warning throw an error and do not allow build to complete.",
|
|
2155
|
-
false
|
|
2156
|
-
).option("--verbose", "Include debug logs.", false).option("--cwd <path>", "The current working directory.", process.cwd()).action(async (opts) => {
|
|
2157
|
-
const options = v7.parse(schema4, opts);
|
|
2158
|
-
_intro(context.package.version);
|
|
2159
|
-
await _build(options);
|
|
2160
|
-
outro3(color10.green("All done!"));
|
|
2161
|
-
});
|
|
2162
|
-
var _build = async (options) => {
|
|
2163
|
-
const loading = spinner3();
|
|
2164
|
-
const categories = [];
|
|
2165
|
-
const outFile = path8.join(options.cwd, OUTPUT_FILE);
|
|
2166
|
-
for (const dir of options.dirs) {
|
|
2167
|
-
const dirPath = path8.join(options.cwd, dir);
|
|
2168
|
-
loading.start(`Building ${color10.cyan(dirPath)}`);
|
|
2169
|
-
if (options.output && fs8.existsSync(outFile)) fs8.rmSync(outFile);
|
|
2170
|
-
const builtCategories = buildBlocksDirectory(dirPath, { ...options });
|
|
2171
|
-
for (const category of builtCategories) {
|
|
2172
|
-
if (categories.find((cat) => cat.name === category.name) !== void 0) {
|
|
2173
|
-
const error = "a category with the same name already exists!";
|
|
2174
|
-
if (options.errorOnWarn) {
|
|
2175
|
-
program3.error(
|
|
2176
|
-
color10.red(
|
|
2177
|
-
`\`${color10.bold(`${dir}/${category.name}`)}\` could not be added because ${error}`
|
|
2178
|
-
)
|
|
2179
|
-
);
|
|
2180
|
-
} else {
|
|
2181
|
-
console.warn(
|
|
2182
|
-
`${VERTICAL_LINE} ${WARN} Skipped adding \`${color10.cyan(`${dir}/${category.name}`)}\` because ${error}`
|
|
2183
|
-
);
|
|
2184
|
-
}
|
|
2185
|
-
continue;
|
|
2186
|
-
}
|
|
2187
|
-
categories.push(category);
|
|
2188
|
-
}
|
|
2189
|
-
loading.stop(`Built ${color10.cyan(dirPath)}`);
|
|
2190
|
-
}
|
|
2191
|
-
loading.start("Checking manifest");
|
|
2192
|
-
const warnings = [];
|
|
2193
|
-
for (const category of categories) {
|
|
2194
|
-
for (const block of category.blocks) {
|
|
2195
|
-
for (const dep of block.localDependencies) {
|
|
2196
|
-
const [depCategoryName, depBlockName] = dep.split("/");
|
|
2197
|
-
const depCategory = categories.find(
|
|
2198
|
-
(cat) => cat.name.trim() === depCategoryName.trim()
|
|
2199
|
-
);
|
|
2200
|
-
const invalidDependencyError = () => {
|
|
2201
|
-
const error = `depends on ${color10.bold(dep)} which doesn't exist!`;
|
|
2202
|
-
if (options.errorOnWarn) {
|
|
2203
|
-
warnings.push(
|
|
2204
|
-
color10.red(`${color10.bold(`${category.name}/${block.name}`)} ${error}`)
|
|
2205
|
-
);
|
|
2206
|
-
} else {
|
|
2207
|
-
warnings.push(
|
|
2208
|
-
`${VERTICAL_LINE} ${WARN} ${color10.bold(`${category.name}/${block.name}`)} ${error}`
|
|
2209
|
-
);
|
|
2210
|
-
}
|
|
2211
|
-
};
|
|
2212
|
-
if (!depCategory) {
|
|
2213
|
-
invalidDependencyError();
|
|
2214
|
-
continue;
|
|
2215
|
-
}
|
|
2216
|
-
if (depCategory.blocks.find((b) => b.name === depBlockName) === void 0) {
|
|
2217
|
-
invalidDependencyError();
|
|
2218
|
-
}
|
|
2219
|
-
}
|
|
2220
|
-
for (const dep of [...block.dependencies, ...block.devDependencies]) {
|
|
2221
|
-
if (!dep.includes("@")) {
|
|
2222
|
-
const error = `You haven't installed ${color10.bold(dep)} as a dependency so your users could get any version of it when they install your block!`;
|
|
2223
|
-
if (options.errorOnWarn) {
|
|
2224
|
-
warnings.push(color10.red(error));
|
|
2225
|
-
} else {
|
|
2226
|
-
warnings.push(`${VERTICAL_LINE} ${WARN} ${error}`);
|
|
2227
|
-
}
|
|
2228
|
-
}
|
|
2229
|
-
}
|
|
2230
|
-
}
|
|
2231
|
-
}
|
|
2232
|
-
loading.stop("Completed checking manifest.");
|
|
2233
|
-
if (warnings.length > 0) {
|
|
2234
|
-
for (const warning of warnings) {
|
|
2235
|
-
console.log(warning);
|
|
2236
|
-
}
|
|
2237
|
-
if (options.errorOnWarn) {
|
|
2238
|
-
program3.error("Had warnings while checking manifest.");
|
|
2239
|
-
}
|
|
2240
|
-
}
|
|
2241
|
-
if (options.output) {
|
|
2242
|
-
loading.start(`Writing output to \`${color10.cyan(outFile)}\``);
|
|
2243
|
-
fs8.writeFileSync(outFile, JSON.stringify(categories, null, " "));
|
|
2244
|
-
loading.stop(`Wrote output to \`${color10.cyan(outFile)}\``);
|
|
2245
|
-
}
|
|
2246
|
-
};
|
|
2247
|
-
|
|
2248
|
-
// src/commands/diff.ts
|
|
2249
|
-
import fs9 from "node:fs";
|
|
2250
|
-
import { cancel as cancel3, confirm as confirm3, isCancel as isCancel3, outro as outro4, spinner as spinner4 } from "@clack/prompts";
|
|
2251
|
-
import color12 from "chalk";
|
|
2252
|
-
import { Command as Command4, program as program4 } from "commander";
|
|
2253
|
-
import { diffLines } from "diff";
|
|
2254
|
-
import path9 from "pathe";
|
|
2255
|
-
import * as v8 from "valibot";
|
|
2256
|
-
|
|
2257
|
-
// src/utils/diff.ts
|
|
2258
|
-
import color11 from "chalk";
|
|
2259
|
-
import { diffChars } from "diff";
|
|
2260
|
-
|
|
2261
|
-
// src/utils/blocks/utils/array-sum.ts
|
|
2262
|
-
var arraySum = (arr, fn) => {
|
|
2263
|
-
let total = 0;
|
|
2264
|
-
for (const item of arr) {
|
|
2265
|
-
total = total + fn(item);
|
|
2266
|
-
}
|
|
2267
|
-
return total;
|
|
2268
|
-
};
|
|
2269
|
-
|
|
2270
|
-
// src/utils/diff.ts
|
|
2271
|
-
var isWhitespace = (str) => /^\s+$/g.test(str);
|
|
2272
|
-
var trimSingleNewLine = (str) => {
|
|
2273
|
-
let i = str.length - 1;
|
|
2274
|
-
while (isWhitespace(str[i]) && i >= 0) {
|
|
2275
|
-
if (str[i] === "\n") {
|
|
2276
|
-
if (str[i - 1] === "\r") {
|
|
2277
|
-
return str.slice(0, i - 1);
|
|
2278
|
-
}
|
|
2279
|
-
return str.slice(0, i);
|
|
2280
|
-
}
|
|
2281
|
-
i--;
|
|
2282
|
-
}
|
|
2283
|
-
return str;
|
|
2284
|
-
};
|
|
2285
|
-
var formatDiff = ({
|
|
2286
|
-
from,
|
|
2287
|
-
to,
|
|
2288
|
-
changes,
|
|
2289
|
-
expand = false,
|
|
2290
|
-
maxUnchanged = 5,
|
|
2291
|
-
colorRemoved = color11.red,
|
|
2292
|
-
colorAdded = color11.green,
|
|
2293
|
-
colorCharsRemoved = color11.bgRed,
|
|
2294
|
-
colorCharsAdded = color11.bgGreen,
|
|
2295
|
-
prefix,
|
|
2296
|
-
onUnchanged,
|
|
2297
|
-
intro: intro2
|
|
2298
|
-
}) => {
|
|
2299
|
-
let result = "";
|
|
2300
|
-
const length = arraySum(changes, (change) => change.count ?? 0).toString().length + 1;
|
|
2301
|
-
let lineOffset = 0;
|
|
2302
|
-
if (changes.length === 1 && !changes[0].added && !changes[0].removed) {
|
|
2303
|
-
return onUnchanged({
|
|
2304
|
-
from,
|
|
2305
|
-
to,
|
|
2306
|
-
changes,
|
|
2307
|
-
expand,
|
|
2308
|
-
maxUnchanged,
|
|
2309
|
-
colorAdded,
|
|
2310
|
-
colorRemoved,
|
|
2311
|
-
prefix,
|
|
2312
|
-
onUnchanged,
|
|
2313
|
-
intro: intro2
|
|
2314
|
-
});
|
|
2315
|
-
}
|
|
2316
|
-
result += intro2({
|
|
2317
|
-
from,
|
|
2318
|
-
to,
|
|
2319
|
-
changes,
|
|
2320
|
-
expand,
|
|
2321
|
-
maxUnchanged,
|
|
2322
|
-
colorAdded,
|
|
2323
|
-
colorRemoved,
|
|
2324
|
-
prefix,
|
|
2325
|
-
onUnchanged,
|
|
2326
|
-
intro: intro2
|
|
2327
|
-
});
|
|
2328
|
-
const linePrefix = (line) => color11.gray(`${prefix?.() ?? ""}${leftPadMin(`${line + 1 + lineOffset} `, length)} `);
|
|
2329
|
-
for (let i = 0; i < changes.length; i++) {
|
|
2330
|
-
const change = changes[i];
|
|
2331
|
-
const hasPreviousChange = changes[i - 1]?.added || changes[i - 1]?.removed;
|
|
2332
|
-
const hasNextChange = changes[i + 1]?.added || changes[i + 1]?.removed;
|
|
2333
|
-
if (!change.added && !change.removed) {
|
|
2334
|
-
if (!expand && change.count !== void 0 && change.count > maxUnchanged) {
|
|
2335
|
-
const prevLineOffset = lineOffset;
|
|
2336
|
-
const ls = get(trimSingleNewLine(change.value));
|
|
2337
|
-
let shownLines = 0;
|
|
2338
|
-
if (hasNextChange) shownLines += maxUnchanged;
|
|
2339
|
-
if (hasPreviousChange) shownLines += maxUnchanged;
|
|
2340
|
-
if (shownLines >= ls.length) {
|
|
2341
|
-
result += `${join(ls, {
|
|
2342
|
-
prefix: linePrefix
|
|
2343
|
-
})}
|
|
2344
|
-
`;
|
|
2345
|
-
lineOffset += ls.length;
|
|
2346
|
-
continue;
|
|
2347
|
-
}
|
|
2348
|
-
if (hasPreviousChange) {
|
|
2349
|
-
result += `${join(ls.slice(0, maxUnchanged), {
|
|
2350
|
-
prefix: linePrefix
|
|
2351
|
-
})}
|
|
2352
|
-
`;
|
|
2353
|
-
}
|
|
2354
|
-
if (ls.length > shownLines) {
|
|
2355
|
-
const count = ls.length - shownLines;
|
|
2356
|
-
result += `${join(
|
|
2357
|
-
get(
|
|
2358
|
-
color11.gray(
|
|
2359
|
-
`+ ${count} more unchanged (${color11.italic("-E to expand")})`
|
|
2360
|
-
)
|
|
2361
|
-
),
|
|
2362
|
-
{
|
|
2363
|
-
prefix: () => `${prefix?.() ?? ""}${leftPadMin(" ", length)} `
|
|
2364
|
-
}
|
|
2365
|
-
)}
|
|
2366
|
-
`;
|
|
2367
|
-
}
|
|
2368
|
-
if (hasNextChange) {
|
|
2369
|
-
lineOffset = lineOffset + ls.length - maxUnchanged;
|
|
2370
|
-
result += `${join(ls.slice(ls.length - maxUnchanged), {
|
|
2371
|
-
prefix: linePrefix
|
|
2372
|
-
})}
|
|
2373
|
-
`;
|
|
2374
|
-
}
|
|
2375
|
-
lineOffset = prevLineOffset + change.count;
|
|
2376
|
-
continue;
|
|
2377
|
-
}
|
|
2378
|
-
result += `${join(get(trimSingleNewLine(change.value)), {
|
|
2379
|
-
prefix: linePrefix
|
|
2380
|
-
})}
|
|
2381
|
-
`;
|
|
2382
|
-
lineOffset += change.count ?? 0;
|
|
2383
|
-
continue;
|
|
2384
|
-
}
|
|
2385
|
-
const colorLineChange = (change2) => {
|
|
2386
|
-
if (change2.added) {
|
|
2387
|
-
return colorAdded(trimSingleNewLine(change2.value));
|
|
2388
|
-
}
|
|
2389
|
-
if (change2.removed) {
|
|
2390
|
-
return colorRemoved(trimSingleNewLine(change2.value));
|
|
2391
|
-
}
|
|
2392
|
-
return change2.value;
|
|
2393
|
-
};
|
|
2394
|
-
const colorCharChange = (change2) => {
|
|
2395
|
-
if (change2.added) {
|
|
2396
|
-
return colorCharsAdded(trimSingleNewLine(change2.value));
|
|
2397
|
-
}
|
|
2398
|
-
if (change2.removed) {
|
|
2399
|
-
return colorCharsRemoved(trimSingleNewLine(change2.value));
|
|
2400
|
-
}
|
|
2401
|
-
return change2.value;
|
|
2402
|
-
};
|
|
2403
|
-
if (change.removed && change.count === 1 && changes[i + 1]?.added && changes[i + 1]?.count === 1) {
|
|
2404
|
-
const diffedChars = diffChars(change.value, changes[i + 1].value);
|
|
2405
|
-
const sentence = diffedChars.map((chg) => colorCharChange(chg)).join("");
|
|
2406
|
-
result += `${linePrefix(0)}${sentence}`;
|
|
2407
|
-
lineOffset += 1;
|
|
2408
|
-
i++;
|
|
2409
|
-
} else {
|
|
2410
|
-
if (isWhitespace(change.value)) {
|
|
2411
|
-
result += `${join(get(colorCharChange(change)), {
|
|
2412
|
-
prefix: (line) => `${linePrefix(line)}${colorCharChange({ removed: true, value: " ", added: false })}`
|
|
2413
|
-
})}
|
|
2414
|
-
`;
|
|
2415
|
-
if (!change.removed) {
|
|
2416
|
-
lineOffset += change.count ?? 0;
|
|
2417
|
-
}
|
|
2418
|
-
} else {
|
|
2419
|
-
result += `${join(get(colorLineChange(change)), {
|
|
2420
|
-
prefix: linePrefix
|
|
2421
|
-
})}
|
|
2422
|
-
`;
|
|
2423
|
-
if (!change.removed) {
|
|
2424
|
-
lineOffset += change.count ?? 0;
|
|
2425
|
-
}
|
|
2426
|
-
}
|
|
2427
|
-
}
|
|
2428
|
-
}
|
|
2429
|
-
return result;
|
|
2430
|
-
};
|
|
2431
|
-
|
|
2432
|
-
// src/commands/diff.ts
|
|
2433
|
-
var schema5 = v8.object({
|
|
2434
|
-
expand: v8.boolean(),
|
|
2435
|
-
maxUnchanged: v8.number(),
|
|
2436
|
-
repo: v8.optional(v8.string()),
|
|
2437
|
-
allow: v8.boolean(),
|
|
2438
|
-
cwd: v8.string()
|
|
2439
|
-
});
|
|
2440
|
-
var diff = new Command4("diff").description("Compares local blocks to the blocks in the provided repository.").option("-E, --expand", "Expands the diff so you see everything.", false).option(
|
|
2441
|
-
"--max-unchanged <number>",
|
|
2442
|
-
"Maximum unchanged lines that will show without being collapsed.",
|
|
2443
|
-
(val) => Number.parseInt(val),
|
|
2444
|
-
// this is such a dumb api thing
|
|
2445
|
-
3
|
|
2446
|
-
).option("--repo <repo>", "Repository to download the blocks from.").option("-A, --allow", "Allow jsrepo to download code from the provided repo.", false).option("--cwd <path>", "The current working directory.", process.cwd()).action(async (opts) => {
|
|
2447
|
-
const options = v8.parse(schema5, opts);
|
|
2448
|
-
_intro(context.package.version);
|
|
2449
|
-
await _diff(options);
|
|
2450
|
-
outro4(color12.green("All done!"));
|
|
2451
|
-
});
|
|
2452
|
-
var _diff = async (options) => {
|
|
2453
|
-
const loading = spinner4();
|
|
2454
|
-
const config = getConfig(options.cwd).match(
|
|
2455
|
-
(val) => val,
|
|
2456
|
-
(err) => program4.error(color12.red(err))
|
|
2457
|
-
);
|
|
2458
|
-
let repoPaths = config.repos;
|
|
2459
|
-
if (options.repo) repoPaths = [options.repo];
|
|
2460
|
-
if (!options.allow && options.repo) {
|
|
2461
|
-
const result = await confirm3({
|
|
2462
|
-
message: `Allow ${color12.cyan("jsrepo")} to download and run code from ${color12.cyan(options.repo)}?`,
|
|
2463
|
-
initialValue: true
|
|
2464
|
-
});
|
|
2465
|
-
if (isCancel3(result) || !result) {
|
|
2466
|
-
cancel3("Canceled!");
|
|
2467
|
-
process.exit(0);
|
|
2468
|
-
}
|
|
2469
|
-
}
|
|
2470
|
-
loading.start(`Fetching blocks from ${color12.cyan(repoPaths.join(", "))}`);
|
|
2471
|
-
const blocksMap = (await fetchBlocks(...repoPaths)).match(
|
|
2472
|
-
(val) => val,
|
|
2473
|
-
({ repo, message }) => {
|
|
2474
|
-
loading.stop(`Failed fetching blocks from ${color12.cyan(repo)}`);
|
|
2475
|
-
program4.error(color12.red(message));
|
|
2476
|
-
}
|
|
2477
|
-
);
|
|
2478
|
-
loading.stop(`Retrieved blocks from ${color12.cyan(repoPaths.join(", "))}`);
|
|
2479
|
-
const installedBlocks = getInstalled(blocksMap, config, options.cwd);
|
|
2480
|
-
for (const blockSpecifier of installedBlocks) {
|
|
2481
|
-
let found = false;
|
|
2482
|
-
for (const repo of repoPaths) {
|
|
2483
|
-
const providerInfo = (await getProviderInfo(repo)).unwrap();
|
|
2484
|
-
const fullSpecifier = `${providerInfo.name}/${providerInfo.owner}/${providerInfo.repoName}/${blockSpecifier.specifier}`;
|
|
2485
|
-
const block = blocksMap.get(fullSpecifier);
|
|
2486
|
-
if (block === void 0) continue;
|
|
2487
|
-
const watermark = getWatermark(context.package.version, repo);
|
|
2488
|
-
found = true;
|
|
2489
|
-
process.stdout.write(`${VERTICAL_LINE}
|
|
2490
|
-
`);
|
|
2491
|
-
process.stdout.write(`${VERTICAL_LINE} ${fullSpecifier}
|
|
2492
|
-
`);
|
|
2493
|
-
for (const file of block.files) {
|
|
2494
|
-
if (!config.includeTests && isTestFile(file)) continue;
|
|
2495
|
-
process.stdout.write(`${VERTICAL_LINE}
|
|
2496
|
-
`);
|
|
2497
|
-
const sourcePath = path9.join(block.directory, file);
|
|
2498
|
-
const response = await providerInfo.provider.fetchRaw(providerInfo, sourcePath);
|
|
2499
|
-
if (response.isErr()) {
|
|
2500
|
-
program4.error(color12.red(`There was an error trying to get ${fullSpecifier}`));
|
|
2501
|
-
}
|
|
2502
|
-
let remoteContent = response.unwrap();
|
|
2503
|
-
const directory = path9.join(options.cwd, config.path, block.category);
|
|
2504
|
-
let localPath = path9.join(directory, file);
|
|
2505
|
-
let prettyLocalPath = path9.join(config.path, block.category, file);
|
|
2506
|
-
if (block.subdirectory) {
|
|
2507
|
-
localPath = path9.join(directory, block.name, file);
|
|
2508
|
-
prettyLocalPath = path9.join(config.path, block.category, block.name, file);
|
|
2509
|
-
}
|
|
2510
|
-
let fileContent = "";
|
|
2511
|
-
if (fs9.existsSync(localPath)) {
|
|
2512
|
-
fileContent = fs9.readFileSync(localPath).toString();
|
|
2513
|
-
}
|
|
2514
|
-
if (config.watermark) {
|
|
2515
|
-
const lang = languages.find((lang2) => lang2.matches(sourcePath));
|
|
2516
|
-
if (lang) {
|
|
2517
|
-
const comment = lang.comment(watermark);
|
|
2518
|
-
remoteContent = `${comment}
|
|
2519
|
-
|
|
2520
|
-
${remoteContent}`;
|
|
2521
|
-
}
|
|
2522
|
-
}
|
|
2523
|
-
const changes = diffLines(fileContent, remoteContent);
|
|
2524
|
-
const from = path9.join(
|
|
2525
|
-
`${providerInfo.name}/${providerInfo.owner}/${providerInfo.repoName}`,
|
|
2526
|
-
sourcePath
|
|
2527
|
-
);
|
|
2528
|
-
const formattedDiff = formatDiff({
|
|
2529
|
-
from,
|
|
2530
|
-
to: prettyLocalPath,
|
|
2531
|
-
changes,
|
|
2532
|
-
expand: options.expand,
|
|
2533
|
-
maxUnchanged: options.maxUnchanged,
|
|
2534
|
-
colorAdded: color12.greenBright,
|
|
2535
|
-
colorRemoved: color12.redBright,
|
|
2536
|
-
colorCharsAdded: color12.bgGreenBright,
|
|
2537
|
-
colorCharsRemoved: color12.bgRedBright,
|
|
2538
|
-
prefix: () => `${VERTICAL_LINE} `,
|
|
2539
|
-
onUnchanged: ({ from: from2, to, prefix }) => `${prefix?.() ?? ""}${color12.cyan(from2)} \u2192 ${color12.gray(to)} ${color12.gray("(unchanged)")}
|
|
2540
|
-
`,
|
|
2541
|
-
intro: ({ from: from2, to, changes: changes2, prefix }) => {
|
|
2542
|
-
const totalChanges = changes2.filter((a) => a.added).length;
|
|
2543
|
-
return `${prefix?.() ?? ""}${color12.cyan(from2)} \u2192 ${color12.gray(to)} (${totalChanges} change${totalChanges === 1 ? "" : "s"})
|
|
2544
|
-
${prefix?.() ?? ""}
|
|
2545
|
-
`;
|
|
2546
|
-
}
|
|
2547
|
-
});
|
|
2548
|
-
process.stdout.write(formattedDiff);
|
|
2549
|
-
}
|
|
2550
|
-
break;
|
|
2551
|
-
}
|
|
2552
|
-
if (!found) {
|
|
2553
|
-
program4.error(
|
|
2554
|
-
color12.red(`Invalid block! ${color12.bold(blockSpecifier)} does not exist!`)
|
|
2555
|
-
);
|
|
2556
|
-
}
|
|
2557
|
-
}
|
|
2558
|
-
};
|
|
2559
|
-
|
|
2560
|
-
// src/commands/init.ts
|
|
2561
|
-
import fs10 from "node:fs";
|
|
2562
|
-
import { cancel as cancel4, confirm as confirm4, isCancel as isCancel4, outro as outro5, password as password2, select as select2, spinner as spinner5, text as text2 } from "@clack/prompts";
|
|
2563
|
-
import color13 from "chalk";
|
|
2564
|
-
import { Command as Command5, Option as Option2, program as program5 } from "commander";
|
|
2565
|
-
import { detect as detect2, resolveCommand as resolveCommand3 } from "package-manager-detector";
|
|
2566
|
-
import path10 from "pathe";
|
|
2567
|
-
import * as v9 from "valibot";
|
|
2568
|
-
var schema6 = v9.object({
|
|
2569
|
-
path: v9.optional(v9.string()),
|
|
2570
|
-
repos: v9.optional(v9.array(v9.string())),
|
|
2571
|
-
watermark: v9.boolean(),
|
|
2572
|
-
tests: v9.optional(v9.boolean()),
|
|
2573
|
-
formatter: v9.optional(formatterSchema),
|
|
2574
|
-
project: v9.optional(v9.boolean()),
|
|
2575
|
-
registry: v9.optional(v9.boolean()),
|
|
2576
|
-
script: v9.string(),
|
|
2577
|
-
yes: v9.boolean(),
|
|
2578
|
-
cwd: v9.string()
|
|
2579
|
-
});
|
|
2580
|
-
var init = new Command5("init").description("Initializes your project with a configuration file.").option("--path <path>", "Path to install the blocks / Path to build the blocks from.").option("--repos [repos...]", "Repository to install the blocks from.").option(
|
|
2581
|
-
"--no-watermark",
|
|
2582
|
-
"Will not add a watermark to each file upon adding it to your project."
|
|
2583
|
-
).option("--tests", "Will include tests with the blocks.").addOption(
|
|
2584
|
-
new Option2(
|
|
2585
|
-
"--formatter <formatter>",
|
|
2586
|
-
"What formatter to use when adding or updating blocks."
|
|
2587
|
-
).choices(["prettier", "biome"])
|
|
2588
|
-
).option("-P, --project", "Takes you through the steps to initialize a project.").option("-R, --registry", "Takes you through the steps to initialize a registry.").option("--script <name>", "The name of the build script. (For Registry setup)", "build").option("-y, --yes", "Skip confirmation prompt.", false).option("--cwd <path>", "The current working directory.", process.cwd()).action(async (opts) => {
|
|
2589
|
-
const options = v9.parse(schema6, opts);
|
|
2590
|
-
_intro(context.package.version);
|
|
2591
|
-
if (options.registry !== void 0 && options.project !== void 0) {
|
|
2592
|
-
program5.error(
|
|
2593
|
-
color13.red(
|
|
2594
|
-
`You cannot provide both ${color13.bold("--project")} and ${color13.bold("--registry")} at the same time.`
|
|
2595
|
-
)
|
|
2596
|
-
);
|
|
2597
|
-
}
|
|
2598
|
-
if (options.registry === void 0 && options.project === void 0) {
|
|
2599
|
-
const response = await select2({
|
|
2600
|
-
message: "Initialize a project or registry?",
|
|
2601
|
-
options: [
|
|
2602
|
-
{ value: "project", label: "project" },
|
|
2603
|
-
{ value: "registry", label: "registry" }
|
|
2604
|
-
],
|
|
2605
|
-
initialValue: "project"
|
|
2606
|
-
});
|
|
2607
|
-
if (isCancel4(response)) {
|
|
2608
|
-
cancel4("Canceled!");
|
|
2609
|
-
process.exit(0);
|
|
2610
|
-
}
|
|
2611
|
-
options.registry = response === "registry";
|
|
2612
|
-
}
|
|
2613
|
-
if (options.registry) {
|
|
2614
|
-
await _initRegistry(options);
|
|
2615
|
-
} else {
|
|
2616
|
-
await _initProject(options);
|
|
2617
|
-
}
|
|
2618
|
-
outro5(color13.green("All done!"));
|
|
2619
|
-
});
|
|
2620
|
-
var _initProject = async (options) => {
|
|
2621
|
-
const storage = get2();
|
|
2622
|
-
const initialConfig = getConfig(options.cwd);
|
|
2623
|
-
const loading = spinner5();
|
|
2624
|
-
if (!options.path) {
|
|
2625
|
-
const result = await text2({
|
|
2626
|
-
message: "Where should we add the blocks?",
|
|
2627
|
-
validate(value) {
|
|
2628
|
-
if (value.trim() === "") return "Please provide a value";
|
|
2629
|
-
},
|
|
2630
|
-
initialValue: initialConfig.isOk() ? initialConfig.unwrap().path : "src/blocks"
|
|
2631
|
-
});
|
|
2632
|
-
if (isCancel4(result)) {
|
|
2633
|
-
cancel4("Canceled!");
|
|
2634
|
-
process.exit(0);
|
|
2635
|
-
}
|
|
2636
|
-
options.path = result;
|
|
2637
|
-
}
|
|
2638
|
-
if (!options.repos) {
|
|
2639
|
-
options.repos = initialConfig.isOk() ? initialConfig.unwrap().repos : [];
|
|
2640
|
-
while (true) {
|
|
2641
|
-
const confirmResult = await confirm4({
|
|
2642
|
-
message: `Add ${options.repos.length > 0 ? "another" : "a"} repo?`,
|
|
2643
|
-
initialValue: options.repos.length === 0
|
|
2644
|
-
// default to yes for first repo
|
|
2645
|
-
});
|
|
2646
|
-
if (isCancel4(confirmResult)) {
|
|
2647
|
-
cancel4("Canceled!");
|
|
2648
|
-
process.exit(0);
|
|
2649
|
-
}
|
|
2650
|
-
if (!confirmResult) break;
|
|
2651
|
-
const result = await text2({
|
|
2652
|
-
message: "Where should we download the blocks from?",
|
|
2653
|
-
placeholder: "github/ieedan/std",
|
|
2654
|
-
validate: (val) => {
|
|
2655
|
-
if (val.trim().length === 0) return "Please provide a value";
|
|
2656
|
-
if (!providers.find((provider2) => provider2.matches(val))) {
|
|
2657
|
-
return `Invalid provider! Valid providers (${providers.map((provider2) => provider2.name()).join(", ")})`;
|
|
2658
|
-
}
|
|
2659
|
-
}
|
|
2660
|
-
});
|
|
2661
|
-
if (isCancel4(result)) {
|
|
2662
|
-
cancel4("Canceled!");
|
|
2663
|
-
process.exit(0);
|
|
2664
|
-
}
|
|
2665
|
-
const provider = providers.find((p) => p.matches(result));
|
|
2666
|
-
if (!provider) {
|
|
2667
|
-
program5.error(color13.red("Invalid provider!"));
|
|
2668
|
-
}
|
|
2669
|
-
const tokenKey = `${provider.name()}-token`;
|
|
2670
|
-
const token = storage.get(tokenKey);
|
|
2671
|
-
if (!token) {
|
|
2672
|
-
const result2 = await confirm4({
|
|
2673
|
-
message: "Would you like to add an auth token?",
|
|
2674
|
-
initialValue: false
|
|
2675
|
-
});
|
|
2676
|
-
if (isCancel4(result2)) {
|
|
2677
|
-
cancel4("Canceled!");
|
|
2678
|
-
process.exit(0);
|
|
2679
|
-
}
|
|
2680
|
-
if (result2) {
|
|
2681
|
-
const response = await password2({
|
|
2682
|
-
message: "Paste your token",
|
|
2683
|
-
validate(value) {
|
|
2684
|
-
if (value.trim() === "") return "Please provide a value";
|
|
2685
|
-
}
|
|
2686
|
-
});
|
|
2687
|
-
if (isCancel4(response)) {
|
|
2688
|
-
cancel4("Canceled!");
|
|
2689
|
-
process.exit(0);
|
|
2690
|
-
}
|
|
2691
|
-
storage.set(tokenKey, response);
|
|
2692
|
-
}
|
|
2693
|
-
}
|
|
2694
|
-
options.repos.push(result);
|
|
2695
|
-
}
|
|
2696
|
-
}
|
|
2697
|
-
if (!options.formatter) {
|
|
2698
|
-
let defaultFormatter = initialConfig.isErr() ? "none" : initialConfig.unwrap().formatter ?? "none";
|
|
2699
|
-
if (fs10.existsSync(path10.join(options.cwd, ".prettierrc"))) {
|
|
2700
|
-
defaultFormatter = "prettier";
|
|
2701
|
-
}
|
|
2702
|
-
if (fs10.existsSync(path10.join(options.cwd, "biome.json"))) {
|
|
2703
|
-
defaultFormatter = "biome";
|
|
2704
|
-
}
|
|
2705
|
-
const response = await select2({
|
|
2706
|
-
message: "What formatter would you like to use?",
|
|
2707
|
-
options: ["Prettier", "Biome", "None"].map((val) => ({
|
|
2708
|
-
value: val.toLowerCase(),
|
|
2709
|
-
label: val
|
|
2710
|
-
})),
|
|
2711
|
-
initialValue: defaultFormatter
|
|
2712
|
-
});
|
|
2713
|
-
if (isCancel4(response)) {
|
|
2714
|
-
cancel4("Canceled!");
|
|
2715
|
-
process.exit(0);
|
|
2716
|
-
}
|
|
2717
|
-
if (response !== "none") {
|
|
2718
|
-
options.formatter = response;
|
|
2719
|
-
}
|
|
2720
|
-
}
|
|
2721
|
-
const config = {
|
|
2722
|
-
$schema: `https://unpkg.com/jsrepo@${context.package.version}/schema.json`,
|
|
2723
|
-
repos: options.repos,
|
|
2724
|
-
path: options.path,
|
|
2725
|
-
includeTests: initialConfig.isOk() && options.tests === void 0 ? initialConfig.unwrap().includeTests : options.tests ?? false,
|
|
2726
|
-
watermark: options.watermark,
|
|
2727
|
-
formatter: options.formatter
|
|
2728
|
-
};
|
|
2729
|
-
loading.start(`Writing config to \`${CONFIG_NAME}\``);
|
|
2730
|
-
fs10.writeFileSync(
|
|
2731
|
-
path10.join(options.cwd, CONFIG_NAME),
|
|
2732
|
-
`${JSON.stringify(config, null, " ")}
|
|
2733
|
-
`
|
|
2734
|
-
);
|
|
2735
|
-
fs10.mkdirSync(path10.join(options.cwd, config.path), { recursive: true });
|
|
2736
|
-
loading.stop(`Wrote config to \`${CONFIG_NAME}\`.`);
|
|
2737
|
-
};
|
|
2738
|
-
var _initRegistry = async (options) => {
|
|
2739
|
-
const loading = spinner5();
|
|
2740
|
-
const packagePath = path10.join(options.cwd, "package.json");
|
|
2741
|
-
if (!fs10.existsSync(packagePath)) {
|
|
2742
|
-
program5.error(color13.red(`Couldn't find your ${color13.bold("package.json")}!`));
|
|
2743
|
-
}
|
|
2744
|
-
if (!options.path) {
|
|
2745
|
-
const response = await text2({
|
|
2746
|
-
message: "Where are your blocks located?",
|
|
2747
|
-
defaultValue: "./blocks",
|
|
2748
|
-
initialValue: "./blocks",
|
|
2749
|
-
placeholder: "./blocks"
|
|
2750
|
-
});
|
|
2751
|
-
if (isCancel4(response)) {
|
|
2752
|
-
cancel4("Canceled!");
|
|
2753
|
-
process.exit(0);
|
|
2754
|
-
}
|
|
2755
|
-
options.path = response;
|
|
2756
|
-
}
|
|
2757
|
-
const pkg = JSON.parse(fs10.readFileSync(packagePath).toString());
|
|
2758
|
-
const scriptAlreadyExists = pkg.scripts !== void 0 && pkg.scripts[options.script] !== void 0;
|
|
2759
|
-
if (!options.yes && scriptAlreadyExists) {
|
|
2760
|
-
const response = await confirm4({
|
|
2761
|
-
message: `The \`${color13.cyan(options.script)}\` already exists overwrite?`,
|
|
2762
|
-
initialValue: false
|
|
2763
|
-
});
|
|
2764
|
-
if (isCancel4(response)) {
|
|
2765
|
-
cancel4("Canceled!");
|
|
2766
|
-
process.exit(0);
|
|
2767
|
-
}
|
|
2768
|
-
if (!response) {
|
|
2769
|
-
const response2 = await text2({
|
|
2770
|
-
message: "What would you like to call the script?",
|
|
2771
|
-
defaultValue: "build:registry",
|
|
2772
|
-
placeholder: "build:registry",
|
|
2773
|
-
initialValue: "build:registry",
|
|
2774
|
-
validate: (val) => {
|
|
2775
|
-
if (val.trim().length === 0) return "Please provide a value!";
|
|
2776
|
-
}
|
|
2777
|
-
});
|
|
2778
|
-
if (isCancel4(response2)) {
|
|
2779
|
-
cancel4("Canceled!");
|
|
2780
|
-
process.exit(0);
|
|
2781
|
-
}
|
|
2782
|
-
options.script = response2;
|
|
2783
|
-
}
|
|
2784
|
-
}
|
|
2785
|
-
const alreadyInstalled = pkg.devDependencies && pkg.devDependencies.jsrepo !== void 0;
|
|
2786
|
-
let installAsDevDependency = options.yes || alreadyInstalled;
|
|
2787
|
-
if (!options.yes && !alreadyInstalled) {
|
|
2788
|
-
const response = await confirm4({
|
|
2789
|
-
message: `Add ${JSREPO} as a dev dependency?`,
|
|
2790
|
-
initialValue: true
|
|
2791
|
-
});
|
|
2792
|
-
if (isCancel4(response)) {
|
|
2793
|
-
cancel4("Canceled!");
|
|
2794
|
-
process.exit(0);
|
|
2795
|
-
}
|
|
2796
|
-
installAsDevDependency = response;
|
|
2797
|
-
}
|
|
2798
|
-
const pm = (await detect2({ cwd: "cwd" }))?.agent ?? "npm";
|
|
2799
|
-
let buildScript = "";
|
|
2800
|
-
if (installAsDevDependency) {
|
|
2801
|
-
buildScript += "jsrepo build ";
|
|
2802
|
-
} else {
|
|
2803
|
-
const command = resolveCommand3(pm, "execute", ["jsrepo", "build"]);
|
|
2804
|
-
if (!command) program5.error(color13.red(`Error resolving execute command for ${pm}`));
|
|
2805
|
-
buildScript += `${command.command} ${command.args.join(" ")} `;
|
|
2806
|
-
}
|
|
2807
|
-
if (options.path !== "./build") {
|
|
2808
|
-
buildScript += `--dirs ${options.path}`;
|
|
2809
|
-
}
|
|
2810
|
-
if (pkg.scripts === void 0) {
|
|
2811
|
-
pkg.scripts = {};
|
|
2812
|
-
}
|
|
2813
|
-
pkg.scripts[options.script] = buildScript;
|
|
2814
|
-
loading.start(`Adding \`${color13.cyan(options.script)}\` to scripts in package.json`);
|
|
2815
|
-
try {
|
|
2816
|
-
fs10.writeFileSync(packagePath, JSON.stringify(pkg, null, " "));
|
|
2817
|
-
} catch (err) {
|
|
2818
|
-
program5.error(color13.red(`Error writing to \`${color13.bold(packagePath)}\`. Error: ${err}`));
|
|
2819
|
-
}
|
|
2820
|
-
loading.stop(`Added \`${color13.cyan(options.script)}\` to scripts in package.json`);
|
|
2821
|
-
let installed = alreadyInstalled;
|
|
2822
|
-
if (installAsDevDependency && !alreadyInstalled) {
|
|
2823
|
-
let shouldInstall = options.yes;
|
|
2824
|
-
if (!options.yes) {
|
|
2825
|
-
const response = await confirm4({
|
|
2826
|
-
message: "Install dependencies?",
|
|
2827
|
-
initialValue: true
|
|
2828
|
-
});
|
|
2829
|
-
if (isCancel4(response)) {
|
|
2830
|
-
cancel4("Canceled!");
|
|
2831
|
-
process.exit(0);
|
|
2832
|
-
}
|
|
2833
|
-
shouldInstall = response;
|
|
2834
|
-
}
|
|
2835
|
-
if (shouldInstall) {
|
|
2836
|
-
loading.start(`Installing ${JSREPO}`);
|
|
2837
|
-
const installedResult = await installDependencies({
|
|
2838
|
-
pm,
|
|
2839
|
-
deps: ["jsrepo"],
|
|
2840
|
-
dev: true,
|
|
2841
|
-
cwd: options.cwd
|
|
2842
|
-
});
|
|
2843
|
-
installedResult.match(
|
|
2844
|
-
() => loading.stop(`Installed ${JSREPO}.`),
|
|
2845
|
-
(err) => {
|
|
2846
|
-
loading.stop(`Failed to install ${JSREPO}.`);
|
|
2847
|
-
program5.error(err);
|
|
2848
|
-
}
|
|
2849
|
-
);
|
|
2850
|
-
installed = true;
|
|
2851
|
-
}
|
|
2852
|
-
}
|
|
2853
|
-
let steps = [];
|
|
2854
|
-
if (!installed && installAsDevDependency) {
|
|
2855
|
-
const cmd = resolveCommand3(pm, "install", ["jsrepo", "-D"]);
|
|
2856
|
-
steps.push(
|
|
2857
|
-
`Install ${JSREPO} as a dev dependency \`${color13.cyan(`${cmd?.command} ${cmd?.args.join(" ")}`)}\``
|
|
2858
|
-
);
|
|
2859
|
-
}
|
|
2860
|
-
steps.push(`Add blocks to \`${color13.cyan(options.path)}\`.`);
|
|
2861
|
-
const runScript = resolveCommand3(pm, "run", [options.script]);
|
|
2862
|
-
steps.push(
|
|
2863
|
-
`Run \`${color13.cyan(`${runScript?.command} ${runScript?.args.join(" ")}`)}\` to build the registry.`
|
|
2864
|
-
);
|
|
2865
|
-
steps = steps.map((step, i) => `${i + 1}. ${step}`);
|
|
2866
|
-
const next = nextSteps(steps);
|
|
2867
|
-
process.stdout.write(next);
|
|
2868
|
-
};
|
|
2869
|
-
|
|
2870
|
-
// src/commands/test.ts
|
|
2871
|
-
import fs11 from "node:fs";
|
|
2872
|
-
import { cancel as cancel5, confirm as confirm5, isCancel as isCancel5, outro as outro6, spinner as spinner6 } from "@clack/prompts";
|
|
2873
|
-
import color14 from "chalk";
|
|
2874
|
-
import { Argument, Command as Command6, program as program6 } from "commander";
|
|
2875
|
-
import { execa as execa2 } from "execa";
|
|
2876
|
-
import { resolveCommand as resolveCommand4 } from "package-manager-detector/commands";
|
|
2877
|
-
import { detect as detect3 } from "package-manager-detector/detect";
|
|
2878
|
-
import path11 from "pathe";
|
|
2879
|
-
import { Project as Project2 } from "ts-morph";
|
|
2880
|
-
import * as v10 from "valibot";
|
|
2881
|
-
var schema7 = v10.object({
|
|
2882
|
-
repo: v10.optional(v10.string()),
|
|
2883
|
-
allow: v10.boolean(),
|
|
2884
|
-
debug: v10.boolean(),
|
|
2885
|
-
verbose: v10.boolean(),
|
|
2886
|
-
cwd: v10.string()
|
|
2887
|
-
});
|
|
2888
|
-
var test = new Command6("test").description("Tests local blocks against most recent remote tests.").addArgument(new Argument("[blocks...]", "The blocks you want to test.").default([])).option("--repo <repo>", "Repository to download the blocks from.").option("-A, --allow", "Allow jsrepo to download code from the provided repo.", false).option("--debug", "Leaves the temp test file around for debugging upon failure.", false).option("--verbose", "Include debug logs.", false).option("--cwd <path>", "The current working directory.", process.cwd()).action(async (blockNames, opts) => {
|
|
2889
|
-
const options = v10.parse(schema7, opts);
|
|
2890
|
-
_intro(context.package.version);
|
|
2891
|
-
await _test(blockNames, options);
|
|
2892
|
-
outro6(color14.green("All done!"));
|
|
2893
|
-
});
|
|
2894
|
-
var _test = async (blockNames, options) => {
|
|
2895
|
-
const verbose = (msg) => {
|
|
2896
|
-
if (options.verbose) {
|
|
2897
|
-
console.info(`${INFO} ${msg}`);
|
|
2898
|
-
}
|
|
2899
|
-
};
|
|
2900
|
-
verbose(`Attempting to test ${JSON.stringify(blockNames)}`);
|
|
2901
|
-
const config = getConfig(options.cwd).match(
|
|
2902
|
-
(val) => val,
|
|
2903
|
-
(err) => program6.error(color14.red(err))
|
|
2904
|
-
);
|
|
2905
|
-
const loading = spinner6();
|
|
2906
|
-
const blocksMap = /* @__PURE__ */ new Map();
|
|
2907
|
-
let repoPaths = config.repos;
|
|
2908
|
-
if (options.repo) repoPaths = [options.repo];
|
|
2909
|
-
if (!options.allow && options.repo) {
|
|
2910
|
-
const result = await confirm5({
|
|
2911
|
-
message: `Allow ${color14.cyan("jsrepo")} to download and run code from ${color14.cyan(options.repo)}?`,
|
|
2912
|
-
initialValue: true
|
|
2913
|
-
});
|
|
2914
|
-
if (isCancel5(result) || !result) {
|
|
2915
|
-
cancel5("Canceled!");
|
|
2916
|
-
process.exit(0);
|
|
2917
|
-
}
|
|
2918
|
-
}
|
|
2919
|
-
verbose(`Fetching blocks from ${color14.cyan(repoPaths.join(", "))}`);
|
|
2920
|
-
if (!options.verbose) loading.start(`Fetching blocks from ${color14.cyan(repoPaths.join(", "))}`);
|
|
2921
|
-
for (const repo of repoPaths) {
|
|
2922
|
-
const providerInfo = (await getProviderInfo(repo)).match(
|
|
2923
|
-
(info) => info,
|
|
2924
|
-
(err) => program6.error(color14.red(err))
|
|
2925
|
-
);
|
|
2926
|
-
const manifest = await providerInfo.provider.fetchManifest(providerInfo);
|
|
2927
|
-
verbose(`Got info for provider ${color14.cyan(providerInfo.name)}`);
|
|
2928
|
-
if (manifest.isErr()) {
|
|
2929
|
-
if (!options.verbose) loading.stop(`Error fetching ${color14.cyan(repo)}`);
|
|
2930
|
-
program6.error(
|
|
2931
|
-
color14.red(
|
|
2932
|
-
`There was an error fetching the \`${OUTPUT_FILE}\` from the repository ${color14.cyan(
|
|
2933
|
-
repo
|
|
2934
|
-
)} make sure the target repository has a \`${OUTPUT_FILE}\` in its root?`
|
|
2935
|
-
)
|
|
2936
|
-
);
|
|
2937
|
-
}
|
|
2938
|
-
const categories = manifest.unwrap();
|
|
2939
|
-
for (const category of categories) {
|
|
2940
|
-
for (const block of category.blocks) {
|
|
2941
|
-
blocksMap.set(
|
|
2942
|
-
`${providerInfo.name}/${providerInfo.owner}/${providerInfo.repoName}/${category.name}/${block.name}`,
|
|
2943
|
-
{
|
|
2944
|
-
...block,
|
|
2945
|
-
sourceRepo: providerInfo
|
|
2946
|
-
}
|
|
2947
|
-
);
|
|
2948
|
-
}
|
|
2949
|
-
}
|
|
2950
|
-
}
|
|
2951
|
-
verbose(`Retrieved blocks from ${color14.cyan(repoPaths.join(", "))}`);
|
|
2952
|
-
if (!options.verbose) loading.stop(`Retrieved blocks from ${color14.cyan(repoPaths.join(", "))}`);
|
|
2953
|
-
const tempTestDirectory = path11.resolve(
|
|
2954
|
-
path11.join(options.cwd, `blocks-tests-temp-${Date.now()}`)
|
|
2955
|
-
);
|
|
2956
|
-
verbose(`Trying to create the temp directory ${color14.bold(tempTestDirectory)}.`);
|
|
2957
|
-
fs11.mkdirSync(tempTestDirectory, { recursive: true });
|
|
2958
|
-
const cleanUp = () => {
|
|
2959
|
-
fs11.rmSync(tempTestDirectory, { recursive: true, force: true });
|
|
2960
|
-
};
|
|
2961
|
-
const installedBlocks = getInstalled(blocksMap, config, options.cwd).map(
|
|
2962
|
-
(val) => val.specifier
|
|
2963
|
-
);
|
|
2964
|
-
let testingBlocks = blockNames;
|
|
2965
|
-
if (blockNames.length === 0) {
|
|
2966
|
-
testingBlocks = installedBlocks;
|
|
2967
|
-
}
|
|
2968
|
-
if (testingBlocks.length === 0) {
|
|
2969
|
-
cleanUp();
|
|
2970
|
-
program6.error(color14.red("There were no blocks found in your project!"));
|
|
2971
|
-
}
|
|
2972
|
-
const testingBlocksMapped = [];
|
|
2973
|
-
for (const blockSpecifier of testingBlocks) {
|
|
2974
|
-
let block = void 0;
|
|
2975
|
-
if (!providers.find((p) => blockSpecifier.startsWith(p.name()))) {
|
|
2976
|
-
for (const repo of repoPaths) {
|
|
2977
|
-
const providerInfo = (await getProviderInfo(repo)).unwrap();
|
|
2978
|
-
const tempBlock = blocksMap.get(
|
|
2979
|
-
`${providerInfo.name}/${providerInfo.owner}/${providerInfo.repoName}/${blockSpecifier}`
|
|
2980
|
-
);
|
|
2981
|
-
if (tempBlock === void 0) continue;
|
|
2982
|
-
block = tempBlock;
|
|
2983
|
-
break;
|
|
2984
|
-
}
|
|
2985
|
-
} else {
|
|
2986
|
-
if (repoPaths.length === 0) {
|
|
2987
|
-
const [providerName, owner, repoName, ...rest] = blockSpecifier.split("/");
|
|
2988
|
-
let repo;
|
|
2989
|
-
if (rest.length > 2) {
|
|
2990
|
-
repo = `${providerName}/${owner}/${repoName}/${rest.slice(0, rest.length - 2).join("/")}`;
|
|
2991
|
-
} else {
|
|
2992
|
-
repo = `${providerName}/${owner}/${repoName}`;
|
|
2993
|
-
}
|
|
2994
|
-
const providerInfo = (await getProviderInfo(repo)).match(
|
|
2995
|
-
(val) => val,
|
|
2996
|
-
(err) => program6.error(color14.red(err))
|
|
2997
|
-
);
|
|
2998
|
-
const categories = (await providerInfo.provider.fetchManifest(providerInfo)).match(
|
|
2999
|
-
(val) => val,
|
|
3000
|
-
(err) => program6.error(color14.red(err))
|
|
3001
|
-
);
|
|
3002
|
-
for (const category of categories) {
|
|
3003
|
-
for (const block2 of category.blocks) {
|
|
3004
|
-
blocksMap.set(
|
|
3005
|
-
`${providerInfo.name}/${providerInfo.owner}/${providerInfo.repoName}/${category.name}/${block2.name}`,
|
|
3006
|
-
{
|
|
3007
|
-
...block2,
|
|
3008
|
-
sourceRepo: providerInfo
|
|
3009
|
-
}
|
|
3010
|
-
);
|
|
3011
|
-
}
|
|
3012
|
-
}
|
|
3013
|
-
}
|
|
3014
|
-
block = blocksMap.get(blockSpecifier);
|
|
3015
|
-
}
|
|
3016
|
-
if (!block) {
|
|
3017
|
-
program6.error(
|
|
3018
|
-
color14.red(`Invalid block! ${color14.bold(blockSpecifier)} does not exist!`)
|
|
3019
|
-
);
|
|
3020
|
-
}
|
|
3021
|
-
testingBlocksMapped.push({ name: blockSpecifier, block });
|
|
3022
|
-
}
|
|
3023
|
-
for (const { block } of testingBlocksMapped) {
|
|
3024
|
-
const providerInfo = block.sourceRepo;
|
|
3025
|
-
const fullSpecifier = `${block.sourceRepo.url}/${block.category}/${block.name}`;
|
|
3026
|
-
if (!options.verbose) {
|
|
3027
|
-
loading.start(`Setting up test file for ${color14.cyan(fullSpecifier)}`);
|
|
3028
|
-
}
|
|
3029
|
-
if (!block.tests) {
|
|
3030
|
-
loading.stop(`No tests found for ${color14.cyan(fullSpecifier)}`);
|
|
3031
|
-
continue;
|
|
3032
|
-
}
|
|
3033
|
-
const getSourceFile = async (filePath) => {
|
|
3034
|
-
const content = await providerInfo.provider.fetchRaw(providerInfo, filePath);
|
|
3035
|
-
if (content.isErr()) {
|
|
3036
|
-
loading.stop(color14.red(`Error fetching ${color14.bold(filePath)}`));
|
|
3037
|
-
program6.error(color14.red(`There was an error trying to get ${fullSpecifier}`));
|
|
3038
|
-
}
|
|
3039
|
-
return content.unwrap();
|
|
3040
|
-
};
|
|
3041
|
-
verbose(`Downloading and copying test files for ${fullSpecifier}`);
|
|
3042
|
-
const testFiles = [];
|
|
3043
|
-
for (const testFile of block.files.filter((file) => isTestFile(file))) {
|
|
3044
|
-
const content = await getSourceFile(path11.join(block.directory, testFile));
|
|
3045
|
-
const destPath = path11.join(tempTestDirectory, testFile);
|
|
3046
|
-
fs11.writeFileSync(destPath, content);
|
|
3047
|
-
testFiles.push(destPath);
|
|
3048
|
-
}
|
|
3049
|
-
const project = new Project2();
|
|
3050
|
-
for (const file of testFiles) {
|
|
3051
|
-
verbose(`Opening test file ${file}`);
|
|
3052
|
-
const tempFile = project.addSourceFileAtPath(file);
|
|
3053
|
-
for (const importDeclaration of tempFile.getImportDeclarations()) {
|
|
3054
|
-
const moduleSpecifier = importDeclaration.getModuleSpecifierValue();
|
|
3055
|
-
let newModuleSpecifier = void 0;
|
|
3056
|
-
if (moduleSpecifier.startsWith(".")) {
|
|
3057
|
-
if (block.subdirectory) {
|
|
3058
|
-
newModuleSpecifier = path11.join(
|
|
3059
|
-
"../",
|
|
3060
|
-
config.path,
|
|
3061
|
-
block.category,
|
|
3062
|
-
block.name,
|
|
3063
|
-
moduleSpecifier
|
|
3064
|
-
);
|
|
3065
|
-
} else {
|
|
3066
|
-
newModuleSpecifier = path11.join(
|
|
3067
|
-
"../",
|
|
3068
|
-
config.path,
|
|
3069
|
-
block.category,
|
|
3070
|
-
moduleSpecifier
|
|
3071
|
-
);
|
|
3072
|
-
}
|
|
3073
|
-
}
|
|
3074
|
-
if (newModuleSpecifier) {
|
|
3075
|
-
importDeclaration.setModuleSpecifier(newModuleSpecifier.replaceAll(/\\/g, "/"));
|
|
3076
|
-
}
|
|
3077
|
-
}
|
|
3078
|
-
}
|
|
3079
|
-
project.saveSync();
|
|
3080
|
-
verbose(`Completed ${color14.cyan.bold(fullSpecifier)} test file`);
|
|
3081
|
-
if (!options.verbose) {
|
|
3082
|
-
loading.stop(`Completed setup for ${color14.bold(fullSpecifier)}`);
|
|
3083
|
-
}
|
|
3084
|
-
}
|
|
3085
|
-
verbose("Beginning testing");
|
|
3086
|
-
const pm = await detect3({ cwd: options.cwd });
|
|
3087
|
-
if (pm == null) {
|
|
3088
|
-
program6.error(color14.red("Could not detect package manager"));
|
|
3089
|
-
}
|
|
3090
|
-
const resolved = resolveCommand4(pm.agent, "execute", ["vitest", "run", tempTestDirectory]);
|
|
3091
|
-
if (resolved == null) {
|
|
3092
|
-
program6.error(color14.red(`Could not resolve add command for '${pm.agent}'.`));
|
|
3093
|
-
}
|
|
3094
|
-
const { command, args } = resolved;
|
|
3095
|
-
const testCommand = `${command} ${args.join(" ")}`;
|
|
3096
|
-
const testingProcess = execa2({
|
|
3097
|
-
cwd: options.cwd,
|
|
3098
|
-
stdio: ["ignore", "pipe", "pipe"]
|
|
3099
|
-
})`${testCommand}`;
|
|
3100
|
-
const handler = (data) => console.info(data.toString());
|
|
3101
|
-
testingProcess.stdout.on("data", handler);
|
|
3102
|
-
testingProcess.stderr.on("data", handler);
|
|
3103
|
-
try {
|
|
3104
|
-
await testingProcess;
|
|
3105
|
-
cleanUp();
|
|
3106
|
-
} catch (err) {
|
|
3107
|
-
if (options.debug) {
|
|
3108
|
-
console.info(
|
|
3109
|
-
`${color14.bold("--debug")} flag provided. Skipping cleanup. Run '${color14.bold(
|
|
3110
|
-
testCommand
|
|
3111
|
-
)}' to retry tests.
|
|
3112
|
-
`
|
|
3113
|
-
);
|
|
3114
|
-
} else {
|
|
3115
|
-
cleanUp();
|
|
3116
|
-
}
|
|
3117
|
-
program6.error(color14.red(`Tests failed! Error ${err}`));
|
|
3118
|
-
}
|
|
3119
|
-
};
|
|
3120
|
-
|
|
3121
|
-
// src/commands/update.ts
|
|
3122
|
-
import fs12 from "node:fs";
|
|
3123
|
-
import { cancel as cancel6, confirm as confirm6, isCancel as isCancel6, multiselect as multiselect2, outro as outro7, spinner as spinner7 } from "@clack/prompts";
|
|
3124
|
-
import color15 from "chalk";
|
|
3125
|
-
import { Command as Command7, program as program7 } from "commander";
|
|
3126
|
-
import { diffLines as diffLines2 } from "diff";
|
|
3127
|
-
import { resolveCommand as resolveCommand5 } from "package-manager-detector/commands";
|
|
3128
|
-
import { detect as detect4 } from "package-manager-detector/detect";
|
|
3129
|
-
import path12 from "pathe";
|
|
3130
|
-
import * as v11 from "valibot";
|
|
3131
|
-
var schema8 = v11.object({
|
|
3132
|
-
all: v11.boolean(),
|
|
3133
|
-
expand: v11.boolean(),
|
|
3134
|
-
maxUnchanged: v11.number(),
|
|
3135
|
-
repo: v11.optional(v11.string()),
|
|
3136
|
-
allow: v11.boolean(),
|
|
3137
|
-
yes: v11.boolean(),
|
|
3138
|
-
verbose: v11.boolean(),
|
|
3139
|
-
cwd: v11.string()
|
|
3140
|
-
});
|
|
3141
|
-
var update = new Command7("update").argument("[blocks...]", "Names of the blocks you want to update. ex: (utils/math)").option("--all", "Update all installed components.", false).option("-E, --expand", "Expands the diff so you see everything.", false).option(
|
|
3142
|
-
"--max-unchanged <number>",
|
|
3143
|
-
"Maximum unchanged lines that will show without being collapsed.",
|
|
3144
|
-
(val) => Number.parseInt(val),
|
|
3145
|
-
// this is such a dumb api thing
|
|
3146
|
-
3
|
|
3147
|
-
).option("--repo <repo>", "Repository to download the blocks from.").option("-A, --allow", "Allow jsrepo to download code from the provided repo.", false).option("-y, --yes", "Skip confirmation prompt.", false).option("--verbose", "Include debug logs.", false).option("--cwd <path>", "The current working directory.", process.cwd()).action(async (blockNames, opts) => {
|
|
3148
|
-
const options = v11.parse(schema8, opts);
|
|
3149
|
-
_intro(context.package.version);
|
|
3150
|
-
await _update(blockNames, options);
|
|
3151
|
-
outro7(color15.green("All done!"));
|
|
3152
|
-
});
|
|
3153
|
-
var _update = async (blockNames, options) => {
|
|
3154
|
-
const verbose = (msg) => {
|
|
3155
|
-
if (options.verbose) {
|
|
3156
|
-
console.info(`${INFO} ${msg}`);
|
|
3157
|
-
}
|
|
3158
|
-
};
|
|
3159
|
-
verbose(`Attempting to update ${JSON.stringify(blockNames)}`);
|
|
3160
|
-
const loading = spinner7();
|
|
3161
|
-
const config = getConfig(options.cwd).match(
|
|
3162
|
-
(val) => val,
|
|
3163
|
-
(err) => program7.error(color15.red(err))
|
|
3164
|
-
);
|
|
3165
|
-
let repoPaths = config.repos;
|
|
3166
|
-
if (options.repo) repoPaths = [options.repo];
|
|
3167
|
-
for (const blockSpecifier of blockNames) {
|
|
3168
|
-
if (providers.find((p) => blockSpecifier.startsWith(p.name()))) {
|
|
3169
|
-
program7.error(
|
|
3170
|
-
color15.red(
|
|
3171
|
-
`Invalid value provided for block names \`${color15.bold(blockSpecifier)}\`. Block names are expected to be provided in the format of \`${color15.bold("<category>/<name>")}\``
|
|
3172
|
-
)
|
|
3173
|
-
);
|
|
3174
|
-
}
|
|
3175
|
-
}
|
|
3176
|
-
if (!options.allow && options.repo) {
|
|
3177
|
-
const result = await confirm6({
|
|
3178
|
-
message: `Allow ${color15.cyan("jsrepo")} to download and run code from ${color15.cyan(options.repo)}?`,
|
|
3179
|
-
initialValue: true
|
|
3180
|
-
});
|
|
3181
|
-
if (isCancel6(result) || !result) {
|
|
3182
|
-
cancel6("Canceled!");
|
|
3183
|
-
process.exit(0);
|
|
3184
|
-
}
|
|
3185
|
-
}
|
|
3186
|
-
verbose(`Fetching blocks from ${color15.cyan(repoPaths.join(", "))}`);
|
|
3187
|
-
if (!options.verbose) loading.start(`Fetching blocks from ${color15.cyan(repoPaths.join(", "))}`);
|
|
3188
|
-
const blocksMap = (await fetchBlocks(...repoPaths)).match(
|
|
3189
|
-
(val) => val,
|
|
3190
|
-
({ repo, message }) => {
|
|
3191
|
-
loading.stop(`Failed fetching blocks from ${color15.cyan(repo)}`);
|
|
3192
|
-
program7.error(color15.red(message));
|
|
3193
|
-
}
|
|
3194
|
-
);
|
|
3195
|
-
if (!options.verbose) loading.stop(`Retrieved blocks from ${color15.cyan(repoPaths.join(", "))}`);
|
|
3196
|
-
verbose(`Retrieved blocks from ${color15.cyan(repoPaths.join(", "))}`);
|
|
3197
|
-
const installedBlocks = getInstalled(blocksMap, config, options.cwd);
|
|
3198
|
-
if (installedBlocks.length === 0) {
|
|
3199
|
-
program7.error(
|
|
3200
|
-
color15.red(
|
|
3201
|
-
`You haven't installed any blocks yet. Did you mean to \`${color15.bold("add")}\`?`
|
|
3202
|
-
)
|
|
3203
|
-
);
|
|
3204
|
-
}
|
|
3205
|
-
let updatingBlockNames = blockNames;
|
|
3206
|
-
if (options.all) {
|
|
3207
|
-
updatingBlockNames = installedBlocks.map((block) => block.specifier);
|
|
3208
|
-
}
|
|
3209
|
-
if (updatingBlockNames.length === 0) {
|
|
3210
|
-
const promptResult = await multiselect2({
|
|
3211
|
-
message: "Which blocks would you like to update?",
|
|
3212
|
-
options: installedBlocks.map((block) => {
|
|
3213
|
-
return {
|
|
3214
|
-
label: `${color15.cyan(block.block.category)}/${block.block.name}`,
|
|
3215
|
-
value: block.specifier
|
|
3216
|
-
};
|
|
3217
|
-
}),
|
|
3218
|
-
required: true
|
|
3219
|
-
});
|
|
3220
|
-
if (isCancel6(promptResult)) {
|
|
3221
|
-
cancel6("Canceled!");
|
|
3222
|
-
process.exit(0);
|
|
3223
|
-
}
|
|
3224
|
-
updatingBlockNames = promptResult;
|
|
3225
|
-
}
|
|
3226
|
-
verbose(`Preparing to update ${color15.cyan(updatingBlockNames.join(", "))}`);
|
|
3227
|
-
const updatingBlocks = (await resolveTree(updatingBlockNames, blocksMap, repoPaths)).match(
|
|
3228
|
-
(val) => val,
|
|
3229
|
-
program7.error
|
|
3230
|
-
);
|
|
3231
|
-
const pm = (await detect4({ cwd: options.cwd }))?.agent ?? "npm";
|
|
3232
|
-
const tasks = [];
|
|
3233
|
-
let devDeps = /* @__PURE__ */ new Set();
|
|
3234
|
-
let deps = /* @__PURE__ */ new Set();
|
|
3235
|
-
const { prettierOptions, biomeOptions } = await loadFormatterConfig({
|
|
3236
|
-
formatter: config.formatter,
|
|
3237
|
-
cwd: options.cwd
|
|
3238
|
-
});
|
|
3239
|
-
for (const { block } of updatingBlocks) {
|
|
3240
|
-
const fullSpecifier = `${block.sourceRepo.url}/${block.category}/${block.name}`;
|
|
3241
|
-
const watermark = getWatermark(context.package.version, block.sourceRepo.url);
|
|
3242
|
-
const providerInfo = block.sourceRepo;
|
|
3243
|
-
verbose(`Attempting to add ${fullSpecifier}`);
|
|
3244
|
-
const directory = path12.join(options.cwd, config.path, block.category);
|
|
3245
|
-
const files = [];
|
|
3246
|
-
const getSourceFile = async (filePath) => {
|
|
3247
|
-
const content = await providerInfo.provider.fetchRaw(providerInfo, filePath, {
|
|
3248
|
-
verbose
|
|
3249
|
-
});
|
|
3250
|
-
if (content.isErr()) {
|
|
3251
|
-
loading.stop(color15.red(`Error fetching ${color15.bold(filePath)}`));
|
|
3252
|
-
program7.error(color15.red(`There was an error trying to get ${fullSpecifier}`));
|
|
3253
|
-
}
|
|
3254
|
-
return content.unwrap();
|
|
3255
|
-
};
|
|
3256
|
-
for (const sourceFile of block.files) {
|
|
3257
|
-
if (!config.includeTests && isTestFile(sourceFile)) continue;
|
|
3258
|
-
const sourcePath = path12.join(block.directory, sourceFile);
|
|
3259
|
-
let destPath;
|
|
3260
|
-
if (block.subdirectory) {
|
|
3261
|
-
destPath = path12.join(directory, block.name, sourceFile);
|
|
3262
|
-
} else {
|
|
3263
|
-
destPath = path12.join(directory, sourceFile);
|
|
3264
|
-
}
|
|
3265
|
-
const content = await getSourceFile(sourcePath);
|
|
3266
|
-
fs12.mkdirSync(destPath.slice(0, destPath.length - sourceFile.length), {
|
|
3267
|
-
recursive: true
|
|
3268
|
-
});
|
|
3269
|
-
files.push({ content, destPath, fileName: sourceFile });
|
|
3270
|
-
}
|
|
3271
|
-
process.stdout.write(`${VERTICAL_LINE}
|
|
3272
|
-
`);
|
|
3273
|
-
process.stdout.write(`${VERTICAL_LINE} ${fullSpecifier}
|
|
3274
|
-
`);
|
|
3275
|
-
for (const file of files) {
|
|
3276
|
-
const lang = languages.find((lang2) => lang2.matches(file.destPath));
|
|
3277
|
-
let remoteContent = file.content;
|
|
3278
|
-
if (lang) {
|
|
3279
|
-
if (config.watermark) {
|
|
3280
|
-
const comment = lang.comment(watermark);
|
|
3281
|
-
remoteContent = `${comment}
|
|
3282
|
-
|
|
3283
|
-
${remoteContent}`;
|
|
3284
|
-
}
|
|
3285
|
-
remoteContent = await lang.format(remoteContent, {
|
|
3286
|
-
filePath: file.destPath,
|
|
3287
|
-
formatter: config.formatter,
|
|
3288
|
-
prettierOptions,
|
|
3289
|
-
biomeOptions
|
|
3290
|
-
});
|
|
3291
|
-
}
|
|
3292
|
-
let acceptedChanges = options.yes;
|
|
3293
|
-
if (!options.yes) {
|
|
3294
|
-
process.stdout.write(`${VERTICAL_LINE}
|
|
3295
|
-
`);
|
|
3296
|
-
let localContent = "";
|
|
3297
|
-
if (fs12.existsSync(file.destPath)) {
|
|
3298
|
-
localContent = fs12.readFileSync(file.destPath).toString();
|
|
3299
|
-
}
|
|
3300
|
-
const changes = diffLines2(localContent, remoteContent);
|
|
3301
|
-
const from = path12.join(
|
|
3302
|
-
`${providerInfo.name}/${providerInfo.owner}/${providerInfo.repoName}`,
|
|
3303
|
-
file.fileName
|
|
3304
|
-
);
|
|
3305
|
-
const to = path12.relative(options.cwd, file.destPath);
|
|
3306
|
-
const formattedDiff = formatDiff({
|
|
3307
|
-
from,
|
|
3308
|
-
to,
|
|
3309
|
-
changes,
|
|
3310
|
-
expand: options.expand,
|
|
3311
|
-
maxUnchanged: options.maxUnchanged,
|
|
3312
|
-
colorAdded: color15.greenBright,
|
|
3313
|
-
colorRemoved: color15.redBright,
|
|
3314
|
-
colorCharsAdded: color15.bgGreenBright,
|
|
3315
|
-
colorCharsRemoved: color15.bgRedBright,
|
|
3316
|
-
prefix: () => `${VERTICAL_LINE} `,
|
|
3317
|
-
onUnchanged: ({ from: from2, to: to2, prefix }) => `${prefix?.() ?? ""}${color15.cyan(from2)} \u2192 ${color15.gray(to2)} ${color15.gray("(unchanged)")}
|
|
3318
|
-
`,
|
|
3319
|
-
intro: ({ from: from2, to: to2, changes: changes2, prefix }) => {
|
|
3320
|
-
const totalChanges = changes2.filter((a) => a.added).length;
|
|
3321
|
-
return `${prefix?.() ?? ""}${color15.cyan(from2)} \u2192 ${color15.gray(to2)} (${totalChanges} change${totalChanges === 1 ? "" : "s"})
|
|
3322
|
-
${prefix?.() ?? ""}
|
|
3323
|
-
`;
|
|
3324
|
-
}
|
|
3325
|
-
});
|
|
3326
|
-
process.stdout.write(formattedDiff);
|
|
3327
|
-
if (changes.length > 1 || localContent === "") {
|
|
3328
|
-
const confirmResult = await confirm6({
|
|
3329
|
-
message: "Accept changes?",
|
|
3330
|
-
initialValue: true
|
|
3331
|
-
});
|
|
3332
|
-
if (isCancel6(confirmResult)) {
|
|
3333
|
-
cancel6("Canceled!");
|
|
3334
|
-
process.exit(0);
|
|
3335
|
-
}
|
|
3336
|
-
acceptedChanges = confirmResult;
|
|
3337
|
-
}
|
|
3338
|
-
}
|
|
3339
|
-
if (acceptedChanges) {
|
|
3340
|
-
await runTasks(
|
|
3341
|
-
[
|
|
3342
|
-
{
|
|
3343
|
-
loadingMessage: `Writing changes to ${color15.cyan(file.destPath)}`,
|
|
3344
|
-
completedMessage: `Wrote changes to ${color15.cyan(file.destPath)}.`,
|
|
3345
|
-
run: async () => fs12.writeFileSync(file.destPath, remoteContent)
|
|
3346
|
-
}
|
|
3347
|
-
],
|
|
3348
|
-
{
|
|
3349
|
-
verbose: options.verbose ? verbose : void 0
|
|
3350
|
-
}
|
|
3351
|
-
);
|
|
3352
|
-
}
|
|
3353
|
-
}
|
|
3354
|
-
if (config.includeTests && block.tests) {
|
|
3355
|
-
verbose("Trying to include tests");
|
|
3356
|
-
const { devDependencies } = JSON.parse(
|
|
3357
|
-
fs12.readFileSync(path12.join(options.cwd, "package.json")).toString()
|
|
3358
|
-
);
|
|
3359
|
-
if (devDependencies === void 0 || devDependencies.vitest === void 0) {
|
|
3360
|
-
devDeps.add("vitest");
|
|
3361
|
-
}
|
|
3362
|
-
}
|
|
3363
|
-
for (const dep of block.devDependencies) {
|
|
3364
|
-
devDeps.add(dep);
|
|
3365
|
-
}
|
|
3366
|
-
for (const dep of block.dependencies) {
|
|
3367
|
-
deps.add(dep);
|
|
3368
|
-
}
|
|
3369
|
-
}
|
|
3370
|
-
await runTasks(tasks, { verbose: options.verbose ? verbose : void 0 });
|
|
3371
|
-
const requiredDependencies = returnShouldInstall(deps, devDeps, { cwd: options.cwd });
|
|
3372
|
-
deps = requiredDependencies.dependencies;
|
|
3373
|
-
devDeps = requiredDependencies.devDependencies;
|
|
3374
|
-
const hasDependencies = deps.size > 0 || devDeps.size > 0;
|
|
3375
|
-
if (hasDependencies) {
|
|
3376
|
-
let install = options.yes;
|
|
3377
|
-
if (!options.yes) {
|
|
3378
|
-
const result = await confirm6({
|
|
3379
|
-
message: "Would you like to install dependencies?",
|
|
3380
|
-
initialValue: true
|
|
3381
|
-
});
|
|
3382
|
-
if (isCancel6(result)) {
|
|
3383
|
-
cancel6("Canceled!");
|
|
3384
|
-
process.exit(0);
|
|
3385
|
-
}
|
|
3386
|
-
install = result;
|
|
3387
|
-
}
|
|
3388
|
-
if (install) {
|
|
3389
|
-
if (deps.size > 0) {
|
|
3390
|
-
if (!options.verbose)
|
|
3391
|
-
loading.start(`Installing dependencies with ${color15.cyan(pm)}`);
|
|
3392
|
-
(await installDependencies({
|
|
3393
|
-
pm,
|
|
3394
|
-
deps: Array.from(deps),
|
|
3395
|
-
dev: false,
|
|
3396
|
-
cwd: options.cwd
|
|
3397
|
-
})).match(
|
|
3398
|
-
(installed) => {
|
|
3399
|
-
if (!options.verbose)
|
|
3400
|
-
loading.stop(`Installed ${color15.cyan(installed.join(", "))}`);
|
|
3401
|
-
},
|
|
3402
|
-
(err) => {
|
|
3403
|
-
if (!options.verbose) loading.stop("Failed to install dependencies");
|
|
3404
|
-
program7.error(err);
|
|
3405
|
-
}
|
|
3406
|
-
);
|
|
3407
|
-
}
|
|
3408
|
-
if (devDeps.size > 0) {
|
|
3409
|
-
if (!options.verbose)
|
|
3410
|
-
loading.start(`Installing dependencies with ${color15.cyan(pm)}`);
|
|
3411
|
-
(await installDependencies({
|
|
3412
|
-
pm,
|
|
3413
|
-
deps: Array.from(devDeps),
|
|
3414
|
-
dev: true,
|
|
3415
|
-
cwd: options.cwd
|
|
3416
|
-
})).match(
|
|
3417
|
-
(installed) => {
|
|
3418
|
-
if (!options.verbose)
|
|
3419
|
-
loading.stop(`Installed ${color15.cyan(installed.join(", "))}`);
|
|
3420
|
-
},
|
|
3421
|
-
(err) => {
|
|
3422
|
-
if (!options.verbose) loading.stop("Failed to install dev dependencies");
|
|
3423
|
-
program7.error(err);
|
|
3424
|
-
}
|
|
3425
|
-
);
|
|
3426
|
-
}
|
|
3427
|
-
}
|
|
3428
|
-
let steps = [];
|
|
3429
|
-
if (!install) {
|
|
3430
|
-
if (deps.size > 0) {
|
|
3431
|
-
const cmd = resolveCommand5(pm, "install", [...deps]);
|
|
3432
|
-
steps.push(
|
|
3433
|
-
`Install dependencies \`${color15.cyan(`${cmd?.command} ${cmd?.args.join(" ")}`)}\``
|
|
3434
|
-
);
|
|
3435
|
-
}
|
|
3436
|
-
if (devDeps.size > 0) {
|
|
3437
|
-
const cmd = resolveCommand5(pm, "install", [...devDeps, "-D"]);
|
|
3438
|
-
steps.push(
|
|
3439
|
-
`Install dev dependencies \`${color15.cyan(`${cmd?.command} ${cmd?.args.join(" ")}`)}\``
|
|
3440
|
-
);
|
|
3441
|
-
}
|
|
3442
|
-
}
|
|
3443
|
-
steps = steps.map((step, i) => `${i + 1}. ${step}`);
|
|
3444
|
-
if (!install) {
|
|
3445
|
-
steps.push("");
|
|
3446
|
-
}
|
|
3447
|
-
steps.push(`Import the blocks from \`${color15.cyan(config.path)}\``);
|
|
3448
|
-
const next = nextSteps(steps);
|
|
3449
|
-
process.stdout.write(next);
|
|
3450
|
-
}
|
|
3451
|
-
};
|
|
3452
|
-
|
|
3453
|
-
// src/index.ts
|
|
3454
|
-
var resolveRelativeToRoot = (p) => {
|
|
3455
|
-
const dirname = fileURLToPath(import.meta.url);
|
|
3456
|
-
return path13.join(dirname, "../..", p);
|
|
3457
|
-
};
|
|
3458
|
-
var { version, name, description, repository } = JSON.parse(
|
|
3459
|
-
fs13.readFileSync(resolveRelativeToRoot("package.json"), "utf-8")
|
|
3460
|
-
);
|
|
3461
|
-
var context = {
|
|
3462
|
-
package: {
|
|
3463
|
-
name,
|
|
3464
|
-
description,
|
|
3465
|
-
version,
|
|
3466
|
-
repository
|
|
3467
|
-
},
|
|
3468
|
-
resolveRelativeToRoot
|
|
3469
|
-
};
|
|
3470
|
-
console.clear();
|
|
3471
|
-
program8.name(name).description(description).version(version).addCommand(add).addCommand(auth).addCommand(init).addCommand(test).addCommand(build).addCommand(update).addCommand(diff);
|
|
3472
|
-
program8.parse();
|
|
3473
|
-
export {
|
|
3474
|
-
context
|
|
3475
|
-
};
|
|
15
|
+
`),H={name:()=>"github",defaultBranch:()=>"main",resolveRaw:async(t,e)=>{let r=await H.info(t);return new URL(e,`https://raw.githubusercontent.com/${r.owner}/${r.repoName}/refs/${r.refs}/${r.ref}/`)},fetchRaw:async(t,e,{verbose:r}={})=>{let o=await H.info(t),n=await H.resolveRaw(o,e);r?.(`Trying to fetch from ${n}`);try{let i=ye().get(`${H.name()}-token`),s=new Headers;i!==void 0&&s.append("Authorization",`token ${i}`);let a=await xt(n,{headers:s});return r?.(`Got a response from ${n} ${a.status} ${a.statusText}`),a.ok?O(await a.text()):Ve(o,e,H.defaultBranch())}catch(i){return r?.(`erroring in response ${i} `),Ve(o,e,H.defaultBranch())}},fetchManifest:async t=>{let e=await H.fetchRaw(t,ce);if(e.isErr())return P(e.unwrapErr());let r=B.parse(B.array(at),JSON.parse(e.unwrap()));return O(r)},info:async t=>{if(typeof t!="string")return t;let e=t.replaceAll(/(https:\/\/github.com\/)|(github\/)/g,""),[r,o,...n]=e.split("/"),i=H.defaultBranch(),s=ye().get(`${H.name()}-token`),a=new Octokit({auth:s});if(n[0]==="tree")i=n[1];else try{let{data:h}=await a.rest.repos.get({owner:r,repo:o});i=h.default_branch;}catch{}let d="heads";if(i!==H.defaultBranch())try{let{data:h}=await a.rest.git.listMatchingRefs({owner:r,repo:o,ref:"tags"});h.some(f=>f.ref===`refs/tags/${i}`)&&(d="tags");}catch{d="heads";}return {refs:d,url:t,name:H.name(),repoName:o,owner:r,ref:i,provider:H}},matches:t=>t.toLowerCase().startsWith("https://github.com")||t.toLowerCase().startsWith("github")},ue={name:()=>"gitlab",defaultBranch:()=>"main",resolveRaw:async(t,e)=>{let r=await ue.info(t);return new URL(`${encodeURIComponent(e)}/raw?ref=${r.ref}`,`https://gitlab.com/api/v4/projects/${encodeURIComponent(`${r.owner}/${r.repoName}`)}/repository/files/`)},fetchRaw:async(t,e,{verbose:r}={})=>{let o=await H.info(t),n=await ue.resolveRaw(o,e);r?.(`Trying to fetch from ${n}`);try{let i=ye().get(`${ue.name()}-token`),s=new Headers;i!==void 0&&s.append("PRIVATE-TOKEN",`${i}`);let a=await xt(n,{headers:s});return r?.(`Got a response from ${n} ${a.status} ${a.statusText}`),a.ok?O(await a.text()):Ve(o,e,ue.defaultBranch())}catch{return Ve(o,e,ue.defaultBranch())}},fetchManifest:async t=>{let e=await ue.fetchRaw(t,ce);if(e.isErr())return P(e.unwrapErr());let r=B.parse(B.array(at),JSON.parse(e.unwrap()));return O(r)},info:async t=>{if(typeof t!="string")return t;let e=t.replaceAll(/(https:\/\/gitlab.com\/)|(gitlab\/)/g,""),[r,o,...n]=e.split("/"),i=ue.defaultBranch(),s="heads";if(n[0]==="-"&&n[1]==="tree")if(n[2].includes("?")){let[a,d]=n[2].split("?");i=a,d.startsWith("ref_type=")&&d.slice(10)==="tags"&&(s="tags");}else i=n[2];return {refs:s,url:t,name:ue.name(),repoName:o,owner:r,ref:i,provider:ue}},matches:t=>t.toLowerCase().startsWith("https://gitlab.com")||t.toLowerCase().startsWith("gitlab")},le={name:()=>"bitbucket",defaultBranch:()=>"master",resolveRaw:async(t,e)=>{let r=await le.info(t);return new URL(e,`https://api.bitbucket.org/2.0/repositories/${r.owner}/${r.repoName}/src/${r.ref}/`)},fetchRaw:async(t,e,{verbose:r}={})=>{let o=await le.info(t),n=await le.resolveRaw(o,e);r?.(`Trying to fetch from ${n}`);try{let i=ye().get(`${le.name()}-token`),s=new Headers;i!==void 0&&s.append("Authorization",`Bearer ${i}`);let a=await xt(n,{headers:s});return r?.(`Got a response from ${n} ${a.status} ${a.statusText}`),a.ok?O(await a.text()):Ve(o,e,le.defaultBranch())}catch{return Ve(o,e,le.defaultBranch())}},fetchManifest:async t=>{let e=await le.fetchRaw(t,ce);if(e.isErr())return P(e.unwrapErr());let r=B.parse(B.array(at),JSON.parse(e.unwrap()));return O(r)},info:async t=>{if(typeof t!="string")return t;let e=t.replaceAll(/(https:\/\/bitbucket.org\/)|(bitbucket\/)/g,""),[r,o,...n]=e.split("/"),i="heads",s=le.defaultBranch();return n[0]==="src"&&(s=n[1]),{refs:i,url:t,name:le.name(),repoName:o,owner:r,ref:s,provider:le}},matches:t=>t.toLowerCase().startsWith("https://bitbucket.org")||t.toLowerCase().startsWith("bitbucket")},_=[H,ue,le],ve=async t=>{let e=_.find(r=>r.matches(t));return e?O(await e.info(t)):P(`Only ${_.map((r,o)=>`${o===_.length-1?"and":""}${I.cyan(r.name())}`).join(", ")} repositories are supported at this time!`)},Me=async(...t)=>{let e=new Map;for(let r of t){let o=await ve(r);if(o.isErr())return P({message:o.unwrapErr(),repo:r});let n=o.unwrap(),i=await n.provider.fetchManifest(n);if(i.isErr())return P({message:i.unwrapErr(),repo:r});let s=i.unwrap();for(let a of s)for(let d of a.blocks)e.set(`${n.name}/${n.owner}/${n.repoName}/${a.name}/${d.name}`,{...d,sourceRepo:n});}return O(e)};var Qe=async(t,e,r)=>{let o=new Map;for(let n of t){let i;if(_.find(a=>n.startsWith(a.name()))){let[a,d,h,...f]=n.split("/");i=e.get(`${a}/${d}/${h}/${f.slice(f.length-2).join("/")}`);}else {if(r.length===0)return P(I.red(`If your config doesn't repos then you must provide the repo in the block specifier ex: \`${I.bold(`github/<owner>/<name>/${n}`)}\`!`));for(let a of r){let d=(await ve(a)).unwrap(),h=e.get(`${d.name}/${d.owner}/${d.repoName}/${n}`);if(h!==void 0){i=h;break}}}if(!i)return P(`Invalid block! ${I.bold(n)} does not exist!`);let s=`${i.category}/${i.name}`;if(o.set(s,{name:i.name,subDependency:!1,block:i}),i.localDependencies&&i.localDependencies.length>0){let a=await Qe(i.localDependencies.filter(d=>!o.has(d)),e,r);if(a.isErr())return P(a.unwrapErr());for(let d of a.unwrap())o.set(d.name,d);}}return O(Gt(o,(n,i)=>i))},ke=(t,e,r)=>{let o=[];for(let[n,i]of t){let s=J.join(r,e.path,i.category),a=J.join(s,i.files[0]);i.subdirectory&&(a=J.join(s,i.name)),Ne.existsSync(a)&&o.push({specifier:`${i.category}/${i.name}`,path:a,block:i});}return o};var Se="jsrepo.json",St=B.union([B.literal("prettier"),B.literal("biome")]),zr=B.object({$schema:B.string(),repos:B.optional(B.array(B.string()),[]),includeTests:B.boolean(),path:B.pipe(B.string(),B.minLength(1)),watermark:B.optional(B.boolean(),!0),formatter:B.optional(St)}),ge=t=>{if(!Ne.existsSync(J.join(t,Se)))return P("Could not find your configuration file! Please run `init`.");let e=B.safeParse(zr,JSON.parse(Ne.readFileSync(J.join(t,Se)).toString()));return e.success?O(e.output):P(`There was an error reading your \`${Se}\` file!`)};var Re=async({pm:t,deps:e,dev:r,cwd:o})=>{let n;if(r?n=resolveCommand$1(t,"install",[...e,"-D"]):n=resolveCommand$1(t,"install",[...e]),n==null)return P(I.red(`Could not resolve add command for '${t}'.`));try{return await execa(n.command,[...n.args],{cwd:o}),O(e)}catch{return P(I.red(`Failed to install ${I.bold(e.join(", "))}! Failed while running '${I.bold(`${n.command} ${n.args.join(" ")}`)}'`))}};var lt=async({formatter:t,cwd:e})=>{let r=null;t==="prettier"&&(r=await Xe.resolveConfig(J.join(e,".prettierrc")));let o=null;if(t==="biome"){let n=J.join(e,"biome.json");Ne.existsSync(n)&&(o=JSON.parse(Ne.readFileSync(n).toString()));}return {biomeOptions:o,prettierOptions:r}};var Je=(t,e)=>`jsrepo ${t}
|
|
16
|
+
Installed from ${e}
|
|
17
|
+
${new Date().toLocaleDateString().replaceAll("/","-")}`;var et=async(t,{verbose:e=void 0})=>{let r=spinner();for(let o of t){e?e(o.loadingMessage):r.start(o.loadingMessage);try{await o.run();}catch(n){r.stop(`Error while ${o.loadingMessage}`),console.error(n);}e?e(o.completedMessage):r.stop(o.completedMessage);}},Ue=t=>{let e=20;t.map(n=>{let i=Ht(xe(n),4);i.length>e&&(e=i.length);});let r="Next Steps",o=`${N}
|
|
18
|
+
`;return o+=`${vt} ${r} ${yt.repeat(e-r.length-1)}${Ut}
|
|
19
|
+
`,o+=`${N} ${" ".repeat(e)} ${N}
|
|
20
|
+
`,t.map(n=>{o+=`${N} ${Kt(n,e-1)} ${N}
|
|
21
|
+
`;}),o+=`${N} ${" ".repeat(e)} ${N}
|
|
22
|
+
`,o+=`${vt}${yt.repeat(e+2)}${zt}
|
|
23
|
+
`,o},K=t=>intro(`${I.bgHex("#f7df1e").black(" jsrepo ")}${I.gray(` v${t} `)}`);var to=B.object({repo:B.optional(B.string()),allow:B.boolean(),yes:B.boolean(),verbose:B.boolean(),cwd:B.string()}),jt=new Command("add").argument("[blocks...]","Names of the blocks you want to add to your project. ex: (utils/math, github/ieedan/std/utils/math)").option("--repo <repo>","Repository to download the blocks from.").option("-A, --allow","Allow jsrepo to download code from the provided repo.",!1).option("-y, --yes","Skip confirmation prompt.",!1).option("--verbose","Include debug logs.",!1).option("--cwd <path>","The current working directory.",process.cwd()).action(async(t,e)=>{let r=B.parse(to,e);K(M.package.version),await ro(t,r),outro(I.green("All done!"));}),ro=async(t,e)=>{let r=l=>{e.verbose&&console.info(`${Le} ${l}`);};r(`Attempting to add ${JSON.stringify(t)}`);let o=spinner(),n=ge(e.cwd),i=n.isErr(),s;if(n.isErr()){let l=await confirm({message:`You don't have ${fe} initialized in your project. Do you want to continue?`,initialValue:!1});(isCancel(l)||!l)&&(cancel("Canceled!"),process.exit(0)),s={$schema:"",includeTests:!1,watermark:!0,path:"./src/blocks",repos:[]};}else s=n.unwrap();let a=s.repos;e.repo&&(a=[e.repo]);for(let l of t){if(!_.find(C=>l.startsWith(C.name())))continue;let[p,c,y,...R]=l.split("/"),u;if(R.length>2?u=`${p}/${c}/${y}/${R.slice(0,R.length-2).join("/")}`:u=`${p}/${c}/${y}`,!a.find(C=>C===u)){if(!e.allow){let C=await confirm({message:`Allow ${fe} to download and run code from ${I.cyan(u)}?`,initialValue:!0});(isCancel(C)||!C)&&(cancel("Canceled!"),process.exit(0));}a.push(u);}}if(!e.allow&&e.repo){let l=await confirm({message:`Allow ${fe} to download and run code from ${I.cyan(e.repo)}?`,initialValue:!0});(isCancel(l)||!l)&&(cancel("Canceled!"),process.exit(0));}a.length===0&&(i&&program.error(I.red(`Fully quality blocks ex: (github/ieedan/std/utils/math) or provide the \`${I.bold("--repo")}\` flag to specify a registry.`)),program.error(I.red(`There were no repos present in your config and you didn't provide the \`${I.bold("--repo")}\` flag with a repo.`))),r(`Fetching blocks from ${I.cyan(a.join(", "))}`),e.verbose||o.start(`Fetching blocks from ${I.cyan(a.join(", "))}`);let d=(await Me(...a)).match(l=>l,({repo:l,message:p})=>{o.stop(`Failed fetching blocks from ${I.cyan(l)}`),program.error(I.red(p));});e.verbose||o.stop(`Retrieved blocks from ${I.cyan(a.join(", "))}`),r(`Retrieved blocks from ${I.cyan(a.join(", "))}`);let h=ke(d,s,e.cwd).map(l=>l.specifier),f=t;if(f.length===0){let l=await multiselect({message:"Select which blocks to add.",options:Array.from(d.entries()).map(([p,c])=>{let y=`${c.category}/${c.name}`,R=h.findIndex(C=>C===y)!==-1,u;return a.length>1?u=`${I.cyan(`${c.sourceRepo.name}/${c.sourceRepo.owner}/${c.sourceRepo.repoName}/${c.category}`)}/${c.name}`:u=`${I.cyan(c.category)}/${c.name}`,{label:R?I.gray(u):u,value:p,hint:R?"Installed":void 0}}),required:!0});isCancel(l)&&(cancel("Canceled!"),process.exit(0)),f=l;}r(`Installing blocks ${I.cyan(f.join(", "))}`),e.verbose&&console.log("Blocks map: ",d);let $=(await Qe(f,d,a)).match(l=>l,l=>program.error(l)),v=(await detect({cwd:e.cwd}))?.agent??"npm",m=[],b=new Set,S=new Set;if(i){let l=await text({message:"Where would you like to add the blocks?",initialValue:s.path,defaultValue:s.path,placeholder:s.path,validate(p){if(p.trim()==="")return "Please provide a value"}});if(isCancel(l)&&(cancel("Canceled!"),process.exit(0)),s.path=l,!e.yes){let p=await confirm({message:"Include tests?",initialValue:s.includeTests});isCancel(p)&&(cancel("Canceled!"),process.exit(0)),s.includeTests=p;let c=await confirm({message:"Add watermark?",initialValue:s.watermark});isCancel(c)&&(cancel("Canceled!"),process.exit(0)),s.watermark=c;}}let{prettierOptions:j,biomeOptions:T}=await lt({formatter:s.formatter,cwd:e.cwd});for(let{block:l}of $){let p=`${l.sourceRepo.url}/${l.category}/${l.name}`,c=`${l.category}/${l.name}`,y=Je(M.package.version,l.sourceRepo.url),R=l.sourceRepo;r(`Setting up ${p}`);let u=J.join(e.cwd,s.path,l.category);if((!l.subdirectory&&Ne.existsSync(J.join(u,l.files[0]))||l.subdirectory&&Ne.existsSync(J.join(u,l.name)))&&!e.yes){let k=await confirm({message:`${I.cyan(c)} already exists in your project would you like to overwrite it?`,initialValue:!1});(isCancel(k)||!k)&&(cancel("Canceled!"),process.exit(0));}m.push({loadingMessage:`Adding ${p}`,completedMessage:`Added ${p}`,run:async()=>{r(`Creating directory ${I.bold(u)}`),Ne.mkdirSync(u,{recursive:!0}),r(`Created directory ${I.bold(u)}`);let k=[],F=async x=>{let X=await R.provider.fetchRaw(R,x,{verbose:r});return X.isErr()&&(o.stop(I.red(`Error fetching ${I.bold(x)}`)),program.error(I.red(`There was an error trying to get ${p}`))),X.unwrap()};for(let x of l.files){if(!s.includeTests&&ae(x))continue;let X=J.join(l.directory,x),Z;l.subdirectory?Z=J.join(u,l.name,x):Z=J.join(u,x),r(`Adding ${I.bold(X)}`);let Fe=await F(X),Ye=Z.slice(0,Z.length-x.length);r(`Creating directory ${I.bold(Ye)}`),Ne.mkdirSync(Ye,{recursive:!0}),r(`Created directory ${I.bold(Ye)}`),k.push({content:Fe,destPath:Z}),r(`Got ${I.bold(X)}`);}for(let x of k){let X=he.find(Fe=>Fe.matches(x.destPath)),Z=x.content;X&&(s.watermark&&(Z=`${X.comment(y)}
|
|
24
|
+
|
|
25
|
+
${Z}`),r(`Formatting ${I.bold(x.destPath)}`),Z=await X.format(Z,{filePath:x.destPath,formatter:s.formatter,prettierOptions:j,biomeOptions:T})),r(`Writing to ${I.bold(x.destPath)}`),Ne.writeFileSync(x.destPath,Z);}if(s.includeTests&&l.tests){r("Trying to include tests");let{devDependencies:x}=JSON.parse(Ne.readFileSync(J.join(e.cwd,"package.json")).toString());(x===void 0||x.vitest===void 0)&&b.add("vitest");}for(let x of l.devDependencies)b.add(x);for(let x of l.dependencies)S.add(x);}});}await et(m,{verbose:e.verbose?r:void 0});let w=it(S,b,{cwd:e.cwd});if(S=w.dependencies,b=w.devDependencies,S.size>0||b.size>0){let l=e.yes;if(!e.yes){let y=await confirm({message:"Would you like to install dependencies?",initialValue:!0});isCancel(y)&&(cancel("Canceled!"),process.exit(0)),l=y;}l&&(S.size>0&&(e.verbose||o.start(`Installing dependencies with ${I.cyan(v)}`),(await Re({pm:v,deps:Array.from(S),dev:!1,cwd:e.cwd})).match(y=>{e.verbose||o.stop(`Installed ${I.cyan(y.join(", "))}`);},y=>{e.verbose||o.stop("Failed to install dependencies"),program.error(y);})),b.size>0&&(e.verbose||o.start(`Installing dependencies with ${I.cyan(v)}`),(await Re({pm:v,deps:Array.from(b),dev:!0,cwd:e.cwd})).match(y=>{e.verbose||o.stop(`Installed ${I.cyan(y.join(", "))}`);},y=>{e.verbose||o.stop("Failed to install dev dependencies"),program.error(y);})));let p=[];if(!l){if(S.size>0){let y=resolveCommand(v,"install",[...S]);p.push(`Install dependencies \`${I.cyan(`${y?.command} ${y?.args.join(" ")}`)}\``);}if(b.size>0){let y=resolveCommand(v,"install",[...b,"-D"]);p.push(`Install dev dependencies \`${I.cyan(`${y?.command} ${y?.args.join(" ")}`)}\``);}}p=p.map((y,R)=>`${R+1}. ${y}`),l||p.push(""),p.push(`Import the blocks from \`${I.cyan(s.path)}\``);let c=Ue(p);process.stdout.write(c);}};var lo=B.object({token:B.optional(B.string()),provider:B.optional(B.string()),logout:B.boolean(),cwd:B.string()}),At=new Command("auth").description("Provide a token for access to private repositories.").option("--token <token>","The token to use for authenticating to your provider.").addOption(new Option("--provider <name>","The provider this token belongs to.").choices(_.map(t=>t.name()))).option("--logout","Erase tokens from each provider from storage.",!1).option("--cwd <path>","The current working directory.",process.cwd()).action(async t=>{let e=B.parse(lo,t);K(M.package.version),await po(e),outro(I.green("All done!"));}),po=async t=>{let e=ye();if(t.logout){for(let r of _){let o=`${r.name()}-token`;if(e.get(o)===void 0){process.stdout.write(`${N}
|
|
26
|
+
`),process.stdout.write(I.gray(`${N} Already logged out of ${r.name()}.
|
|
27
|
+
`));continue}let n=await confirm({message:`Remove ${r.name()} token?`,initialValue:!0});isCancel(n)&&(cancel("Canceled!"),process.exit(0)),n&&e.delete(o);}return}if(_.length>1){let r=await select({message:"Which provider is this token for?",options:_.map(o=>({label:o.name(),value:o.name()})),initialValue:_[0].name()});isCancel(r)&&(cancel("Canceled!"),process.exit(0)),t.provider=r;}else t.provider=_[0].name();if(t.token===void 0){let r=await password({message:"Paste your token",validate(o){if(o.trim()==="")return "Please provide a value"}});(isCancel(r)||!r)&&(cancel("Canceled!"),process.exit(0)),t.token=r;}e.set(`${t.provider}-token`,t.token);};var go=B.object({dirs:B.array(B.string()),includeBlocks:B.array(B.string()),includeCategories:B.array(B.string()),excludeDeps:B.array(B.string()),output:B.boolean(),errorOnWarn:B.boolean(),verbose:B.boolean(),cwd:B.string()}),Nt=new Command("build").description(`Builds the provided --dirs in the project root into a \`${ce}\` file.`).option("--dirs [dirs...]","The directories containing the blocks.",["./blocks"]).option("--include-blocks [blockNames...]","Include only the blocks with these names.",[]).option("--include-categories [categoryNames...]","Include only the categories with these names.",[]).option("--exclude-deps [deps...]","Dependencies that should not be added.",[]).option("--no-output",`Do not output a \`${ce}\` file.`).option("--error-on-warn","If there is a warning throw an error and do not allow build to complete.",!1).option("--verbose","Include debug logs.",!1).option("--cwd <path>","The current working directory.",process.cwd()).action(async t=>{let e=B.parse(go,t);K(M.package.version),await ho(e),outro(I.green("All done!"));}),ho=async t=>{let e=spinner(),r=[],o=J.join(t.cwd,ce);for(let i of t.dirs){let s=J.join(t.cwd,i);e.start(`Building ${I.cyan(s)}`),t.output&&Ne.existsSync(o)&&Ne.rmSync(o);let a=tr(s,{...t});for(let d of a){if(r.find(h=>h.name===d.name)!==void 0){let h="a category with the same name already exists!";t.errorOnWarn?program.error(I.red(`\`${I.bold(`${i}/${d.name}`)}\` could not be added because ${h}`)):console.warn(`${N} ${ie} Skipped adding \`${I.cyan(`${i}/${d.name}`)}\` because ${h}`);continue}r.push(d);}e.stop(`Built ${I.cyan(s)}`);}e.start("Checking manifest");let n=[];for(let i of r)for(let s of i.blocks){for(let a of s.localDependencies){let[d,h]=a.split("/"),f=r.find(v=>v.name.trim()===d.trim()),$=()=>{let v=`depends on ${I.bold(a)} which doesn't exist!`;t.errorOnWarn?n.push(I.red(`${I.bold(`${i.name}/${s.name}`)} ${v}`)):n.push(`${N} ${ie} ${I.bold(`${i.name}/${s.name}`)} ${v}`);};if(!f){$();continue}f.blocks.find(v=>v.name===h)===void 0&&$();}for(let a of [...s.dependencies,...s.devDependencies])if(!a.includes("@")){let d=`You haven't installed ${I.bold(a)} as a dependency so your users could get any version of it when they install your block!`;t.errorOnWarn?n.push(I.red(d)):n.push(`${N} ${ie} ${d}`);}}if(e.stop("Completed checking manifest."),n.length>0){for(let i of n)console.log(i);t.errorOnWarn&&program.error("Had warnings while checking manifest.");}t.output&&(e.start(`Writing output to \`${I.cyan(o)}\``),Ne.writeFileSync(o,JSON.stringify(r,null," ")),e.stop(`Wrote output to \`${I.cyan(o)}\``));};var mr=(t,e)=>{let r=0;for(let o of t)r=r+e(o);return r};var ur=t=>/^\s+$/g.test(t),Ge=t=>{let e=t.length-1;for(;ur(t[e])&&e>=0;){if(t[e]===`
|
|
28
|
+
`)return t[e-1]==="\r"?t.slice(0,e-1):t.slice(0,e);e--;}return t},dt=({from:t,to:e,changes:r,expand:o=!1,maxUnchanged:n=5,colorRemoved:i=I.red,colorAdded:s=I.green,colorCharsRemoved:a=I.bgRed,colorCharsAdded:d=I.bgGreen,prefix:h,onUnchanged:f,intro:$})=>{let v="",m=mr(r,j=>j.count??0).toString().length+1,b=0;if(r.length===1&&!r[0].added&&!r[0].removed)return f({from:t,to:e,changes:r,expand:o,maxUnchanged:n,colorAdded:s,colorRemoved:i,prefix:h,onUnchanged:f,intro:$});v+=$({from:t,to:e,changes:r,expand:o,maxUnchanged:n,colorAdded:s,colorRemoved:i,prefix:h,onUnchanged:f,intro:$});let S=j=>I.gray(`${h?.()??""}${qe(`${j+1+b} `,m)} `);for(let j=0;j<r.length;j++){let T=r[j],w=r[j-1]?.added||r[j-1]?.removed,g=r[j+1]?.added||r[j+1]?.removed;if(!T.added&&!T.removed){if(!o&&T.count!==void 0&&T.count>n){let c=b,y=se(Ge(T.value)),R=0;if(g&&(R+=n),w&&(R+=n),R>=y.length){v+=`${Q(y,{prefix:S})}
|
|
29
|
+
`,b+=y.length;continue}if(w&&(v+=`${Q(y.slice(0,n),{prefix:S})}
|
|
30
|
+
`),y.length>R){let u=y.length-R;v+=`${Q(se(I.gray(`+ ${u} more unchanged (${I.italic("-E to expand")})`)),{prefix:()=>`${h?.()??""}${qe(" ",m)} `})}
|
|
31
|
+
`;}g&&(b=b+y.length-n,v+=`${Q(y.slice(y.length-n),{prefix:S})}
|
|
32
|
+
`),b=c+T.count;continue}v+=`${Q(se(Ge(T.value)),{prefix:S})}
|
|
33
|
+
`,b+=T.count??0;continue}let l=c=>c.added?s(Ge(c.value)):c.removed?i(Ge(c.value)):c.value,p=c=>c.added?d(Ge(c.value)):c.removed?a(Ge(c.value)):c.value;if(T.removed&&T.count===1&&r[j+1]?.added&&r[j+1]?.count===1){let y=diffChars(T.value,r[j+1].value).map(R=>p(R)).join("");v+=`${S(0)}${y}`,b+=1,j++;}else ur(T.value)?(v+=`${Q(se(p(T)),{prefix:c=>`${S(c)}${p({removed:!0,value:" ",added:!1})}`})}
|
|
34
|
+
`,T.removed||(b+=T.count??0)):(v+=`${Q(se(l(T)),{prefix:S})}
|
|
35
|
+
`,T.removed||(b+=T.count??0));}return v};var xo=B.object({expand:B.boolean(),maxUnchanged:B.number(),repo:B.optional(B.string()),allow:B.boolean(),cwd:B.string()}),Dt=new Command("diff").description("Compares local blocks to the blocks in the provided repository.").option("-E, --expand","Expands the diff so you see everything.",!1).option("--max-unchanged <number>","Maximum unchanged lines that will show without being collapsed.",t=>Number.parseInt(t),3).option("--repo <repo>","Repository to download the blocks from.").option("-A, --allow","Allow jsrepo to download code from the provided repo.",!1).option("--cwd <path>","The current working directory.",process.cwd()).action(async t=>{let e=B.parse(xo,t);K(M.package.version),await Io(e),outro(I.green("All done!"));}),Io=async t=>{let e=spinner(),r=ge(t.cwd).match(s=>s,s=>program.error(I.red(s))),o=r.repos;if(t.repo&&(o=[t.repo]),!t.allow&&t.repo){let s=await confirm({message:`Allow ${I.cyan("jsrepo")} to download and run code from ${I.cyan(t.repo)}?`,initialValue:!0});(isCancel(s)||!s)&&(cancel("Canceled!"),process.exit(0));}e.start(`Fetching blocks from ${I.cyan(o.join(", "))}`);let n=(await Me(...o)).match(s=>s,({repo:s,message:a})=>{e.stop(`Failed fetching blocks from ${I.cyan(s)}`),program.error(I.red(a));});e.stop(`Retrieved blocks from ${I.cyan(o.join(", "))}`);let i=ke(n,r,t.cwd);for(let s of i){let a=!1;for(let d of o){let h=(await ve(d)).unwrap(),f=`${h.name}/${h.owner}/${h.repoName}/${s.specifier}`,$=n.get(f);if($===void 0)continue;let v=Je(M.package.version,d);a=!0,process.stdout.write(`${N}
|
|
36
|
+
`),process.stdout.write(`${N} ${f}
|
|
37
|
+
`);for(let m of $.files){if(!r.includeTests&&ae(m))continue;process.stdout.write(`${N}
|
|
38
|
+
`);let b=J.join($.directory,m),S=await h.provider.fetchRaw(h,b);S.isErr()&&program.error(I.red(`There was an error trying to get ${f}`));let j=S.unwrap(),T=J.join(t.cwd,r.path,$.category),w=J.join(T,m),g=J.join(r.path,$.category,m);$.subdirectory&&(w=J.join(T,$.name,m),g=J.join(r.path,$.category,$.name,m));let l="";if(Ne.existsSync(w)&&(l=Ne.readFileSync(w).toString()),r.watermark){let R=he.find(u=>u.matches(b));R&&(j=`${R.comment(v)}
|
|
39
|
+
|
|
40
|
+
${j}`);}let p=diffLines(l,j),c=J.join(`${h.name}/${h.owner}/${h.repoName}`,b),y=dt({from:c,to:g,changes:p,expand:t.expand,maxUnchanged:t.maxUnchanged,colorAdded:I.greenBright,colorRemoved:I.redBright,colorCharsAdded:I.bgGreenBright,colorCharsRemoved:I.bgRedBright,prefix:()=>`${N} `,onUnchanged:({from:R,to:u,prefix:C})=>`${C?.()??""}${I.cyan(R)} \u2192 ${I.gray(u)} ${I.gray("(unchanged)")}
|
|
41
|
+
`,intro:({from:R,to:u,changes:C,prefix:k})=>{let F=C.filter(x=>x.added).length;return `${k?.()??""}${I.cyan(R)} \u2192 ${I.gray(u)} (${F} change${F===1?"":"s"})
|
|
42
|
+
${k?.()??""}
|
|
43
|
+
`}});process.stdout.write(y);}break}a||program.error(I.red(`Invalid block! ${I.bold(s)} does not exist!`));}};var Ao=B.object({path:B.optional(B.string()),repos:B.optional(B.array(B.string())),watermark:B.boolean(),tests:B.optional(B.boolean()),formatter:B.optional(St),project:B.optional(B.boolean()),registry:B.optional(B.boolean()),script:B.string(),yes:B.boolean(),cwd:B.string()}),Bt=new Command("init").description("Initializes your project with a configuration file.").option("--path <path>","Path to install the blocks / Path to build the blocks from.").option("--repos [repos...]","Repository to install the blocks from.").option("--no-watermark","Will not add a watermark to each file upon adding it to your project.").option("--tests","Will include tests with the blocks.").addOption(new Option("--formatter <formatter>","What formatter to use when adding or updating blocks.").choices(["prettier","biome"])).option("-P, --project","Takes you through the steps to initialize a project.").option("-R, --registry","Takes you through the steps to initialize a registry.").option("--script <name>","The name of the build script. (For Registry setup)","build").option("-y, --yes","Skip confirmation prompt.",!1).option("--cwd <path>","The current working directory.",process.cwd()).action(async t=>{let e=B.parse(Ao,t);if(K(M.package.version),e.registry!==void 0&&e.project!==void 0&&program.error(I.red(`You cannot provide both ${I.bold("--project")} and ${I.bold("--registry")} at the same time.`)),e.registry===void 0&&e.project===void 0){let r=await select({message:"Initialize a project or registry?",options:[{value:"project",label:"project"},{value:"registry",label:"registry"}],initialValue:"project"});isCancel(r)&&(cancel("Canceled!"),process.exit(0)),e.registry=r==="registry";}e.registry?await No(e):await Po(e),outro(I.green("All done!"));}),Po=async t=>{let e=ye(),r=ge(t.cwd),o=spinner();if(!t.path){let i=await text({message:"Where should we add the blocks?",validate(s){if(s.trim()==="")return "Please provide a value"},initialValue:r.isOk()?r.unwrap().path:"src/blocks"});isCancel(i)&&(cancel("Canceled!"),process.exit(0)),t.path=i;}if(!t.repos)for(t.repos=r.isOk()?r.unwrap().repos:[];;){let i=await confirm({message:`Add ${t.repos.length>0?"another":"a"} repo?`,initialValue:t.repos.length===0});if(isCancel(i)&&(cancel("Canceled!"),process.exit(0)),!i)break;let s=await text({message:"Where should we download the blocks from?",placeholder:"github/ieedan/std",validate:f=>{if(f.trim().length===0)return "Please provide a value";if(!_.find($=>$.matches(f)))return `Invalid provider! Valid providers (${_.map($=>$.name()).join(", ")})`}});isCancel(s)&&(cancel("Canceled!"),process.exit(0));let a=_.find(f=>f.matches(s));a||program.error(I.red("Invalid provider!"));let d=`${a.name()}-token`;if(!e.get(d)){let f=await confirm({message:"Would you like to add an auth token?",initialValue:!1});if(isCancel(f)&&(cancel("Canceled!"),process.exit(0)),f){let $=await password({message:"Paste your token",validate(v){if(v.trim()==="")return "Please provide a value"}});isCancel($)&&(cancel("Canceled!"),process.exit(0)),e.set(d,$);}}t.repos.push(s);}if(!t.formatter){let i=r.isErr()?"none":r.unwrap().formatter??"none";Ne.existsSync(J.join(t.cwd,".prettierrc"))&&(i="prettier"),Ne.existsSync(J.join(t.cwd,"biome.json"))&&(i="biome");let s=await select({message:"What formatter would you like to use?",options:["Prettier","Biome","None"].map(a=>({value:a.toLowerCase(),label:a})),initialValue:i});isCancel(s)&&(cancel("Canceled!"),process.exit(0)),s!=="none"&&(t.formatter=s);}let n={$schema:`https://unpkg.com/jsrepo@${M.package.version}/schema.json`,repos:t.repos,path:t.path,includeTests:r.isOk()&&t.tests===void 0?r.unwrap().includeTests:t.tests??!1,watermark:t.watermark,formatter:t.formatter};o.start(`Writing config to \`${Se}\``),Ne.writeFileSync(J.join(t.cwd,Se),`${JSON.stringify(n,null," ")}
|
|
44
|
+
`),Ne.mkdirSync(J.join(t.cwd,n.path),{recursive:!0}),o.stop(`Wrote config to \`${Se}\`.`);},No=async t=>{let e=spinner(),r=J.join(t.cwd,"package.json");if(Ne.existsSync(r)||program.error(I.red(`Couldn't find your ${I.bold("package.json")}!`)),!t.path){let m=await text({message:"Where are your blocks located?",defaultValue:"./blocks",initialValue:"./blocks",placeholder:"./blocks"});isCancel(m)&&(cancel("Canceled!"),process.exit(0)),t.path=m;}let o=JSON.parse(Ne.readFileSync(r).toString()),n=o.scripts!==void 0&&o.scripts[t.script]!==void 0;if(!t.yes&&n){let m=await confirm({message:`The \`${I.cyan(t.script)}\` already exists overwrite?`,initialValue:!1});if(isCancel(m)&&(cancel("Canceled!"),process.exit(0)),!m){let b=await text({message:"What would you like to call the script?",defaultValue:"build:registry",placeholder:"build:registry",initialValue:"build:registry",validate:S=>{if(S.trim().length===0)return "Please provide a value!"}});isCancel(b)&&(cancel("Canceled!"),process.exit(0)),t.script=b;}}let i=o.devDependencies&&o.devDependencies.jsrepo!==void 0,s=t.yes||i;if(!t.yes&&!i){let m=await confirm({message:`Add ${fe} as a dev dependency?`,initialValue:!0});isCancel(m)&&(cancel("Canceled!"),process.exit(0)),s=m;}let a=(await detect$1({cwd:"cwd"}))?.agent??"npm",d="";if(s)d+="jsrepo build ";else {let m=resolveCommand$1(a,"execute",["jsrepo","build"]);m||program.error(I.red(`Error resolving execute command for ${a}`)),d+=`${m.command} ${m.args.join(" ")} `;}t.path!=="./build"&&(d+=`--dirs ${t.path}`),o.scripts===void 0&&(o.scripts={}),o.scripts[t.script]=d,e.start(`Adding \`${I.cyan(t.script)}\` to scripts in package.json`);try{Ne.writeFileSync(r,JSON.stringify(o,null," "));}catch(m){program.error(I.red(`Error writing to \`${I.bold(r)}\`. Error: ${m}`));}e.stop(`Added \`${I.cyan(t.script)}\` to scripts in package.json`);let h=i;if(s&&!i){let m=t.yes;if(!t.yes){let b=await confirm({message:"Install dependencies?",initialValue:!0});isCancel(b)&&(cancel("Canceled!"),process.exit(0)),m=b;}m&&(e.start(`Installing ${fe}`),(await Re({pm:a,deps:["jsrepo"],dev:!0,cwd:t.cwd})).match(()=>e.stop(`Installed ${fe}.`),S=>{e.stop(`Failed to install ${fe}.`),program.error(S);}),h=!0);}let f=[];if(!h&&s){let m=resolveCommand$1(a,"install",["jsrepo","-D"]);f.push(`Install ${fe} as a dev dependency \`${I.cyan(`${m?.command} ${m?.args.join(" ")}`)}\``);}f.push(`Add blocks to \`${I.cyan(t.path)}\`.`);let $=resolveCommand$1(a,"run",[t.script]);f.push(`Run \`${I.cyan(`${$?.command} ${$?.args.join(" ")}`)}\` to build the registry.`),f=f.map((m,b)=>`${b+1}. ${m}`);let v=Ue(f);process.stdout.write(v);};var Go=B.object({repo:B.optional(B.string()),allow:B.boolean(),debug:B.boolean(),verbose:B.boolean(),cwd:B.string()}),_t=new Command("test").description("Tests local blocks against most recent remote tests.").addArgument(new Argument("[blocks...]","The blocks you want to test.").default([])).option("--repo <repo>","Repository to download the blocks from.").option("-A, --allow","Allow jsrepo to download code from the provided repo.",!1).option("--debug","Leaves the temp test file around for debugging upon failure.",!1).option("--verbose","Include debug logs.",!1).option("--cwd <path>","The current working directory.",process.cwd()).action(async(t,e)=>{let r=B.parse(Go,e);K(M.package.version),await Ho(t,r),outro(I.green("All done!"));}),Ho=async(t,e)=>{let r=g=>{e.verbose&&console.info(`${Le} ${g}`);};r(`Attempting to test ${JSON.stringify(t)}`);let o=ge(e.cwd).match(g=>g,g=>program.error(I.red(g))),n=spinner(),i=new Map,s=o.repos;if(e.repo&&(s=[e.repo]),!e.allow&&e.repo){let g=await confirm({message:`Allow ${I.cyan("jsrepo")} to download and run code from ${I.cyan(e.repo)}?`,initialValue:!0});(isCancel(g)||!g)&&(cancel("Canceled!"),process.exit(0));}r(`Fetching blocks from ${I.cyan(s.join(", "))}`),e.verbose||n.start(`Fetching blocks from ${I.cyan(s.join(", "))}`);for(let g of s){let l=(await ve(g)).match(y=>y,y=>program.error(I.red(y))),p=await l.provider.fetchManifest(l);r(`Got info for provider ${I.cyan(l.name)}`),p.isErr()&&(e.verbose||n.stop(`Error fetching ${I.cyan(g)}`),program.error(I.red(`There was an error fetching the \`${ce}\` from the repository ${I.cyan(g)} make sure the target repository has a \`${ce}\` in its root?`)));let c=p.unwrap();for(let y of c)for(let R of y.blocks)i.set(`${l.name}/${l.owner}/${l.repoName}/${y.name}/${R.name}`,{...R,sourceRepo:l});}r(`Retrieved blocks from ${I.cyan(s.join(", "))}`),e.verbose||n.stop(`Retrieved blocks from ${I.cyan(s.join(", "))}`);let a=J.resolve(J.join(e.cwd,`blocks-tests-temp-${Date.now()}`));r(`Trying to create the temp directory ${I.bold(a)}.`),Ne.mkdirSync(a,{recursive:!0});let d=()=>{Ne.rmSync(a,{recursive:!0,force:!0});},h=ke(i,o,e.cwd).map(g=>g.specifier),f=t;t.length===0&&(f=h),f.length===0&&(d(),program.error(I.red("There were no blocks found in your project!")));let $=[];for(let g of f){let l;if(_.find(p=>g.startsWith(p.name()))){if(s.length===0){let[p,c,y,...R]=g.split("/"),u;R.length>2?u=`${p}/${c}/${y}/${R.slice(0,R.length-2).join("/")}`:u=`${p}/${c}/${y}`;let C=(await ve(u)).match(F=>F,F=>program.error(I.red(F))),k=(await C.provider.fetchManifest(C)).match(F=>F,F=>program.error(I.red(F)));for(let F of k)for(let x of F.blocks)i.set(`${C.name}/${C.owner}/${C.repoName}/${F.name}/${x.name}`,{...x,sourceRepo:C});}l=i.get(g);}else for(let p of s){let c=(await ve(p)).unwrap(),y=i.get(`${c.name}/${c.owner}/${c.repoName}/${g}`);if(y!==void 0){l=y;break}}l||program.error(I.red(`Invalid block! ${I.bold(g)} does not exist!`)),$.push({name:g,block:l});}for(let{block:g}of $){let l=g.sourceRepo,p=`${g.sourceRepo.url}/${g.category}/${g.name}`;if(e.verbose||n.start(`Setting up test file for ${I.cyan(p)}`),!g.tests){n.stop(`No tests found for ${I.cyan(p)}`);continue}let c=async u=>{let C=await l.provider.fetchRaw(l,u);return C.isErr()&&(n.stop(I.red(`Error fetching ${I.bold(u)}`)),program.error(I.red(`There was an error trying to get ${p}`))),C.unwrap()};r(`Downloading and copying test files for ${p}`);let y=[];for(let u of g.files.filter(C=>ae(C))){let C=await c(J.join(g.directory,u)),k=J.join(a,u);Ne.writeFileSync(k,C),y.push(k);}let R=new Project;for(let u of y){r(`Opening test file ${u}`);let C=R.addSourceFileAtPath(u);for(let k of C.getImportDeclarations()){let F=k.getModuleSpecifierValue(),x;F.startsWith(".")&&(g.subdirectory?x=J.join("../",o.path,g.category,g.name,F):x=J.join("../",o.path,g.category,F)),x&&k.setModuleSpecifier(x.replaceAll(/\\/g,"/"));}}R.saveSync(),r(`Completed ${I.cyan.bold(p)} test file`),e.verbose||n.stop(`Completed setup for ${I.bold(p)}`);}r("Beginning testing");let v=await detect({cwd:e.cwd});v==null&&program.error(I.red("Could not detect package manager"));let m=resolveCommand(v.agent,"execute",["vitest","run",a]);m==null&&program.error(I.red(`Could not resolve add command for '${v.agent}'.`));let{command:b,args:S}=m,j=`${b} ${S.join(" ")}`,T=execa({cwd:e.cwd,stdio:["ignore","pipe","pipe"]})`${j}`,w=g=>console.info(g.toString());T.stdout.on("data",w),T.stderr.on("data",w);try{await T,d();}catch(g){e.debug?console.info(`${I.bold("--debug")} flag provided. Skipping cleanup. Run '${I.bold(j)}' to retry tests.
|
|
45
|
+
`):d(),program.error(I.red(`Tests failed! Error ${g}`));}};var en=B.object({all:B.boolean(),expand:B.boolean(),maxUnchanged:B.number(),repo:B.optional(B.string()),allow:B.boolean(),yes:B.boolean(),verbose:B.boolean(),cwd:B.string()}),Vt=new Command("update").argument("[blocks...]","Names of the blocks you want to update. ex: (utils/math)").option("--all","Update all installed components.",!1).option("-E, --expand","Expands the diff so you see everything.",!1).option("--max-unchanged <number>","Maximum unchanged lines that will show without being collapsed.",t=>Number.parseInt(t),3).option("--repo <repo>","Repository to download the blocks from.").option("-A, --allow","Allow jsrepo to download code from the provided repo.",!1).option("-y, --yes","Skip confirmation prompt.",!1).option("--verbose","Include debug logs.",!1).option("--cwd <path>","The current working directory.",process.cwd()).action(async(t,e)=>{let r=B.parse(en,e);K(M.package.version),await tn(t,r),outro(I.green("All done!"));}),tn=async(t,e)=>{let r=w=>{e.verbose&&console.info(`${Le} ${w}`);};r(`Attempting to update ${JSON.stringify(t)}`);let o=spinner(),n=ge(e.cwd).match(w=>w,w=>program.error(I.red(w))),i=n.repos;e.repo&&(i=[e.repo]);for(let w of t)_.find(g=>w.startsWith(g.name()))&&program.error(I.red(`Invalid value provided for block names \`${I.bold(w)}\`. Block names are expected to be provided in the format of \`${I.bold("<category>/<name>")}\``));if(!e.allow&&e.repo){let w=await confirm({message:`Allow ${I.cyan("jsrepo")} to download and run code from ${I.cyan(e.repo)}?`,initialValue:!0});(isCancel(w)||!w)&&(cancel("Canceled!"),process.exit(0));}r(`Fetching blocks from ${I.cyan(i.join(", "))}`),e.verbose||o.start(`Fetching blocks from ${I.cyan(i.join(", "))}`);let s=(await Me(...i)).match(w=>w,({repo:w,message:g})=>{o.stop(`Failed fetching blocks from ${I.cyan(w)}`),program.error(I.red(g));});e.verbose||o.stop(`Retrieved blocks from ${I.cyan(i.join(", "))}`),r(`Retrieved blocks from ${I.cyan(i.join(", "))}`);let a=ke(s,n,e.cwd);a.length===0&&program.error(I.red(`You haven't installed any blocks yet. Did you mean to \`${I.bold("add")}\`?`));let d=t;if(e.all&&(d=a.map(w=>w.specifier)),d.length===0){let w=await multiselect({message:"Which blocks would you like to update?",options:a.map(g=>({label:`${I.cyan(g.block.category)}/${g.block.name}`,value:g.specifier})),required:!0});isCancel(w)&&(cancel("Canceled!"),process.exit(0)),d=w;}r(`Preparing to update ${I.cyan(d.join(", "))}`);let h=(await Qe(d,s,i)).match(w=>w,program.error),f=(await detect({cwd:e.cwd}))?.agent??"npm",$=[],v=new Set,m=new Set,{prettierOptions:b,biomeOptions:S}=await lt({formatter:n.formatter,cwd:e.cwd});for(let{block:w}of h){let g=`${w.sourceRepo.url}/${w.category}/${w.name}`,l=Je(M.package.version,w.sourceRepo.url),p=w.sourceRepo;r(`Attempting to add ${g}`);let c=J.join(e.cwd,n.path,w.category),y=[],R=async u=>{let C=await p.provider.fetchRaw(p,u,{verbose:r});return C.isErr()&&(o.stop(I.red(`Error fetching ${I.bold(u)}`)),program.error(I.red(`There was an error trying to get ${g}`))),C.unwrap()};for(let u of w.files){if(!n.includeTests&&ae(u))continue;let C=J.join(w.directory,u),k;w.subdirectory?k=J.join(c,w.name,u):k=J.join(c,u);let F=await R(C);Ne.mkdirSync(k.slice(0,k.length-u.length),{recursive:!0}),y.push({content:F,destPath:k,fileName:u});}process.stdout.write(`${N}
|
|
46
|
+
`),process.stdout.write(`${N} ${g}
|
|
47
|
+
`);for(let u of y){let C=he.find(x=>x.matches(u.destPath)),k=u.content;C&&(n.watermark&&(k=`${C.comment(l)}
|
|
48
|
+
|
|
49
|
+
${k}`),k=await C.format(k,{filePath:u.destPath,formatter:n.formatter,prettierOptions:b,biomeOptions:S}));let F=e.yes;if(!e.yes){process.stdout.write(`${N}
|
|
50
|
+
`);let x="";Ne.existsSync(u.destPath)&&(x=Ne.readFileSync(u.destPath).toString());let X=diffLines(x,k),Z=J.join(`${p.name}/${p.owner}/${p.repoName}`,u.fileName),Fe=J.relative(e.cwd,u.destPath),Ye=dt({from:Z,to:Fe,changes:X,expand:e.expand,maxUnchanged:e.maxUnchanged,colorAdded:I.greenBright,colorRemoved:I.redBright,colorCharsAdded:I.bgGreenBright,colorCharsRemoved:I.bgRedBright,prefix:()=>`${N} `,onUnchanged:({from:Be,to:gt,prefix:ht})=>`${ht?.()??""}${I.cyan(Be)} \u2192 ${I.gray(gt)} ${I.gray("(unchanged)")}
|
|
51
|
+
`,intro:({from:Be,to:gt,changes:ht,prefix:Mt})=>{let Jt=ht.filter(Cr=>Cr.added).length;return `${Mt?.()??""}${I.cyan(Be)} \u2192 ${I.gray(gt)} (${Jt} change${Jt===1?"":"s"})
|
|
52
|
+
${Mt?.()??""}
|
|
53
|
+
`}});if(process.stdout.write(Ye),X.length>1||x===""){let Be=await confirm({message:"Accept changes?",initialValue:!0});isCancel(Be)&&(cancel("Canceled!"),process.exit(0)),F=Be;}}F&&await et([{loadingMessage:`Writing changes to ${I.cyan(u.destPath)}`,completedMessage:`Wrote changes to ${I.cyan(u.destPath)}.`,run:async()=>Ne.writeFileSync(u.destPath,k)}],{verbose:e.verbose?r:void 0});}if(n.includeTests&&w.tests){r("Trying to include tests");let{devDependencies:u}=JSON.parse(Ne.readFileSync(J.join(e.cwd,"package.json")).toString());(u===void 0||u.vitest===void 0)&&v.add("vitest");}for(let u of w.devDependencies)v.add(u);for(let u of w.dependencies)m.add(u);}await et($,{verbose:e.verbose?r:void 0});let j=it(m,v,{cwd:e.cwd});if(m=j.dependencies,v=j.devDependencies,m.size>0||v.size>0){let w=e.yes;if(!e.yes){let p=await confirm({message:"Would you like to install dependencies?",initialValue:!0});isCancel(p)&&(cancel("Canceled!"),process.exit(0)),w=p;}w&&(m.size>0&&(e.verbose||o.start(`Installing dependencies with ${I.cyan(f)}`),(await Re({pm:f,deps:Array.from(m),dev:!1,cwd:e.cwd})).match(p=>{e.verbose||o.stop(`Installed ${I.cyan(p.join(", "))}`);},p=>{e.verbose||o.stop("Failed to install dependencies"),program.error(p);})),v.size>0&&(e.verbose||o.start(`Installing dependencies with ${I.cyan(f)}`),(await Re({pm:f,deps:Array.from(v),dev:!0,cwd:e.cwd})).match(p=>{e.verbose||o.stop(`Installed ${I.cyan(p.join(", "))}`);},p=>{e.verbose||o.stop("Failed to install dev dependencies"),program.error(p);})));let g=[];if(!w){if(m.size>0){let p=resolveCommand(f,"install",[...m]);g.push(`Install dependencies \`${I.cyan(`${p?.command} ${p?.args.join(" ")}`)}\``);}if(v.size>0){let p=resolveCommand(f,"install",[...v,"-D"]);g.push(`Install dev dependencies \`${I.cyan(`${p?.command} ${p?.args.join(" ")}`)}\``);}}g=g.map((p,c)=>`${c+1}. ${p}`),w||g.push(""),g.push(`Import the blocks from \`${I.cyan(n.path)}\``);let l=Ue(g);process.stdout.write(l);}};var $r=t=>{let e=fileURLToPath(import.meta.url);return J.join(e,"../..",t)},{version:br,name:kr,description:Rr,repository:an}=JSON.parse(Ne.readFileSync($r("package.json"),"utf-8")),M={package:{name:kr,description:Rr,version:br,repository:an},resolveRelativeToRoot:$r};console.clear();program.name(kr).description(Rr).version(br).addCommand(jt).addCommand(At).addCommand(Bt).addCommand(_t).addCommand(Nt).addCommand(Vt).addCommand(Dt);program.parse();export{M as context};
|