@rhseung/ps-cli 1.0.0

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.
@@ -0,0 +1,641 @@
1
+ #!/usr/bin/env node
2
+
3
+ // src/services/solved-api.ts
4
+ var BASE_URL = "https://solved.ac/api/v3";
5
+ var USER_AGENT = "ps-cli/1.0.0";
6
+ async function fetchWithRetry(url, options = {}, maxRetries = 3) {
7
+ let lastError = null;
8
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
9
+ try {
10
+ const response = await fetch(url, {
11
+ ...options,
12
+ headers: {
13
+ "User-Agent": USER_AGENT,
14
+ ...options.headers
15
+ }
16
+ });
17
+ if (response.status === 429) {
18
+ const retryAfter = response.headers.get("Retry-After");
19
+ const waitTime = retryAfter ? parseInt(retryAfter, 10) * 1e3 : (attempt + 1) * 1e3;
20
+ await new Promise((resolve) => setTimeout(resolve, waitTime));
21
+ continue;
22
+ }
23
+ if (!response.ok) {
24
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
25
+ }
26
+ return response;
27
+ } catch (error) {
28
+ lastError = error instanceof Error ? error : new Error(String(error));
29
+ if (attempt < maxRetries - 1) {
30
+ await new Promise(
31
+ (resolve) => setTimeout(resolve, (attempt + 1) * 1e3)
32
+ );
33
+ }
34
+ }
35
+ }
36
+ throw lastError || new Error("Request failed after retries");
37
+ }
38
+ async function getProblem(problemId) {
39
+ const url = `${BASE_URL}/problem/show?problemId=${problemId}`;
40
+ const response = await fetchWithRetry(url);
41
+ const data = await response.json();
42
+ return data;
43
+ }
44
+ async function getUserStats(handle) {
45
+ const url = `${BASE_URL}/user/show?handle=${handle}`;
46
+ const response = await fetchWithRetry(url);
47
+ const data = await response.json();
48
+ return data;
49
+ }
50
+
51
+ // src/utils/tier.ts
52
+ var TIER_NAMES = [
53
+ void 0,
54
+ "Bronze V",
55
+ "Bronze IV",
56
+ "Bronze III",
57
+ "Bronze II",
58
+ "Bronze I",
59
+ "Silver V",
60
+ "Silver IV",
61
+ "Silver III",
62
+ "Silver II",
63
+ "Silver I",
64
+ "Gold V",
65
+ "Gold IV",
66
+ "Gold III",
67
+ "Gold II",
68
+ "Gold I",
69
+ "Platinum V",
70
+ "Platinum IV",
71
+ "Platinum III",
72
+ "Platinum II",
73
+ "Platinum I",
74
+ "Diamond V",
75
+ "Diamond IV",
76
+ "Diamond III",
77
+ "Diamond II",
78
+ "Diamond I",
79
+ "Ruby V",
80
+ "Ruby IV",
81
+ "Ruby III",
82
+ "Ruby II",
83
+ "Ruby I",
84
+ "Master"
85
+ ];
86
+ var TIER_COLORS = [
87
+ void 0,
88
+ "#9d4900",
89
+ "#a54f00",
90
+ "#ad5600",
91
+ "#b55d0a",
92
+ "#c67739",
93
+ "#38546e",
94
+ "#3d5a74",
95
+ "#435f7a",
96
+ "#496580",
97
+ "#4e6a86",
98
+ "#d28500",
99
+ "#df8f00",
100
+ "#ec9a00",
101
+ "#f9a518",
102
+ "#ffb028",
103
+ "#00c78b",
104
+ "#00d497",
105
+ "#27e2a4",
106
+ "#3ef0b1",
107
+ "#51fdbd",
108
+ "#009ee5",
109
+ "#00a9f0",
110
+ "#00b4fc",
111
+ "#2bbfff",
112
+ "#41caff",
113
+ "#e0004c",
114
+ "#ea0053",
115
+ "#f5005a",
116
+ "#ff0062",
117
+ "#ff3071",
118
+ "#b300e0"
119
+ ];
120
+ var TIER_IMAGE_BASE_URL = "https://d2gd6pc034wcta.cloudfront.net/tier";
121
+ function getTierName(level) {
122
+ if (level === 0) return "Unrated";
123
+ if (level >= 1 && level < TIER_NAMES.length) {
124
+ return TIER_NAMES[level] || "Unrated";
125
+ }
126
+ return "Unrated";
127
+ }
128
+ function getTierColor(level) {
129
+ if (level === 0) return "#2d2d2d";
130
+ if (level >= 1 && level < TIER_COLORS.length) {
131
+ return TIER_COLORS[level] || "#2d2d2d";
132
+ }
133
+ return "#2d2d2d";
134
+ }
135
+ function getTierImageUrl(level) {
136
+ return `${TIER_IMAGE_BASE_URL}/${level}.svg`;
137
+ }
138
+
139
+ // node_modules/chalk/source/vendor/ansi-styles/index.js
140
+ var ANSI_BACKGROUND_OFFSET = 10;
141
+ var wrapAnsi16 = (offset = 0) => (code) => `\x1B[${code + offset}m`;
142
+ var wrapAnsi256 = (offset = 0) => (code) => `\x1B[${38 + offset};5;${code}m`;
143
+ var wrapAnsi16m = (offset = 0) => (red, green, blue) => `\x1B[${38 + offset};2;${red};${green};${blue}m`;
144
+ var styles = {
145
+ modifier: {
146
+ reset: [0, 0],
147
+ // 21 isn't widely supported and 22 does the same thing
148
+ bold: [1, 22],
149
+ dim: [2, 22],
150
+ italic: [3, 23],
151
+ underline: [4, 24],
152
+ overline: [53, 55],
153
+ inverse: [7, 27],
154
+ hidden: [8, 28],
155
+ strikethrough: [9, 29]
156
+ },
157
+ color: {
158
+ black: [30, 39],
159
+ red: [31, 39],
160
+ green: [32, 39],
161
+ yellow: [33, 39],
162
+ blue: [34, 39],
163
+ magenta: [35, 39],
164
+ cyan: [36, 39],
165
+ white: [37, 39],
166
+ // Bright color
167
+ blackBright: [90, 39],
168
+ gray: [90, 39],
169
+ // Alias of `blackBright`
170
+ grey: [90, 39],
171
+ // Alias of `blackBright`
172
+ redBright: [91, 39],
173
+ greenBright: [92, 39],
174
+ yellowBright: [93, 39],
175
+ blueBright: [94, 39],
176
+ magentaBright: [95, 39],
177
+ cyanBright: [96, 39],
178
+ whiteBright: [97, 39]
179
+ },
180
+ bgColor: {
181
+ bgBlack: [40, 49],
182
+ bgRed: [41, 49],
183
+ bgGreen: [42, 49],
184
+ bgYellow: [43, 49],
185
+ bgBlue: [44, 49],
186
+ bgMagenta: [45, 49],
187
+ bgCyan: [46, 49],
188
+ bgWhite: [47, 49],
189
+ // Bright color
190
+ bgBlackBright: [100, 49],
191
+ bgGray: [100, 49],
192
+ // Alias of `bgBlackBright`
193
+ bgGrey: [100, 49],
194
+ // Alias of `bgBlackBright`
195
+ bgRedBright: [101, 49],
196
+ bgGreenBright: [102, 49],
197
+ bgYellowBright: [103, 49],
198
+ bgBlueBright: [104, 49],
199
+ bgMagentaBright: [105, 49],
200
+ bgCyanBright: [106, 49],
201
+ bgWhiteBright: [107, 49]
202
+ }
203
+ };
204
+ var modifierNames = Object.keys(styles.modifier);
205
+ var foregroundColorNames = Object.keys(styles.color);
206
+ var backgroundColorNames = Object.keys(styles.bgColor);
207
+ var colorNames = [...foregroundColorNames, ...backgroundColorNames];
208
+ function assembleStyles() {
209
+ const codes = /* @__PURE__ */ new Map();
210
+ for (const [groupName, group] of Object.entries(styles)) {
211
+ for (const [styleName, style] of Object.entries(group)) {
212
+ styles[styleName] = {
213
+ open: `\x1B[${style[0]}m`,
214
+ close: `\x1B[${style[1]}m`
215
+ };
216
+ group[styleName] = styles[styleName];
217
+ codes.set(style[0], style[1]);
218
+ }
219
+ Object.defineProperty(styles, groupName, {
220
+ value: group,
221
+ enumerable: false
222
+ });
223
+ }
224
+ Object.defineProperty(styles, "codes", {
225
+ value: codes,
226
+ enumerable: false
227
+ });
228
+ styles.color.close = "\x1B[39m";
229
+ styles.bgColor.close = "\x1B[49m";
230
+ styles.color.ansi = wrapAnsi16();
231
+ styles.color.ansi256 = wrapAnsi256();
232
+ styles.color.ansi16m = wrapAnsi16m();
233
+ styles.bgColor.ansi = wrapAnsi16(ANSI_BACKGROUND_OFFSET);
234
+ styles.bgColor.ansi256 = wrapAnsi256(ANSI_BACKGROUND_OFFSET);
235
+ styles.bgColor.ansi16m = wrapAnsi16m(ANSI_BACKGROUND_OFFSET);
236
+ Object.defineProperties(styles, {
237
+ rgbToAnsi256: {
238
+ value(red, green, blue) {
239
+ if (red === green && green === blue) {
240
+ if (red < 8) {
241
+ return 16;
242
+ }
243
+ if (red > 248) {
244
+ return 231;
245
+ }
246
+ return Math.round((red - 8) / 247 * 24) + 232;
247
+ }
248
+ return 16 + 36 * Math.round(red / 255 * 5) + 6 * Math.round(green / 255 * 5) + Math.round(blue / 255 * 5);
249
+ },
250
+ enumerable: false
251
+ },
252
+ hexToRgb: {
253
+ value(hex) {
254
+ const matches = /[a-f\d]{6}|[a-f\d]{3}/i.exec(hex.toString(16));
255
+ if (!matches) {
256
+ return [0, 0, 0];
257
+ }
258
+ let [colorString] = matches;
259
+ if (colorString.length === 3) {
260
+ colorString = [...colorString].map((character) => character + character).join("");
261
+ }
262
+ const integer = Number.parseInt(colorString, 16);
263
+ return [
264
+ /* eslint-disable no-bitwise */
265
+ integer >> 16 & 255,
266
+ integer >> 8 & 255,
267
+ integer & 255
268
+ /* eslint-enable no-bitwise */
269
+ ];
270
+ },
271
+ enumerable: false
272
+ },
273
+ hexToAnsi256: {
274
+ value: (hex) => styles.rgbToAnsi256(...styles.hexToRgb(hex)),
275
+ enumerable: false
276
+ },
277
+ ansi256ToAnsi: {
278
+ value(code) {
279
+ if (code < 8) {
280
+ return 30 + code;
281
+ }
282
+ if (code < 16) {
283
+ return 90 + (code - 8);
284
+ }
285
+ let red;
286
+ let green;
287
+ let blue;
288
+ if (code >= 232) {
289
+ red = ((code - 232) * 10 + 8) / 255;
290
+ green = red;
291
+ blue = red;
292
+ } else {
293
+ code -= 16;
294
+ const remainder = code % 36;
295
+ red = Math.floor(code / 36) / 5;
296
+ green = Math.floor(remainder / 6) / 5;
297
+ blue = remainder % 6 / 5;
298
+ }
299
+ const value = Math.max(red, green, blue) * 2;
300
+ if (value === 0) {
301
+ return 30;
302
+ }
303
+ let result = 30 + (Math.round(blue) << 2 | Math.round(green) << 1 | Math.round(red));
304
+ if (value === 2) {
305
+ result += 60;
306
+ }
307
+ return result;
308
+ },
309
+ enumerable: false
310
+ },
311
+ rgbToAnsi: {
312
+ value: (red, green, blue) => styles.ansi256ToAnsi(styles.rgbToAnsi256(red, green, blue)),
313
+ enumerable: false
314
+ },
315
+ hexToAnsi: {
316
+ value: (hex) => styles.ansi256ToAnsi(styles.hexToAnsi256(hex)),
317
+ enumerable: false
318
+ }
319
+ });
320
+ return styles;
321
+ }
322
+ var ansiStyles = assembleStyles();
323
+ var ansi_styles_default = ansiStyles;
324
+
325
+ // node_modules/chalk/source/vendor/supports-color/index.js
326
+ import process from "process";
327
+ import os from "os";
328
+ import tty from "tty";
329
+ function hasFlag(flag, argv = globalThis.Deno ? globalThis.Deno.args : process.argv) {
330
+ const prefix = flag.startsWith("-") ? "" : flag.length === 1 ? "-" : "--";
331
+ const position = argv.indexOf(prefix + flag);
332
+ const terminatorPosition = argv.indexOf("--");
333
+ return position !== -1 && (terminatorPosition === -1 || position < terminatorPosition);
334
+ }
335
+ var { env } = process;
336
+ var flagForceColor;
337
+ if (hasFlag("no-color") || hasFlag("no-colors") || hasFlag("color=false") || hasFlag("color=never")) {
338
+ flagForceColor = 0;
339
+ } else if (hasFlag("color") || hasFlag("colors") || hasFlag("color=true") || hasFlag("color=always")) {
340
+ flagForceColor = 1;
341
+ }
342
+ function envForceColor() {
343
+ if ("FORCE_COLOR" in env) {
344
+ if (env.FORCE_COLOR === "true") {
345
+ return 1;
346
+ }
347
+ if (env.FORCE_COLOR === "false") {
348
+ return 0;
349
+ }
350
+ return env.FORCE_COLOR.length === 0 ? 1 : Math.min(Number.parseInt(env.FORCE_COLOR, 10), 3);
351
+ }
352
+ }
353
+ function translateLevel(level) {
354
+ if (level === 0) {
355
+ return false;
356
+ }
357
+ return {
358
+ level,
359
+ hasBasic: true,
360
+ has256: level >= 2,
361
+ has16m: level >= 3
362
+ };
363
+ }
364
+ function _supportsColor(haveStream, { streamIsTTY, sniffFlags = true } = {}) {
365
+ const noFlagForceColor = envForceColor();
366
+ if (noFlagForceColor !== void 0) {
367
+ flagForceColor = noFlagForceColor;
368
+ }
369
+ const forceColor = sniffFlags ? flagForceColor : noFlagForceColor;
370
+ if (forceColor === 0) {
371
+ return 0;
372
+ }
373
+ if (sniffFlags) {
374
+ if (hasFlag("color=16m") || hasFlag("color=full") || hasFlag("color=truecolor")) {
375
+ return 3;
376
+ }
377
+ if (hasFlag("color=256")) {
378
+ return 2;
379
+ }
380
+ }
381
+ if ("TF_BUILD" in env && "AGENT_NAME" in env) {
382
+ return 1;
383
+ }
384
+ if (haveStream && !streamIsTTY && forceColor === void 0) {
385
+ return 0;
386
+ }
387
+ const min = forceColor || 0;
388
+ if (env.TERM === "dumb") {
389
+ return min;
390
+ }
391
+ if (process.platform === "win32") {
392
+ const osRelease = os.release().split(".");
393
+ if (Number(osRelease[0]) >= 10 && Number(osRelease[2]) >= 10586) {
394
+ return Number(osRelease[2]) >= 14931 ? 3 : 2;
395
+ }
396
+ return 1;
397
+ }
398
+ if ("CI" in env) {
399
+ if (["GITHUB_ACTIONS", "GITEA_ACTIONS", "CIRCLECI"].some((key) => key in env)) {
400
+ return 3;
401
+ }
402
+ if (["TRAVIS", "APPVEYOR", "GITLAB_CI", "BUILDKITE", "DRONE"].some((sign) => sign in env) || env.CI_NAME === "codeship") {
403
+ return 1;
404
+ }
405
+ return min;
406
+ }
407
+ if ("TEAMCITY_VERSION" in env) {
408
+ return /^(9\.(0*[1-9]\d*)\.|\d{2,}\.)/.test(env.TEAMCITY_VERSION) ? 1 : 0;
409
+ }
410
+ if (env.COLORTERM === "truecolor") {
411
+ return 3;
412
+ }
413
+ if (env.TERM === "xterm-kitty") {
414
+ return 3;
415
+ }
416
+ if (env.TERM === "xterm-ghostty") {
417
+ return 3;
418
+ }
419
+ if (env.TERM === "wezterm") {
420
+ return 3;
421
+ }
422
+ if ("TERM_PROGRAM" in env) {
423
+ const version = Number.parseInt((env.TERM_PROGRAM_VERSION || "").split(".")[0], 10);
424
+ switch (env.TERM_PROGRAM) {
425
+ case "iTerm.app": {
426
+ return version >= 3 ? 3 : 2;
427
+ }
428
+ case "Apple_Terminal": {
429
+ return 2;
430
+ }
431
+ }
432
+ }
433
+ if (/-256(color)?$/i.test(env.TERM)) {
434
+ return 2;
435
+ }
436
+ if (/^screen|^xterm|^vt100|^vt220|^rxvt|color|ansi|cygwin|linux/i.test(env.TERM)) {
437
+ return 1;
438
+ }
439
+ if ("COLORTERM" in env) {
440
+ return 1;
441
+ }
442
+ return min;
443
+ }
444
+ function createSupportsColor(stream, options = {}) {
445
+ const level = _supportsColor(stream, {
446
+ streamIsTTY: stream && stream.isTTY,
447
+ ...options
448
+ });
449
+ return translateLevel(level);
450
+ }
451
+ var supportsColor = {
452
+ stdout: createSupportsColor({ isTTY: tty.isatty(1) }),
453
+ stderr: createSupportsColor({ isTTY: tty.isatty(2) })
454
+ };
455
+ var supports_color_default = supportsColor;
456
+
457
+ // node_modules/chalk/source/utilities.js
458
+ function stringReplaceAll(string, substring, replacer) {
459
+ let index = string.indexOf(substring);
460
+ if (index === -1) {
461
+ return string;
462
+ }
463
+ const substringLength = substring.length;
464
+ let endIndex = 0;
465
+ let returnValue = "";
466
+ do {
467
+ returnValue += string.slice(endIndex, index) + substring + replacer;
468
+ endIndex = index + substringLength;
469
+ index = string.indexOf(substring, endIndex);
470
+ } while (index !== -1);
471
+ returnValue += string.slice(endIndex);
472
+ return returnValue;
473
+ }
474
+ function stringEncaseCRLFWithFirstIndex(string, prefix, postfix, index) {
475
+ let endIndex = 0;
476
+ let returnValue = "";
477
+ do {
478
+ const gotCR = string[index - 1] === "\r";
479
+ returnValue += string.slice(endIndex, gotCR ? index - 1 : index) + prefix + (gotCR ? "\r\n" : "\n") + postfix;
480
+ endIndex = index + 1;
481
+ index = string.indexOf("\n", endIndex);
482
+ } while (index !== -1);
483
+ returnValue += string.slice(endIndex);
484
+ return returnValue;
485
+ }
486
+
487
+ // node_modules/chalk/source/index.js
488
+ var { stdout: stdoutColor, stderr: stderrColor } = supports_color_default;
489
+ var GENERATOR = /* @__PURE__ */ Symbol("GENERATOR");
490
+ var STYLER = /* @__PURE__ */ Symbol("STYLER");
491
+ var IS_EMPTY = /* @__PURE__ */ Symbol("IS_EMPTY");
492
+ var levelMapping = [
493
+ "ansi",
494
+ "ansi",
495
+ "ansi256",
496
+ "ansi16m"
497
+ ];
498
+ var styles2 = /* @__PURE__ */ Object.create(null);
499
+ var applyOptions = (object, options = {}) => {
500
+ if (options.level && !(Number.isInteger(options.level) && options.level >= 0 && options.level <= 3)) {
501
+ throw new Error("The `level` option should be an integer from 0 to 3");
502
+ }
503
+ const colorLevel = stdoutColor ? stdoutColor.level : 0;
504
+ object.level = options.level === void 0 ? colorLevel : options.level;
505
+ };
506
+ var chalkFactory = (options) => {
507
+ const chalk2 = (...strings) => strings.join(" ");
508
+ applyOptions(chalk2, options);
509
+ Object.setPrototypeOf(chalk2, createChalk.prototype);
510
+ return chalk2;
511
+ };
512
+ function createChalk(options) {
513
+ return chalkFactory(options);
514
+ }
515
+ Object.setPrototypeOf(createChalk.prototype, Function.prototype);
516
+ for (const [styleName, style] of Object.entries(ansi_styles_default)) {
517
+ styles2[styleName] = {
518
+ get() {
519
+ const builder = createBuilder(this, createStyler(style.open, style.close, this[STYLER]), this[IS_EMPTY]);
520
+ Object.defineProperty(this, styleName, { value: builder });
521
+ return builder;
522
+ }
523
+ };
524
+ }
525
+ styles2.visible = {
526
+ get() {
527
+ const builder = createBuilder(this, this[STYLER], true);
528
+ Object.defineProperty(this, "visible", { value: builder });
529
+ return builder;
530
+ }
531
+ };
532
+ var getModelAnsi = (model, level, type, ...arguments_) => {
533
+ if (model === "rgb") {
534
+ if (level === "ansi16m") {
535
+ return ansi_styles_default[type].ansi16m(...arguments_);
536
+ }
537
+ if (level === "ansi256") {
538
+ return ansi_styles_default[type].ansi256(ansi_styles_default.rgbToAnsi256(...arguments_));
539
+ }
540
+ return ansi_styles_default[type].ansi(ansi_styles_default.rgbToAnsi(...arguments_));
541
+ }
542
+ if (model === "hex") {
543
+ return getModelAnsi("rgb", level, type, ...ansi_styles_default.hexToRgb(...arguments_));
544
+ }
545
+ return ansi_styles_default[type][model](...arguments_);
546
+ };
547
+ var usedModels = ["rgb", "hex", "ansi256"];
548
+ for (const model of usedModels) {
549
+ styles2[model] = {
550
+ get() {
551
+ const { level } = this;
552
+ return function(...arguments_) {
553
+ const styler = createStyler(getModelAnsi(model, levelMapping[level], "color", ...arguments_), ansi_styles_default.color.close, this[STYLER]);
554
+ return createBuilder(this, styler, this[IS_EMPTY]);
555
+ };
556
+ }
557
+ };
558
+ const bgModel = "bg" + model[0].toUpperCase() + model.slice(1);
559
+ styles2[bgModel] = {
560
+ get() {
561
+ const { level } = this;
562
+ return function(...arguments_) {
563
+ const styler = createStyler(getModelAnsi(model, levelMapping[level], "bgColor", ...arguments_), ansi_styles_default.bgColor.close, this[STYLER]);
564
+ return createBuilder(this, styler, this[IS_EMPTY]);
565
+ };
566
+ }
567
+ };
568
+ }
569
+ var proto = Object.defineProperties(() => {
570
+ }, {
571
+ ...styles2,
572
+ level: {
573
+ enumerable: true,
574
+ get() {
575
+ return this[GENERATOR].level;
576
+ },
577
+ set(level) {
578
+ this[GENERATOR].level = level;
579
+ }
580
+ }
581
+ });
582
+ var createStyler = (open, close, parent) => {
583
+ let openAll;
584
+ let closeAll;
585
+ if (parent === void 0) {
586
+ openAll = open;
587
+ closeAll = close;
588
+ } else {
589
+ openAll = parent.openAll + open;
590
+ closeAll = close + parent.closeAll;
591
+ }
592
+ return {
593
+ open,
594
+ close,
595
+ openAll,
596
+ closeAll,
597
+ parent
598
+ };
599
+ };
600
+ var createBuilder = (self, _styler, _isEmpty) => {
601
+ const builder = (...arguments_) => applyStyle(builder, arguments_.length === 1 ? "" + arguments_[0] : arguments_.join(" "));
602
+ Object.setPrototypeOf(builder, proto);
603
+ builder[GENERATOR] = self;
604
+ builder[STYLER] = _styler;
605
+ builder[IS_EMPTY] = _isEmpty;
606
+ return builder;
607
+ };
608
+ var applyStyle = (self, string) => {
609
+ if (self.level <= 0 || !string) {
610
+ return self[IS_EMPTY] ? "" : string;
611
+ }
612
+ let styler = self[STYLER];
613
+ if (styler === void 0) {
614
+ return string;
615
+ }
616
+ const { openAll, closeAll } = styler;
617
+ if (string.includes("\x1B")) {
618
+ while (styler !== void 0) {
619
+ string = stringReplaceAll(string, styler.close, styler.open);
620
+ styler = styler.parent;
621
+ }
622
+ }
623
+ const lfIndex = string.indexOf("\n");
624
+ if (lfIndex !== -1) {
625
+ string = stringEncaseCRLFWithFirstIndex(string, closeAll, openAll, lfIndex);
626
+ }
627
+ return openAll + string + closeAll;
628
+ };
629
+ Object.defineProperties(createChalk.prototype, styles2);
630
+ var chalk = createChalk();
631
+ var chalkStderr = createChalk({ level: stderrColor ? stderrColor.level : 0 });
632
+ var source_default = chalk;
633
+
634
+ export {
635
+ getProblem,
636
+ getUserStats,
637
+ getTierName,
638
+ getTierColor,
639
+ getTierImageUrl,
640
+ source_default
641
+ };
@@ -0,0 +1,68 @@
1
+ #!/usr/bin/env node
2
+ import {
3
+ getLanguageConfig
4
+ } from "./chunk-TQXMB7XV.js";
5
+
6
+ // src/services/runner.ts
7
+ import { readFile } from "fs/promises";
8
+ import { join } from "path";
9
+ import { execa, execaCommand } from "execa";
10
+ async function runSolution({
11
+ problemDir,
12
+ language,
13
+ inputPath,
14
+ timeoutMs = 5e3
15
+ }) {
16
+ const langConfig = getLanguageConfig(language);
17
+ const solutionFile = `solution.${langConfig.extension}`;
18
+ const solutionPath = join(problemDir, solutionFile);
19
+ const input = await readFile(inputPath, "utf-8");
20
+ const start = Date.now();
21
+ try {
22
+ if (langConfig.compileCommand) {
23
+ await execaCommand(langConfig.compileCommand, {
24
+ cwd: problemDir,
25
+ timeout: timeoutMs
26
+ });
27
+ }
28
+ const child = execa(langConfig.runCommand, [solutionPath], {
29
+ cwd: problemDir,
30
+ input,
31
+ timeout: timeoutMs
32
+ });
33
+ const result = await child;
34
+ const exitCode = result.exitCode ?? null;
35
+ const { stdout, stderr } = result;
36
+ const durationMs = Date.now() - start;
37
+ return {
38
+ stdout,
39
+ stderr,
40
+ exitCode,
41
+ timedOut: false,
42
+ durationMs
43
+ };
44
+ } catch (error) {
45
+ const durationMs = Date.now() - start;
46
+ if (error instanceof Error && "timedOut" in error) {
47
+ const err = error;
48
+ return {
49
+ stdout: err.stdout ?? "",
50
+ stderr: err.stderr ?? err.shortMessage ?? err.message,
51
+ exitCode: err.exitCode ?? null,
52
+ timedOut: Boolean(err.timedOut),
53
+ durationMs
54
+ };
55
+ }
56
+ return {
57
+ stdout: "",
58
+ stderr: error instanceof Error ? error.message : String(error),
59
+ exitCode: null,
60
+ timedOut: false,
61
+ durationMs
62
+ };
63
+ }
64
+ }
65
+
66
+ export {
67
+ runSolution
68
+ };