@vue-skuilder/cli 0.1.5 ā 0.1.7
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/CLAUDE.md +84 -0
- package/dist/cli.js +8 -0
- package/dist/cli.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +46 -1
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/pack.js +17 -0
- package/dist/commands/pack.js.map +1 -1
- package/dist/commands/studio.d.ts +3 -0
- package/dist/commands/studio.d.ts.map +1 -0
- package/dist/commands/studio.js +396 -0
- package/dist/commands/studio.js.map +1 -0
- package/dist/commands/unpack.d.ts +3 -0
- package/dist/commands/unpack.d.ts.map +1 -0
- package/dist/commands/unpack.js +228 -0
- package/dist/commands/unpack.js.map +1 -0
- package/dist/studio-ui-assets/assets/BrowseView-BJbixGOU.js +2 -0
- package/dist/studio-ui-assets/assets/BrowseView-BJbixGOU.js.map +1 -0
- package/dist/studio-ui-assets/assets/BrowseView-CM4HBO4j.css +1 -0
- package/dist/studio-ui-assets/assets/BulkImportView-DB6DYDJU.js +2 -0
- package/dist/studio-ui-assets/assets/BulkImportView-DB6DYDJU.js.map +1 -0
- package/dist/studio-ui-assets/assets/BulkImportView-g4wQUfPA.css +1 -0
- package/dist/studio-ui-assets/assets/CourseEditorView-BIlhlhw1.js +2 -0
- package/dist/studio-ui-assets/assets/CourseEditorView-BIlhlhw1.js.map +1 -0
- package/dist/studio-ui-assets/assets/CourseEditorView-WuPNLVKp.css +1 -0
- package/dist/studio-ui-assets/assets/CreateCardView-CyNOKCkm.css +1 -0
- package/dist/studio-ui-assets/assets/CreateCardView-DPjPvzzt.js +2 -0
- package/dist/studio-ui-assets/assets/CreateCardView-DPjPvzzt.js.map +1 -0
- package/dist/studio-ui-assets/assets/edit-ui.es-DiUxqbgF.js +330 -0
- package/dist/studio-ui-assets/assets/edit-ui.es-DiUxqbgF.js.map +1 -0
- package/dist/studio-ui-assets/assets/index--zY88pg6.css +14 -0
- package/dist/studio-ui-assets/assets/index-BnAv1C72.js +287 -0
- package/dist/studio-ui-assets/assets/index-BnAv1C72.js.map +1 -0
- package/dist/studio-ui-assets/assets/index-DHMXQY3-.js +192 -0
- package/dist/studio-ui-assets/assets/index-DHMXQY3-.js.map +1 -0
- package/dist/studio-ui-assets/assets/materialdesignicons-webfont-B7mPwVP_.ttf +0 -0
- package/dist/studio-ui-assets/assets/materialdesignicons-webfont-CSr8KVlo.eot +0 -0
- package/dist/studio-ui-assets/assets/materialdesignicons-webfont-Dp5v-WZN.woff2 +0 -0
- package/dist/studio-ui-assets/assets/materialdesignicons-webfont-PXm3-2wK.woff +0 -0
- package/dist/studio-ui-assets/assets/vue-DZcMATiC.js +28 -0
- package/dist/studio-ui-assets/assets/vue-DZcMATiC.js.map +1 -0
- package/dist/studio-ui-assets/assets/vuetify-qg7mRxy_.js +6 -0
- package/dist/studio-ui-assets/assets/vuetify-qg7mRxy_.js.map +1 -0
- package/dist/studio-ui-assets/index.html +16 -0
- package/dist/types.d.ts +5 -0
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js.map +1 -1
- package/dist/utils/NodeFileSystemAdapter.d.ts +14 -0
- package/dist/utils/NodeFileSystemAdapter.d.ts.map +1 -0
- package/dist/utils/NodeFileSystemAdapter.js +55 -0
- package/dist/utils/NodeFileSystemAdapter.js.map +1 -0
- package/dist/utils/pack-courses.d.ts +13 -0
- package/dist/utils/pack-courses.d.ts.map +1 -0
- package/dist/utils/pack-courses.js +54 -0
- package/dist/utils/pack-courses.js.map +1 -0
- package/dist/utils/prompts.d.ts.map +1 -1
- package/dist/utils/prompts.js +206 -21
- package/dist/utils/prompts.js.map +1 -1
- package/dist/utils/template.d.ts +5 -1
- package/dist/utils/template.d.ts.map +1 -1
- package/dist/utils/template.js +71 -7
- package/dist/utils/template.js.map +1 -1
- package/package.json +7 -4
- package/src/cli.ts +8 -0
- package/src/commands/init.ts +62 -6
- package/src/commands/pack.ts +24 -1
- package/src/commands/studio.ts +497 -0
- package/src/commands/unpack.ts +259 -0
- package/src/types.ts +6 -0
- package/src/utils/NodeFileSystemAdapter.ts +72 -0
- package/src/utils/pack-courses.ts +77 -0
- package/src/utils/prompts.ts +252 -39
- package/src/utils/template.ts +83 -8
package/dist/utils/template.js
CHANGED
|
@@ -43,7 +43,7 @@ export async function copyDirectory(source, destination, excludePatterns = ['nod
|
|
|
43
43
|
/**
|
|
44
44
|
* Transform package.json to use published dependencies instead of workspace references
|
|
45
45
|
*/
|
|
46
|
-
export async function transformPackageJson(packageJsonPath, projectName, cliVersion) {
|
|
46
|
+
export async function transformPackageJson(packageJsonPath, projectName, cliVersion, config) {
|
|
47
47
|
const content = await fs.readFile(packageJsonPath, 'utf-8');
|
|
48
48
|
const packageJson = JSON.parse(content);
|
|
49
49
|
// Update basic project info
|
|
@@ -63,6 +63,18 @@ export async function transformPackageJson(packageJsonPath, projectName, cliVers
|
|
|
63
63
|
if (packageJson.devDependencies && !packageJson.devDependencies['terser']) {
|
|
64
64
|
packageJson.devDependencies['terser'] = '^5.39.0';
|
|
65
65
|
}
|
|
66
|
+
// Add CLI as devDependency for all projects
|
|
67
|
+
if (!packageJson.devDependencies) {
|
|
68
|
+
packageJson.devDependencies = {};
|
|
69
|
+
}
|
|
70
|
+
packageJson.devDependencies['@vue-skuilder/cli'] = `^${cliVersion}`;
|
|
71
|
+
// Add studio script for static data layer projects
|
|
72
|
+
if (config.dataLayerType === 'static') {
|
|
73
|
+
if (!packageJson.scripts) {
|
|
74
|
+
packageJson.scripts = {};
|
|
75
|
+
}
|
|
76
|
+
packageJson.scripts['studio'] = 'skuilder studio';
|
|
77
|
+
}
|
|
66
78
|
// Remove CLI-specific fields that don't belong in generated projects
|
|
67
79
|
delete packageJson.publishConfig;
|
|
68
80
|
await fs.writeFile(packageJsonPath, JSON.stringify(packageJson, null, 2));
|
|
@@ -142,9 +154,16 @@ export async function generateSkuilderConfig(configPath, config) {
|
|
|
142
154
|
title: config.title,
|
|
143
155
|
dataLayerType: config.dataLayerType,
|
|
144
156
|
};
|
|
145
|
-
|
|
157
|
+
// For dynamic data layer, use the specified course ID
|
|
158
|
+
if (config.dataLayerType === 'couch' && config.course) {
|
|
146
159
|
skuilderConfig.course = config.course;
|
|
147
160
|
}
|
|
161
|
+
// For static data layer with imported courses, use the first course as primary
|
|
162
|
+
if (config.dataLayerType === 'static' &&
|
|
163
|
+
config.importCourseIds &&
|
|
164
|
+
config.importCourseIds.length > 0) {
|
|
165
|
+
skuilderConfig.course = config.importCourseIds[0];
|
|
166
|
+
}
|
|
148
167
|
if (config.couchdbUrl) {
|
|
149
168
|
skuilderConfig.couchdbUrl = config.couchdbUrl;
|
|
150
169
|
}
|
|
@@ -153,6 +172,38 @@ export async function generateSkuilderConfig(configPath, config) {
|
|
|
153
172
|
}
|
|
154
173
|
await fs.writeFile(configPath, JSON.stringify(skuilderConfig, null, 2));
|
|
155
174
|
}
|
|
175
|
+
/**
|
|
176
|
+
* Transform tsconfig.json to be standalone (remove base config reference)
|
|
177
|
+
*/
|
|
178
|
+
export async function transformTsConfig(tsconfigPath) {
|
|
179
|
+
const content = await fs.readFile(tsconfigPath, 'utf-8');
|
|
180
|
+
const tsconfig = JSON.parse(content);
|
|
181
|
+
// Remove the extends reference to the monorepo base config
|
|
182
|
+
delete tsconfig.extends;
|
|
183
|
+
// Merge in the essential settings from the base config that scaffolded apps need
|
|
184
|
+
tsconfig.compilerOptions = {
|
|
185
|
+
...tsconfig.compilerOptions,
|
|
186
|
+
// Essential TypeScript settings from base config
|
|
187
|
+
strict: true,
|
|
188
|
+
skipLibCheck: true,
|
|
189
|
+
forceConsistentCasingInFileNames: true,
|
|
190
|
+
esModuleInterop: true,
|
|
191
|
+
allowSyntheticDefaultImports: true,
|
|
192
|
+
// Keep existing Vue/Vite-specific settings
|
|
193
|
+
target: tsconfig.compilerOptions.target || 'ESNext',
|
|
194
|
+
useDefineForClassFields: tsconfig.compilerOptions.useDefineForClassFields,
|
|
195
|
+
module: tsconfig.compilerOptions.module || 'ESNext',
|
|
196
|
+
moduleResolution: tsconfig.compilerOptions.moduleResolution || 'bundler',
|
|
197
|
+
jsx: tsconfig.compilerOptions.jsx || 'preserve',
|
|
198
|
+
resolveJsonModule: tsconfig.compilerOptions.resolveJsonModule,
|
|
199
|
+
isolatedModules: tsconfig.compilerOptions.isolatedModules,
|
|
200
|
+
lib: tsconfig.compilerOptions.lib || ['ESNext', 'DOM'],
|
|
201
|
+
noEmit: tsconfig.compilerOptions.noEmit,
|
|
202
|
+
baseUrl: tsconfig.compilerOptions.baseUrl || '.',
|
|
203
|
+
types: tsconfig.compilerOptions.types || ['vite/client'],
|
|
204
|
+
};
|
|
205
|
+
await fs.writeFile(tsconfigPath, JSON.stringify(tsconfig, null, 2));
|
|
206
|
+
}
|
|
156
207
|
/**
|
|
157
208
|
* Generate .gitignore file for the project
|
|
158
209
|
*/
|
|
@@ -278,9 +329,17 @@ Thumbs.db
|
|
|
278
329
|
* Generate project README.md
|
|
279
330
|
*/
|
|
280
331
|
export async function generateReadme(readmePath, config) {
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
332
|
+
let dataLayerInfo = '';
|
|
333
|
+
if (config.dataLayerType === 'static') {
|
|
334
|
+
dataLayerInfo = 'This project uses a static data layer with JSON files.';
|
|
335
|
+
if (config.importCourseIds && config.importCourseIds.length > 0) {
|
|
336
|
+
const courseList = config.importCourseIds.map((id) => `- ${id}`).join('\n');
|
|
337
|
+
dataLayerInfo += `\n\n**Imported Courses:**\n${courseList}\n\nCourse data is stored in \`public/static-courses/\` and loaded automatically.`;
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
else {
|
|
341
|
+
dataLayerInfo = `This project connects to CouchDB at: ${config.couchdbUrl || '[URL not specified]'}`;
|
|
342
|
+
}
|
|
284
343
|
const readme = `# ${config.title}
|
|
285
344
|
|
|
286
345
|
A Skuilder course application built with Vue 3, Vuetify, and Pinia.
|
|
@@ -318,7 +377,7 @@ Course configuration is managed in \`skuilder.config.json\`. You can modify:
|
|
|
318
377
|
|
|
319
378
|
Current theme: **${config.theme.name}** (${config.theme.defaultMode} mode)
|
|
320
379
|
- Primary: ${config.theme.light.colors.primary}
|
|
321
|
-
- Secondary: ${config.theme.light.colors.secondary}
|
|
380
|
+
- Secondary: ${config.theme.light.colors.secondary}
|
|
322
381
|
- Accent: ${config.theme.light.colors.accent}
|
|
323
382
|
|
|
324
383
|
This theme includes both light and dark variants. The application will use the ${config.theme.defaultMode} theme by default, but users can toggle between light and dark modes in their settings.
|
|
@@ -381,12 +440,17 @@ export async function processTemplate(projectPath, config, cliVersion) {
|
|
|
381
440
|
await copyDirectory(templatePath, projectPath);
|
|
382
441
|
console.log(chalk.blue('āļø Configuring package.json...'));
|
|
383
442
|
const packageJsonPath = path.join(projectPath, 'package.json');
|
|
384
|
-
await transformPackageJson(packageJsonPath, config.projectName, cliVersion);
|
|
443
|
+
await transformPackageJson(packageJsonPath, config.projectName, cliVersion, config);
|
|
385
444
|
console.log(chalk.blue('š§ Creating vite.config.ts...'));
|
|
386
445
|
const viteConfigPath = path.join(projectPath, 'vite.config.ts');
|
|
387
446
|
if (existsSync(viteConfigPath)) {
|
|
388
447
|
await createViteConfig(viteConfigPath);
|
|
389
448
|
}
|
|
449
|
+
console.log(chalk.blue('š§ Transforming tsconfig.json...'));
|
|
450
|
+
const tsconfigPath = path.join(projectPath, 'tsconfig.json');
|
|
451
|
+
if (existsSync(tsconfigPath)) {
|
|
452
|
+
await transformTsConfig(tsconfigPath);
|
|
453
|
+
}
|
|
390
454
|
console.log(chalk.blue('š§ Generating configuration...'));
|
|
391
455
|
const configPath = path.join(projectPath, 'skuilder.config.json');
|
|
392
456
|
await generateSkuilderConfig(configPath, config);
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"template.js","sourceRoot":"","sources":["../../src/utils/template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChD,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,8CAA8C;IAC9C,IAAI,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAElD,OAAO,UAAU,KAAK,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/C,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,CAAC,CAAC;QAChG,IAAI,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;YAChC,OAAO,eAAe,CAAC;QACzB,CAAC;QACD,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,IAAI,KAAK,CACb,oFAAoF,CACrF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAc,EACd,WAAmB,EACnB,kBAA4B,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC;IAEvE,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAElE,MAAM,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEjD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAEpD,yBAAyB;QACzB,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;YACpE,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,aAAa,CAAC,UAAU,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;QAC7D,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,eAAuB,EACvB,WAAmB,EACnB,UAAkB;
|
|
1
|
+
{"version":3,"file":"template.js","sourceRoot":"","sources":["../../src/utils/template.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,IAAI,EAAE,EAAE,UAAU,EAAE,MAAM,IAAI,CAAC;AAChD,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,MAAM,KAAK,CAAC;AACpC,OAAO,KAAK,MAAM,OAAO,CAAC;AAG1B,MAAM,UAAU,GAAG,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAClD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;AAE3C;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB;IACxC,8CAA8C;IAC9C,IAAI,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,EAAE,IAAI,CAAC,CAAC;IAElD,OAAO,UAAU,KAAK,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,CAAC;QAC/C,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,cAAc,EAAE,eAAe,EAAE,eAAe,CAAC,CAAC;QAChG,IAAI,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;YAChC,OAAO,eAAe,CAAC;QACzB,CAAC;QACD,UAAU,GAAG,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAED,MAAM,IAAI,KAAK,CACb,oFAAoF,CACrF,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,aAAa,CACjC,MAAc,EACd,WAAmB,EACnB,kBAA4B,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,SAAS,CAAC;IAEvE,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;IAElE,MAAM,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAEjD,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;QAC5B,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QACjD,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;QAEpD,yBAAyB;QACzB,IAAI,eAAe,CAAC,IAAI,CAAC,CAAC,OAAO,EAAE,EAAE,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;YACpE,SAAS;QACX,CAAC;QAED,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;YACxB,MAAM,aAAa,CAAC,UAAU,EAAE,QAAQ,EAAE,eAAe,CAAC,CAAC;QAC7D,CAAC;aAAM,CAAC;YACN,MAAM,EAAE,CAAC,QAAQ,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;QAC1C,CAAC;IACH,CAAC;AACH,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,oBAAoB,CACxC,eAAuB,EACvB,WAAmB,EACnB,UAAkB,EAClB,MAAqB;IAErB,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;IAC5D,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAExC,4BAA4B;IAC5B,WAAW,CAAC,IAAI,GAAG,WAAW,CAAC;IAC/B,WAAW,CAAC,WAAW,GAAG,gCAAgC,WAAW,EAAE,CAAC;IACxE,WAAW,CAAC,OAAO,GAAG,OAAO,CAAC;IAE9B,yDAAyD;IACzD,IAAI,WAAW,CAAC,YAAY,EAAE,CAAC;QAC7B,KAAK,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,CAAC,YAAY,CAAC,EAAE,CAAC;YAC1E,IAAI,OAAO,OAAO,KAAK,QAAQ,IAAI,OAAO,CAAC,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;gBACpE,kDAAkD;gBAClD,WAAW,CAAC,YAAY,CAAC,OAAO,CAAC,GAAG,IAAI,UAAU,EAAE,CAAC;YACvD,CAAC;QACH,CAAC;IACH,CAAC;IAED,0DAA0D;IAC1D,IAAI,WAAW,CAAC,eAAe,IAAI,CAAC,WAAW,CAAC,eAAe,CAAC,QAAQ,CAAC,EAAE,CAAC;QAC1E,WAAW,CAAC,eAAe,CAAC,QAAQ,CAAC,GAAG,SAAS,CAAC;IACpD,CAAC;IAED,4CAA4C;IAC5C,IAAI,CAAC,WAAW,CAAC,eAAe,EAAE,CAAC;QACjC,WAAW,CAAC,eAAe,GAAG,EAAE,CAAC;IACnC,CAAC;IACD,WAAW,CAAC,eAAe,CAAC,mBAAmB,CAAC,GAAG,IAAI,UAAU,EAAE,CAAC;IAEpE,mDAAmD;IACnD,IAAI,MAAM,CAAC,aAAa,KAAK,QAAQ,EAAE,CAAC;QACtC,IAAI,CAAC,WAAW,CAAC,OAAO,EAAE,CAAC;YACzB,WAAW,CAAC,OAAO,GAAG,EAAE,CAAC;QAC3B,CAAC;QACD,WAAW,CAAC,OAAO,CAAC,QAAQ,CAAC,GAAG,iBAAiB,CAAC;IACpD,CAAC;IAED,qEAAqE;IACrE,OAAO,WAAW,CAAC,aAAa,CAAC;IAEjC,MAAM,EAAE,CAAC,SAAS,CAAC,eAAe,EAAE,IAAI,CAAC,SAAS,CAAC,WAAW,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC5E,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,gBAAgB,CAAC,cAAsB;IAC3D,qDAAqD;IACrD,MAAM,kBAAkB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAyD5B,CAAC;IAEA,MAAM,EAAE,CAAC,SAAS,CAAC,cAAc,EAAE,kBAAkB,CAAC,CAAC;AACzD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,sBAAsB,CAC1C,UAAkB,EAClB,MAAqB;IAErB,MAAM,cAAc,GAAmB;QACrC,KAAK,EAAE,MAAM,CAAC,KAAK;QACnB,aAAa,EAAE,MAAM,CAAC,aAAa;KACpC,CAAC;IAEF,sDAAsD;IACtD,IAAI,MAAM,CAAC,aAAa,KAAK,OAAO,IAAI,MAAM,CAAC,MAAM,EAAE,CAAC;QACtD,cAAc,CAAC,MAAM,GAAG,MAAM,CAAC,MAAM,CAAC;IACxC,CAAC;IAED,+EAA+E;IAC/E,IACE,MAAM,CAAC,aAAa,KAAK,QAAQ;QACjC,MAAM,CAAC,eAAe;QACtB,MAAM,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EACjC,CAAC;QACD,cAAc,CAAC,MAAM,GAAG,MAAM,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;IACpD,CAAC;IAED,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;QACtB,cAAc,CAAC,UAAU,GAAG,MAAM,CAAC,UAAU,CAAC;IAChD,CAAC;IAED,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;QACjB,cAAc,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC;IACtC,CAAC;IAED,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,IAAI,CAAC,SAAS,CAAC,cAAc,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AAC1E,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,YAAoB;IAC1D,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,YAAY,EAAE,OAAO,CAAC,CAAC;IACzD,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC;IAErC,2DAA2D;IAC3D,OAAO,QAAQ,CAAC,OAAO,CAAC;IAExB,iFAAiF;IACjF,QAAQ,CAAC,eAAe,GAAG;QACzB,GAAG,QAAQ,CAAC,eAAe;QAC3B,iDAAiD;QACjD,MAAM,EAAE,IAAI;QACZ,YAAY,EAAE,IAAI;QAClB,gCAAgC,EAAE,IAAI;QACtC,eAAe,EAAE,IAAI;QACrB,4BAA4B,EAAE,IAAI;QAClC,2CAA2C;QAC3C,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC,MAAM,IAAI,QAAQ;QACnD,uBAAuB,EAAE,QAAQ,CAAC,eAAe,CAAC,uBAAuB;QACzE,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC,MAAM,IAAI,QAAQ;QACnD,gBAAgB,EAAE,QAAQ,CAAC,eAAe,CAAC,gBAAgB,IAAI,SAAS;QACxE,GAAG,EAAE,QAAQ,CAAC,eAAe,CAAC,GAAG,IAAI,UAAU;QAC/C,iBAAiB,EAAE,QAAQ,CAAC,eAAe,CAAC,iBAAiB;QAC7D,eAAe,EAAE,QAAQ,CAAC,eAAe,CAAC,eAAe;QACzD,GAAG,EAAE,QAAQ,CAAC,eAAe,CAAC,GAAG,IAAI,CAAC,QAAQ,EAAE,KAAK,CAAC;QACtD,MAAM,EAAE,QAAQ,CAAC,eAAe,CAAC,MAAM;QACvC,OAAO,EAAE,QAAQ,CAAC,eAAe,CAAC,OAAO,IAAI,GAAG;QAChD,KAAK,EAAE,QAAQ,CAAC,eAAe,CAAC,KAAK,IAAI,CAAC,aAAa,CAAC;KACzD,CAAC;IAEF,MAAM,EAAE,CAAC,SAAS,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC;AACtE,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,iBAAiB,CAAC,aAAqB;IAC3D,MAAM,gBAAgB,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAkH1B,CAAC;IAEA,MAAM,EAAE,CAAC,SAAS,CAAC,aAAa,EAAE,gBAAgB,CAAC,CAAC;AACtD,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,UAAkB,EAAE,MAAqB;IAC5E,IAAI,aAAa,GAAG,EAAE,CAAC;IAEvB,IAAI,MAAM,CAAC,aAAa,KAAK,QAAQ,EAAE,CAAC;QACtC,aAAa,GAAG,wDAAwD,CAAC;QAEzE,IAAI,MAAM,CAAC,eAAe,IAAI,MAAM,CAAC,eAAe,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChE,MAAM,UAAU,GAAG,MAAM,CAAC,eAAe,CAAC,GAAG,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC5E,aAAa,IAAI,8BAA8B,UAAU,mFAAmF,CAAC;QAC/I,CAAC;IACH,CAAC;SAAM,CAAC;QACN,aAAa,GAAG,wCAAwC,MAAM,CAAC,UAAU,IAAI,qBAAqB,EAAE,CAAC;IACvG,CAAC;IAED,MAAM,MAAM,GAAG,KAAK,MAAM,CAAC,KAAK;;;;;;EAMhC,aAAa;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBA6BI,MAAM,CAAC,KAAK,CAAC,IAAI,OAAO,MAAM,CAAC,KAAK,CAAC,WAAW;aACtD,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,OAAO;eAC/B,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,SAAS;YACtC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM;;iFAEqC,MAAM,CAAC,KAAK,CAAC,WAAW;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CA+CxG,CAAC;IAEA,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;AACzC,CAAC;AAED;;GAEG;AACH,MAAM,CAAC,KAAK,UAAU,eAAe,CACnC,WAAmB,EACnB,MAAqB,EACrB,UAAkB;IAElB,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,uCAAuC,CAAC,CAAC,CAAC;IACjE,MAAM,YAAY,GAAG,MAAM,oBAAoB,EAAE,CAAC;IAElD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,CAAC;IACvD,MAAM,aAAa,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;IAE/C,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,iCAAiC,CAAC,CAAC,CAAC;IAC3D,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,cAAc,CAAC,CAAC;IAC/D,MAAM,oBAAoB,CAAC,eAAe,EAAE,MAAM,CAAC,WAAW,EAAE,UAAU,EAAE,MAAM,CAAC,CAAC;IAEpF,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,+BAA+B,CAAC,CAAC,CAAC;IACzD,MAAM,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,gBAAgB,CAAC,CAAC;IAChE,IAAI,UAAU,CAAC,cAAc,CAAC,EAAE,CAAC;QAC/B,MAAM,gBAAgB,CAAC,cAAc,CAAC,CAAC;IACzC,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,kCAAkC,CAAC,CAAC,CAAC;IAC5D,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,eAAe,CAAC,CAAC;IAC7D,IAAI,UAAU,CAAC,YAAY,CAAC,EAAE,CAAC;QAC7B,MAAM,iBAAiB,CAAC,YAAY,CAAC,CAAC;IACxC,CAAC;IAED,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,gCAAgC,CAAC,CAAC,CAAC;IAC1D,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,sBAAsB,CAAC,CAAC;IAClE,MAAM,sBAAsB,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAEjD,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,uBAAuB,CAAC,CAAC,CAAC;IACjD,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;IACvD,MAAM,cAAc,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC;IAEzC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,IAAI,CAAC,6BAA6B,CAAC,CAAC,CAAC;IACvD,MAAM,aAAa,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,YAAY,CAAC,CAAC;IAC3D,MAAM,iBAAiB,CAAC,aAAa,CAAC,CAAC;IAEvC,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,KAAK,CAAC,iCAAiC,CAAC,CAAC,CAAC;AAC9D,CAAC"}
|
package/package.json
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
"publishConfig": {
|
|
4
4
|
"access": "public"
|
|
5
5
|
},
|
|
6
|
-
"version": "0.1.
|
|
6
|
+
"version": "0.1.7",
|
|
7
7
|
"type": "module",
|
|
8
8
|
"description": "CLI scaffolding tool for vue-skuilder projects",
|
|
9
9
|
"bin": {
|
|
@@ -18,7 +18,9 @@
|
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
"scripts": {
|
|
21
|
-
"build": "rm -rf dist && tsc",
|
|
21
|
+
"build": "rm -rf dist && npm run build:studio-ui && tsc && npm run embed:studio-ui",
|
|
22
|
+
"build:studio-ui": "cd ../studio-ui && npm run build",
|
|
23
|
+
"embed:studio-ui": "mkdir -p dist/studio-ui-assets && cp -r ../studio-ui/dist/* dist/studio-ui-assets/",
|
|
22
24
|
"dev": "tsc --watch",
|
|
23
25
|
"lint": "npx eslint .",
|
|
24
26
|
"lint:fix": "npx eslint . --fix",
|
|
@@ -33,8 +35,8 @@
|
|
|
33
35
|
"course"
|
|
34
36
|
],
|
|
35
37
|
"dependencies": {
|
|
36
|
-
"@vue-skuilder/db": "0.1.
|
|
37
|
-
"@vue-skuilder/standalone-ui": "^0.1.
|
|
38
|
+
"@vue-skuilder/db": "0.1.7",
|
|
39
|
+
"@vue-skuilder/standalone-ui": "^0.1.7",
|
|
38
40
|
"chalk": "^5.3.0",
|
|
39
41
|
"commander": "^11.0.0",
|
|
40
42
|
"fs-extra": "^11.2.0",
|
|
@@ -45,6 +47,7 @@
|
|
|
45
47
|
"@types/fs-extra": "^11.0.0",
|
|
46
48
|
"@types/inquirer": "^9.0.0",
|
|
47
49
|
"@types/node": "^20.0.0",
|
|
50
|
+
"@vue-skuilder/studio-ui": "0.1.7",
|
|
48
51
|
"typescript": "~5.7.2"
|
|
49
52
|
},
|
|
50
53
|
"engines": {
|
package/src/cli.ts
CHANGED
|
@@ -6,6 +6,8 @@ import { fileURLToPath } from 'url';
|
|
|
6
6
|
import { dirname, join } from 'path';
|
|
7
7
|
import { createInitCommand } from './commands/init.js';
|
|
8
8
|
import { createPackCommand } from './commands/pack.js';
|
|
9
|
+
import { createUnpackCommand } from './commands/unpack.js';
|
|
10
|
+
import { createStudioCommand } from './commands/studio.js';
|
|
9
11
|
|
|
10
12
|
const __filename = fileURLToPath(import.meta.url);
|
|
11
13
|
const __dirname = dirname(__filename);
|
|
@@ -24,6 +26,8 @@ program
|
|
|
24
26
|
// Add commands
|
|
25
27
|
program.addCommand(createInitCommand());
|
|
26
28
|
program.addCommand(createPackCommand());
|
|
29
|
+
program.addCommand(createUnpackCommand());
|
|
30
|
+
program.addCommand(createStudioCommand());
|
|
27
31
|
|
|
28
32
|
program.on('--help', () => {
|
|
29
33
|
console.log('');
|
|
@@ -33,6 +37,10 @@ program.on('--help', () => {
|
|
|
33
37
|
console.log(' $ skuilder init physics --no-interactive --data-layer=dynamic');
|
|
34
38
|
console.log(' $ skuilder pack sample-course-id');
|
|
35
39
|
console.log(' $ skuilder pack biology-101 --server http://localhost:5984 --username admin');
|
|
40
|
+
console.log(' $ skuilder unpack ./static-courses/biology-101');
|
|
41
|
+
console.log(' $ skuilder unpack ./my-course --database test-migration --validate');
|
|
42
|
+
console.log(' $ skuilder studio ./my-sui-course');
|
|
43
|
+
console.log(' $ skuilder studio . --port 5985 --no-browser');
|
|
36
44
|
});
|
|
37
45
|
|
|
38
46
|
program.parse();
|
package/src/commands/init.ts
CHANGED
|
@@ -3,13 +3,14 @@ import { Command } from 'commander';
|
|
|
3
3
|
import { existsSync, readFileSync } from 'fs';
|
|
4
4
|
import path, { dirname, join } from 'path';
|
|
5
5
|
import { fileURLToPath } from 'url';
|
|
6
|
-
import { CliOptions } from '../types.js';
|
|
6
|
+
import { CliOptions, PREDEFINED_THEMES } from '../types.js';
|
|
7
7
|
import {
|
|
8
8
|
confirmProjectCreation,
|
|
9
9
|
displayThemePreview,
|
|
10
10
|
gatherProjectConfig,
|
|
11
11
|
} from '../utils/prompts.js';
|
|
12
12
|
import { processTemplate } from '../utils/template.js';
|
|
13
|
+
import { packCourses } from '../utils/pack-courses.js';
|
|
13
14
|
|
|
14
15
|
const __filename = fileURLToPath(import.meta.url);
|
|
15
16
|
const __dirname = dirname(__filename);
|
|
@@ -44,6 +45,18 @@ async function initCommand(projectName: string, options: InitOptions): Promise<v
|
|
|
44
45
|
process.exit(1);
|
|
45
46
|
}
|
|
46
47
|
|
|
48
|
+
// Validate theme option
|
|
49
|
+
const validThemes = Object.keys(PREDEFINED_THEMES);
|
|
50
|
+
if (!validThemes.includes(options.theme)) {
|
|
51
|
+
console.error(
|
|
52
|
+
chalk.red(`ā Invalid theme: "${options.theme}"`)
|
|
53
|
+
);
|
|
54
|
+
console.error(
|
|
55
|
+
chalk.yellow(`Valid themes: ${validThemes.join(', ')}`)
|
|
56
|
+
);
|
|
57
|
+
process.exit(1);
|
|
58
|
+
}
|
|
59
|
+
|
|
47
60
|
// Check if directory already exists
|
|
48
61
|
const projectPath = path.resolve(process.cwd(), projectName);
|
|
49
62
|
if (existsSync(projectPath)) {
|
|
@@ -82,6 +95,36 @@ async function initCommand(projectName: string, options: InitOptions): Promise<v
|
|
|
82
95
|
// Process template and create project
|
|
83
96
|
await processTemplate(projectPath, config, cliVersion);
|
|
84
97
|
|
|
98
|
+
// Import course data if requested for static data layer
|
|
99
|
+
if (config.dataLayerType === 'static' && config.importCourseData && config.importCourseIds && config.importCourseIds.length > 0) {
|
|
100
|
+
console.log(chalk.cyan('\nš¦ Importing course data...\n'));
|
|
101
|
+
|
|
102
|
+
try {
|
|
103
|
+
await packCourses({
|
|
104
|
+
server: config.importServerUrl!,
|
|
105
|
+
username: config.importUsername,
|
|
106
|
+
password: config.importPassword,
|
|
107
|
+
courseIds: config.importCourseIds,
|
|
108
|
+
targetProjectDir: projectPath
|
|
109
|
+
});
|
|
110
|
+
|
|
111
|
+
console.log(chalk.green('ā
Course data imported successfully!'));
|
|
112
|
+
} catch (error: unknown) {
|
|
113
|
+
console.error(chalk.red('\nā Failed to import course data:'));
|
|
114
|
+
let errorMessage = 'Unknown error';
|
|
115
|
+
if (error instanceof Error) {
|
|
116
|
+
errorMessage = error.message;
|
|
117
|
+
} else if (typeof error === 'string') {
|
|
118
|
+
errorMessage = error;
|
|
119
|
+
} else if (error && typeof error === 'object' && 'message' in error) {
|
|
120
|
+
errorMessage = String((error as { message: unknown }).message);
|
|
121
|
+
}
|
|
122
|
+
console.error(chalk.red(errorMessage));
|
|
123
|
+
console.log(chalk.yellow('\nā ļø Project created successfully, but without course data.'));
|
|
124
|
+
console.log(chalk.yellow('You can import course data later using the pack command.'));
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
85
128
|
// Success message
|
|
86
129
|
console.log(chalk.green('\nš Project created successfully!\n'));
|
|
87
130
|
|
|
@@ -104,11 +147,24 @@ async function initCommand(projectName: string, options: InitOptions): Promise<v
|
|
|
104
147
|
);
|
|
105
148
|
}
|
|
106
149
|
} else {
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
150
|
+
if (config.importCourseIds && config.importCourseIds.length > 0) {
|
|
151
|
+
console.log(
|
|
152
|
+
chalk.yellow(
|
|
153
|
+
`š Note: This project uses static data with ${config.importCourseIds.length} imported course(s).`
|
|
154
|
+
)
|
|
155
|
+
);
|
|
156
|
+
console.log(
|
|
157
|
+
chalk.yellow(
|
|
158
|
+
`š Course data is available in the public/static-courses/ directory.`
|
|
159
|
+
)
|
|
160
|
+
);
|
|
161
|
+
} else {
|
|
162
|
+
console.log(
|
|
163
|
+
chalk.yellow(
|
|
164
|
+
'š Note: This project uses static data. No course data has been imported.'
|
|
165
|
+
)
|
|
166
|
+
);
|
|
167
|
+
}
|
|
112
168
|
}
|
|
113
169
|
} catch (error: unknown) {
|
|
114
170
|
console.error(chalk.red('\nā Failed to create project:'));
|
package/src/commands/pack.ts
CHANGED
|
@@ -3,7 +3,7 @@ import PouchDB from 'pouchdb';
|
|
|
3
3
|
import fs from 'fs-extra';
|
|
4
4
|
import path from 'path';
|
|
5
5
|
import chalk from 'chalk';
|
|
6
|
-
import { CouchDBToStaticPacker } from '@vue-skuilder/db/packer';
|
|
6
|
+
import { CouchDBToStaticPacker, AttachmentData } from '@vue-skuilder/db/packer';
|
|
7
7
|
|
|
8
8
|
export function createPackCommand(): Command {
|
|
9
9
|
return new Command('pack')
|
|
@@ -94,6 +94,9 @@ async function packCourse(courseId: string, options: PackOptions) {
|
|
|
94
94
|
console.log(chalk.white(`š Documents: ${packedData.manifest.documentCount}`));
|
|
95
95
|
console.log(chalk.white(`šļø Chunks: ${packedData.manifest.chunks.length}`));
|
|
96
96
|
console.log(chalk.white(`šļø Indices: ${packedData.manifest.indices.length}`));
|
|
97
|
+
if (packedData.attachments && packedData.attachments.size > 0) {
|
|
98
|
+
console.log(chalk.white(`š Attachments: ${packedData.attachments.size}`));
|
|
99
|
+
}
|
|
97
100
|
console.log(chalk.white(`š Location: ${outputDir}`));
|
|
98
101
|
|
|
99
102
|
} catch (error: unknown) {
|
|
@@ -124,6 +127,7 @@ interface PackedData {
|
|
|
124
127
|
};
|
|
125
128
|
chunks: Map<string, unknown[]>;
|
|
126
129
|
indices: Map<string, unknown>;
|
|
130
|
+
attachments?: Map<string, AttachmentData>;
|
|
127
131
|
}
|
|
128
132
|
|
|
129
133
|
async function writePackedData(
|
|
@@ -160,4 +164,23 @@ async function writePackedData(
|
|
|
160
164
|
indexCount++;
|
|
161
165
|
}
|
|
162
166
|
console.log(chalk.gray(`šļø Wrote ${indexCount} indices`));
|
|
167
|
+
|
|
168
|
+
// Write attachments
|
|
169
|
+
if (packedData.attachments && packedData.attachments.size > 0) {
|
|
170
|
+
console.log(chalk.cyan('š Writing attachments...'));
|
|
171
|
+
|
|
172
|
+
let attachmentCount = 0;
|
|
173
|
+
for (const [attachmentPath, attachmentData] of packedData.attachments) {
|
|
174
|
+
const fullAttachmentPath = path.join(outputDir, attachmentPath);
|
|
175
|
+
|
|
176
|
+
// Ensure directory exists
|
|
177
|
+
await fs.ensureDir(path.dirname(fullAttachmentPath));
|
|
178
|
+
|
|
179
|
+
// Write binary file
|
|
180
|
+
await fs.writeFile(fullAttachmentPath, attachmentData.buffer);
|
|
181
|
+
attachmentCount++;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
console.log(chalk.gray(`š Wrote ${attachmentCount} attachment files`));
|
|
185
|
+
}
|
|
163
186
|
}
|