coursecode 0.1.20 → 0.1.22

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.
@@ -621,6 +621,7 @@ Courses linked to GitHub for production deploys are protected from accidental CL
621
621
 
622
622
  - **`--preview` always allowed** — useful for testing without touching production pointer
623
623
  - **`.coursecoderc.json`** carries `sourceType` and `githubRepo` (committed to repo by cloud's GitHub integration), so anyone cloning gets the guard automatically
624
+ - **Self-healing on unlink:** If the cloud course is unlinked from GitHub, both `status()` and `deploy()` reconcile — they detect the server no longer reports `source_type: 'github'` and clear the local `sourceType`/`githubRepo` from `.coursecoderc.json`. No manual cleanup or repo commit needed.
624
625
  - CLI error code: `github_source_blocked` (structured JSON for Desktop/CI consumers)
625
626
 
626
627
  ---
package/lib/cloud.js CHANGED
@@ -982,6 +982,21 @@ export async function deploy(options = {}) {
982
982
  if (handled) return;
983
983
  } else if (!statusRes.ok) {
984
984
  await handleResponse(statusRes);
985
+ } else {
986
+ // Reconcile local sourceType with cloud truth (handles unlink-via-dashboard)
987
+ try {
988
+ const statusData = JSON.parse(await statusRes.text());
989
+ const serverSourceType = statusData.source?.type || statusData.source_type;
990
+ const localRc = readRcConfig();
991
+ if (localRc?.sourceType === 'github' && serverSourceType !== 'github') {
992
+ updateRcConfig((rc) => {
993
+ delete rc.sourceType;
994
+ delete rc.githubRepo;
995
+ return rc;
996
+ });
997
+ log(' ℹ️ GitHub link removed on Cloud — updated local config.\n');
998
+ }
999
+ } catch { /* non-critical — guard will use whatever rcConfig has */ }
985
1000
  }
986
1001
  }
987
1002
 
@@ -1318,6 +1333,20 @@ export async function status(options = {}) {
1318
1333
 
1319
1334
  const data = await handleResponse(firstRes, { retryFn: makeRequest, _isRetry: false });
1320
1335
 
1336
+ // Reconcile local sourceType with cloud truth (handles unlink-via-dashboard)
1337
+ const localRc = readRcConfig();
1338
+ const serverSourceType = data.source?.type || data.source_type;
1339
+ if (localRc?.sourceType === 'github' && serverSourceType !== 'github') {
1340
+ updateRcConfig((rc) => {
1341
+ delete rc.sourceType;
1342
+ delete rc.githubRepo;
1343
+ return rc;
1344
+ });
1345
+ if (!options.json) {
1346
+ console.log(' ℹ️ GitHub link removed on Cloud — updated local config.\n');
1347
+ }
1348
+ }
1349
+
1321
1350
  if (options.json) {
1322
1351
  process.stdout.write(JSON.stringify(data) + '\n');
1323
1352
  return;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "coursecode",
3
- "version": "0.1.20",
3
+ "version": "0.1.22",
4
4
  "description": "Multi-format course authoring framework with CLI tools (SCORM 2004, SCORM 1.2, cmi5, LTI 1.3)",
5
5
  "type": "module",
6
6
  "bin": {
@@ -35,6 +35,9 @@
35
35
  "./stub-player": {
36
36
  "types": "./lib/stub-player.d.ts",
37
37
  "default": "./lib/stub-player.js"
38
+ },
39
+ "./vite-plugin-content-discovery": {
40
+ "default": "./lib/vite-plugin-content-discovery.js"
38
41
  }
39
42
  },
40
43
  "scripts": {
@@ -99,6 +102,7 @@
99
102
  },
100
103
  "dependencies": {
101
104
  "@modelcontextprotocol/sdk": "^1.0.0",
105
+ "acorn": "^8.15.0",
102
106
  "archiver": "^7.0.1",
103
107
  "commander": "^14.0.3",
104
108
  "lz-string": "^1.5.0",
@@ -116,7 +120,6 @@
116
120
  "@vitejs/plugin-legacy": "^7.2.1",
117
121
  "@vitest/coverage-v8": "^4.0.18",
118
122
  "@xapi/cmi5": "^1.4.0",
119
- "acorn": "^8.15.0",
120
123
  "eslint": "^10.0.0",
121
124
  "globals": "^17.3.0",
122
125
  "jose": "^6.1.3",