From 4e498cb27b1d5b3bff81394914310c445c893a2f Mon Sep 17 00:00:00 2001 From: NiloCK Date: Wed, 12 Nov 2025 15:26:18 -0400 Subject: [PATCH 1/5] add crsID <> dependencyName mapping --- .../src/impl/static/StaticDataLayerProvider.ts | 2 +- packages/db/src/impl/static/coursesDB.ts | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/packages/db/src/impl/static/StaticDataLayerProvider.ts b/packages/db/src/impl/static/StaticDataLayerProvider.ts index 7edb9adba..c40232a1d 100644 --- a/packages/db/src/impl/static/StaticDataLayerProvider.ts +++ b/packages/db/src/impl/static/StaticDataLayerProvider.ts @@ -138,7 +138,7 @@ export class StaticDataLayerProvider implements DataLayerProvider { } getCoursesDB(): CoursesDBInterface { - return new StaticCoursesDB(this.manifests); + return new StaticCoursesDB(this.manifests, this.dependencyNameToCourseId); } async getClassroomDB( diff --git a/packages/db/src/impl/static/coursesDB.ts b/packages/db/src/impl/static/coursesDB.ts index 6881713e1..25230d64a 100644 --- a/packages/db/src/impl/static/coursesDB.ts +++ b/packages/db/src/impl/static/coursesDB.ts @@ -6,10 +6,23 @@ import { StaticCourseManifest } from '../../util/packer/types'; import { logger } from '../../util/logger'; export class StaticCoursesDB implements CoursesDBInterface { - constructor(private manifests: Record) {} + constructor( + private manifests: Record, + private dependencyNameToCourseId?: Map + ) {} async getCourseConfig(courseId: string): Promise { - const manifest = this.manifests[courseId]; + // Try direct lookup by courseId first + let manifest = this.manifests[courseId]; + + // If not found, try lookup by dependency name (backwards compatibility) + if (!manifest && this.dependencyNameToCourseId) { + const mappedCourseId = this.dependencyNameToCourseId.get(courseId); + if (mappedCourseId) { + manifest = this.manifests[mappedCourseId]; + } + } + if (!manifest) { logger.warn(`Course manifest for ${courseId} not found`); throw new Error(`Course ${courseId} not found`); From 80fc0e868e4b16aed19980c62cb355f0eb1829d5 Mon Sep 17 00:00:00 2001 From: NiloCK Date: Wed, 12 Nov 2025 15:26:51 -0400 Subject: [PATCH 2/5] rm golang external test crs dep.... ID collision with local packed version caused problems --- docs/public/skuilder.json | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/public/skuilder.json b/docs/public/skuilder.json index 691974674..abe6213c4 100644 --- a/docs/public/skuilder.json +++ b/docs/public/skuilder.json @@ -4,7 +4,6 @@ "description": "The root manifest for the vue-skuilder documentation site.", "dependencies": { "@skuilder/hero-course": "/vue-skuilder/static-courses/2aeb8315ef78f3e89ca386992d00825b/skuilder.json", - "@skuilder/external-test": "https://patched-network.github.io/demo-chess/static-courses/2aeb8315ef78f3e89ca386992d00825b/skuilder.json", "@skuilder/demo-chess": "https://patched-network.github.io/demo-chess/static-courses/demo-chess/skuilder.json" } } From 392a518af1f86af784f735d6ccf1941ec23e1fff Mon Sep 17 00:00:00 2001 From: NiloCK Date: Wed, 12 Nov 2025 15:27:25 -0400 Subject: [PATCH 3/5] rm working docs --- agent/BACKPORT_CHECKLIST.md | 273 -------------------------- agent/a.1.assessment.md | 210 -------------------- agent/a.2.plan.md | 379 ------------------------------------ agent/a.3.todo.md | 217 --------------------- 4 files changed, 1079 deletions(-) delete mode 100644 agent/BACKPORT_CHECKLIST.md delete mode 100644 agent/a.1.assessment.md delete mode 100644 agent/a.2.plan.md delete mode 100644 agent/a.3.todo.md diff --git a/agent/BACKPORT_CHECKLIST.md b/agent/BACKPORT_CHECKLIST.md deleted file mode 100644 index 11f05fd9e..000000000 --- a/agent/BACKPORT_CHECKLIST.md +++ /dev/null @@ -1,273 +0,0 @@ -# Backport Checklist for Scaffolding Templates - -Changes tested in `/flutor` that need to be propagated to vue-skuilder template packages. - -**Note:** This document is self-contained. All necessary code examples and rationale are included below. - -## How to Use This Document - -1. **Copy this file** to the vue-skuilder monorepo for reference -2. **Apply changes 1-6** to the template packages (standalone-ui, sk-contributor) -3. **Test** using the testing checklist at the bottom -4. **Ignore** the "Infrastructure Changes" section - those are already in the monorepo - -**Files to Update:** -- `/packages/standalone-ui/vite.config.ts` -- `/packages/standalone-ui/src/questions/index.ts` -- `/packages/standalone-ui/src/main.ts` -- `/packages/standalone-ui/src/questions/*QuestionView.vue` (all view components) -- `/packages/sk-contributor/` (same files as above) -- `/packages/standalone-ui/src/questions/README.md` (examples) - -## Context - -These fixes enable custom questions to work in both: -- **Standalone mode** (`yarn dev`) - already worked -- **Studio mode** (`yarn studio`) - now works after these fixes - -The root cause was a combination of: -1. Browser unable to resolve bare imports in dynamically loaded modules -2. Missing view component names for runtime lookup -3. Side-effect import not running (views array staying empty) -4. Incorrect views export format for studio-ui consumption - -## 1. Vite Config - External Dependencies & Terser -**File:** `vite.config.ts` -**Location:** Library build configuration -**Change:** -```typescript -build: buildMode === 'library' - ? { - // ... - terserOptions: { - keep_classnames: true, - keep_fnames: true, // ADD: Preserve function names - mangle: { - properties: false, // ADD: Don't mangle static properties like seedData - }, - }, - rollupOptions: { - // CRITICAL: Do NOT externalize dependencies for studio mode - // Browser cannot resolve bare imports without import maps - external: [ - // Leave empty - bundle everything for browser compatibility - ], - } - } -``` -**Why:** -- Terser options prevent minification from mangling static properties (seedData, views, dataShapes) -- Empty externals array bundles all dependencies so browser can load the module without import maps -- Previously tried externalizing to avoid duplication, but browser can't resolve `import { X } from "@vue-skuilder/courseware"` at runtime -**Affects:** -- `/packages/standalone-ui/vite.config.ts` -- CLI template generation for new projects - ---- - -## 2. Question Index - Views Export Format -**File:** `src/questions/index.ts` -**Location:** `allCustomQuestions()` function -**Change:** -```typescript -// OLD (broken): -const views: ViewComponent[] = []; -questionClasses.forEach((questionClass) => { - if (questionClass.views) { - questionClass.views.forEach((view) => { - views.push(view); - }); - } -}); - -// NEW (working): -const views: Array<{ name: string; component: ViewComponent }> = []; -questionClasses.forEach((questionClass) => { - if (questionClass.views) { - questionClass.views.forEach((view) => { - const viewName = (view as any).name || (view as any).__name; - if (viewName) { - if (!views.find((existing) => existing.name === viewName)) { - views.push({ name: viewName, component: view }); - } - } else { - console.warn('[allCustomQuestions] View component missing name property:', view); - } - }); - } -}); -``` -**Why:** Studio-ui expects `{ name, component }` format (see studio-ui/src/main.ts:183-189) -**Affects:** -- `/packages/standalone-ui/src/questions/index.ts` -- `/packages/sk-contributor/src/questions/index.ts` - ---- - -## 3. Question Index - TypeScript Interface -**File:** `src/questions/index.ts` -**Location:** `CustomQuestionsExport` interface -**Change:** -```typescript -export interface CustomQuestionsExport { - courses: CourseWare[]; - questionClasses: Array; - dataShapes: DataShape[]; - views: Array<{ name: string; component: ViewComponent }>; // CHANGED from ViewComponent[] - inlineComponents: Record; - meta: { /* ... */ }; -} -``` -**Why:** Matches runtime format -**Affects:** -- `/packages/standalone-ui/src/questions/index.ts` -- `/packages/sk-contributor/src/questions/index.ts` - ---- - -## 4. Main.ts - Import Questions Index -**File:** `src/main.ts` -**Location:** Before `allCourseWare.courses.push(exampleCourse)` -**Change:** -```typescript -// Import allCourseWare singleton and exampleCourse -import { allCourseWare } from '@vue-skuilder/courseware'; -// Import from index.ts to ensure view setup code runs -import './questions/index'; // ADD THIS LINE -import { exampleCourse } from './questions/exampleCourse'; -``` -**Why:** Ensures static view setup runs before course registration -**Affects:** -- `/packages/standalone-ui/src/main.ts` -- `/packages/sk-contributor/src/main.ts` - ---- - -## 5. Question Class - Direct Inline Views -**File:** `src/questions/MyQuestion.ts` -**Location:** Question class static properties -**Change:** -```typescript -// Import at top -import { markRaw } from 'vue'; -import MyQuestionView from './MyQuestionView.vue'; - -export class MyQuestion extends Question { - public static dataShapes = [/* ... */]; - - // Direct inline registration - no external setup needed - public static views = [markRaw(MyQuestionView)]; // CHANGED from empty array - - // ... -} -``` -**Why:** Self-contained, works immediately, no fragile side-effects -**Affects:** -- Template examples in `/packages/standalone-ui/src/questions/README.md` -- Template examples in `/packages/sk-contributor/src/questions/README.md` -- Existing template questions (NumberRangeQuestion, etc.) - ---- - -## 6. Vue Component - DefineOptions Name -**File:** `src/questions/MyQuestionView.vue` -**Location:** Script setup -**Change:** -```typescript -