@learnpack/learnpack 2.1.26 → 2.1.28

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.
Files changed (56) hide show
  1. package/README.md +10 -10
  2. package/lib/commands/start.js +15 -4
  3. package/lib/managers/file.d.ts +1 -0
  4. package/lib/managers/file.js +8 -1
  5. package/lib/managers/server/routes.js +48 -14
  6. package/lib/managers/session.d.ts +1 -1
  7. package/lib/managers/session.js +39 -12
  8. package/lib/managers/socket.d.ts +1 -1
  9. package/lib/managers/socket.js +57 -43
  10. package/lib/models/action.d.ts +1 -1
  11. package/lib/models/config.d.ts +1 -1
  12. package/lib/models/exercise-obj.d.ts +3 -0
  13. package/lib/models/session.d.ts +4 -1
  14. package/lib/models/socket.d.ts +7 -6
  15. package/lib/models/status.d.ts +1 -1
  16. package/lib/utils/api.d.ts +2 -0
  17. package/lib/utils/api.js +51 -6
  18. package/oclif.manifest.json +1 -1
  19. package/package.json +3 -1
  20. package/src/commands/audit.ts +113 -113
  21. package/src/commands/clean.ts +10 -10
  22. package/src/commands/download.ts +18 -18
  23. package/src/commands/init.ts +39 -39
  24. package/src/commands/login.ts +13 -13
  25. package/src/commands/logout.ts +9 -9
  26. package/src/commands/publish.ts +25 -25
  27. package/src/commands/start.ts +101 -75
  28. package/src/commands/test.ts +34 -34
  29. package/src/managers/config/allowed_files.ts +2 -2
  30. package/src/managers/config/defaults.ts +2 -2
  31. package/src/managers/config/exercise.ts +79 -79
  32. package/src/managers/config/index.ts +145 -145
  33. package/src/managers/file.ts +74 -65
  34. package/src/managers/server/index.ts +32 -31
  35. package/src/managers/server/routes.ts +139 -90
  36. package/src/managers/session.ts +53 -24
  37. package/src/managers/socket.ts +92 -79
  38. package/src/models/action.ts +8 -1
  39. package/src/models/config-manager.ts +2 -2
  40. package/src/models/config.ts +7 -2
  41. package/src/models/exercise-obj.ts +6 -3
  42. package/src/models/plugin-config.ts +2 -2
  43. package/src/models/session.ts +5 -2
  44. package/src/models/socket.ts +12 -6
  45. package/src/models/status.ts +15 -14
  46. package/src/plugin/command/compile.ts +10 -10
  47. package/src/plugin/command/test.ts +14 -14
  48. package/src/plugin/index.ts +5 -5
  49. package/src/plugin/plugin.ts +26 -26
  50. package/src/plugin/utils.ts +23 -23
  51. package/src/utils/BaseCommand.ts +16 -16
  52. package/src/utils/api.ts +143 -91
  53. package/src/utils/audit.ts +93 -96
  54. package/src/utils/exercisesQueue.ts +15 -15
  55. package/src/utils/fileQueue.ts +85 -85
  56. package/src/utils/watcher.ts +14 -14
@@ -1,5 +1,5 @@
1
- import * as shell from "shelljs";
2
- import { IPluginConfig } from "../models/plugin-config";
1
+ import * as shell from "shelljs"
2
+ import { IPluginConfig } from "../models/plugin-config"
3
3
  /**
4
4
  * Main Plugin Runner, it defines the behavior of a learnpack plugin
5
5
  * dividing it in "actions" like: Compile, test, etc.
@@ -7,88 +7,88 @@ import { IPluginConfig } from "../models/plugin-config";
7
7
  */
8
8
  export default (pluginConfig: IPluginConfig) => {
9
9
  return async (args: any) => {
10
- const { action, exercise, socket, configuration } = args;
10
+ const { action, exercise, socket, configuration } = args
11
11
 
12
12
  if (pluginConfig.language === undefined)
13
- throw new Error(`Missing language on the plugin configuration object`);
13
+ throw new Error(`Missing language on the plugin configuration object`)
14
14
 
15
15
  if (typeof action !== "string") {
16
- throw new TypeError("Missing action property on hook details");
16
+ throw new TypeError("Missing action property on hook details")
17
17
  }
18
18
 
19
19
  if (!exercise || exercise === undefined) {
20
- throw new Error("Missing exercise information");
20
+ throw new Error("Missing exercise information")
21
21
  }
22
22
 
23
23
  type actionType = "compile" | "test";
24
24
 
25
25
  // if the action does not exist I don't do anything
26
26
  if (pluginConfig[action as actionType] === undefined) {
27
- console.log(`Ignoring ${action}`);
28
- return () => null;
27
+ console.log(`Ignoring ${action}`)
28
+ return () => null
29
29
  }
30
30
 
31
31
  // ignore if the plugin language its not the same as the exercise language
32
32
  if (exercise.language !== pluginConfig.language) {
33
- return () => null;
33
+ return () => null
34
34
  }
35
35
 
36
36
  if (!exercise.files || exercise.files.length === 0) {
37
- throw new Error(`No files to process`);
37
+ throw new Error(`No files to process`)
38
38
  }
39
39
 
40
40
  try {
41
- const _action = pluginConfig[action as actionType];
41
+ const _action = pluginConfig[action as actionType]
42
42
 
43
43
  if (_action === null || typeof _action !== "object")
44
44
  throw new Error(
45
45
  `The ${pluginConfig.language} ${action} module must export an object configuration`
46
- );
46
+ )
47
47
  if (_action.validate === undefined)
48
48
  throw new Error(
49
49
  `Missing validate method for ${pluginConfig.language} ${action}`
50
- );
50
+ )
51
51
  if (_action.run === undefined)
52
52
  throw new Error(
53
53
  `Missing run method for ${pluginConfig.language} ${action}`
54
- );
54
+ )
55
55
  if (_action.dependencies !== undefined) {
56
56
  if (!Array.isArray(_action.dependencies))
57
57
  throw new Error(
58
58
  `${action}.dependencies must be an array of package names`
59
- );
59
+ )
60
60
 
61
61
  for (const packageName of _action.dependencies) {
62
62
  if (!shell.which(packageName)) {
63
63
  throw new Error(
64
64
  `🚫 You need to have ${packageName} installed to run test the exercises`
65
- );
65
+ )
66
66
  }
67
67
  }
68
68
  }
69
69
 
70
- const valid = await _action.validate({ exercise, configuration });
70
+ const valid = await _action.validate({ exercise, configuration })
71
71
  if (valid) {
72
72
  // look for the command standard implementation and execute it
73
- const execute = require("./command/" + action + ".js").default;
73
+ const execute = require("./command/" + action + ".js").default
74
74
  // no matter the command, the response must always be a stdout
75
75
  const stdout = await execute({
76
76
  ...args,
77
77
  action: _action,
78
78
  configuration,
79
- });
79
+ })
80
80
 
81
81
  // Map the action names to socket messaging standards
82
- const actionToSuccessMapper = { compile: "compiler", test: "testing" };
82
+ const actionToSuccessMapper = { compile: "compiler", test: "testing" }
83
83
 
84
- socket.success(actionToSuccessMapper[action as actionType], stdout);
85
- return stdout;
84
+ socket.success(actionToSuccessMapper[action as actionType], stdout)
85
+ return stdout
86
86
  }
87
87
  } catch (error: any) {
88
88
  if (error.type === undefined)
89
- socket.fatal(error);
89
+ socket.fatal(error)
90
90
  else
91
- socket.error(error.type, error.stdout);
91
+ socket.error(error.type, error.stdout)
92
92
  }
93
- };
94
- };
93
+ }
94
+ }
@@ -1,74 +1,74 @@
1
- import * as chalk from "chalk";
1
+ import * as chalk from "chalk"
2
2
 
3
3
  const getMatches = (reg: RegExp, content: string) => {
4
- const inputs = [];
5
- let m;
4
+ const inputs = []
5
+ let m
6
6
  while ((m = reg.exec(content)) !== null) {
7
7
  // This is necessary to avoid infinite loops with zero-width matches
8
8
  if (m.index === reg.lastIndex)
9
- reg.lastIndex++;
9
+ reg.lastIndex++
10
10
 
11
11
  // The result can be accessed through the `m`-variable.
12
- inputs.push(m[1] || null);
12
+ inputs.push(m[1] || null)
13
13
  }
14
14
 
15
- return inputs;
16
- };
15
+ return inputs
16
+ }
17
17
 
18
18
  const cleanStdout = (buffer: string, inputs: string[]) => {
19
19
  if (Array.isArray(inputs))
20
20
  for (let i = 0; i < inputs.length; i++)
21
21
  if (inputs[i])
22
- buffer = buffer.replace(inputs[i], "");
22
+ buffer = buffer.replace(inputs[i], "")
23
23
 
24
- return buffer;
25
- };
24
+ return buffer
25
+ }
26
26
 
27
27
  const indent = (string: string, options: any, count = 1) => {
28
28
  options = {
29
29
  indent: " ",
30
30
  includeEmptyLines: false,
31
31
  ...options,
32
- };
32
+ }
33
33
 
34
34
  if (typeof string !== "string") {
35
35
  throw new TypeError(
36
36
  `Expected \`input\` to be a \`string\`, got \`${typeof string}\``
37
- );
37
+ )
38
38
  }
39
39
 
40
40
  if (typeof count !== "number") {
41
41
  throw new TypeError(
42
42
  `Expected \`count\` to be a \`number\`, got \`${typeof count}\``
43
- );
43
+ )
44
44
  }
45
45
 
46
46
  if (count < 0) {
47
47
  throw new RangeError(
48
48
  `Expected \`count\` to be at least 0, got \`${count}\``
49
- );
49
+ )
50
50
  }
51
51
 
52
52
  if (typeof options.indent !== "string") {
53
53
  throw new TypeError(
54
54
  `Expected \`options.indent\` to be a \`string\`, got \`${typeof options.indent}\``
55
- );
55
+ )
56
56
  }
57
57
 
58
58
  if (count === 0) {
59
- return string;
59
+ return string
60
60
  }
61
61
 
62
- const regex = options.includeEmptyLines ? /^/gm : /^(?!\s*$)/gm;
62
+ const regex = options.includeEmptyLines ? /^/gm : /^(?!\s*$)/gm
63
63
 
64
- return string.replace(regex, options.indent.repeat(count));
65
- };
64
+ return string.replace(regex, options.indent.repeat(count))
65
+ }
66
66
 
67
67
  const Console = {
68
68
  // _debug: true,
69
69
  _debug: process.env.DEBUG === "true",
70
70
  startDebug: function () {
71
- this._debug = true;
71
+ this._debug = true
72
72
  },
73
73
  log: (msg: string, ...args: any[]) => console.log(chalk.gray(msg), ...args),
74
74
  error: (msg: string, ...args: any[]) =>
@@ -80,8 +80,8 @@ const Console = {
80
80
  help: (msg: string) =>
81
81
  console.log(`${chalk.white.bold("⚠ help:")} ${chalk.white(msg)}`),
82
82
  debug(...args: any[]) {
83
- this._debug && console.log(chalk.magentaBright(`⚠ debug: `), args);
83
+ this._debug && console.log(chalk.magentaBright(`⚠ debug: `), args)
84
84
  },
85
- };
85
+ }
86
86
 
87
- export default { getMatches, cleanStdout, indent, Console };
87
+ export default { getMatches, cleanStdout, indent, Console }
@@ -1,42 +1,42 @@
1
- import { Command } from "@oclif/command";
2
- import Console from "./console";
3
- import { createInterface } from "readline";
1
+ import { Command } from "@oclif/command"
2
+ import Console from "./console"
3
+ import { createInterface } from "readline"
4
4
  // import SessionManager from '../managers/session'
5
5
 
6
6
  class BaseCommand extends Command {
7
7
  async catch(err: any) {
8
- Console.debug("COMMAND CATCH", err);
8
+ Console.debug("COMMAND CATCH", err)
9
9
 
10
- throw err;
10
+ throw err
11
11
  }
12
12
 
13
13
  async init() {
14
- const { flags, args } = this.parse(BaseCommand);
15
- Console.debug("COMMAND INIT");
16
- Console.debug("These are your flags: ", flags);
17
- Console.debug("These are your args: ", args);
14
+ const { flags, args } = this.parse(BaseCommand)
15
+ Console.debug("COMMAND INIT")
16
+ Console.debug("These are your flags: ", flags)
17
+ Console.debug("These are your args: ", args)
18
18
 
19
19
  // quick fix for listening to the process termination on windows
20
20
  if (process.platform === "win32") {
21
21
  const rl = createInterface({
22
22
  input: process.stdin,
23
23
  output: process.stdout,
24
- });
24
+ })
25
25
 
26
26
  rl.on("SIGINT", function () {
27
27
  // process.emit('SIGINT')
28
28
  // process.emit('SIGINT')
29
- });
29
+ })
30
30
  }
31
31
 
32
32
  process.on("SIGINT", function () {
33
- Console.debug("Terminated (SIGINT)");
34
- process.exit();
35
- });
33
+ Console.debug("Terminated (SIGINT)")
34
+ process.exit()
35
+ })
36
36
  }
37
37
 
38
38
  async finally() {
39
- Console.debug("COMMAND FINALLY");
39
+ Console.debug("COMMAND FINALLY")
40
40
  // called after run and catch regardless of whether or not the command errored
41
41
  }
42
42
 
@@ -45,4 +45,4 @@ class BaseCommand extends Command {
45
45
  }
46
46
  }
47
47
 
48
- export default BaseCommand;
48
+ export default BaseCommand
package/src/utils/api.ts CHANGED
@@ -1,7 +1,8 @@
1
- import Console from "../utils/console";
2
- import * as storage from "node-persist";
3
- import cli from "cli-ux";
4
- const HOST = "https://learnpack.herokuapp.com";
1
+ import Console from "../utils/console"
2
+ import * as storage from "node-persist"
3
+ import cli from "cli-ux"
4
+ const HOST = "https://breathecode.herokuapp.com"
5
+ const RIGOBOT_HOST = "https://rigobot.herokuapp.com"
5
6
 
6
7
  // eslint-disable-next-line
7
8
  const _fetch = require("node-fetch");
@@ -18,65 +19,107 @@ interface IOptions {
18
19
  }
19
20
 
20
21
  const fetch = async (url: string, options: IOptions = {}) => {
21
- const headers: IHeaders = { "Content-Type": "application/json" };
22
- let session = null;
22
+ const headers: IHeaders = { "Content-Type": "application/json" }
23
+ Console.log(`Fetching ${url}`)
24
+ let session = null
23
25
  try {
24
- session = await storage.getItem("bc-payload");
26
+ session = await storage.getItem("bc-payload")
25
27
  if (session.token && session.token !== "" && !url.includes("/token"))
26
- headers.Authorization = "Token " + session.token;
28
+ headers.Authorization = "Token " + session.token
27
29
  } catch {}
28
30
 
29
31
  try {
30
32
  const resp = await _fetch(url, {
31
33
  ...options,
32
34
  headers: { ...headers, ...options.headers },
33
- } as any);
35
+ } as any)
34
36
 
35
37
  if (resp.status >= 200 && resp.status < 300)
36
- return await resp.json();
38
+ return await resp.json()
37
39
  if (resp.status === 401)
38
- throw APIError("Invalid authentication credentials", 401);
40
+ throw APIError("Invalid authentication credentials", 401)
39
41
  else if (resp.status === 404)
40
- throw APIError("Package not found", 404);
42
+ throw APIError("Package not found", 404)
41
43
  else if (resp.status >= 500)
42
- throw APIError("Impossible to connect with the server", 500);
44
+ throw APIError("Impossible to connect with the server", 500)
43
45
  else if (resp.status >= 400) {
44
- const error = await resp.json();
46
+ const error = await resp.json()
45
47
  if (error.detail || error.error) {
46
- throw APIError(error.detail || error.error);
48
+ throw APIError(error.detail || error.error)
47
49
  } else if (error.nonFieldErrors) {
48
- throw APIError(error.nonFieldErrors[0], error);
50
+ throw APIError(error.nonFieldErrors[0], error)
49
51
  } else if (typeof error === "object") {
50
52
  if (Object.keys(error).length > 0) {
51
- const key = error[Object.keys(error)[0]];
52
- throw APIError(`${key}: ${error[key][0]}`, error);
53
+ const key = error[Object.keys(error)[0]]
54
+ throw APIError(`${key}: ${error[key][0]}`, error)
53
55
  }
54
56
  } else {
55
- throw APIError("Uknown error");
57
+ throw APIError("Uknown error")
56
58
  }
57
59
  } else
58
- throw APIError("Uknown error");
60
+ throw APIError("Uknown error")
59
61
  } catch (error) {
60
- Console.error((error as TypeError).message);
61
- throw error;
62
+ Console.error((error as TypeError).message)
63
+ throw error
62
64
  }
63
- };
65
+ }
64
66
 
65
67
  const login = async (identification: string, password: string) => {
66
68
  try {
67
- cli.action.start("Looking for credentials...");
68
- await cli.wait(1000);
69
- const data = await fetch(`${HOST}/v1/auth/token/`, {
70
- body: JSON.stringify({ identification, password }),
69
+ cli.action.start(`Looking for credentials with ${identification}`)
70
+ await cli.wait(1000)
71
+ const url = `${HOST}/v1/auth/login/`
72
+ // Console.log(url);
73
+ const data = await fetch(url, {
74
+ body: JSON.stringify({
75
+ email: identification,
76
+ password: password,
77
+ }),
71
78
  method: "post",
72
- });
73
- cli.action.stop("ready");
74
- return data;
79
+ })
80
+ cli.action.stop("ready")
81
+ const payload = await loginRigo(data.token)
82
+
83
+ return { ...data, rigobot: payload }
75
84
  } catch (error) {
76
- Console.error((error as TypeError).message);
77
- Console.debug(error);
85
+ cli.action.stop("error")
86
+ Console.error((error as TypeError).message)
87
+ Console.debug(error)
88
+ }
89
+ }
90
+
91
+ const loginRigo = async (token: string) => {
92
+ const rigoUrl = `${RIGOBOT_HOST}/v1/auth/me/token?breathecode_token=${token}`
93
+ const rigoResp = await _fetch(rigoUrl)
94
+ const rigobotJson = await rigoResp.json()
95
+ return rigobotJson
96
+ }
97
+
98
+ const getOpenAIToken = async () => {
99
+ const token = await storage.getItem("openai-token")
100
+ return token
101
+ }
102
+
103
+ const getRigoFeedback = async (readme: string, currentCode: string) => {
104
+ const payload = {
105
+ current_code: Buffer.from(currentCode).toString("base64"), // Encode currentCode as base64
106
+ tutorial: Buffer.from(readme).toString("base64"), // Encode readme as base64
78
107
  }
79
- };
108
+
109
+ const session = await storage.getItem("bc-payload")
110
+
111
+ const response = await _fetch(`${RIGOBOT_HOST}/v1/conversation/feedback/`, {
112
+ method: "POST",
113
+ headers: {
114
+ "Content-Type": "application/json",
115
+ Authorization: `Token ${session.rigobot.key}`,
116
+ },
117
+ body: JSON.stringify(payload),
118
+ })
119
+
120
+ const responseData = await response.json()
121
+ return responseData.feedback
122
+ }
80
123
 
81
124
  const publish = async (config: any) => {
82
125
  const keys = [
@@ -88,79 +131,79 @@ const publish = async (config: any) => {
88
131
  "repository",
89
132
  "author",
90
133
  "title",
91
- ];
134
+ ]
92
135
 
93
- const payload: { [key: string]: string } = {};
136
+ const payload: { [key: string]: string } = {}
94
137
  for (const k of keys)
95
- config[k] ? (payload[k] = config[k]) : null;
138
+ config[k] ? (payload[k] = config[k]) : null
96
139
  try {
97
- console.log("Package to publish:", payload);
98
- cli.action.start("Updating package information...");
99
- await cli.wait(1000);
140
+ console.log("Package to publish:", payload)
141
+ cli.action.start("Updating package information...")
142
+ await cli.wait(1000)
100
143
  const data = await fetch(`${HOST}/v1/package/${config.slug}`, {
101
144
  method: "PUT",
102
145
  body: JSON.stringify(payload),
103
- });
104
- cli.action.stop("ready");
105
- return data;
146
+ })
147
+ cli.action.stop("ready")
148
+ return data
106
149
  } catch (error) {
107
- console.log("payload", payload);
108
- Console.error((error as TypeError).message);
109
- Console.debug(error);
110
- throw error;
150
+ console.log("payload", payload)
151
+ Console.error((error as TypeError).message)
152
+ Console.debug(error)
153
+ throw error
111
154
  }
112
- };
155
+ }
113
156
 
114
157
  const update = async (config: any) => {
115
158
  try {
116
- cli.action.start("Updating package information...");
117
- await cli.wait(1000);
159
+ cli.action.start("Updating package information...")
160
+ await cli.wait(1000)
118
161
  const data = await fetch(`${HOST}/v1/package/`, {
119
162
  method: "POST",
120
163
  body: JSON.stringify(config),
121
- });
122
- cli.action.stop("ready");
123
- return data;
164
+ })
165
+ cli.action.stop("ready")
166
+ return data
124
167
  } catch (error) {
125
- Console.error((error as any).message);
126
- Console.debug(error);
127
- throw error;
168
+ Console.error((error as any).message)
169
+ Console.debug(error)
170
+ throw error
128
171
  }
129
- };
172
+ }
130
173
 
131
174
  const getPackage = async (slug: string) => {
132
175
  try {
133
- cli.action.start("Downloading package information...");
134
- await cli.wait(1000);
135
- const data = await fetch(`${HOST}/v1/package/${slug}`);
136
- cli.action.stop("ready");
137
- return data;
176
+ cli.action.start("Downloading package information...")
177
+ await cli.wait(1000)
178
+ const data = await fetch(`${HOST}/v1/package/${slug}`)
179
+ cli.action.stop("ready")
180
+ return data
138
181
  } catch (error) {
139
182
  if ((error as any).status === 404)
140
- Console.error(`Package ${slug} does not exist`);
183
+ Console.error(`Package ${slug} does not exist`)
141
184
  else
142
- Console.error(`Package ${slug} does not exist`);
143
- Console.debug(error);
144
- throw error;
185
+ Console.error(`Package ${slug} does not exist`)
186
+ Console.debug(error)
187
+ throw error
145
188
  }
146
- };
189
+ }
147
190
 
148
191
  const getLangs = async () => {
149
192
  try {
150
- cli.action.start("Downloading language options...");
151
- await cli.wait(1000);
152
- const data = await fetch(`${HOST}/v1/package/language`);
153
- cli.action.stop("ready");
154
- return data;
193
+ cli.action.start("Downloading language options...")
194
+ await cli.wait(1000)
195
+ const data = await fetch(`${HOST}/v1/package/language`)
196
+ cli.action.stop("ready")
197
+ return data
155
198
  } catch (error) {
156
199
  if ((error as any).status === 404)
157
- Console.error("Package slug does not exist");
200
+ Console.error("Package slug does not exist")
158
201
  else
159
- Console.error("Package slug does not exist");
160
- Console.debug(error);
161
- throw error;
202
+ Console.error("Package slug does not exist")
203
+ Console.debug(error)
204
+ throw error
162
205
  }
163
- };
206
+ }
164
207
 
165
208
  const getAllPackages = async ({
166
209
  lang = "",
@@ -170,25 +213,34 @@ const getAllPackages = async ({
170
213
  slug?: string;
171
214
  }) => {
172
215
  try {
173
- cli.action.start("Downloading packages...");
174
- await cli.wait(1000);
216
+ cli.action.start("Downloading packages...")
217
+ await cli.wait(1000)
175
218
  const data = await fetch(
176
219
  `${HOST}/v1/package/all?limit=100&language=${lang}&slug=${slug}`
177
- );
178
- cli.action.stop("ready");
179
- return data;
220
+ )
221
+ cli.action.stop("ready")
222
+ return data
180
223
  } catch (error) {
181
- Console.error(`Package ${slug} does not exist`);
182
- Console.debug(error);
183
- throw error;
224
+ Console.error(`Package ${slug} does not exist`)
225
+ Console.debug(error)
226
+ throw error
184
227
  }
185
- };
228
+ }
186
229
 
187
230
  const APIError = (error: TypeError | string, code?: number) => {
188
- const message: string = (error as TypeError).message || (error as string);
189
- const _err = new Error(message) as any;
190
- _err.status = code || 400;
191
- return _err;
192
- };
231
+ const message: string = (error as TypeError).message || (error as string)
232
+ const _err = new Error(message) as any
233
+ _err.status = code || 400
234
+ return _err
235
+ }
193
236
 
194
- export default { login, publish, update, getPackage, getLangs, getAllPackages };
237
+ export default {
238
+ login,
239
+ publish,
240
+ update,
241
+ getPackage,
242
+ getLangs,
243
+ getAllPackages,
244
+ getRigoFeedback,
245
+ getOpenAIToken,
246
+ }