@vue-skuilder/cli 0.1.6 → 0.1.8-0
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 +122 -8
- package/dist/cli.d.ts +1 -1
- package/dist/cli.d.ts.map +1 -1
- package/dist/cli.js +10 -1
- package/dist/cli.js.map +1 -1
- package/dist/commands/init.d.ts.map +1 -1
- package/dist/commands/init.js +34 -3
- package/dist/commands/init.js.map +1 -1
- package/dist/commands/pack.d.ts +10 -0
- package/dist/commands/pack.d.ts.map +1 -1
- package/dist/commands/pack.js +1 -1
- 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 +931 -0
- package/dist/commands/studio.js.map +1 -0
- package/dist/commands/unpack.d.ts +15 -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/express-assets/app.d.ts +6 -0
- package/dist/express-assets/app.d.ts.map +1 -0
- package/dist/express-assets/app.js +209 -0
- package/dist/express-assets/app.js.map +1 -0
- package/dist/express-assets/assets/classroomDesignDoc.js +24 -0
- package/dist/express-assets/assets/courseValidateDocUpdate.js +56 -0
- package/dist/express-assets/assets/get-tagsDesignDoc.json +9 -0
- package/dist/express-assets/attachment-preprocessing/index.d.ts +11 -0
- package/dist/express-assets/attachment-preprocessing/index.d.ts.map +1 -0
- package/dist/express-assets/attachment-preprocessing/index.js +204 -0
- package/dist/express-assets/attachment-preprocessing/index.js.map +1 -0
- package/dist/express-assets/attachment-preprocessing/normalize.d.ts +7 -0
- package/dist/express-assets/attachment-preprocessing/normalize.d.ts.map +1 -0
- package/dist/express-assets/attachment-preprocessing/normalize.js +90 -0
- package/dist/express-assets/attachment-preprocessing/normalize.js.map +1 -0
- package/dist/express-assets/client-requests/classroom-requests.d.ts +26 -0
- package/dist/express-assets/client-requests/classroom-requests.d.ts.map +1 -0
- package/dist/express-assets/client-requests/classroom-requests.js +171 -0
- package/dist/express-assets/client-requests/classroom-requests.js.map +1 -0
- package/dist/express-assets/client-requests/course-requests.d.ts +10 -0
- package/dist/express-assets/client-requests/course-requests.d.ts.map +1 -0
- package/dist/express-assets/client-requests/course-requests.js +135 -0
- package/dist/express-assets/client-requests/course-requests.js.map +1 -0
- package/dist/express-assets/client-requests/pack-requests.d.ts +19 -0
- package/dist/express-assets/client-requests/pack-requests.d.ts.map +1 -0
- package/dist/express-assets/client-requests/pack-requests.js +130 -0
- package/dist/express-assets/client-requests/pack-requests.js.map +1 -0
- package/dist/express-assets/client.d.ts +31 -0
- package/dist/express-assets/client.d.ts.map +1 -0
- package/dist/express-assets/client.js +70 -0
- package/dist/express-assets/client.js.map +1 -0
- package/dist/express-assets/couchdb/authentication.d.ts +4 -0
- package/dist/express-assets/couchdb/authentication.d.ts.map +1 -0
- package/dist/express-assets/couchdb/authentication.js +69 -0
- package/dist/express-assets/couchdb/authentication.js.map +1 -0
- package/dist/express-assets/couchdb/index.d.ts +18 -0
- package/dist/express-assets/couchdb/index.d.ts.map +1 -0
- package/dist/express-assets/couchdb/index.js +52 -0
- package/dist/express-assets/couchdb/index.js.map +1 -0
- package/dist/express-assets/design-docs.d.ts +63 -0
- package/dist/express-assets/design-docs.d.ts.map +1 -0
- package/dist/express-assets/design-docs.js +90 -0
- package/dist/express-assets/design-docs.js.map +1 -0
- package/dist/express-assets/logger.d.ts +3 -0
- package/dist/express-assets/logger.d.ts.map +1 -0
- package/dist/express-assets/logger.js +62 -0
- package/dist/express-assets/logger.js.map +1 -0
- package/dist/express-assets/routes/logs.d.ts +3 -0
- package/dist/express-assets/routes/logs.d.ts.map +1 -0
- package/dist/express-assets/routes/logs.js +274 -0
- package/dist/express-assets/routes/logs.js.map +1 -0
- package/dist/express-assets/utils/env.d.ts +11 -0
- package/dist/express-assets/utils/env.d.ts.map +1 -0
- package/dist/express-assets/utils/env.js +39 -0
- package/dist/express-assets/utils/env.js.map +1 -0
- package/dist/express-assets/utils/processQueue.d.ts +39 -0
- package/dist/express-assets/utils/processQueue.d.ts.map +1 -0
- package/dist/express-assets/utils/processQueue.js +175 -0
- package/dist/express-assets/utils/processQueue.js.map +1 -0
- package/dist/studio-ui-src/App.vue +132 -0
- package/dist/studio-ui-src/api/index.ts +30 -0
- package/dist/studio-ui-src/components/StudioFlush.vue +108 -0
- package/dist/studio-ui-src/config/development.ts +98 -0
- package/dist/studio-ui-src/index.html +13 -0
- package/dist/studio-ui-src/main.ts +148 -0
- package/dist/studio-ui-src/package.json +35 -0
- package/dist/studio-ui-src/router/index.ts +32 -0
- package/dist/studio-ui-src/stores/useAuthStore.ts +3 -0
- package/dist/studio-ui-src/tsconfig.json +28 -0
- package/dist/studio-ui-src/views/BrowseView.vue +82 -0
- package/dist/studio-ui-src/views/BulkImportView.vue +89 -0
- package/dist/studio-ui-src/views/CourseEditorView.vue +62 -0
- package/dist/studio-ui-src/views/CreateCardView.vue +140 -0
- package/dist/studio-ui-src/vite.config.base.js +100 -0
- package/dist/studio-ui-src/vite.config.ts +26 -0
- package/dist/templates/.skuilder/README.md +29 -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/ExpressManager.d.ts +28 -0
- package/dist/utils/ExpressManager.d.ts.map +1 -0
- package/dist/utils/ExpressManager.js +166 -0
- package/dist/utils/ExpressManager.js.map +1 -0
- package/dist/utils/NodeFileSystemAdapter.d.ts +20 -0
- package/dist/utils/NodeFileSystemAdapter.d.ts.map +1 -0
- package/dist/utils/NodeFileSystemAdapter.js +83 -0
- package/dist/utils/NodeFileSystemAdapter.js.map +1 -0
- package/dist/utils/error-reporting.d.ts +54 -0
- package/dist/utils/error-reporting.d.ts.map +1 -0
- package/dist/utils/error-reporting.js +143 -0
- package/dist/utils/error-reporting.js.map +1 -0
- package/dist/utils/pack-courses.d.ts.map +1 -1
- package/dist/utils/pack-courses.js +10 -27
- package/dist/utils/pack-courses.js.map +1 -1
- package/dist/utils/prompts.d.ts.map +1 -1
- package/dist/utils/prompts.js +24 -0
- package/dist/utils/prompts.js.map +1 -1
- package/dist/utils/questions-hash.d.ts +22 -0
- package/dist/utils/questions-hash.d.ts.map +1 -0
- package/dist/utils/questions-hash.js +96 -0
- package/dist/utils/questions-hash.js.map +1 -0
- package/dist/utils/template.d.ts +2 -2
- package/dist/utils/template.d.ts.map +1 -1
- package/dist/utils/template.js +218 -27
- package/dist/utils/template.js.map +1 -1
- package/eslint.config.mjs +1 -1
- package/package.json +30 -8
- package/src/cli.ts +11 -1
- package/src/commands/init.ts +48 -3
- package/src/commands/pack.ts +1 -1
- package/src/commands/studio.ts +1226 -0
- package/src/commands/unpack.ts +259 -0
- package/src/types.ts +5 -0
- package/src/utils/ExpressManager.ts +210 -0
- package/src/utils/NodeFileSystemAdapter.ts +116 -0
- package/src/utils/error-reporting.ts +192 -0
- package/src/utils/pack-courses.ts +11 -36
- package/src/utils/prompts.ts +34 -0
- package/src/utils/questions-hash.ts +109 -0
- package/src/utils/template.ts +252 -29
- package/templates/.skuilder/README.md +29 -0
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
function(newDoc, oldDoc, userCtx, secObj) {
|
|
2
|
+
// Skip validation for deletions
|
|
3
|
+
if (newDoc._deleted) return;
|
|
4
|
+
|
|
5
|
+
// Always allow admins to do anything
|
|
6
|
+
if (userCtx.roles.indexOf('_admin') !== -1) return;
|
|
7
|
+
|
|
8
|
+
// For CourseConfig document - we need special handling
|
|
9
|
+
if (newDoc._id === 'CourseConfig') {
|
|
10
|
+
// Allow the creator or admins listed in the document to modify it
|
|
11
|
+
if (oldDoc && oldDoc.creator === userCtx.name) return;
|
|
12
|
+
if (oldDoc && oldDoc.admins && Array.isArray(oldDoc.admins) && oldDoc.admins.indexOf(userCtx.name) !== -1) return;
|
|
13
|
+
|
|
14
|
+
// For updates, if user is not creator or admin, deny
|
|
15
|
+
if (oldDoc) {
|
|
16
|
+
throw({forbidden: "Only course creator or admins can modify course configuration"});
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
// For new course config, allow (initial creation is secured at API level)
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
// For all other documents
|
|
24
|
+
var isAdmin = false;
|
|
25
|
+
var isModerator = false;
|
|
26
|
+
|
|
27
|
+
// Course admins and moderators can edit anything
|
|
28
|
+
// (Since we can't check CourseConfig directly, we rely on document author for regular docs)
|
|
29
|
+
|
|
30
|
+
// Document has author field that matches current user - allow
|
|
31
|
+
if (oldDoc && oldDoc.author === userCtx.name) return;
|
|
32
|
+
|
|
33
|
+
// Allow document creation by any authenticated user
|
|
34
|
+
if (!oldDoc) {
|
|
35
|
+
if (!userCtx.name) {
|
|
36
|
+
throw({forbidden: "You must be logged in to create documents"});
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
// Ensure new documents have an author field that matches the current user
|
|
40
|
+
if (!newDoc.author || newDoc.author !== userCtx.name) {
|
|
41
|
+
throw({forbidden: "Document author must match your username"});
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// For updates to existing documents, deny if not the original author
|
|
48
|
+
if (oldDoc && oldDoc.author && oldDoc.author !== userCtx.name) {
|
|
49
|
+
throw({forbidden: "You can only modify your own documents"});
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Special case for design documents - only admins can modify (handled above)
|
|
53
|
+
if (newDoc._id.startsWith('_design/')) {
|
|
54
|
+
throw({forbidden: "Only admins can modify design documents"});
|
|
55
|
+
}
|
|
56
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
{
|
|
2
|
+
"_id": "_design/getTags",
|
|
3
|
+
"views": {
|
|
4
|
+
"get-tags": {
|
|
5
|
+
"map": "function (doc) {\n if (doc.docType && doc.docType === \"TAG\"\n) {\n for (var cardIndex in doc.taggedCards){\n emit(doc.taggedCards[cardIndex], {\n docType: doc.docType,\n name: doc.name,\n snippit: doc.snippit,\n wiki: '',\n taggedCards: []\n });\n }\n }\n}"
|
|
6
|
+
}
|
|
7
|
+
},
|
|
8
|
+
"language": "javascript"
|
|
9
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Apply post-processing to a course database. Runs continuously.
|
|
3
|
+
* @param courseID
|
|
4
|
+
*/
|
|
5
|
+
export declare function postProcessCourse(courseID: string): void;
|
|
6
|
+
/**
|
|
7
|
+
* Connect to CouchDB, monitor changes to uploaded card data,
|
|
8
|
+
* perform post-processing on uploaded media
|
|
9
|
+
*/
|
|
10
|
+
export default function postProcess(): Promise<void>;
|
|
11
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/attachment-preprocessing/index.ts"],"names":[],"mappings":"AA2BA;;;GAGG;AACH,wBAAgB,iBAAiB,CAAC,QAAQ,EAAE,MAAM,GAAG,IAAI,CA2BxD;AAED;;;GAGG;AACH,wBAA8B,WAAW,IAAI,OAAO,CAAC,IAAI,CAAC,CAoDzD"}
|
|
@@ -0,0 +1,204 @@
|
|
|
1
|
+
import CouchDB from '../couchdb/index.js';
|
|
2
|
+
import { normalize } from './normalize.js';
|
|
3
|
+
import AsyncProcessQueue from '../utils/processQueue.js';
|
|
4
|
+
import logger from '../logger.js';
|
|
5
|
+
import { CourseLookup } from '@vue-skuilder/db';
|
|
6
|
+
import ENV from '../utils/env.js';
|
|
7
|
+
// @ts-expect-error [todo]
|
|
8
|
+
const Q = new AsyncProcessQueue(processDocAttachments);
|
|
9
|
+
/**
|
|
10
|
+
* Apply post-processing to a course database. Runs continuously.
|
|
11
|
+
* @param courseID
|
|
12
|
+
*/
|
|
13
|
+
export function postProcessCourse(courseID) {
|
|
14
|
+
try {
|
|
15
|
+
logger.info(`Following course ${courseID}`);
|
|
16
|
+
const crsString = `coursedb-${courseID}`;
|
|
17
|
+
// Get database instance
|
|
18
|
+
const db = CouchDB.use(crsString);
|
|
19
|
+
const courseFilter = filterFactory(courseID);
|
|
20
|
+
db.changesReader
|
|
21
|
+
.start({
|
|
22
|
+
// feed: 'continuous',
|
|
23
|
+
includeDocs: false,
|
|
24
|
+
})
|
|
25
|
+
.on('change', (change) => {
|
|
26
|
+
courseFilter(change).catch((e) => {
|
|
27
|
+
logger.error(`Error in CourseFilter for ${courseID}: ${e}`);
|
|
28
|
+
});
|
|
29
|
+
})
|
|
30
|
+
.on('error', (err) => {
|
|
31
|
+
logger.error(`Error in changes feed for ${crsString}: ${err}`);
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
catch (e) {
|
|
35
|
+
logger.error(`Error in postProcessCourse: ${e}`);
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Connect to CouchDB, monitor changes to uploaded card data,
|
|
40
|
+
* perform post-processing on uploaded media
|
|
41
|
+
*/
|
|
42
|
+
export default async function postProcess() {
|
|
43
|
+
try {
|
|
44
|
+
logger.info(`Following all course databases for changes...`);
|
|
45
|
+
// Existing behavior for platform-ui courses
|
|
46
|
+
const courses = await CourseLookup.allCourses();
|
|
47
|
+
const processedCourseIds = new Set();
|
|
48
|
+
for (const course of courses) {
|
|
49
|
+
try {
|
|
50
|
+
postProcessCourse(course._id);
|
|
51
|
+
processedCourseIds.add(`coursedb-${course._id}`);
|
|
52
|
+
}
|
|
53
|
+
catch (e) {
|
|
54
|
+
logger.error(`Error processing course ${course._id}: ${e}`);
|
|
55
|
+
throw e;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
// Studio mode: discover additional databases not in coursedb-lookup
|
|
59
|
+
if (ENV.NODE_ENV === 'studio') {
|
|
60
|
+
logger.info('Studio mode detected: scanning for additional course databases...');
|
|
61
|
+
try {
|
|
62
|
+
const allDbs = await CouchDB.db.list();
|
|
63
|
+
const studioDbs = allDbs.filter(db => db.startsWith('coursedb-') &&
|
|
64
|
+
!processedCourseIds.has(db));
|
|
65
|
+
logger.info(`Found ${studioDbs.length} potential studio databases`);
|
|
66
|
+
for (const studioDb of studioDbs) {
|
|
67
|
+
const courseId = studioDb.replace('coursedb-', '');
|
|
68
|
+
try {
|
|
69
|
+
if (await hasCourseConfig(studioDb)) {
|
|
70
|
+
logger.info(`Starting postprocessing for studio database: ${studioDb}`);
|
|
71
|
+
postProcessCourse(courseId);
|
|
72
|
+
}
|
|
73
|
+
else {
|
|
74
|
+
logger.debug(`Skipping ${studioDb}: no course config found`);
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
catch (e) {
|
|
78
|
+
logger.error(`Error processing studio database ${studioDb}: ${e}`);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch (e) {
|
|
83
|
+
logger.error(`Error discovering studio databases: ${e}`);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
catch (e) {
|
|
88
|
+
logger.error(`Error in postProcess: ${e}`);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function filterFactory(courseID) {
|
|
92
|
+
const courseDatabase = CouchDB.use(`coursedb-${courseID}`);
|
|
93
|
+
return async function filterChanges(changeItem) {
|
|
94
|
+
try {
|
|
95
|
+
const docNoAttachments = await courseDatabase.get(changeItem.id, {
|
|
96
|
+
attachments: false,
|
|
97
|
+
});
|
|
98
|
+
if (docNoAttachments._attachments &&
|
|
99
|
+
Object.keys(docNoAttachments._attachments).length > 0 &&
|
|
100
|
+
(docNoAttachments['processed'] === undefined ||
|
|
101
|
+
docNoAttachments['processed'] === false)) {
|
|
102
|
+
const doc = await courseDatabase.get(changeItem.id, {
|
|
103
|
+
attachments: true,
|
|
104
|
+
});
|
|
105
|
+
const processingRequest = {
|
|
106
|
+
courseID,
|
|
107
|
+
docID: doc._id,
|
|
108
|
+
fields: [],
|
|
109
|
+
};
|
|
110
|
+
const atts = doc._attachments;
|
|
111
|
+
for (const attachment in atts) {
|
|
112
|
+
const content_type = atts[attachment]['content_type'];
|
|
113
|
+
logger.info(`Course: ${courseID}\n\tAttachment ${attachment} in:\n\t${doc._id}\n should be processed...`);
|
|
114
|
+
if (content_type.includes('audio')) {
|
|
115
|
+
processingRequest.fields.push({
|
|
116
|
+
name: attachment,
|
|
117
|
+
mimetype: content_type,
|
|
118
|
+
});
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
Q.addRequest(processingRequest);
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
catch (e) {
|
|
125
|
+
logger.error(`Error processing doc ${changeItem.id}: ${e}`);
|
|
126
|
+
}
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
async function processDocAttachments(request) {
|
|
130
|
+
if (request.fields.length == 0) {
|
|
131
|
+
logger.info(`No attachments to process for ${request.docID}`);
|
|
132
|
+
return {
|
|
133
|
+
error: 'No attachments to process',
|
|
134
|
+
ok: true,
|
|
135
|
+
status: 'warning',
|
|
136
|
+
};
|
|
137
|
+
}
|
|
138
|
+
const courseDatabase = CouchDB.use(`coursedb-${request.courseID}`);
|
|
139
|
+
const doc = await courseDatabase.get(request.docID, {
|
|
140
|
+
attachments: true,
|
|
141
|
+
att_encoding_info: true,
|
|
142
|
+
});
|
|
143
|
+
for (const field of request.fields) {
|
|
144
|
+
logger.info(`Converting ${field.name}`);
|
|
145
|
+
const attachment = doc._attachments[field.name].data;
|
|
146
|
+
if (field.mimetype.includes('audio')) {
|
|
147
|
+
try {
|
|
148
|
+
const converted = await normalize(attachment);
|
|
149
|
+
field.returnData = converted;
|
|
150
|
+
}
|
|
151
|
+
catch (e) {
|
|
152
|
+
logger.info(`Exception caught: ${e}`);
|
|
153
|
+
throw e;
|
|
154
|
+
}
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
logger.info('Conversions finished');
|
|
158
|
+
request.fields.forEach((field) => {
|
|
159
|
+
logger.info(`Replacing doc Data for ${field.name}`);
|
|
160
|
+
if (doc['processed']) {
|
|
161
|
+
doc['processed'].push(field.name);
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
doc['processed'] = [field.name];
|
|
165
|
+
}
|
|
166
|
+
doc._attachments[field.name].data = field.returnData;
|
|
167
|
+
});
|
|
168
|
+
// request was a noop.
|
|
169
|
+
// Mark as processed in order to avoid inifinte loop
|
|
170
|
+
if (request.fields.length === 0) {
|
|
171
|
+
doc['processed'] = true;
|
|
172
|
+
}
|
|
173
|
+
const resp = (await courseDatabase.insert(doc));
|
|
174
|
+
resp.status = 'ok';
|
|
175
|
+
logger.info(`Processing request reinsert result: ${JSON.stringify(resp)}`);
|
|
176
|
+
return resp;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Check if a database contains course configuration (indicating it's a valid course database)
|
|
180
|
+
*/
|
|
181
|
+
async function hasCourseConfig(databaseName) {
|
|
182
|
+
try {
|
|
183
|
+
const db = CouchDB.use(databaseName);
|
|
184
|
+
// Try to find a course configuration document
|
|
185
|
+
// Course databases should have documents with course metadata
|
|
186
|
+
const result = await db.find({
|
|
187
|
+
selector: {
|
|
188
|
+
$or: [
|
|
189
|
+
{ 'type': 'course' },
|
|
190
|
+
{ 'shape': { $exists: true } },
|
|
191
|
+
{ 'course_id': { $exists: true } },
|
|
192
|
+
{ 'courseID': { $exists: true } }
|
|
193
|
+
]
|
|
194
|
+
},
|
|
195
|
+
limit: 1
|
|
196
|
+
});
|
|
197
|
+
return result.docs && result.docs.length > 0;
|
|
198
|
+
}
|
|
199
|
+
catch (e) {
|
|
200
|
+
logger.debug(`Error checking course config for ${databaseName}: ${e}`);
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/attachment-preprocessing/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.d.ts","sourceRoot":"","sources":["../../src/attachment-preprocessing/normalize.ts"],"names":[],"mappings":"AAgEA;;;;GAIG;AACH,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAqDjE"}
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
import fs from 'fs';
|
|
2
|
+
import logger from '../logger.js';
|
|
3
|
+
import { promisify } from 'util';
|
|
4
|
+
import { exec as execCallback } from 'child_process';
|
|
5
|
+
const exec = promisify(execCallback);
|
|
6
|
+
import FFMPEGstatic from 'ffmpeg-static';
|
|
7
|
+
if (!FFMPEGstatic) {
|
|
8
|
+
const e = 'FFMPEGstatic executable not found';
|
|
9
|
+
logger.error(e);
|
|
10
|
+
throw new Error(e);
|
|
11
|
+
}
|
|
12
|
+
// string | null here - but we know it's a string from the above check
|
|
13
|
+
const FFMPEG = FFMPEGstatic;
|
|
14
|
+
logger.info(`FFMPEG path: ${FFMPEG}`);
|
|
15
|
+
checkFFMPEGVersion().catch((e) => {
|
|
16
|
+
const msg = 'FFMPEG version check failed';
|
|
17
|
+
logger.error(msg, e);
|
|
18
|
+
throw new Error(msg + e);
|
|
19
|
+
});
|
|
20
|
+
async function checkFFMPEGVersion() {
|
|
21
|
+
try {
|
|
22
|
+
if (!fs.existsSync(FFMPEG)) {
|
|
23
|
+
const e = `FFMPEG executable not found at path: ${FFMPEG}`;
|
|
24
|
+
logger.error(e);
|
|
25
|
+
throw new Error(e);
|
|
26
|
+
}
|
|
27
|
+
const result = await exec(`${FFMPEG} -version`);
|
|
28
|
+
const version = result.stdout.split('\n')[0];
|
|
29
|
+
logger.info(`FFMPEG version: ${version}`);
|
|
30
|
+
// Verify loudnorm filter availability
|
|
31
|
+
const filters = await exec(`${FFMPEG} -filters | grep loudnorm`);
|
|
32
|
+
if (!filters.stdout.includes('loudnorm')) {
|
|
33
|
+
throw new Error('loudnorm filter not available');
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
logger.error('FFMPEG version check failed:', error);
|
|
38
|
+
throw error;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Returns normalized, base-64 encoded mp3
|
|
43
|
+
*
|
|
44
|
+
* @param fileData the base-64 encoded mp3 data from couchdb
|
|
45
|
+
*/
|
|
46
|
+
export async function normalize(fileData) {
|
|
47
|
+
const encoding = 'base64';
|
|
48
|
+
const tmpDir = fs.mkdtempSync(`audioNormalize-${encoding}-`);
|
|
49
|
+
const fileName = tmpDir + '/file.mp3';
|
|
50
|
+
fs.writeFileSync(fileName, fileData, {
|
|
51
|
+
encoding,
|
|
52
|
+
});
|
|
53
|
+
const ext = '.' + fileName.split('.')[1];
|
|
54
|
+
const PADDED = tmpDir + '/padded' + ext;
|
|
55
|
+
const PADDED_NORMALIZED = tmpDir + '/paddedNormalized' + ext;
|
|
56
|
+
const NORMALIZED = tmpDir + '/normalized' + ext;
|
|
57
|
+
try {
|
|
58
|
+
// elongate
|
|
59
|
+
await exec(FFMPEG + ` -i ${fileName} -af "adelay=10000|10000" ${PADDED}`);
|
|
60
|
+
const info = await exec(FFMPEG +
|
|
61
|
+
` -i ${PADDED} -af loudnorm=I=-16:TP=-1.5:LRA=11:print_format=json -f null -`);
|
|
62
|
+
const data = JSON.parse(info.stderr.substring(info.stderr.indexOf('{')));
|
|
63
|
+
// normalize the elongated file
|
|
64
|
+
await exec(FFMPEG +
|
|
65
|
+
` -i ${PADDED} -af ` +
|
|
66
|
+
`loudnorm=I=-16:TP=-1.5:LRA=11:measured_I=${data.input_i}:` +
|
|
67
|
+
`measured_LRA=${data.input_lra}:measured_TP=${data.input_tp}:` +
|
|
68
|
+
`measured_thresh=${data.input_thresh}:offset=${data.target_offset}:linear=true:` +
|
|
69
|
+
`print_format=summary -ar 48k ${PADDED_NORMALIZED}`);
|
|
70
|
+
// cut off the elongated part
|
|
71
|
+
await exec(FFMPEG +
|
|
72
|
+
` -i ${PADDED_NORMALIZED} -ss 00:00:10.000 -acodec copy ${NORMALIZED}`);
|
|
73
|
+
const ret = fs.readFileSync(NORMALIZED, {
|
|
74
|
+
encoding,
|
|
75
|
+
});
|
|
76
|
+
return ret;
|
|
77
|
+
}
|
|
78
|
+
catch (e) {
|
|
79
|
+
logger.error(e);
|
|
80
|
+
throw e;
|
|
81
|
+
}
|
|
82
|
+
finally {
|
|
83
|
+
const files = fs.readdirSync(tmpDir);
|
|
84
|
+
files.forEach((file) => {
|
|
85
|
+
fs.unlinkSync(tmpDir + '/' + file);
|
|
86
|
+
});
|
|
87
|
+
fs.rmdirSync(tmpDir);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
//# sourceMappingURL=normalize.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"normalize.js","sourceRoot":"","sources":["../../src/attachment-preprocessing/normalize.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
import { ClassroomConfig, Status } from '@vue-skuilder/common';
|
|
2
|
+
import AsyncProcessQueue from '../utils/processQueue.js';
|
|
3
|
+
export declare const CLASSROOM_DB_LOOKUP = "classdb-lookup";
|
|
4
|
+
export declare const ClassroomLeaveQueue: AsyncProcessQueue<{
|
|
5
|
+
classID: string;
|
|
6
|
+
} & {
|
|
7
|
+
username: string;
|
|
8
|
+
}, import("@vue-skuilder/common").IServerResponse | null>;
|
|
9
|
+
export declare const ClassroomJoinQueue: AsyncProcessQueue<{
|
|
10
|
+
joinCode: string;
|
|
11
|
+
registerAs: "student" | "teacher" | "aide" | "admin";
|
|
12
|
+
user: string;
|
|
13
|
+
}, {
|
|
14
|
+
errorText?: string;
|
|
15
|
+
status: Status;
|
|
16
|
+
ok: boolean;
|
|
17
|
+
id_course: string;
|
|
18
|
+
course_name: string;
|
|
19
|
+
} | null>;
|
|
20
|
+
export declare const ClassroomCreationQueue: AsyncProcessQueue<ClassroomConfig, {
|
|
21
|
+
status: Status;
|
|
22
|
+
ok: boolean;
|
|
23
|
+
joincode: string;
|
|
24
|
+
uuid: string;
|
|
25
|
+
} | null>;
|
|
26
|
+
//# sourceMappingURL=classroom-requests.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classroom-requests.d.ts","sourceRoot":"","sources":["../../src/client-requests/classroom-requests.ts"],"names":[],"mappings":"AAEA,OAAO,EACL,eAAe,EAIf,MAAM,EACP,MAAM,sBAAsB,CAAC;AAO9B,OAAO,iBAA6B,MAAM,0BAA0B,CAAC;AAGrE,eAAO,MAAM,mBAAmB,mBAAmB,CAAC;AAuMpD,eAAO,MAAM,mBAAmB;;;cAEO,MAAM;yDAE5B,CAAC;AAElB,eAAO,MAAM,kBAAkB;;;;;;;;;;SAIf,CAAC;AAEjB,eAAO,MAAM,sBAAsB;;;;;SAIjB,CAAC"}
|
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
import hashids from 'hashids';
|
|
2
|
+
import { Status, } from '@vue-skuilder/common';
|
|
3
|
+
import { classroomDbDesignDoc } from '../design-docs.js';
|
|
4
|
+
import CouchDB, { docCount, useOrCreateDB, } from '../couchdb/index.js';
|
|
5
|
+
import AsyncProcessQueue from '../utils/processQueue.js';
|
|
6
|
+
import logger from '../logger.js';
|
|
7
|
+
export const CLASSROOM_DB_LOOKUP = 'classdb-lookup';
|
|
8
|
+
const CLASSROOM_CONFIG = 'ClassroomConfig';
|
|
9
|
+
// async function deleteClassroom(_classroom_id: string) {}
|
|
10
|
+
async function getClassID(joinCode) {
|
|
11
|
+
try {
|
|
12
|
+
const doc = await (await useOrCreateDB(CLASSROOM_DB_LOOKUP)).get(joinCode);
|
|
13
|
+
return doc.uuid;
|
|
14
|
+
}
|
|
15
|
+
catch {
|
|
16
|
+
return '';
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
async function getClassroomConfig(id) {
|
|
20
|
+
return (await useOrCreateDB(getClassDBNames(id).studentDB)).get(CLASSROOM_CONFIG);
|
|
21
|
+
}
|
|
22
|
+
async function writeClassroomConfig(config, classID) {
|
|
23
|
+
logger.info(`Writing config for class: ${classID}`);
|
|
24
|
+
const dbNames = getClassDBNames(classID);
|
|
25
|
+
const studentDB = await useOrCreateDB(dbNames.studentDB);
|
|
26
|
+
const teacherDB = await useOrCreateDB(dbNames.teacherDB);
|
|
27
|
+
return Promise.all([
|
|
28
|
+
studentDB
|
|
29
|
+
.get(CLASSROOM_CONFIG)
|
|
30
|
+
.then((doc) => {
|
|
31
|
+
return studentDB.insert({
|
|
32
|
+
_id: CLASSROOM_CONFIG,
|
|
33
|
+
_rev: doc._rev,
|
|
34
|
+
...config,
|
|
35
|
+
});
|
|
36
|
+
})
|
|
37
|
+
.catch((_err) => {
|
|
38
|
+
return studentDB.insert({
|
|
39
|
+
_id: CLASSROOM_CONFIG,
|
|
40
|
+
...config,
|
|
41
|
+
});
|
|
42
|
+
}),
|
|
43
|
+
teacherDB
|
|
44
|
+
.get(CLASSROOM_CONFIG)
|
|
45
|
+
.then((doc) => {
|
|
46
|
+
return teacherDB.insert({
|
|
47
|
+
_id: CLASSROOM_CONFIG,
|
|
48
|
+
_rev: doc._rev,
|
|
49
|
+
...config,
|
|
50
|
+
});
|
|
51
|
+
})
|
|
52
|
+
.catch((_err) => {
|
|
53
|
+
return teacherDB.insert({
|
|
54
|
+
_id: CLASSROOM_CONFIG,
|
|
55
|
+
...config,
|
|
56
|
+
});
|
|
57
|
+
}),
|
|
58
|
+
]);
|
|
59
|
+
}
|
|
60
|
+
function getClassDBNames(classId) {
|
|
61
|
+
return {
|
|
62
|
+
studentDB: `classdb-student-${classId}`,
|
|
63
|
+
teacherDB: `classdb-teacher-${classId}`,
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
async function createClassroom(config) {
|
|
67
|
+
logger.info(`CreateClass Request:
|
|
68
|
+
${JSON.stringify(config)}`);
|
|
69
|
+
const num = (await docCount(CLASSROOM_DB_LOOKUP)) + 1; //
|
|
70
|
+
const uuid = (await CouchDB.uuids(1)).uuids[0];
|
|
71
|
+
const hasher = new hashids('', 6, 'abcdefghijklmnopqrstuvwxyz123456789');
|
|
72
|
+
const studentDbName = `classdb-student-${uuid}`;
|
|
73
|
+
const teacherDbName = `classdb-teacher-${uuid}`;
|
|
74
|
+
config.joinCode = hasher.encode(num);
|
|
75
|
+
const security = {
|
|
76
|
+
// _id: '_security',
|
|
77
|
+
admins: {
|
|
78
|
+
names: [],
|
|
79
|
+
roles: [],
|
|
80
|
+
},
|
|
81
|
+
members: {
|
|
82
|
+
names: config.teachers,
|
|
83
|
+
roles: [],
|
|
84
|
+
},
|
|
85
|
+
};
|
|
86
|
+
const [studentdb, teacherdb, lookup] = await Promise.all([
|
|
87
|
+
useOrCreateDB(studentDbName),
|
|
88
|
+
useOrCreateDB(teacherDbName),
|
|
89
|
+
useOrCreateDB('classdb-lookup'),
|
|
90
|
+
]);
|
|
91
|
+
await Promise.all([
|
|
92
|
+
studentdb.insert({
|
|
93
|
+
validate_doc_update: classroomDbDesignDoc,
|
|
94
|
+
}, '_design/_auth'),
|
|
95
|
+
// studentdb.insert(security, '_security'),
|
|
96
|
+
teacherdb.insert(security, '_security'),
|
|
97
|
+
lookup.insert({
|
|
98
|
+
num,
|
|
99
|
+
uuid,
|
|
100
|
+
}, config.joinCode),
|
|
101
|
+
writeClassroomConfig(config, uuid),
|
|
102
|
+
]);
|
|
103
|
+
const res = {
|
|
104
|
+
ok: true,
|
|
105
|
+
status: 'ok',
|
|
106
|
+
};
|
|
107
|
+
const ret = {
|
|
108
|
+
joincode: config.joinCode,
|
|
109
|
+
uuid: uuid,
|
|
110
|
+
...res,
|
|
111
|
+
};
|
|
112
|
+
logger.info(JSON.stringify(ret));
|
|
113
|
+
return ret;
|
|
114
|
+
}
|
|
115
|
+
async function leaveClassroom(req) {
|
|
116
|
+
const cfg = await getClassroomConfig(req.classID);
|
|
117
|
+
if (cfg) {
|
|
118
|
+
const index = cfg.students.indexOf(req.username);
|
|
119
|
+
if (index !== -1) {
|
|
120
|
+
cfg.students.splice(index, 1);
|
|
121
|
+
}
|
|
122
|
+
await writeClassroomConfig(cfg, req.classID);
|
|
123
|
+
return {
|
|
124
|
+
status: Status.ok,
|
|
125
|
+
ok: true,
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
else {
|
|
129
|
+
return {
|
|
130
|
+
status: Status.error,
|
|
131
|
+
ok: false,
|
|
132
|
+
errorText: 'Course with this ID not found.',
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
async function joinClassroom(req) {
|
|
137
|
+
const classID = await getClassID(req.joinCode);
|
|
138
|
+
if (classID) {
|
|
139
|
+
const classDBNames = getClassDBNames(classID);
|
|
140
|
+
void (await useOrCreateDB(classDBNames.studentDB)).get('ClassroomConfig');
|
|
141
|
+
logger.info(`joinClassroom running...
|
|
142
|
+
\tRequest: ${JSON.stringify(req)}`);
|
|
143
|
+
const cfg = await getClassroomConfig(classID);
|
|
144
|
+
if (req.registerAs === 'student') {
|
|
145
|
+
if (cfg.students.indexOf(req.user) === -1) {
|
|
146
|
+
cfg.students.push(req.user);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
await writeClassroomConfig(cfg, classID);
|
|
150
|
+
const res = {
|
|
151
|
+
ok: true,
|
|
152
|
+
status: Status.ok,
|
|
153
|
+
id_course: classID,
|
|
154
|
+
course_name: cfg.name,
|
|
155
|
+
};
|
|
156
|
+
return res;
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
return {
|
|
160
|
+
ok: false,
|
|
161
|
+
status: Status.error,
|
|
162
|
+
id_course: '',
|
|
163
|
+
course_name: '',
|
|
164
|
+
errorText: 'No course found with this joincode!',
|
|
165
|
+
};
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
export const ClassroomLeaveQueue = new AsyncProcessQueue(leaveClassroom);
|
|
169
|
+
export const ClassroomJoinQueue = new AsyncProcessQueue(joinClassroom);
|
|
170
|
+
export const ClassroomCreationQueue = new AsyncProcessQueue(createClassroom);
|
|
171
|
+
//# sourceMappingURL=classroom-requests.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"classroom-requests.js","sourceRoot":"","sources":["../../src/client-requests/classroom-requests.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { CreateCourse } from '@vue-skuilder/common';
|
|
2
|
+
import AsyncProcessQueue from '../utils/processQueue.js';
|
|
3
|
+
export declare function initCourseDBDesignDocInsert(): Promise<void>;
|
|
4
|
+
export type CreateCourseResp = CreateCourse['response'];
|
|
5
|
+
export declare const CourseCreationQueue: AsyncProcessQueue<import("@vue-skuilder/common").CourseConfig, {
|
|
6
|
+
status: import("@vue-skuilder/common").Status;
|
|
7
|
+
ok: boolean;
|
|
8
|
+
courseID: string;
|
|
9
|
+
} | null>;
|
|
10
|
+
//# sourceMappingURL=course-requests.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"course-requests.d.ts","sourceRoot":"","sources":["../../src/client-requests/course-requests.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AAGpD,OAAO,iBAA6B,MAAM,0BAA0B,CAAC;AAgDrE,wBAAsB,2BAA2B,IAAI,OAAO,CAAC,IAAI,CAAC,CA4CjE;AAqFD,MAAM,MAAM,gBAAgB,GAAG,YAAY,CAAC,UAAU,CAAC,CAAC;AAExD,eAAO,MAAM,mBAAmB;;;;SAIjB,CAAC"}
|