@vue-skuilder/cli 0.1.11-7 → 0.1.11

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.
@@ -183,11 +183,9 @@ async function launchStudio(coursePath: string, options: StudioOptions) {
183
183
  );
184
184
 
185
185
  // Phase 9.5: Launch Express backend
186
- console.log(chalk.cyan(`⚡ Starting Express backend server...`));
187
186
  const expressResult = await startExpressBackend(
188
187
  couchDBManager.getConnectionDetails(),
189
- resolvedPath,
190
- unpackResult.courseId
188
+ unpackResult.databaseName
191
189
  );
192
190
  expressServer = expressResult.server;
193
191
 
@@ -201,7 +199,8 @@ async function launchStudio(coursePath: string, options: StudioOptions) {
201
199
  const studioUIPort = await startStudioUIServer(
202
200
  couchDBManager.getConnectionDetails(),
203
201
  unpackResult,
204
- studioUIPath
202
+ studioUIPath,
203
+ expressResult.url
205
204
  );
206
205
 
207
206
  console.log(chalk.green(`✅ Studio session ready!`));
@@ -210,7 +209,7 @@ async function launchStudio(coursePath: string, options: StudioOptions) {
210
209
  console.log(chalk.gray(` Express API: ${expressResult.url}`));
211
210
 
212
211
  // Display MCP connection information
213
- const mcpInfo = getMCPConnectionInfo(unpackResult, couchDBManager, resolvedPath);
212
+ const mcpInfo = getMCPConnectionInfo(unpackResult, couchDBManager);
214
213
  console.log(chalk.blue(`🔗 MCP Server: ${mcpInfo.command}`));
215
214
  console.log(chalk.gray(` Connect MCP clients using the command above`));
216
215
  console.log(chalk.gray(` Environment variables for MCP:`));
@@ -219,7 +218,7 @@ async function launchStudio(coursePath: string, options: StudioOptions) {
219
218
  });
220
219
 
221
220
  // Display .mcp.json content for Claude Code integration
222
- const mcpJsonContent = generateMCPJson(unpackResult, couchDBManager, resolvedPath);
221
+ const mcpJsonContent = generateMCPJson(unpackResult, couchDBManager);
223
222
  console.log(chalk.blue(`📋 .mcp.json content:`));
224
223
  console.log(chalk.gray(mcpJsonContent));
225
224
 
@@ -407,7 +406,8 @@ interface UnpackResult {
407
406
  async function startStudioUIServer(
408
407
  connectionDetails: ConnectionDetails,
409
408
  unpackResult: UnpackResult,
410
- studioPath: string
409
+ studioPath: string,
410
+ expressApiUrl?: string
411
411
  ): Promise<number> {
412
412
  // Serve from built dist directory if it exists, otherwise fallback to source
413
413
  const distPath = path.join(studioPath, 'dist');
@@ -458,6 +458,9 @@ async function startStudioUIServer(
458
458
  name: '${unpackResult.databaseName}',
459
459
  courseId: '${unpackResult.courseId}',
460
460
  originalCourseId: '${unpackResult.courseId}'
461
+ },
462
+ express: {
463
+ url: '${expressApiUrl || 'http://localhost:3000'}'
461
464
  }
462
465
  };
463
466
  </script>
@@ -486,6 +489,9 @@ async function startStudioUIServer(
486
489
  name: '${unpackResult.databaseName}',
487
490
  courseId: '${unpackResult.courseId}',
488
491
  originalCourseId: '${unpackResult.courseId}'
492
+ },
493
+ express: {
494
+ url: '${expressApiUrl || 'http://localhost:3000'}'
489
495
  }
490
496
  };
491
497
  </script>
@@ -562,8 +568,7 @@ async function openBrowser(url: string): Promise<void> {
562
568
  */
563
569
  async function startExpressBackend(
564
570
  couchDbConnectionDetails: ConnectionDetails,
565
- _projectPath: string,
566
- courseId: string
571
+ databaseName: string
567
572
  ): Promise<{ server: http.Server; port: number; url: string }> {
568
573
  console.log(chalk.blue('⚡ Starting Express backend server...'));
569
574
 
@@ -584,7 +589,7 @@ async function startExpressBackend(
584
589
  username: couchDbConnectionDetails.username,
585
590
  password: couchDbConnectionDetails.password,
586
591
  },
587
- courseIDs: [courseId],
592
+ courseIDs: [databaseName],
588
593
  version: VERSION,
589
594
  nodeEnv: 'studio',
590
595
  cors: {
@@ -594,6 +599,9 @@ async function startExpressBackend(
594
599
  };
595
600
 
596
601
  try {
602
+ // Set NODE_ENV for studio mode authentication bypass
603
+ process.env.NODE_ENV = 'studio';
604
+
597
605
  // Create Express app using factory
598
606
  const app = createExpressApp(config);
599
607
 
@@ -836,9 +844,9 @@ async function buildDefaultStudioUI(buildPath: string): Promise<string> {
836
844
  const studioPackageJsonPath = path.join(buildPath, 'package.json');
837
845
  await transformPackageJsonForStudioBuild(studioPackageJsonPath);
838
846
 
839
- // Fix Vite config to use npm packages instead of monorepo paths
840
- console.log(chalk.gray(` Updating Vite configuration for standalone build...`));
841
- await fixViteConfigForStandaloneBuild(buildPath);
847
+ // Fix Vite config to use npm packages and resolve custom questions imports
848
+ console.log(chalk.gray(` Updating Vite configuration for studio build...`));
849
+ await createStudioViteConfig(buildPath);
842
850
 
843
851
  // Run Vite build process
844
852
  console.log(chalk.gray(` Running Vite build process...`));
@@ -1036,9 +1044,9 @@ async function buildStudioUIWithCustomQuestions(
1036
1044
  const studioPackageJsonPath = path.join(buildPath, 'package.json');
1037
1045
  await transformPackageJsonForStudioBuild(studioPackageJsonPath);
1038
1046
 
1039
- // Step 2.5: Fix Vite config to use npm packages instead of monorepo paths
1040
- console.log(chalk.gray(` Updating Vite configuration for standalone build...`));
1041
- await fixViteConfigForStandaloneBuild(buildPath);
1047
+ // Step 2.5: Fix Vite config to use npm packages and resolve custom questions imports
1048
+ console.log(chalk.gray(` Updating Vite configuration for studio build...`));
1049
+ await createStudioViteConfig(buildPath);
1042
1050
 
1043
1051
  // Step 3: Install custom questions package
1044
1052
  console.log(
@@ -1259,9 +1267,9 @@ async function runViteBuild(buildPath: string): Promise<void> {
1259
1267
  }
1260
1268
 
1261
1269
  /**
1262
- * Fix Vite configuration to work in standalone build environment
1270
+ * Create Vite configuration for studio-ui build environment
1263
1271
  */
1264
- async function fixViteConfigForStandaloneBuild(buildPath: string): Promise<void> {
1272
+ async function createStudioViteConfig(buildPath: string): Promise<void> {
1265
1273
  const viteConfigPath = path.join(buildPath, 'vite.config.ts');
1266
1274
 
1267
1275
  if (!fs.existsSync(viteConfigPath)) {
@@ -1269,9 +1277,9 @@ async function fixViteConfigForStandaloneBuild(buildPath: string): Promise<void>
1269
1277
  return;
1270
1278
  }
1271
1279
 
1272
- // Create a clean standalone vite config for external projects
1273
- // Relies on standard npm package resolution instead of monorepo paths
1274
- const standaloneViteConfig = `import { defineConfig } from 'vite';
1280
+ // Create a clean studio vite config for studio-ui environment
1281
+ // Includes aliases to resolve custom questions imports
1282
+ const studioViteConfig = `import { defineConfig } from 'vite';
1275
1283
  import vue from '@vitejs/plugin-vue';
1276
1284
 
1277
1285
  export default defineConfig({
@@ -1297,9 +1305,17 @@ export default defineConfig({
1297
1305
  },
1298
1306
  resolve: {
1299
1307
  extensions: ['.js', '.ts', '.json', '.vue'],
1308
+ alias: {
1309
+ // Resolve @vue-skuilder packages to npm packages for custom questions import
1310
+ '@vue-skuilder/common': '@vue-skuilder/common',
1311
+ '@vue-skuilder/courseware': '@vue-skuilder/courseware',
1312
+ '@vue-skuilder/db': '@vue-skuilder/db',
1313
+ '@vue-skuilder/common-ui': '@vue-skuilder/common-ui',
1314
+ '@vue-skuilder/edit-ui': '@vue-skuilder/edit-ui'
1315
+ },
1300
1316
  dedupe: [
1301
1317
  'vue',
1302
- 'vuetify',
1318
+ 'vuetify',
1303
1319
  'vue-router',
1304
1320
  'pinia',
1305
1321
  '@vue-skuilder/db',
@@ -1311,50 +1327,23 @@ export default defineConfig({
1311
1327
  }
1312
1328
  });`;
1313
1329
 
1314
- fs.writeFileSync(viteConfigPath, standaloneViteConfig);
1315
- console.log(chalk.gray(` Vite config replaced with standalone version`));
1330
+ fs.writeFileSync(viteConfigPath, studioViteConfig);
1331
+ console.log(chalk.gray(` Vite config replaced with studio version`));
1316
1332
  }
1317
1333
 
1318
1334
  /**
1319
- * Determine the correct MCP server executable path/command based on project context
1335
+ * Determine the correct MCP server executable path.
1336
+ * This is now greatly simplified because the bundled server is always
1337
+ * located relative to this `studio.ts` file.
1320
1338
  */
1321
- function resolveMCPExecutable(projectPath: string): {
1322
- command: string;
1323
- args: string[];
1324
- isNpx: boolean;
1325
- } {
1326
- // Check if we're in the monorepo (packages/cli exists)
1327
- const monorepoCliPath = path.join(projectPath, 'packages', 'cli', 'dist', 'mcp-server.js');
1328
- if (fs.existsSync(monorepoCliPath)) {
1329
- return {
1330
- command: './packages/cli/dist/mcp-server.js',
1331
- args: [],
1332
- isNpx: false,
1333
- };
1334
- }
1339
+ function resolveMCPExecutable(): { command: string; args: string[] } {
1340
+ // Resolve the path to the bundled server relative to the current file.
1341
+ // __dirname is the `dist/commands` directory.
1342
+ const serverPath = path.resolve(__dirname, '..', 'mcp-server.js');
1335
1343
 
1336
- // Check if @vue-skuilder/cli is installed as a dependency
1337
- const scaffoldedCliPath = path.join(
1338
- projectPath,
1339
- 'node_modules',
1340
- '@vue-skuilder',
1341
- 'cli',
1342
- 'dist',
1343
- 'mcp-server.js'
1344
- );
1345
- if (fs.existsSync(scaffoldedCliPath)) {
1346
- return {
1347
- command: './node_modules/@vue-skuilder/cli/dist/mcp-server.js',
1348
- args: [],
1349
- isNpx: false,
1350
- };
1351
- }
1352
-
1353
- // Fallback to npx approach
1354
1344
  return {
1355
- command: 'npx',
1356
- args: ['@vue-skuilder/cli', 'mcp-server'],
1357
- isNpx: true,
1345
+ command: 'node',
1346
+ args: [serverPath],
1358
1347
  };
1359
1348
  }
1360
1349
 
@@ -1363,19 +1352,16 @@ function resolveMCPExecutable(projectPath: string): {
1363
1352
  */
1364
1353
  function getMCPConnectionInfo(
1365
1354
  unpackResult: UnpackResult,
1366
- couchDBManager: CouchDBManager,
1367
- projectPath: string
1355
+ couchDBManager: CouchDBManager
1368
1356
  ): { command: string; env: Record<string, string> } {
1369
1357
  const couchDetails = couchDBManager.getConnectionDetails();
1370
- const executable = resolveMCPExecutable(projectPath);
1358
+ const executable = resolveMCPExecutable();
1359
+ const port = couchDetails.port || 5985;
1371
1360
 
1372
1361
  // Build command string for display
1373
- let commandStr: string;
1374
- if (executable.isNpx) {
1375
- commandStr = `${executable.command} ${executable.args.join(' ')} ${unpackResult.databaseName} ${couchDetails.port}`;
1376
- } else {
1377
- commandStr = `node ${executable.command} ${unpackResult.databaseName} ${couchDetails.port}`;
1378
- }
1362
+ const commandStr = `${executable.command} ${executable.args.join(' ')} ${
1363
+ unpackResult.databaseName
1364
+ } ${port}`;
1379
1365
 
1380
1366
  return {
1381
1367
  command: commandStr,
@@ -1394,12 +1380,11 @@ function getMCPConnectionInfo(
1394
1380
  function generateMCPJson(
1395
1381
  unpackResult: UnpackResult,
1396
1382
  couchDBManager: CouchDBManager,
1397
- projectPath: string,
1398
1383
  serverName: string = 'vue-skuilder-studio'
1399
1384
  ): string {
1400
1385
  const couchDetails = couchDBManager.getConnectionDetails();
1401
1386
  const port = couchDetails.port || 5985;
1402
- const executable = resolveMCPExecutable(projectPath);
1387
+ const executable = resolveMCPExecutable();
1403
1388
 
1404
1389
  const mcpConfig = {
1405
1390
  mcpServers: {
package/src/mcp-server.ts CHANGED
@@ -1,7 +1,9 @@
1
- #!/usr/bin/env node
1
+ // MCP Server for Vue-Skuilder courses
2
+ // This file is bundled into a self-contained executable
2
3
 
3
4
  import { initializeDataLayer, getDataLayer, initializeTuiLogging } from '@vue-skuilder/db';
4
5
  import { MCPServer } from '@vue-skuilder/mcp';
6
+ import { consoleLogger } from '@vue-skuilder/common';
5
7
  import { StdioServerTransport } from '@modelcontextprotocol/sdk/server/stdio.js';
6
8
 
7
9
  initializeTuiLogging();
@@ -42,10 +44,11 @@ async function main() {
42
44
  await initializeDataLayer(couchdbConfig);
43
45
  const courseDB = getDataLayer().getCourseDB(courseId);
44
46
 
45
- // Create and start MCP server
47
+ // Create and start MCP server with console logger
46
48
  const server = new MCPServer(courseDB, {
47
49
  enableSourceLinking: true,
48
50
  maxCardsPerQuery: 50,
51
+ logger: consoleLogger,
49
52
  });
50
53
 
51
54
  const transport = new StdioServerTransport();
@@ -53,7 +56,9 @@ async function main() {
53
56
 
54
57
  console.error('MCP Server started successfully!');
55
58
  console.error(`Course: ${courseId}`);
56
- console.error('Available resources: course://config, cards://all, tags://all, shapes://all');
59
+ console.error('Available resources: course://config, cards://all, cards://tag/{tagName}, cards://shape/{shapeName}, cards://elo/{eloRange}');
60
+ console.error(' shapes://all, shapes://{shapeName}, schema://{dataShapeName}');
61
+ console.error(' tags://all, tags://stats, tags://{tagName}, tags://union/{tags}, tags://intersect/{tags}, tags://exclusive/{tags}, tags://distribution');
57
62
  console.error('Available tools: create_card, update_card, tag_card, delete_card');
58
63
  console.error('Available prompts: fill-in-card-authoring, elo-scoring-guidance');
59
64
  console.error('Ready for MCP client connections via stdio');
@@ -200,27 +200,22 @@ export default defineConfig({
200
200
  },
201
201
  rollupOptions: {
202
202
  // External packages that shouldn't be bundled in library mode
203
+ // For studio integration, we bundle vue-skuilder packages to avoid npm resolution issues
203
204
  external: [
204
- 'vue',
205
- 'vue-router',
206
- 'vuetify',
207
- 'pinia',
208
- '@vue-skuilder/common',
209
- '@vue-skuilder/common-ui',
210
- '@vue-skuilder/courseware',
211
- '@vue-skuilder/db',
205
+ // Bundle everything for studio integration - no externals
212
206
  ],
213
207
  output: {
214
208
  // Global variables for UMD build
215
209
  globals: {
216
- 'vue': 'Vue',
210
+ vue: 'Vue',
217
211
  'vue-router': 'VueRouter',
218
- 'vuetify': 'Vuetify',
219
- 'pinia': 'Pinia',
220
- '@vue-skuilder/common': 'VueSkuilderCommon',
221
- '@vue-skuilder/common-ui': 'VueSkuilderCommonUI',
222
- '@vue-skuilder/courseware': 'VueSkuilderCourseWare',
223
- '@vue-skuilder/db': 'VueSkuilderDB',
212
+ vuetify: 'Vuetify',
213
+ pinia: 'Pinia',
214
+ // Remove globals for bundled packages
215
+ // '@vue-skuilder/common': 'VueSkuilderCommon',
216
+ // '@vue-skuilder/common-ui': 'VueSkuilderCommonUI',
217
+ // '@vue-skuilder/courseware': 'VueSkuilderCourseWare',
218
+ // '@vue-skuilder/db': 'VueSkuilderDB',
224
219
  },
225
220
  exports: 'named',
226
221
  // Preserve CSS in the output bundle
@@ -421,6 +416,7 @@ node_modules/
421
416
  # Production builds
422
417
  /dist
423
418
  /build
419
+ /dist-lib
424
420
 
425
421
  # Local env files
426
422
  .env
@@ -1,103 +0,0 @@
1
- import { resolve } from 'path';
2
-
3
- const isDev = process.env.NODE_ENV !== 'production';
4
-
5
- console.info(`[VITE] shared config loaded in ${isDev ? 'development' : 'production'} mode`);
6
-
7
- /**
8
- * Creates shared alias mappings for monorepo packages
9
- * @param {string} rootDir - Path to the monorepo root directory
10
- * @returns {Object} Alias configuration object
11
- */
12
- export function createBaseAliases(rootDir = process.cwd()) {
13
- return {
14
- // Inter-package aliases using actual package names from imports
15
- '@vue-skuilder/db': isDev
16
- ? resolve(rootDir, './packages/db/src') // Dev: source directory
17
- : resolve(rootDir, './packages/db/dist/index.mjs'), // Prod: ES module build
18
- '@vue-skuilder/common': isDev
19
- ? resolve(rootDir, './packages/common/src') // Dev: source directory
20
- : resolve(rootDir, './packages/common/dist/index.mjs'),
21
-
22
- // specific built-style imports must precede the package alias, otherwise
23
- // the package prefixes get aliased out before this alias is applied
24
-
25
- '@vue-skuilder/common-ui/style': resolve(rootDir, './packages/common-ui/dist/assets/index.css'),
26
- '@vue-skuilder/courseware/style': resolve(
27
- rootDir,
28
- './packages/courseware/dist/assets/index.css'
29
- ),
30
- '@vue-skuilder/edit-ui/style': resolve(rootDir, './packages/edit-ui/dist/assets/index.css'),
31
-
32
- '@vue-skuilder/common-ui': isDev
33
- ? resolve(rootDir, './packages/common-ui/src') // Dev: source directory
34
- : resolve(rootDir, './packages/common-ui/dist/common-ui.es.js'),
35
- '@vue-skuilder/courseware': isDev
36
- ? resolve(rootDir, './packages/courseware/src') // Dev: source directory
37
- : resolve(rootDir, './packages/courseware/dist/index.mjs'),
38
- '@vue-skuilder/edit-ui': isDev
39
- ? resolve(rootDir, './packages/edit-ui/src') // Dev: source directory
40
- : resolve(rootDir, './packages/edit-ui/dist/edit-ui.es.js'),
41
-
42
- '@vue-skuilder/express': isDev
43
- ? resolve(rootDir, './packages/express/src') // Dev: source directory
44
- : resolve(rootDir, './packages/express/dist/index.mjs'), // Assuming ESM build, adjust if different
45
- '@vue-skuilder/platform-ui': isDev
46
- ? resolve(rootDir, './packages/platform-ui/src') // App, resolve to src dir
47
- : resolve(rootDir, './packages/platform-ui/dist'), // App, resolve to dist dir
48
- '@vue-skuilder/standalone-ui': isDev
49
- ? resolve(rootDir, './packages/standalone-ui/src') // App, resolve to src dir
50
- : resolve(rootDir, './packages/standalone-ui/dist'), // App, resolve to dist dir
51
- '@vue-skuilder/e2e-db': isDev
52
- ? resolve(rootDir, './packages/e2e-db/src') // Dev: source directory
53
- : resolve(rootDir, './packages/e2e-db/dist/index.js'), // Assuming CJS build for tests
54
- '@vue-skuilder/cli': isDev
55
- ? resolve(rootDir, './packages/cli/src') // Dev: source directory
56
- : resolve(rootDir, './packages/cli/dist/cli.js'), // Assuming CJS build
57
- '@vue-skuilder/client': isDev
58
- ? resolve(rootDir, './packages/client/src') // Dev: source directory
59
- : resolve(rootDir, './packages/client/dist/index.js'), // Assuming CJS build
60
-
61
- // Intra-package aliases for internal imports (matching tsconfig.base.json)
62
- // These always point to src directories, as they are used for internal package resolution
63
- // or by other packages in dev mode when they override the @vue-skuilder/* alias
64
- '@db': resolve(rootDir, './packages/db/src'),
65
- '@common': resolve(rootDir, './packages/common/src'),
66
- '@cui': resolve(rootDir, './packages/common-ui/src'),
67
- '@courseware': resolve(rootDir, './packages/courseware/src'),
68
- '@eui': resolve(rootDir, './packages/edit-ui/src'),
69
- '@express': resolve(rootDir, './packages/express/src'),
70
- '@pui': resolve(rootDir, './packages/platform-ui/src'), // App, resolve to src dir
71
- '@sui': resolve(rootDir, './packages/standalone-ui/src'), // App, resolve to src dir
72
- '@e2e-db': resolve(rootDir, './packages/e2e-db/src'),
73
- '@cli': resolve(rootDir, './packages/cli/src'),
74
- '@client': resolve(rootDir, './packages/client/src'),
75
- };
76
- }
77
-
78
- /**
79
- * Creates shared Vite resolve configuration
80
- * @param {string} rootDir - Path to the monorepo root directory
81
- * @param {Object} localAliases - Package-specific aliases to merge
82
- * @returns {Object} Vite resolve configuration
83
- */
84
- export function createBaseResolve(rootDir = process.cwd(), localAliases = {}) {
85
- return {
86
- alias: {
87
- ...createBaseAliases(rootDir),
88
- ...localAliases,
89
- },
90
- extensions: ['.js', '.ts', '.json', '.vue'],
91
- dedupe: [
92
- 'vue',
93
- 'vuetify',
94
- 'vue-router',
95
- 'pinia',
96
- '@vue-skuilder/db',
97
- '@vue-skuilder/common',
98
- '@vue-skuilder/common-ui',
99
- '@vue-skuilder/courseware',
100
- '@vue-skuilder/edit-ui',
101
- ],
102
- };
103
- }