@learnpack/learnpack 5.0.319 → 5.0.322

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.
@@ -10,7 +10,7 @@
10
10
  />
11
11
 
12
12
  <title>Learnpack Creator: Craft tutorials in seconds!</title>
13
- <script type="module" crossorigin src="/creator/assets/index-XZDcEWl9.js"></script>
13
+ <script type="module" crossorigin src="/creator/assets/index-BhqDgBS9.js"></script>
14
14
  <link rel="stylesheet" crossorigin href="/creator/assets/index-CjddKHB_.css">
15
15
  </head>
16
16
  <body>
@@ -4,5 +4,5 @@ type TNeededPlugins = {
4
4
  notInstalled: string[];
5
5
  };
6
6
  export declare const checkNotInstalledPlugins: (exercises: IExercise[], installedPlugins: string[], command: any) => Promise<TNeededPlugins>;
7
- export declare const checkNotInstalledDependencies: (neededPlugins: string[]) => Promise<boolean | undefined>;
7
+ export declare const checkNotInstalledDependencies: (neededPlugins: string[]) => Promise<boolean>;
8
8
  export {};
@@ -114,18 +114,47 @@ const installDependencies = async (deps, packageManager) => {
114
114
  else if (packageManager === "pip") {
115
115
  command = `pip install ${deps.join(" ")}`;
116
116
  }
117
- const { stdout, stderr } = await exec(command);
118
- if (stderr && (stderr.includes("npm ERR!") || stderr.includes("Traceback"))) {
119
- console_1.default.error(`Error executing ${command}.`);
120
- console_1.default.error(stderr);
121
- return;
117
+ try {
118
+ const { stdout, stderr } = await exec(command);
119
+ if (stderr &&
120
+ (stderr.includes("npm ERR!") || stderr.includes("Traceback"))) {
121
+ console_1.default.error(`Error executing ${command}.`);
122
+ console_1.default.error(stderr);
123
+ return;
124
+ }
125
+ console_1.default.info(`Dependencies ${deps.join(" ")} installed...`);
126
+ return true;
127
+ }
128
+ catch (error) {
129
+ // Si npm/pip retorna código > 0, exec lanzará una excepción
130
+ const execError = error;
131
+ const stdout = execError.stdout || "";
132
+ const stderr = execError.stderr || "";
133
+ const errorMessage = stderr || execError.message || String(error);
134
+ // Verificar si es un error real
135
+ if (errorMessage.includes("npm ERR!") ||
136
+ errorMessage.includes("Traceback")) {
137
+ console_1.default.error(`Error executing ${command}.`);
138
+ console_1.default.error(errorMessage);
139
+ return;
140
+ }
141
+ // Si no es un error real, podría ser solo un warning
142
+ // Verificar si la instalación fue exitosa a pesar del warning
143
+ if (stdout &&
144
+ (stdout.includes("added") || stdout.includes("Successfully installed"))) {
145
+ console_1.default.info(`Dependencies ${deps.join(" ")} installed...`);
146
+ return true;
147
+ }
148
+ // Si no hay indicios de éxito, se asume fallo (retorna undefined implícitamente)
149
+ console_1.default.debug(`${command} returned non-zero exit code, but may be just a warning:`, errorMessage);
122
150
  }
123
- console_1.default.info(`Dependencies ${deps.join(" ")} installed...`);
124
- return true;
125
151
  };
126
152
  const checkNotInstalledDependencies = async (neededPlugins) => {
127
153
  console_1.default.info("Checking needed dependencies...");
128
- const jsPluginsDependencies = ["jest@29.7.0", "jest-environment-jsdom@29.7.0"];
154
+ const jsPluginsDependencies = [
155
+ "jest@29.7.0",
156
+ "jest-environment-jsdom@29.7.0",
157
+ ];
129
158
  // pytest up to 6.2.5
130
159
  const pyPluginsDependencies = ["pytest", "pytest-testdox", "mock"];
131
160
  const npmLsCommand = "npm ls jest jest-environment-jsdom -g";
@@ -141,14 +170,29 @@ const checkNotInstalledDependencies = async (neededPlugins) => {
141
170
  pytestNeeded = true;
142
171
  }
143
172
  if (jestNeeded) {
144
- const { stdout, stderr } = await exec("npm ls -g");
145
- if (stderr) {
146
- console_1.default.error(`Error executing ${npmLsCommand}. Use debug for more info`);
147
- console_1.default.debug(stderr);
148
- return false;
173
+ try {
174
+ const { stdout, stderr } = await exec("npm ls -g");
175
+ // Solo considerar errores reales, no warnings
176
+ if (stderr && stderr.includes("npm ERR!")) {
177
+ console_1.default.error(`Error executing npm ls -g. Use debug for more info`);
178
+ console_1.default.debug(stderr);
179
+ return false;
180
+ }
181
+ if (includesAll(stdout, jsPluginsDependencies))
182
+ return true;
183
+ }
184
+ catch (error) {
185
+ // Si npm retorna código > 0, exec lanzará una excepción
186
+ // Verificar si es un error real o solo un warning
187
+ const errorMessage = (error === null || error === void 0 ? void 0 : error.stderr) || (error === null || error === void 0 ? void 0 : error.message) || String(error);
188
+ if (errorMessage.includes("npm ERR!")) {
189
+ console_1.default.error(`Error executing npm ls -g. Use debug for more info`);
190
+ console_1.default.debug(errorMessage);
191
+ return false;
192
+ }
193
+ // Si no es un error real, continuar (podría ser solo un warning)
194
+ console_1.default.debug("npm ls -g returned non-zero exit code, but may be just a warning:", errorMessage);
149
195
  }
150
- if (includesAll(stdout, jsPluginsDependencies))
151
- return true;
152
196
  console_1.default.error("The jest dependencies are not installed");
153
197
  const confirmInstall = await cli_ux_1.cli.confirm("Do you want to install the needed dependencies? (y/n)");
154
198
  if (!confirmInstall) {
@@ -167,14 +211,28 @@ const checkNotInstalledDependencies = async (neededPlugins) => {
167
211
  console_1.default.error("Error upgrading pip. Please install pip manually, run: pip install --upgrade pip");
168
212
  console_1.default.debug(error);
169
213
  }
170
- const { stdout, stderr } = await exec("pip list");
171
- if (stderr) {
172
- console_1.default.error(`Error executing pip list. Use debug for more info`);
173
- console_1.default.debug(stderr);
174
- return;
214
+ try {
215
+ const { stdout, stderr } = await exec("pip list");
216
+ // Solo considerar errores reales, no warnings
217
+ if (stderr && stderr.includes("Traceback")) {
218
+ console_1.default.error(`Error executing pip list. Use debug for more info`);
219
+ console_1.default.debug(stderr);
220
+ return false;
221
+ }
222
+ if (includesAll(stdout, pyPluginsDependencies))
223
+ return true;
224
+ }
225
+ catch (error) {
226
+ // Si pip retorna código > 0, verificar si es un error real
227
+ const errorMessage = (error === null || error === void 0 ? void 0 : error.stderr) || (error === null || error === void 0 ? void 0 : error.message) || String(error);
228
+ if (errorMessage.includes("Traceback")) {
229
+ console_1.default.error(`Error executing pip list. Use debug for more info`);
230
+ console_1.default.debug(errorMessage);
231
+ return false;
232
+ }
233
+ // Si no es un error real, continuar
234
+ console_1.default.debug("pip list returned non-zero exit code, but may be just a warning:", errorMessage);
175
235
  }
176
- if (includesAll(stdout, pyPluginsDependencies))
177
- return true;
178
236
  console_1.default.error("The pytest dependencies are not installed");
179
237
  const confirmInstall = await cli_ux_1.cli.confirm("Do you want to install the needed dependencies? (y/n)");
180
238
  if (!confirmInstall) {
@@ -0,0 +1,97 @@
1
+ import { Request, Response, NextFunction } from "express";
2
+ /**
3
+ * Interface for application errors with additional information
4
+ */
5
+ export interface AppError extends Error {
6
+ statusCode?: number;
7
+ code?: string;
8
+ isOperational?: boolean;
9
+ details?: any;
10
+ }
11
+ /**
12
+ * Base class for operational errors (expected errors)
13
+ */
14
+ export declare class OperationalError extends Error implements AppError {
15
+ statusCode: number;
16
+ code: string;
17
+ isOperational: boolean;
18
+ details?: any;
19
+ constructor(message: string, details?: any, statusCode?: number, code?: string);
20
+ }
21
+ /**
22
+ * Validation error (400)
23
+ */
24
+ export declare class ValidationError extends OperationalError {
25
+ constructor(message: string, details?: any);
26
+ }
27
+ /**
28
+ * Authentication error (401)
29
+ */
30
+ export declare class UnauthorizedError extends OperationalError {
31
+ constructor(message: string, details?: any);
32
+ }
33
+ /**
34
+ * Authorization error (403)
35
+ */
36
+ export declare class ForbiddenError extends OperationalError {
37
+ constructor(message: string, details?: any);
38
+ }
39
+ /**
40
+ * Resource not found error (404)
41
+ */
42
+ export declare class NotFoundError extends OperationalError {
43
+ constructor(message: string, details?: any);
44
+ }
45
+ /**
46
+ * Conflict error (409)
47
+ */
48
+ export declare class ConflictError extends OperationalError {
49
+ constructor(message: string, details?: any);
50
+ }
51
+ /**
52
+ * Internal server error (500)
53
+ */
54
+ export declare class InternalServerError extends OperationalError {
55
+ constructor(message: string, details?: any);
56
+ }
57
+ /**
58
+ * Wrapper for async handlers that automatically catches errors
59
+ *
60
+ * Usage:
61
+ * app.get('/route', asyncHandler(async (req, res) => {
62
+ * // your async code here
63
+ * }))
64
+ * @param fn - Async handler function to wrap
65
+ * @returns Express middleware that automatically catches errors
66
+ */
67
+ export declare const asyncHandler: (fn: (req: Request, res: Response, next: NextFunction) => Promise<any>) => (req: Request, res: Response, next: NextFunction) => void;
68
+ /**
69
+ * Middleware to handle not found routes (404)
70
+ * Must be placed after all routes but before the error handler
71
+ * @param req - Express Request object
72
+ * @param res - Express Response object
73
+ * @param next - Express next function
74
+ * @returns void
75
+ */
76
+ export declare const notFoundHandler: (req: Request, res: Response, next: NextFunction) => void;
77
+ /**
78
+ * Global error handling middleware
79
+ * Must be the last middleware in the chain
80
+ *
81
+ * Catches all unhandled synchronous and asynchronous errors
82
+ * @param error - The caught error
83
+ * @param req - Express Request object
84
+ * @param res - Express Response object
85
+ * @param next - Express next function
86
+ * @returns void
87
+ */
88
+ export declare const errorHandler: (error: AppError | Error, req: Request, res: Response, next: NextFunction) => void;
89
+ /**
90
+ * Helper to quickly create operational errors
91
+ * @param message - Error message
92
+ * @param details - Additional error details
93
+ * @param statusCode - HTTP status code
94
+ * @param code - Custom error code
95
+ * @returns New OperationalError instance
96
+ */
97
+ export declare const createError: (message: string, details?: any, statusCode?: number, code?: string) => OperationalError;
@@ -0,0 +1,239 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createError = exports.errorHandler = exports.notFoundHandler = exports.asyncHandler = exports.InternalServerError = exports.ConflictError = exports.NotFoundError = exports.ForbiddenError = exports.UnauthorizedError = exports.ValidationError = exports.OperationalError = void 0;
4
+ /**
5
+ * Base class for operational errors (expected errors)
6
+ */
7
+ class OperationalError extends Error {
8
+ constructor(message, details, statusCode = 500, code = "OPERATIONAL_ERROR") {
9
+ super(message);
10
+ this.name = this.constructor.name;
11
+ this.statusCode = statusCode;
12
+ this.code = code;
13
+ this.isOperational = true;
14
+ this.details = details;
15
+ // Maintains correct stack trace
16
+ Error.captureStackTrace(this, this.constructor);
17
+ }
18
+ }
19
+ exports.OperationalError = OperationalError;
20
+ /**
21
+ * Validation error (400)
22
+ */
23
+ class ValidationError extends OperationalError {
24
+ constructor(message, details) {
25
+ super(message, details, 400, "VALIDATION_ERROR");
26
+ }
27
+ }
28
+ exports.ValidationError = ValidationError;
29
+ /**
30
+ * Authentication error (401)
31
+ */
32
+ class UnauthorizedError extends OperationalError {
33
+ constructor(message, details) {
34
+ super(message, details, 401, "UNAUTHORIZED");
35
+ }
36
+ }
37
+ exports.UnauthorizedError = UnauthorizedError;
38
+ /**
39
+ * Authorization error (403)
40
+ */
41
+ class ForbiddenError extends OperationalError {
42
+ constructor(message, details) {
43
+ super(message, details, 403, "FORBIDDEN");
44
+ }
45
+ }
46
+ exports.ForbiddenError = ForbiddenError;
47
+ /**
48
+ * Resource not found error (404)
49
+ */
50
+ class NotFoundError extends OperationalError {
51
+ constructor(message, details) {
52
+ super(message, details, 404, "NOT_FOUND");
53
+ }
54
+ }
55
+ exports.NotFoundError = NotFoundError;
56
+ /**
57
+ * Conflict error (409)
58
+ */
59
+ class ConflictError extends OperationalError {
60
+ constructor(message, details) {
61
+ super(message, details, 409, "CONFLICT");
62
+ }
63
+ }
64
+ exports.ConflictError = ConflictError;
65
+ /**
66
+ * Internal server error (500)
67
+ */
68
+ class InternalServerError extends OperationalError {
69
+ constructor(message, details) {
70
+ super(message, details, 500, "INTERNAL_SERVER_ERROR");
71
+ }
72
+ }
73
+ exports.InternalServerError = InternalServerError;
74
+ /**
75
+ * Determines if an error is operational (expected) or programming (unexpected)
76
+ * @param error - The error to check
77
+ * @returns true if the error is operational, false otherwise
78
+ */
79
+ function isOperationalError(error) {
80
+ if (error instanceof OperationalError) {
81
+ return error.isOperational === true;
82
+ }
83
+ return false;
84
+ }
85
+ /**
86
+ * Formats the error for HTTP response
87
+ * @param error - The error to format
88
+ * @param isDevelopment - Whether in development mode
89
+ * @returns Object with the formatted response
90
+ */
91
+ function formatError(error, isDevelopment = false) {
92
+ const isOperational = isOperationalError(error);
93
+ const appError = error;
94
+ const baseResponse = {
95
+ status: "error",
96
+ message: appError.message || "An unexpected error occurred",
97
+ code: appError.code || "INTERNAL_ERROR",
98
+ };
99
+ // In development, include more details
100
+ if (isDevelopment) {
101
+ baseResponse.stack = appError.stack;
102
+ baseResponse.details = appError.details;
103
+ }
104
+ // If it's an operational error, include details if they exist
105
+ if (isOperational && appError.details) {
106
+ baseResponse.details = appError.details;
107
+ }
108
+ // If not operational, don't expose details in production
109
+ if (!isOperational && !isDevelopment) {
110
+ baseResponse.message = "An unexpected error occurred";
111
+ baseResponse.code = "INTERNAL_ERROR";
112
+ }
113
+ return baseResponse;
114
+ }
115
+ /**
116
+ * Determines the appropriate HTTP status code
117
+ * @param error - The error from which to get the status code
118
+ * @returns The HTTP status code
119
+ */
120
+ function getStatusCode(error) {
121
+ if (error.statusCode) {
122
+ return error.statusCode;
123
+ }
124
+ // Common Node.js errors
125
+ if (error.name === "ValidationError")
126
+ return 400;
127
+ if (error.name === "UnauthorizedError")
128
+ return 401;
129
+ if (error.name === "ForbiddenError")
130
+ return 403;
131
+ if (error.name === "NotFoundError")
132
+ return 404;
133
+ if (error.name === "ConflictError")
134
+ return 409;
135
+ // Default to server error
136
+ return 500;
137
+ }
138
+ /**
139
+ * Logs the error in a structured format
140
+ * @param error - The error to log
141
+ * @param req - Express Request object
142
+ * @returns void
143
+ */
144
+ function logError(error, req) {
145
+ const appError = error;
146
+ const isOperational = isOperationalError(error);
147
+ const logData = {
148
+ timestamp: new Date().toISOString(),
149
+ method: req.method,
150
+ url: req.originalUrl,
151
+ statusCode: getStatusCode(error),
152
+ error: {
153
+ name: error.name,
154
+ message: error.message,
155
+ code: appError.code,
156
+ isOperational,
157
+ stack: error.stack,
158
+ details: appError.details,
159
+ },
160
+ ip: req.ip || req.socket.remoteAddress,
161
+ userAgent: req.get("user-agent"),
162
+ };
163
+ // Different log based on error type
164
+ if (isOperational) {
165
+ console.error("⚠️ Operational Error:", JSON.stringify(logData, null, 2));
166
+ }
167
+ else {
168
+ console.error("❌ Unexpected Error:", JSON.stringify(logData, null, 2));
169
+ }
170
+ }
171
+ /**
172
+ * Wrapper for async handlers that automatically catches errors
173
+ *
174
+ * Usage:
175
+ * app.get('/route', asyncHandler(async (req, res) => {
176
+ * // your async code here
177
+ * }))
178
+ * @param fn - Async handler function to wrap
179
+ * @returns Express middleware that automatically catches errors
180
+ */
181
+ const asyncHandler = (fn) => {
182
+ return (req, res, next) => {
183
+ Promise.resolve(fn(req, res, next)).catch(next);
184
+ };
185
+ };
186
+ exports.asyncHandler = asyncHandler;
187
+ /**
188
+ * Middleware to handle not found routes (404)
189
+ * Must be placed after all routes but before the error handler
190
+ * @param req - Express Request object
191
+ * @param res - Express Response object
192
+ * @param next - Express next function
193
+ * @returns void
194
+ */
195
+ const notFoundHandler = (req, res, next) => {
196
+ const error = new NotFoundError(`Route ${req.method} ${req.originalUrl} not found`);
197
+ next(error);
198
+ };
199
+ exports.notFoundHandler = notFoundHandler;
200
+ /**
201
+ * Global error handling middleware
202
+ * Must be the last middleware in the chain
203
+ *
204
+ * Catches all unhandled synchronous and asynchronous errors
205
+ * @param error - The caught error
206
+ * @param req - Express Request object
207
+ * @param res - Express Response object
208
+ * @param next - Express next function
209
+ * @returns void
210
+ */
211
+ const errorHandler = (error, req, res, next) => {
212
+ // If response already sent, delegate to Express default handler
213
+ if (res.headersSent) {
214
+ return next(error);
215
+ }
216
+ // Determine if we're in development mode
217
+ const isDevelopment = process.env.NODE_ENV === "development" || process.env.DEBUG === "true";
218
+ // Log the error
219
+ logError(error, req);
220
+ // Get status code
221
+ const statusCode = getStatusCode(error);
222
+ // Format response
223
+ const response = formatError(error, isDevelopment);
224
+ // Send response
225
+ res.status(statusCode).json(response);
226
+ };
227
+ exports.errorHandler = errorHandler;
228
+ /**
229
+ * Helper to quickly create operational errors
230
+ * @param message - Error message
231
+ * @param details - Additional error details
232
+ * @param statusCode - HTTP status code
233
+ * @param code - Custom error code
234
+ * @returns New OperationalError instance
235
+ */
236
+ const createError = (message, details, statusCode, code) => {
237
+ return new OperationalError(message, details, statusCode || 500, code || "OPERATIONAL_ERROR");
238
+ };
239
+ exports.createError = createError;
@@ -327,7 +327,7 @@ const addInteractivity = async (token, inputs, webhookUrl) => {
327
327
  exports.addInteractivity = addInteractivity;
328
328
  const generateCodeChallenge = async (token, inputs, webhookUrl) => {
329
329
  try {
330
- const response = await axios_1.default.post(`${api_1.RIGOBOT_HOST}/v1/prompting/completion/generate-code-challenge-files/`, {
330
+ const response = await axios_1.default.post(`${api_1.RIGOBOT_HOST}/v1/prompting/completion/create-structured-coding-filles/`, {
331
331
  inputs,
332
332
  include_purpose_objective: false,
333
333
  execute_async: !!webhookUrl,
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@learnpack/learnpack",
3
3
  "description": "Seamlessly build, sell and/or take interactive & auto-graded tutorials, start learning now or build a new tutorial to your audience.",
4
- "version": "5.0.319",
4
+ "version": "5.0.322",
5
5
  "author": "Alejandro Sanchez @alesanchezr",
6
6
  "contributors": [
7
7
  {