@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,24 +1,24 @@
1
- import * as path from "path";
2
- import * as fs from "fs";
3
- import * as shell from "shelljs";
4
- import Console from "../../utils/console";
5
- import watch from "../../utils/watcher";
1
+ import * as path from "path"
2
+ import * as fs from "fs"
3
+ import * as shell from "shelljs"
4
+ import Console from "../../utils/console"
5
+ import watch from "../../utils/watcher"
6
6
  import {
7
7
  ValidationError,
8
8
  NotFoundError,
9
9
  InternalError,
10
- } from "../../utils/errors";
10
+ } from "../../utils/errors"
11
11
 
12
- import defaults from "./defaults";
13
- import { exercise } from "./exercise";
12
+ import defaults from "./defaults"
13
+ import { exercise } from "./exercise"
14
14
 
15
- import { rmSync } from "../file";
16
- import { IConfigObj, TConfigObjAttributes, TMode } from "../../models/config";
15
+ import { rmSync } from "../file"
16
+ import { IConfigObj, TConfigObjAttributes, TMode } from "../../models/config"
17
17
  import {
18
18
  IConfigManagerAttributes,
19
19
  IConfigManager,
20
- } from "../../models/config-manager";
21
- import { IFile } from "../../models/file";
20
+ } from "../../models/config-manager"
21
+ import { IFile } from "../../models/file"
22
22
 
23
23
  /* exercise folder name standard */
24
24
 
@@ -30,49 +30,49 @@ const chalk = require("chalk");
30
30
  /* exercise folder name standard */
31
31
 
32
32
  const getConfigPath = () => {
33
- const possibleFileNames = ["learn.json", ".learn/learn.json"];
34
- const config = possibleFileNames.find(file => fs.existsSync(file)) || null;
33
+ const possibleFileNames = ["learn.json", ".learn/learn.json"]
34
+ const config = possibleFileNames.find(file => fs.existsSync(file)) || null
35
35
  if (config && fs.existsSync(".breathecode"))
36
- return { config, base: ".breathecode" };
36
+ return { config, base: ".breathecode" }
37
37
  if (config === null)
38
38
  throw NotFoundError(
39
39
  "learn.json file not found on current folder, is this a learnpack package?"
40
- );
41
- return { config, base: ".learn" };
42
- };
40
+ )
41
+ return { config, base: ".learn" }
42
+ }
43
43
 
44
44
  const getExercisesPath = (base: string) => {
45
- const possibleFileNames = ["./exercises", base + "/exercises", "./"];
46
- return possibleFileNames.find(file => fs.existsSync(file)) || null;
47
- };
45
+ const possibleFileNames = ["./exercises", base + "/exercises", "./"]
46
+ return possibleFileNames.find(file => fs.existsSync(file)) || null
47
+ }
48
48
 
49
49
  const getGitpodAddress = () => {
50
50
  if (shell.exec("gp -h", { silent: true }).code === 0) {
51
51
  return shell
52
52
  .exec("gp url", { silent: true })
53
- .stdout.replace(/(\r\n|\n|\r)/gm, "");
53
+ .stdout.replace(/(\r\n|\n|\r)/gm, "")
54
54
  }
55
55
 
56
- Console.debug("Gitpod command line tool not found");
57
- return "http://localhost";
58
- };
56
+ Console.debug("Gitpod command line tool not found")
57
+ return "http://localhost"
58
+ }
59
59
 
60
60
  const getCodespacesNamespace = () => {
61
61
  // https://orange-rotary-phone-wxpg49q5gcg4rp-3000.app.github.dev
62
62
  const codespace_name = shell
63
63
  .exec("echo $CODESPACE_NAME", { silent: true })
64
- .stdout.replace(/(\r\n|\n|\r)/gm, "");
64
+ .stdout.replace(/(\r\n|\n|\r)/gm, "")
65
65
 
66
66
  if (
67
67
  !codespace_name ||
68
68
  codespace_name === "" ||
69
69
  codespace_name === undefined
70
70
  ) {
71
- return null;
71
+ return null
72
72
  }
73
73
 
74
- return codespace_name;
75
- };
74
+ return codespace_name
75
+ }
76
76
 
77
77
  export default async ({
78
78
  grading,
@@ -80,46 +80,46 @@ export default async ({
80
80
  disableGrading,
81
81
  version,
82
82
  }: IConfigManagerAttributes): Promise<IConfigManager> => {
83
- const confPath = getConfigPath();
84
- Console.debug("This is the config path: ", confPath);
83
+ const confPath = getConfigPath()
84
+ Console.debug("This is the config path: ", confPath)
85
85
 
86
- let configObj: IConfigObj = {};
86
+ let configObj: IConfigObj = {}
87
87
 
88
88
  if (confPath) {
89
- const bcContent = fs.readFileSync(confPath.config);
90
- let hiddenBcContent = {};
89
+ const bcContent = fs.readFileSync(confPath.config)
90
+ let hiddenBcContent = {}
91
91
  if (fs.existsSync(confPath.base + "/config.json")) {
92
- hiddenBcContent = fs.readFileSync(confPath.base + "/config.json");
93
- hiddenBcContent = JSON.parse(hiddenBcContent as string);
92
+ hiddenBcContent = fs.readFileSync(confPath.base + "/config.json")
93
+ hiddenBcContent = JSON.parse(hiddenBcContent as string)
94
94
  if (!hiddenBcContent)
95
95
  throw new Error(
96
96
  `Invalid ${confPath.base}/config.json syntax: Unable to parse.`
97
- );
97
+ )
98
98
  }
99
99
 
100
- const jsonConfig = JSON.parse(`${bcContent}`);
100
+ const jsonConfig = JSON.parse(`${bcContent}`)
101
101
  if (!jsonConfig)
102
- throw new Error(`Invalid ${confPath.config} syntax: Unable to parse.`);
102
+ throw new Error(`Invalid ${confPath.config} syntax: Unable to parse.`)
103
103
 
104
- let session: number;
104
+ let session: number
105
105
 
106
106
  // add using id to the installation
107
107
  if (!jsonConfig.session) {
108
- session = Math.floor(Math.random() * 10_000_000_000_000_000_000);
108
+ session = Math.floor(Math.random() * 10_000_000_000_000_000_000)
109
109
  } else {
110
- session = jsonConfig.session;
111
- delete jsonConfig.session;
110
+ session = jsonConfig.session
111
+ delete jsonConfig.session
112
112
  }
113
113
 
114
114
  configObj = deepMerge(hiddenBcContent, {
115
115
  config: jsonConfig,
116
116
  session: session,
117
- });
118
- Console.debug("Content from the configuration .json ", configObj);
117
+ })
118
+ Console.debug("Content from the configuration .json ", configObj)
119
119
  } else {
120
120
  throw ValidationError(
121
121
  "No learn.json file has been found, make sure you are in the folder"
122
- );
122
+ )
123
123
  }
124
124
 
125
125
  configObj = deepMerge(defaults || {}, configObj, {
@@ -127,10 +127,10 @@ export default async ({
127
127
  grading: grading || configObj.config?.grading,
128
128
  configPath: confPath.config,
129
129
  },
130
- });
130
+ })
131
131
 
132
132
  if (configObj.config) {
133
- configObj.config.outputPath = confPath.base + "/dist";
133
+ configObj.config.outputPath = confPath.base + "/dist"
134
134
  }
135
135
 
136
136
  Console.debug("This is your configuration object: ", {
@@ -138,50 +138,50 @@ export default async ({
138
138
  exercises: configObj.exercises ?
139
139
  configObj.exercises.map(e => e.slug) :
140
140
  [],
141
- });
141
+ })
142
142
 
143
143
  // auto detect agent (if possible)
144
- const codespaces_workspace = getCodespacesNamespace();
144
+ const codespaces_workspace = getCodespacesNamespace()
145
145
  if (shell.which("gp") && configObj && configObj.config) {
146
- configObj.config.editor.agent = "vscode";
147
- configObj.address = getGitpodAddress();
146
+ configObj.config.editor.agent = "vscode"
147
+ configObj.address = getGitpodAddress()
148
148
  configObj.config.publicUrl = `https://${
149
149
  configObj.config.port
150
- }-${configObj.address?.slice(8)}`;
150
+ }-${configObj.address?.slice(8)}`
151
151
  } else if (configObj.config && codespaces_workspace) {
152
- configObj.config.editor.agent = "vscode";
153
- configObj.address = `https://${codespaces_workspace}.github.dev`;
154
- configObj.config.publicUrl = `https://${codespaces_workspace}-${configObj.config.port}.app.github.dev`;
152
+ configObj.config.editor.agent = "vscode"
153
+ configObj.address = `https://${codespaces_workspace}.github.dev`
154
+ configObj.config.publicUrl = `https://${codespaces_workspace}-${configObj.config.port}.app.github.dev`
155
155
  } else if (configObj.config && !configObj.config.editor.agent) {
156
- configObj.config.editor.agent = "localhost";
156
+ configObj.config.editor.agent = "localhost"
157
157
  }
158
158
 
159
159
  if (configObj.config && !configObj.config.publicUrl)
160
- configObj.config.publicUrl = `${configObj.address}:${configObj.config.port}`;
160
+ configObj.config.publicUrl = `${configObj.address}:${configObj.config.port}`
161
161
 
162
162
  // Assign default editor mode if not set already
163
163
  if (configObj.config && !mode) {
164
- configObj.config.editor.mode = mode as TMode;
164
+ configObj.config.editor.mode = mode as TMode
165
165
  }
166
166
 
167
167
  if (configObj.config && !configObj.config.editor.mode)
168
168
  configObj.config.editor.mode =
169
- configObj.config.editor.agent === "localhost" ? "standalone" : "preview";
169
+ configObj.config.editor.agent === "localhost" ? "standalone" : "preview"
170
170
 
171
171
  if (version && configObj.config)
172
- configObj.config.editor.version = version;
172
+ configObj.config.editor.version = version
173
173
  else if (configObj.config && configObj.config.editor.version === null) {
174
- Console.debug("Config version not found, downloading default.");
174
+ Console.debug("Config version not found, downloading default.")
175
175
  const resp = await fetch(
176
176
  "https://raw.githubusercontent.com/learnpack/coding-ide/learnpack/package.json"
177
- );
178
- const packageJSON = await resp.json();
179
- configObj.config.editor.version = packageJSON.version || "1.0.73";
177
+ )
178
+ const packageJSON = await resp.json()
179
+ configObj.config.editor.version = packageJSON.version || "1.0.73"
180
180
  }
181
181
 
182
182
  if (configObj.config) {
183
- configObj.config.dirPath = "./" + confPath.base;
184
- configObj.config.exercisesPath = getExercisesPath(confPath.base) || "./";
183
+ configObj.config.dirPath = "./" + confPath.base
184
+ configObj.config.exercisesPath = getExercisesPath(confPath.base) || "./"
185
185
  }
186
186
 
187
187
  return {
@@ -192,125 +192,125 @@ configObj.config.editor.version = version;
192
192
  const alias = (_l: string) => {
193
193
  const map: any = {
194
194
  python3: "python",
195
- };
195
+ }
196
196
  if (map[_l])
197
- return map[_l];
198
- return _l;
199
- };
197
+ return map[_l]
198
+ return _l
199
+ }
200
200
 
201
201
  // decode aliases
202
- language = alias(language);
202
+ language = alias(language)
203
203
 
204
204
  if (this.validLanguages[language])
205
- return true;
205
+ return true
206
206
 
207
- Console.debug(`Validating engine for ${language} compilation`);
208
- let result = shell.exec("learnpack plugins", { silent: true });
207
+ Console.debug(`Validating engine for ${language} compilation`)
208
+ let result = shell.exec("learnpack plugins", { silent: true })
209
209
 
210
210
  if (
211
211
  result.code === 0 &&
212
212
  result.stdout.includes(`learnpack-${language}`)
213
213
  ) {
214
- this.validLanguages[language] = true;
215
- return true;
214
+ this.validLanguages[language] = true
215
+ return true
216
216
  }
217
217
 
218
- Console.info(`Language engine for ${language} not found, installing...`);
218
+ Console.info(`Language engine for ${language} not found, installing...`)
219
219
  result = shell.exec(`learnpack plugins:install learnpack-${language}`, {
220
220
  silent: true,
221
- });
221
+ })
222
222
  if (result.code === 0) {
223
223
  socket.log(
224
224
  "compiling",
225
225
  "Installing the python compiler, you will have to reset the exercises after installation by writing on your terminal: $ learnpack run"
226
- );
226
+ )
227
227
  Console.info(
228
228
  `Successfully installed the ${language} exercise engine, \n please start learnpack again by running the following command: \n ${chalk.white(
229
229
  "$ learnpack start"
230
230
  )}\n\n `
231
- );
232
- server.terminate();
233
- return false;
231
+ )
232
+ server.terminate()
233
+ return false
234
234
  }
235
235
 
236
- this.validLanguages[language] = false;
237
- socket.error(`Error installing ${language} exercise engine`);
238
- Console.error(`Error installing ${language} exercise engine`);
239
- Console.log(result.stdout);
240
- throw InternalError(`Error installing ${language} exercise engine`);
236
+ this.validLanguages[language] = false
237
+ socket.error(`Error installing ${language} exercise engine`)
238
+ Console.error(`Error installing ${language} exercise engine`)
239
+ Console.log(result.stdout)
240
+ throw InternalError(`Error installing ${language} exercise engine`)
241
241
  },
242
242
  clean: () => {
243
243
  if (configObj.config) {
244
244
  if (configObj.config.outputPath) {
245
- rmSync(configObj.config.outputPath);
245
+ rmSync(configObj.config.outputPath)
246
246
  }
247
247
 
248
- rmSync(configObj.config.dirPath + "/_app");
249
- rmSync(configObj.config.dirPath + "/reports");
250
- rmSync(configObj.config.dirPath + "/.session");
251
- rmSync(configObj.config.dirPath + "/resets");
248
+ rmSync(configObj.config.dirPath + "/_app")
249
+ rmSync(configObj.config.dirPath + "/reports")
250
+ rmSync(configObj.config.dirPath + "/.session")
251
+ rmSync(configObj.config.dirPath + "/resets")
252
252
 
253
253
  // clean tag gz
254
254
  if (fs.existsSync(configObj.config.dirPath + "/app.tar.gz"))
255
- fs.unlinkSync(configObj.config.dirPath + "/app.tar.gz");
255
+ fs.unlinkSync(configObj.config.dirPath + "/app.tar.gz")
256
256
 
257
257
  if (fs.existsSync(configObj.config.dirPath + "/config.json"))
258
- fs.unlinkSync(configObj.config.dirPath + "/config.json");
258
+ fs.unlinkSync(configObj.config.dirPath + "/config.json")
259
259
 
260
260
  if (fs.existsSync(configObj.config.dirPath + "/vscode_queue.json"))
261
- fs.unlinkSync(configObj.config.dirPath + "/vscode_queue.json");
261
+ fs.unlinkSync(configObj.config.dirPath + "/vscode_queue.json")
262
262
  }
263
263
  },
264
264
  getExercise: slug => {
265
- Console.debug("ExercisePath Slug", slug);
265
+ Console.debug("ExercisePath Slug", slug)
266
266
  const exercise = (configObj.exercises || []).find(
267
267
  ex => ex.slug === slug
268
- );
268
+ )
269
269
  if (!exercise)
270
- throw ValidationError(`Exercise ${slug} not found`);
270
+ throw ValidationError(`Exercise ${slug} not found`)
271
271
 
272
- return exercise;
272
+ return exercise
273
273
  },
274
274
  getAllExercises: () => {
275
- return configObj.exercises;
275
+ return configObj.exercises
276
276
  },
277
277
  startExercise: function (slug: string) {
278
- const exercise = this.getExercise(slug);
278
+ const exercise = this.getExercise(slug)
279
279
 
280
280
  // set config.json with current exercise
281
- configObj.currentExercise = exercise.slug;
281
+ configObj.currentExercise = exercise.slug
282
282
 
283
- this.save();
283
+ this.save()
284
284
 
285
285
  // eslint-disable-next-line
286
286
  exercise.files.forEach((f: IFile) => {
287
287
  if (configObj.config) {
288
- const _path = configObj.config.outputPath + "/" + f.name;
288
+ const _path = configObj.config.outputPath + "/" + f.name
289
289
  if (f.hidden === false && fs.existsSync(_path))
290
- fs.unlinkSync(_path);
290
+ fs.unlinkSync(_path)
291
291
  }
292
- });
292
+ })
293
293
 
294
- return exercise;
294
+ return exercise
295
295
  },
296
296
  noCurrentExercise: function () {
297
- configObj.currentExercise = null;
298
- this.save();
297
+ configObj.currentExercise = null
298
+ this.save()
299
299
  },
300
300
  reset: slug => {
301
301
  if (
302
302
  configObj.config &&
303
303
  !fs.existsSync(`${configObj.config.dirPath}/resets/` + slug)
304
304
  )
305
- throw ValidationError("Could not find the original files for " + slug);
305
+ throw ValidationError("Could not find the original files for " + slug)
306
306
 
307
307
  const exercise = (configObj.exercises || []).find(
308
308
  ex => ex.slug === slug
309
- );
309
+ )
310
310
  if (!exercise)
311
311
  throw ValidationError(
312
312
  `Exercise ${slug} not found on the configuration`
313
- );
313
+ )
314
314
 
315
315
  if (configObj.config) {
316
316
  for (const fileName of fs.readdirSync(
@@ -318,110 +318,110 @@ fs.unlinkSync(_path);
318
318
  )) {
319
319
  const content = fs.readFileSync(
320
320
  `${configObj.config?.dirPath}/resets/${slug}/${fileName}`
321
- );
322
- fs.writeFileSync(`${exercise.path}/${fileName}`, content);
321
+ )
322
+ fs.writeFileSync(`${exercise.path}/${fileName}`, content)
323
323
  }
324
324
  }
325
325
  },
326
326
  buildIndex: function () {
327
- Console.info("Building the exercise index...");
327
+ Console.info("Building the exercise index...")
328
328
 
329
329
  const isDirectory = (source: string) => {
330
- const name = path.basename(source);
330
+ const name = path.basename(source)
331
331
  if (name === path.basename(configObj?.config?.dirPath || ""))
332
- return false;
332
+ return false
333
333
  // ignore folders that start with a dot
334
334
  if (name.charAt(0) === "." || name.charAt(0) === "_")
335
- return false;
335
+ return false
336
336
 
337
- return fs.lstatSync(source).isDirectory();
338
- };
337
+ return fs.lstatSync(source).isDirectory()
338
+ }
339
339
 
340
340
  const getDirectories = (source: string) =>
341
341
  fs
342
342
  .readdirSync(source)
343
343
  .map(name => path.join(source, name))
344
- .filter(isDirectory);
344
+ .filter(isDirectory)
345
345
  // add the .learn folder
346
346
  if (!fs.existsSync(confPath.base))
347
- fs.mkdirSync(confPath.base);
347
+ fs.mkdirSync(confPath.base)
348
348
  // add the outout folder where webpack will publish the the html/css/js files
349
349
  if (
350
350
  configObj.config &&
351
351
  configObj.config.outputPath &&
352
352
  !fs.existsSync(configObj.config.outputPath)
353
353
  )
354
- fs.mkdirSync(configObj.config.outputPath);
354
+ fs.mkdirSync(configObj.config.outputPath)
355
355
 
356
356
  // TODO: we could use npm library front-mater to read the title of the exercises from the README.md
357
357
  const grupedByDirectory = getDirectories(
358
358
  configObj?.config?.exercisesPath || ""
359
- );
359
+ )
360
360
  configObj.exercises =
361
361
  grupedByDirectory.length > 0 ?
362
362
  grupedByDirectory.map((path, position) =>
363
363
  exercise(path, position, configObj)
364
364
  ) :
365
- [exercise(configObj?.config?.exercisesPath || "", 0, configObj)];
366
- this.save();
365
+ [exercise(configObj?.config?.exercisesPath || "", 0, configObj)]
366
+ this.save()
367
367
  },
368
368
  watchIndex: function (onChange: () => void) {
369
369
  if (configObj.config && !configObj.config.exercisesPath)
370
370
  throw ValidationError(
371
371
  "No exercises directory to watch: " + configObj.config.exercisesPath
372
- );
372
+ )
373
373
 
374
- this.buildIndex();
374
+ this.buildIndex()
375
375
  watch(configObj?.config?.exercisesPath || "", onChange)
376
376
  .then((/* eventname, filename */) => {
377
- Console.debug("Changes detected on your exercises");
378
- this.buildIndex();
377
+ Console.debug("Changes detected on your exercises")
378
+ this.buildIndex()
379
379
  if (onChange)
380
- onChange();
380
+ onChange()
381
381
  })
382
382
  .catch(error => {
383
- throw error;
384
- });
383
+ throw error
384
+ })
385
385
  },
386
386
  save: () => {
387
- Console.debug("Saving configuration with: ", configObj);
387
+ Console.debug("Saving configuration with: ", configObj)
388
388
 
389
389
  // remove the duplicates form the actions array
390
390
  // configObj.config.actions = [...new Set(configObj.config.actions)];
391
391
  if (configObj.config) {
392
392
  configObj.config.translations = [
393
393
  ...new Set(configObj.config.translations),
394
- ];
394
+ ]
395
395
  fs.writeFileSync(
396
396
  configObj.config.dirPath + "/config.json",
397
397
  JSON.stringify(configObj, null, 4)
398
- );
398
+ )
399
399
  }
400
400
  },
401
- } as IConfigManager;
402
- };
401
+ } as IConfigManager
402
+ }
403
403
 
404
404
  function deepMerge(...sources: any): any {
405
- let acc: any = {};
405
+ let acc: any = {}
406
406
  for (const source of sources) {
407
407
  if (Array.isArray(source)) {
408
408
  if (!Array.isArray(acc)) {
409
- acc = [];
409
+ acc = []
410
410
  }
411
411
 
412
- acc = [...source];
412
+ acc = [...source]
413
413
  } else if (source instanceof Object) {
414
414
  // eslint-disable-next-line
415
415
  for (let [key, value] of Object.entries(source)) {
416
416
  if (value instanceof Object && key in acc) {
417
- value = deepMerge(acc[key], value);
417
+ value = deepMerge(acc[key], value)
418
418
  }
419
419
 
420
420
  if (value !== undefined)
421
- acc = { ...acc, [key]: value };
421
+ acc = { ...acc, [key]: value }
422
422
  }
423
423
  }
424
424
  }
425
425
 
426
- return acc;
426
+ return acc
427
427
  }