@lukeguo12210/canvas-cli 0.0.2 → 0.0.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +50 -18
- package/dist/bin/canvas.js +197 -95
- package/dist/bin/canvas.js.map +1 -1
- package/package.json +6 -3
- package/skills/canvas-shared/SKILL.md +4 -2
- package/skills/canvas-shared/references/auth.md +50 -3
package/README.md
CHANGED
|
@@ -2,36 +2,40 @@
|
|
|
2
2
|
|
|
3
3
|
[](LICENSE)
|
|
4
4
|
|
|
5
|
-
Canvas
|
|
5
|
+
Connect Canvas courses to AI agents.
|
|
6
6
|
|
|
7
|
-
`@lukeguo12210/canvas-cli` turns Canvas LMS into
|
|
7
|
+
`@lukeguo12210/canvas-cli` turns Canvas LMS into an agent-readable course workspace. Today, students dig through Canvas, download slides, find assignments, copy pages, and upload everything back into LLMs. Canvas CLI makes that one workflow: pull course materials, modules, files, assignments, pages, folders, and review packs into a structure AI agents can immediately understand.
|
|
8
8
|
|
|
9
9
|
[Install](#installation--quick-start) · [Agent Skills](#agent-skills) · [Auth](#authentication) · [Commands](#command-system) · [Security](#security--privacy) · [License](#license) · [Roadmap](#roadmap)
|
|
10
10
|
|
|
11
|
+
## Star History
|
|
12
|
+
|
|
13
|
+
[](https://www.star-history.com/#lukeguo12210/canvas-cli&Date)
|
|
14
|
+
|
|
11
15
|
## Why @lukeguo12210/canvas-cli?
|
|
12
16
|
|
|
13
|
-
- **Built for technical students** — bring Canvas into your terminal, scripts, and
|
|
17
|
+
- **Built for technical students** — bring Canvas into your terminal, scripts, and AI workflow.
|
|
14
18
|
- **Agent-native design** — structured skills teach agents Canvas auth, pagination, course structure, and study workflows.
|
|
15
|
-
- **
|
|
16
|
-
- **Review-pack first** — export
|
|
19
|
+
- **No more manual Canvas digging** — pull slides, files, pages, assignments, folders, and module structure without download/upload loops.
|
|
20
|
+
- **Review-pack first** — export course structure into an agent-readable folder for study sessions.
|
|
17
21
|
- **Canvas-native commands** — simple commands such as `canvas courses list`, `canvas modules list`, and `canvas review pack`.
|
|
18
|
-
- **
|
|
22
|
+
- **Student-facing scope** — starts with the read-only course surface students need for review, planning, and coursework navigation.
|
|
19
23
|
|
|
20
24
|
## Features
|
|
21
25
|
|
|
22
26
|
| Category | Capabilities |
|
|
23
27
|
| --- | --- |
|
|
24
28
|
| Auth | Interactive `canvas auth login`, school picker, Canvas settings walkthrough, local PAT config |
|
|
25
|
-
| Context | Post-login context bootstrap: user profile, active courses, planner, calendar, upcoming assignments, modules |
|
|
26
29
|
| Courses | List, search, inspect, and summarize active courses |
|
|
30
|
+
| Tabs | Inspect visible Canvas course tabs and external tool links |
|
|
27
31
|
| Modules | Traverse modules and module items in Canvas order |
|
|
28
|
-
| Pages |
|
|
32
|
+
| Pages | List pages, inspect Canvas HTML, and export visible pages |
|
|
29
33
|
| Files | List files/folders and download accessible course files safely |
|
|
30
|
-
|
|
|
31
|
-
|
|
|
32
|
-
|
|
|
33
|
-
| Review Packs | Preserve Canvas course structure in an agent-readable
|
|
34
|
-
| Agent Skills |
|
|
34
|
+
| Folders | Browse Canvas folder trees and folder paths |
|
|
35
|
+
| Assignments | List assignments, due dates, descriptions, visible attachments, and exports |
|
|
36
|
+
| Raw API | Run read-only `GET` requests against Canvas API paths |
|
|
37
|
+
| Review Packs | Preserve Canvas course structure in an agent-readable export |
|
|
38
|
+
| Agent Skills | Skills that teach agents exact commands, output shapes, and Canvas workflows |
|
|
35
39
|
|
|
36
40
|
## Status
|
|
37
41
|
|
|
@@ -52,7 +56,7 @@ Planned next:
|
|
|
52
56
|
|
|
53
57
|
- Post-login context bootstrap.
|
|
54
58
|
- Broader review-pack indexing, citations, and linked-file resolution.
|
|
55
|
-
- Grades, submissions, discussions, announcements, calendar, groups, and
|
|
59
|
+
- Grades, submissions, discussions, announcements, calendar, groups, conversations, and richer review indexing.
|
|
56
60
|
|
|
57
61
|
## Installation & Quick Start
|
|
58
62
|
|
|
@@ -74,6 +78,10 @@ npm install -g @lukeguo12210/canvas-cli
|
|
|
74
78
|
# 1. Authenticate with your Canvas school
|
|
75
79
|
canvas auth login
|
|
76
80
|
|
|
81
|
+
# Agent/non-interactive auth
|
|
82
|
+
canvas auth schools search "Columbia"
|
|
83
|
+
canvas auth login --school "Columbia" --token-env CANVAS_TOKEN
|
|
84
|
+
|
|
77
85
|
# 2. List courses
|
|
78
86
|
canvas courses list
|
|
79
87
|
|
|
@@ -133,24 +141,48 @@ canvas review pack --course-id <course-id> --out ./review/<course>
|
|
|
133
141
|
canvas review pack --course-id <course-id> --out ./review/<course> --include-all-files
|
|
134
142
|
```
|
|
135
143
|
|
|
136
|
-
###
|
|
144
|
+
### Full Command Surface
|
|
137
145
|
|
|
138
146
|
```bash
|
|
147
|
+
canvas auth login
|
|
148
|
+
canvas auth login --school "Columbia" --token-env CANVAS_TOKEN
|
|
149
|
+
canvas auth login --school-url https://courseworks2.columbia.edu --school-name "Columbia University (CourseWorks)" --token "paste-token-here"
|
|
150
|
+
canvas auth schools search "Columbia"
|
|
151
|
+
canvas auth status
|
|
152
|
+
canvas auth logout
|
|
153
|
+
canvas config show
|
|
154
|
+
canvas me
|
|
155
|
+
|
|
139
156
|
canvas courses list
|
|
140
157
|
canvas courses search "algorithms"
|
|
158
|
+
canvas courses show <course-id>
|
|
159
|
+
canvas courses overview <course-id>
|
|
160
|
+
canvas tabs list --course-id <course-id>
|
|
161
|
+
|
|
141
162
|
canvas modules list --course-id <course-id>
|
|
142
163
|
canvas modules items --course-id <course-id> --module-id <module-id>
|
|
164
|
+
canvas modules item --course-id <course-id> --module-id <module-id> --item-id <item-id>
|
|
165
|
+
canvas modules export --course-id <course-id> --module-id <module-id> --out ./module
|
|
166
|
+
|
|
143
167
|
canvas assignments list --course-id <course-id>
|
|
168
|
+
canvas assignments show --course-id <course-id> --assignment-id <assignment-id>
|
|
169
|
+
canvas assignments export --course-id <course-id> --assignment-id <assignment-id> --out ./assignment
|
|
170
|
+
|
|
144
171
|
canvas pages list --course-id <course-id>
|
|
145
172
|
canvas pages show --course-id <course-id> --page <url-or-id>
|
|
173
|
+
canvas pages export --course-id <course-id> --page <url-or-id> --out ./page
|
|
174
|
+
|
|
146
175
|
canvas files list --course-id <course-id>
|
|
176
|
+
canvas files show <file-id>
|
|
147
177
|
canvas files download <file-id> --out ./files
|
|
178
|
+
canvas files download-linked --course-id <course-id> --out ./files
|
|
179
|
+
|
|
148
180
|
canvas folders list --course-id <course-id>
|
|
149
|
-
|
|
181
|
+
canvas folders path --course-id <course-id> --path "course files/week 1"
|
|
150
182
|
|
|
151
|
-
|
|
183
|
+
canvas review pack --course-id <course-id> --out ./review/<course>
|
|
184
|
+
canvas review pack --course-id <course-id> --out ./review/<course> --include-all-files
|
|
152
185
|
|
|
153
|
-
```bash
|
|
154
186
|
canvas api get /api/v1/courses
|
|
155
187
|
canvas api get /api/v1/courses/<course-id>/modules --params '{"include":["items"]}'
|
|
156
188
|
```
|
package/dist/bin/canvas.js
CHANGED
|
@@ -519,16 +519,112 @@ async function runPostLoginBootstrap() {
|
|
|
519
519
|
};
|
|
520
520
|
}
|
|
521
521
|
|
|
522
|
+
// src/commands/shared.ts
|
|
523
|
+
async function activeCanvas() {
|
|
524
|
+
const profile = await new ConfigStore().activeProfile();
|
|
525
|
+
return {
|
|
526
|
+
profile,
|
|
527
|
+
client: new CanvasClient({
|
|
528
|
+
baseUrl: profile.baseUrl,
|
|
529
|
+
token: profile.token
|
|
530
|
+
})
|
|
531
|
+
};
|
|
532
|
+
}
|
|
533
|
+
function flagValue(argv, flag) {
|
|
534
|
+
const index = argv.indexOf(flag);
|
|
535
|
+
if (index === -1) {
|
|
536
|
+
return void 0;
|
|
537
|
+
}
|
|
538
|
+
return argv[index + 1];
|
|
539
|
+
}
|
|
540
|
+
function requiredFlag(argv, flag, usage) {
|
|
541
|
+
const value = flagValue(argv, flag);
|
|
542
|
+
if (!value) {
|
|
543
|
+
throw new Error(usage);
|
|
544
|
+
}
|
|
545
|
+
return value;
|
|
546
|
+
}
|
|
547
|
+
function hasFlag(argv, flag) {
|
|
548
|
+
return argv.includes(flag);
|
|
549
|
+
}
|
|
550
|
+
function csvFlag(argv, flag) {
|
|
551
|
+
const raw = flagValue(argv, flag);
|
|
552
|
+
if (!raw) {
|
|
553
|
+
return void 0;
|
|
554
|
+
}
|
|
555
|
+
const values = raw.split(",").map((value) => value.trim()).filter(Boolean);
|
|
556
|
+
return values.length > 0 ? values : void 0;
|
|
557
|
+
}
|
|
558
|
+
function pageOptions(argv) {
|
|
559
|
+
const pageLimitRaw = flagValue(argv, "--page-limit");
|
|
560
|
+
return {
|
|
561
|
+
pageAll: hasFlag(argv, "--page-all"),
|
|
562
|
+
pageLimit: pageLimitRaw ? Number.parseInt(pageLimitRaw, 10) : void 0
|
|
563
|
+
};
|
|
564
|
+
}
|
|
565
|
+
function positionalArgs(argv) {
|
|
566
|
+
const valueFlags = /* @__PURE__ */ new Set([
|
|
567
|
+
"--course-id",
|
|
568
|
+
"--module-id",
|
|
569
|
+
"--item-id",
|
|
570
|
+
"--assignment-id",
|
|
571
|
+
"--quiz-id",
|
|
572
|
+
"--topic-id",
|
|
573
|
+
"--page",
|
|
574
|
+
"--path",
|
|
575
|
+
"--out",
|
|
576
|
+
"--format",
|
|
577
|
+
"--page-limit",
|
|
578
|
+
"--page-size",
|
|
579
|
+
"--page-delay",
|
|
580
|
+
"--enrollment-state",
|
|
581
|
+
"--state",
|
|
582
|
+
"--include",
|
|
583
|
+
"--params",
|
|
584
|
+
"--bucket",
|
|
585
|
+
"--search",
|
|
586
|
+
"--order-by",
|
|
587
|
+
"--sort",
|
|
588
|
+
"--file-id",
|
|
589
|
+
"--folder-id",
|
|
590
|
+
"--group-id",
|
|
591
|
+
"--content-type",
|
|
592
|
+
"--school",
|
|
593
|
+
"--school-query",
|
|
594
|
+
"--school-url",
|
|
595
|
+
"--url",
|
|
596
|
+
"--school-name",
|
|
597
|
+
"--name",
|
|
598
|
+
"--token",
|
|
599
|
+
"--token-env"
|
|
600
|
+
]);
|
|
601
|
+
const values = [];
|
|
602
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
603
|
+
const arg = argv[index];
|
|
604
|
+
if (arg.startsWith("--")) {
|
|
605
|
+
if (valueFlags.has(arg)) {
|
|
606
|
+
index += 1;
|
|
607
|
+
}
|
|
608
|
+
continue;
|
|
609
|
+
}
|
|
610
|
+
values.push(arg);
|
|
611
|
+
}
|
|
612
|
+
return values;
|
|
613
|
+
}
|
|
614
|
+
|
|
522
615
|
// src/commands/auth.ts
|
|
523
616
|
var TOKEN_PURPOSE = "Hyperknow";
|
|
524
617
|
async function handleAuthCommand(argv, options) {
|
|
525
618
|
const [subcommand] = argv;
|
|
526
619
|
if (subcommand === "login") {
|
|
527
|
-
return authLogin(options);
|
|
620
|
+
return authLogin(argv.slice(1), options);
|
|
528
621
|
}
|
|
529
622
|
if (subcommand === "status") {
|
|
530
623
|
return authStatus(options);
|
|
531
624
|
}
|
|
625
|
+
if (subcommand === "schools") {
|
|
626
|
+
return authSchools(argv.slice(1), options);
|
|
627
|
+
}
|
|
532
628
|
if (subcommand === "logout") {
|
|
533
629
|
return authLogout(options);
|
|
534
630
|
}
|
|
@@ -545,16 +641,21 @@ async function handleAuthCommand(argv, options) {
|
|
|
545
641
|
);
|
|
546
642
|
return 1;
|
|
547
643
|
}
|
|
548
|
-
async function authLogin(options) {
|
|
644
|
+
async function authLogin(argv, options) {
|
|
549
645
|
const io = createPrompt();
|
|
550
646
|
try {
|
|
551
|
-
const
|
|
647
|
+
const nonInteractive = hasNonInteractiveLoginArgs(argv);
|
|
648
|
+
const school = nonInteractive ? resolveSchoolFromArgs(argv) : await chooseSchool(io);
|
|
552
649
|
const settingsUrl = `${school.url}/profile/settings`;
|
|
553
|
-
|
|
554
|
-
|
|
555
|
-
|
|
556
|
-
|
|
557
|
-
|
|
650
|
+
const providedToken = await tokenFromArgs(argv);
|
|
651
|
+
let token = providedToken;
|
|
652
|
+
if (!token) {
|
|
653
|
+
process.stdout.write(tokenInstructions(school, settingsUrl));
|
|
654
|
+
await io.question("Press Enter to open Canvas settings in your browser...");
|
|
655
|
+
await openBrowser(settingsUrl);
|
|
656
|
+
process.stdout.write("\nWaiting for your Canvas personal access token.\n");
|
|
657
|
+
token = await promptHidden("Paste token: ");
|
|
658
|
+
}
|
|
558
659
|
if (!token) {
|
|
559
660
|
throw new CanvasCliError("EMPTY_TOKEN", "No token entered.");
|
|
560
661
|
}
|
|
@@ -588,7 +689,7 @@ async function authLogin(options) {
|
|
|
588
689
|
},
|
|
589
690
|
user,
|
|
590
691
|
contextBootstrap: bootstrap,
|
|
591
|
-
next: "canvas
|
|
692
|
+
next: "canvas courses list --active --page-all"
|
|
592
693
|
},
|
|
593
694
|
meta: {
|
|
594
695
|
command: "auth login"
|
|
@@ -604,6 +705,25 @@ async function authLogin(options) {
|
|
|
604
705
|
io.close();
|
|
605
706
|
}
|
|
606
707
|
}
|
|
708
|
+
async function authSchools(argv, options) {
|
|
709
|
+
const [subcommand] = argv;
|
|
710
|
+
const query = subcommand === "search" ? positionalArgs(argv.slice(1)).join(" ") : flagValue(argv, "--query") ?? positionalArgs(argv).join(" ");
|
|
711
|
+
await writeOutput(
|
|
712
|
+
{
|
|
713
|
+
ok: true,
|
|
714
|
+
data: searchSchools(query).map((school) => ({
|
|
715
|
+
name: school.name,
|
|
716
|
+
baseUrl: school.url
|
|
717
|
+
})),
|
|
718
|
+
meta: {
|
|
719
|
+
command: "auth schools",
|
|
720
|
+
query
|
|
721
|
+
}
|
|
722
|
+
},
|
|
723
|
+
options
|
|
724
|
+
);
|
|
725
|
+
return 0;
|
|
726
|
+
}
|
|
607
727
|
async function authStatus(options) {
|
|
608
728
|
const store = new ConfigStore();
|
|
609
729
|
const config = await store.readRedacted();
|
|
@@ -694,11 +814,77 @@ async function chooseSchool(io, write = (message) => process.stdout.write(messag
|
|
|
694
814
|
url: normalizeBaseUrl(school.url)
|
|
695
815
|
};
|
|
696
816
|
}
|
|
817
|
+
function resolveSchoolFromArgs(argv) {
|
|
818
|
+
const schoolUrl = flagValue(argv, "--school-url") ?? flagValue(argv, "--url");
|
|
819
|
+
if (schoolUrl) {
|
|
820
|
+
return makeCustomSchool(flagValue(argv, "--school-name") ?? flagValue(argv, "--name") ?? "Custom Canvas School", schoolUrl);
|
|
821
|
+
}
|
|
822
|
+
const schoolQuery = flagValue(argv, "--school") ?? flagValue(argv, "--school-query");
|
|
823
|
+
if (!schoolQuery) {
|
|
824
|
+
throw new CanvasCliError(
|
|
825
|
+
"MISSING_SCHOOL",
|
|
826
|
+
"Non-interactive auth requires --school <query> or --school-url <url>."
|
|
827
|
+
);
|
|
828
|
+
}
|
|
829
|
+
const matches = searchSchools(schoolQuery, 20);
|
|
830
|
+
if (matches.length === 0) {
|
|
831
|
+
throw new CanvasCliError(
|
|
832
|
+
"SCHOOL_NOT_FOUND",
|
|
833
|
+
`No Canvas school matched "${schoolQuery}". Use --school-url <url> for a custom Canvas URL.`
|
|
834
|
+
);
|
|
835
|
+
}
|
|
836
|
+
const exact = matches.find((school) => {
|
|
837
|
+
return school.name.toLowerCase() === schoolQuery.toLowerCase() || school.url.toLowerCase() === schoolQuery.toLowerCase();
|
|
838
|
+
});
|
|
839
|
+
if (exact) {
|
|
840
|
+
return {
|
|
841
|
+
name: exact.name,
|
|
842
|
+
url: normalizeBaseUrl(exact.url)
|
|
843
|
+
};
|
|
844
|
+
}
|
|
845
|
+
if (matches.length === 1) {
|
|
846
|
+
const school = matches[0];
|
|
847
|
+
return {
|
|
848
|
+
name: school.name,
|
|
849
|
+
url: normalizeBaseUrl(school.url)
|
|
850
|
+
};
|
|
851
|
+
}
|
|
852
|
+
throw new CanvasCliError(
|
|
853
|
+
"AMBIGUOUS_SCHOOL",
|
|
854
|
+
`Multiple schools matched "${schoolQuery}": ${matches.map((school) => `${school.name} (${school.url})`).join("; ")}. Use a more specific --school value or --school-url.`
|
|
855
|
+
);
|
|
856
|
+
}
|
|
857
|
+
async function tokenFromArgs(argv) {
|
|
858
|
+
const directToken = flagValue(argv, "--token");
|
|
859
|
+
if (directToken) {
|
|
860
|
+
return directToken.trim();
|
|
861
|
+
}
|
|
862
|
+
const envName = flagValue(argv, "--token-env");
|
|
863
|
+
if (envName) {
|
|
864
|
+
return process.env[envName]?.trim();
|
|
865
|
+
}
|
|
866
|
+
if (argv.includes("--token-stdin")) {
|
|
867
|
+
return readStdin().then((value) => value.trim());
|
|
868
|
+
}
|
|
869
|
+
return void 0;
|
|
870
|
+
}
|
|
697
871
|
async function promptCustomSchool(io) {
|
|
698
872
|
const name = await io.question("School display name: ");
|
|
699
873
|
const url = await io.question("Canvas base URL: ");
|
|
700
874
|
return makeCustomSchool(name, url);
|
|
701
875
|
}
|
|
876
|
+
function hasNonInteractiveLoginArgs(argv) {
|
|
877
|
+
return Boolean(
|
|
878
|
+
flagValue(argv, "--school") || flagValue(argv, "--school-query") || flagValue(argv, "--school-url") || flagValue(argv, "--url")
|
|
879
|
+
);
|
|
880
|
+
}
|
|
881
|
+
async function readStdin() {
|
|
882
|
+
const chunks = [];
|
|
883
|
+
for await (const chunk of process.stdin) {
|
|
884
|
+
chunks.push(Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk));
|
|
885
|
+
}
|
|
886
|
+
return Buffer.concat(chunks).toString("utf8");
|
|
887
|
+
}
|
|
702
888
|
function tokenInstructions(school, settingsUrl) {
|
|
703
889
|
return `
|
|
704
890
|
Canvas token setup for ${school.name}
|
|
@@ -730,91 +916,6 @@ async function validateToken(client) {
|
|
|
730
916
|
}
|
|
731
917
|
}
|
|
732
918
|
|
|
733
|
-
// src/commands/shared.ts
|
|
734
|
-
async function activeCanvas() {
|
|
735
|
-
const profile = await new ConfigStore().activeProfile();
|
|
736
|
-
return {
|
|
737
|
-
profile,
|
|
738
|
-
client: new CanvasClient({
|
|
739
|
-
baseUrl: profile.baseUrl,
|
|
740
|
-
token: profile.token
|
|
741
|
-
})
|
|
742
|
-
};
|
|
743
|
-
}
|
|
744
|
-
function flagValue(argv, flag) {
|
|
745
|
-
const index = argv.indexOf(flag);
|
|
746
|
-
if (index === -1) {
|
|
747
|
-
return void 0;
|
|
748
|
-
}
|
|
749
|
-
return argv[index + 1];
|
|
750
|
-
}
|
|
751
|
-
function requiredFlag(argv, flag, usage) {
|
|
752
|
-
const value = flagValue(argv, flag);
|
|
753
|
-
if (!value) {
|
|
754
|
-
throw new Error(usage);
|
|
755
|
-
}
|
|
756
|
-
return value;
|
|
757
|
-
}
|
|
758
|
-
function hasFlag(argv, flag) {
|
|
759
|
-
return argv.includes(flag);
|
|
760
|
-
}
|
|
761
|
-
function csvFlag(argv, flag) {
|
|
762
|
-
const raw = flagValue(argv, flag);
|
|
763
|
-
if (!raw) {
|
|
764
|
-
return void 0;
|
|
765
|
-
}
|
|
766
|
-
const values = raw.split(",").map((value) => value.trim()).filter(Boolean);
|
|
767
|
-
return values.length > 0 ? values : void 0;
|
|
768
|
-
}
|
|
769
|
-
function pageOptions(argv) {
|
|
770
|
-
const pageLimitRaw = flagValue(argv, "--page-limit");
|
|
771
|
-
return {
|
|
772
|
-
pageAll: hasFlag(argv, "--page-all"),
|
|
773
|
-
pageLimit: pageLimitRaw ? Number.parseInt(pageLimitRaw, 10) : void 0
|
|
774
|
-
};
|
|
775
|
-
}
|
|
776
|
-
function positionalArgs(argv) {
|
|
777
|
-
const valueFlags = /* @__PURE__ */ new Set([
|
|
778
|
-
"--course-id",
|
|
779
|
-
"--module-id",
|
|
780
|
-
"--item-id",
|
|
781
|
-
"--assignment-id",
|
|
782
|
-
"--quiz-id",
|
|
783
|
-
"--topic-id",
|
|
784
|
-
"--page",
|
|
785
|
-
"--path",
|
|
786
|
-
"--out",
|
|
787
|
-
"--format",
|
|
788
|
-
"--page-limit",
|
|
789
|
-
"--page-size",
|
|
790
|
-
"--page-delay",
|
|
791
|
-
"--enrollment-state",
|
|
792
|
-
"--state",
|
|
793
|
-
"--include",
|
|
794
|
-
"--params",
|
|
795
|
-
"--bucket",
|
|
796
|
-
"--search",
|
|
797
|
-
"--order-by",
|
|
798
|
-
"--sort",
|
|
799
|
-
"--file-id",
|
|
800
|
-
"--folder-id",
|
|
801
|
-
"--group-id",
|
|
802
|
-
"--content-type"
|
|
803
|
-
]);
|
|
804
|
-
const values = [];
|
|
805
|
-
for (let index = 0; index < argv.length; index += 1) {
|
|
806
|
-
const arg = argv[index];
|
|
807
|
-
if (arg.startsWith("--")) {
|
|
808
|
-
if (valueFlags.has(arg)) {
|
|
809
|
-
index += 1;
|
|
810
|
-
}
|
|
811
|
-
continue;
|
|
812
|
-
}
|
|
813
|
-
values.push(arg);
|
|
814
|
-
}
|
|
815
|
-
return values;
|
|
816
|
-
}
|
|
817
|
-
|
|
818
919
|
// src/commands/api.ts
|
|
819
920
|
async function handleApiCommand(argv, options) {
|
|
820
921
|
const [subcommand] = argv;
|
|
@@ -2154,7 +2255,7 @@ async function reviewPack(argv, options) {
|
|
|
2154
2255
|
}
|
|
2155
2256
|
|
|
2156
2257
|
// src/bin/canvas.ts
|
|
2157
|
-
var VERSION = "0.0.
|
|
2258
|
+
var VERSION = "0.0.4";
|
|
2158
2259
|
function helpText() {
|
|
2159
2260
|
return `canvas \u2014 Canvas LMS CLI for students and agents.
|
|
2160
2261
|
|
|
@@ -2164,6 +2265,7 @@ USAGE:
|
|
|
2164
2265
|
COMMANDS:
|
|
2165
2266
|
auth login Interactive Canvas PAT setup
|
|
2166
2267
|
auth status Show redacted auth status
|
|
2268
|
+
auth schools Search supported Canvas school URLs
|
|
2167
2269
|
auth logout Remove local Canvas auth config
|
|
2168
2270
|
config show Show redacted local config
|
|
2169
2271
|
me Show current Canvas user profile
|