epicshop 6.80.2 → 6.82.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.
- package/dist/cli.js +40 -13
- package/dist/commands/workshops.d.ts +1 -1
- package/dist/commands/workshops.js +15 -2
- package/package.json +6 -6
package/dist/cli.js
CHANGED
|
@@ -28,6 +28,13 @@ function formatHelp(helpText) {
|
|
|
28
28
|
.replace(/--[\w-]+/g, (match) => chalk.yellow(match))
|
|
29
29
|
.replace(/-\w(?=\s|,)/g, (match) => chalk.yellow(match));
|
|
30
30
|
}
|
|
31
|
+
function resolveWorkshopContextCwd(explicitWorkshopDir) {
|
|
32
|
+
const fromFlag = explicitWorkshopDir?.trim() ? explicitWorkshopDir.trim() : undefined;
|
|
33
|
+
if (fromFlag)
|
|
34
|
+
return fromFlag;
|
|
35
|
+
const fromEnv = process.env.EPICSHOP_CONTEXT_CWD;
|
|
36
|
+
return fromEnv?.trim() ? fromEnv.trim() : undefined;
|
|
37
|
+
}
|
|
31
38
|
// Set up yargs CLI
|
|
32
39
|
const cli = yargs(args)
|
|
33
40
|
.scriptName('epicshop')
|
|
@@ -767,6 +774,11 @@ const cli = yargs(args)
|
|
|
767
774
|
type: 'boolean',
|
|
768
775
|
description: 'Output saved playgrounds as JSON (saved list)',
|
|
769
776
|
default: false,
|
|
777
|
+
})
|
|
778
|
+
.option('workshop-dir', {
|
|
779
|
+
alias: 'w',
|
|
780
|
+
type: 'string',
|
|
781
|
+
description: 'Path to a workshop directory to use as context (instead of the current working directory)',
|
|
770
782
|
})
|
|
771
783
|
.option('silent', {
|
|
772
784
|
alias: 's',
|
|
@@ -784,9 +796,9 @@ const cli = yargs(args)
|
|
|
784
796
|
.example('$0 playground saved 2026.01.18_11.12.00_01.01.problem', 'Set playground from a saved copy');
|
|
785
797
|
}, async (argv) => {
|
|
786
798
|
const { findWorkshopRoot } = await import("./commands/workshops.js");
|
|
787
|
-
const workshopRoot = await findWorkshopRoot();
|
|
799
|
+
const workshopRoot = await findWorkshopRoot(resolveWorkshopContextCwd(argv.workshopDir));
|
|
788
800
|
if (!workshopRoot) {
|
|
789
|
-
console.error(chalk.red('❌
|
|
801
|
+
console.error(chalk.red('❌ Workshop not found. Please cd into a workshop directory or pass --workshop-dir.'));
|
|
790
802
|
process.exit(1);
|
|
791
803
|
}
|
|
792
804
|
const originalCwd = process.cwd();
|
|
@@ -903,6 +915,11 @@ const cli = yargs(args)
|
|
|
903
915
|
type: 'boolean',
|
|
904
916
|
description: 'Output as JSON',
|
|
905
917
|
default: false,
|
|
918
|
+
})
|
|
919
|
+
.option('workshop-dir', {
|
|
920
|
+
alias: 'w',
|
|
921
|
+
type: 'string',
|
|
922
|
+
description: 'Path to a workshop directory to use as context (instead of the current working directory)',
|
|
906
923
|
})
|
|
907
924
|
.option('silent', {
|
|
908
925
|
alias: 's',
|
|
@@ -917,9 +934,9 @@ const cli = yargs(args)
|
|
|
917
934
|
.example('$0 progress update 01-01-problem --incomplete', 'Mark lesson as incomplete');
|
|
918
935
|
}, async (argv) => {
|
|
919
936
|
const { findWorkshopRoot } = await import("./commands/workshops.js");
|
|
920
|
-
const workshopRoot = await findWorkshopRoot();
|
|
937
|
+
const workshopRoot = await findWorkshopRoot(resolveWorkshopContextCwd(argv.workshopDir));
|
|
921
938
|
if (!workshopRoot) {
|
|
922
|
-
console.error(chalk.red('❌
|
|
939
|
+
console.error(chalk.red('❌ Workshop not found. Please cd into a workshop directory or pass --workshop-dir.'));
|
|
923
940
|
process.exit(1);
|
|
924
941
|
}
|
|
925
942
|
const originalCwd = process.cwd();
|
|
@@ -970,14 +987,19 @@ const cli = yargs(args)
|
|
|
970
987
|
type: 'boolean',
|
|
971
988
|
description: 'Run without output logs',
|
|
972
989
|
default: false,
|
|
990
|
+
})
|
|
991
|
+
.option('workshop-dir', {
|
|
992
|
+
alias: 'w',
|
|
993
|
+
type: 'string',
|
|
994
|
+
description: 'Path to a workshop directory to use as context (instead of the current working directory)',
|
|
973
995
|
})
|
|
974
996
|
.example('$0 diff', 'Select apps to diff (defaults to playground vs solution)')
|
|
975
997
|
.example('$0 diff 01.02.problem 01.02.solution', 'Show diff between two apps');
|
|
976
998
|
}, async (argv) => {
|
|
977
999
|
const { findWorkshopRoot } = await import("./commands/workshops.js");
|
|
978
|
-
const workshopRoot = await findWorkshopRoot();
|
|
1000
|
+
const workshopRoot = await findWorkshopRoot(resolveWorkshopContextCwd(argv.workshopDir));
|
|
979
1001
|
if (!workshopRoot) {
|
|
980
|
-
console.error(chalk.red('❌
|
|
1002
|
+
console.error(chalk.red('❌ Workshop not found. Please cd into a workshop directory or pass --workshop-dir.'));
|
|
981
1003
|
process.exit(1);
|
|
982
1004
|
}
|
|
983
1005
|
const originalCwd = process.cwd();
|
|
@@ -1027,6 +1049,11 @@ const cli = yargs(args)
|
|
|
1027
1049
|
type: 'boolean',
|
|
1028
1050
|
description: 'Run without output logs',
|
|
1029
1051
|
default: false,
|
|
1052
|
+
})
|
|
1053
|
+
.option('workshop-dir', {
|
|
1054
|
+
alias: 'w',
|
|
1055
|
+
type: 'string',
|
|
1056
|
+
description: 'Path to a workshop directory to use as context (instead of the current working directory)',
|
|
1030
1057
|
})
|
|
1031
1058
|
.example('$0 exercises', 'List all exercises with progress')
|
|
1032
1059
|
.example('$0 exercises 1', 'Show details for exercise 1')
|
|
@@ -1034,9 +1061,9 @@ const cli = yargs(args)
|
|
|
1034
1061
|
.example('$0 exercises --json', 'Output exercises as JSON');
|
|
1035
1062
|
}, async (argv) => {
|
|
1036
1063
|
const { findWorkshopRoot } = await import("./commands/workshops.js");
|
|
1037
|
-
const workshopRoot = await findWorkshopRoot();
|
|
1064
|
+
const workshopRoot = await findWorkshopRoot(resolveWorkshopContextCwd(argv.workshopDir));
|
|
1038
1065
|
if (!workshopRoot) {
|
|
1039
|
-
console.error(chalk.red('❌
|
|
1066
|
+
console.error(chalk.red('❌ Workshop not found. Please cd into a workshop directory or pass --workshop-dir.'));
|
|
1040
1067
|
process.exit(1);
|
|
1041
1068
|
}
|
|
1042
1069
|
const originalCwd = process.cwd();
|
|
@@ -1087,7 +1114,7 @@ try {
|
|
|
1087
1114
|
if (args.length === 0) {
|
|
1088
1115
|
// Check if we're inside a workshop first
|
|
1089
1116
|
const { findWorkshopRoot } = await import("./commands/workshops.js");
|
|
1090
|
-
const workshopRoot = await findWorkshopRoot();
|
|
1117
|
+
const workshopRoot = await findWorkshopRoot(resolveWorkshopContextCwd());
|
|
1091
1118
|
// Get workshop title if we're inside one
|
|
1092
1119
|
let workshopTitle = null;
|
|
1093
1120
|
if (workshopRoot) {
|
|
@@ -1495,7 +1522,7 @@ try {
|
|
|
1495
1522
|
}
|
|
1496
1523
|
case 'exercises': {
|
|
1497
1524
|
const { findWorkshopRoot } = await import("./commands/workshops.js");
|
|
1498
|
-
const wsRoot = await findWorkshopRoot();
|
|
1525
|
+
const wsRoot = await findWorkshopRoot(resolveWorkshopContextCwd());
|
|
1499
1526
|
if (!wsRoot) {
|
|
1500
1527
|
console.error(chalk.red('❌ Not inside a workshop directory'));
|
|
1501
1528
|
process.exit(1);
|
|
@@ -1515,7 +1542,7 @@ try {
|
|
|
1515
1542
|
}
|
|
1516
1543
|
case 'playground': {
|
|
1517
1544
|
const { findWorkshopRoot } = await import("./commands/workshops.js");
|
|
1518
|
-
const wsRoot = await findWorkshopRoot();
|
|
1545
|
+
const wsRoot = await findWorkshopRoot(resolveWorkshopContextCwd());
|
|
1519
1546
|
if (!wsRoot) {
|
|
1520
1547
|
console.error(chalk.red('❌ Not inside a workshop directory'));
|
|
1521
1548
|
process.exit(1);
|
|
@@ -1535,7 +1562,7 @@ try {
|
|
|
1535
1562
|
}
|
|
1536
1563
|
case 'progress': {
|
|
1537
1564
|
const { findWorkshopRoot } = await import("./commands/workshops.js");
|
|
1538
|
-
const wsRoot = await findWorkshopRoot();
|
|
1565
|
+
const wsRoot = await findWorkshopRoot(resolveWorkshopContextCwd());
|
|
1539
1566
|
if (!wsRoot) {
|
|
1540
1567
|
console.error(chalk.red('❌ Not inside a workshop directory'));
|
|
1541
1568
|
process.exit(1);
|
|
@@ -1555,7 +1582,7 @@ try {
|
|
|
1555
1582
|
}
|
|
1556
1583
|
case 'diff': {
|
|
1557
1584
|
const { findWorkshopRoot } = await import("./commands/workshops.js");
|
|
1558
|
-
const wsRoot = await findWorkshopRoot();
|
|
1585
|
+
const wsRoot = await findWorkshopRoot(resolveWorkshopContextCwd());
|
|
1559
1586
|
if (!wsRoot) {
|
|
1560
1587
|
console.error(chalk.red('❌ Not inside a workshop directory'));
|
|
1561
1588
|
process.exit(1);
|
|
@@ -4,7 +4,7 @@ import '@epic-web/workshop-utils/init-env';
|
|
|
4
4
|
* looking for a package.json with an epicshop field.
|
|
5
5
|
* Returns the workshop root path if found, null otherwise.
|
|
6
6
|
*/
|
|
7
|
-
export declare function findWorkshopRoot(): Promise<string | null>;
|
|
7
|
+
export declare function findWorkshopRoot(startDir?: string): Promise<string | null>;
|
|
8
8
|
/**
|
|
9
9
|
* Check if the current working directory is inside a workshop
|
|
10
10
|
* (has epicshop config in package.json in current dir or any parent)
|
|
@@ -38,8 +38,21 @@ const EPIC_SITES = [
|
|
|
38
38
|
* looking for a package.json with an epicshop field.
|
|
39
39
|
* Returns the workshop root path if found, null otherwise.
|
|
40
40
|
*/
|
|
41
|
-
export async function findWorkshopRoot() {
|
|
42
|
-
let currentDir =
|
|
41
|
+
export async function findWorkshopRoot(startDir) {
|
|
42
|
+
let currentDir = startDir
|
|
43
|
+
? path.resolve(resolvePathWithTilde(startDir))
|
|
44
|
+
: process.cwd();
|
|
45
|
+
// If the user gave us a file path (or something that isn't a directory),
|
|
46
|
+
// treat the containing folder as the start point.
|
|
47
|
+
try {
|
|
48
|
+
const stat = await fs.promises.stat(currentDir);
|
|
49
|
+
if (!stat.isDirectory()) {
|
|
50
|
+
currentDir = path.dirname(currentDir);
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
catch {
|
|
54
|
+
// If the path doesn't exist, we still attempt to walk upward from it.
|
|
55
|
+
}
|
|
43
56
|
const root = path.parse(currentDir).root;
|
|
44
57
|
while (currentDir !== root) {
|
|
45
58
|
try {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "epicshop",
|
|
3
|
-
"version": "6.
|
|
3
|
+
"version": "6.82.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -99,7 +99,7 @@
|
|
|
99
99
|
"build:watch": "nx watch --projects=epicshop -- nx run \\$NX_PROJECT_NAME:build"
|
|
100
100
|
},
|
|
101
101
|
"dependencies": {
|
|
102
|
-
"@epic-web/workshop-utils": "6.
|
|
102
|
+
"@epic-web/workshop-utils": "6.82.0",
|
|
103
103
|
"@inquirer/prompts": "^8.2.0",
|
|
104
104
|
"@sentry/node": "^10.38.0",
|
|
105
105
|
"chalk": "^5.6.2",
|
|
@@ -108,13 +108,13 @@
|
|
|
108
108
|
"get-port": "^7.1.0",
|
|
109
109
|
"match-sorter": "^8.2.0",
|
|
110
110
|
"open": "^11.0.0",
|
|
111
|
-
"openid-client": "^6.8.
|
|
112
|
-
"ora": "^9.
|
|
111
|
+
"openid-client": "^6.8.2",
|
|
112
|
+
"ora": "^9.3.0",
|
|
113
113
|
"yargs": "^18.0.0"
|
|
114
114
|
},
|
|
115
115
|
"devDependencies": {
|
|
116
|
-
"@epic-web/config": "^1.
|
|
117
|
-
"@types/node": "^25.
|
|
116
|
+
"@epic-web/config": "^1.22.0",
|
|
117
|
+
"@types/node": "^25.2.3",
|
|
118
118
|
"@types/yargs": "^17.0.35",
|
|
119
119
|
"vitest": "^4.0.18",
|
|
120
120
|
"zshy": "^0.7.0"
|