@kaspernj/api-maker 1.0.188 → 1.0.191

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/package.json CHANGED
@@ -16,7 +16,7 @@
16
16
  ]
17
17
  },
18
18
  "name": "@kaspernj/api-maker",
19
- "version": "1.0.188",
19
+ "version": "1.0.191",
20
20
  "description": "",
21
21
  "main": "index.js",
22
22
  "repository": {
@@ -50,6 +50,7 @@
50
50
  "qs": ">= 6.9.3",
51
51
  "replaceall": ">= 0.1.6",
52
52
  "strftime": ">= 0.10.0",
53
+ "uniqunize": "^1.0.1",
53
54
  "wake-event": ">= 0.0.1"
54
55
  },
55
56
  "peerDependencies": {
@@ -71,6 +72,6 @@
71
72
  "eslint-plugin-react": "^7.23.2",
72
73
  "i18n-on-steroids": "^1.0.2",
73
74
  "jest": "^28.0.3",
74
- "jsdom": "^19.0.0"
75
+ "jsdom": "^20.0.0"
75
76
  }
76
77
  }
@@ -14,6 +14,17 @@ const {ValidationErrors} = require("./validation-errors.cjs")
14
14
 
15
15
  const shared = {}
16
16
 
17
+ const newCustomEvent = (validationErrors) => {
18
+ return new CustomEvent("validation-errors", {detail: validationErrors})
19
+ }
20
+
21
+ const sendValidationErrorsEvent = (validationErrors, options) => {
22
+ if (options && options.form) {
23
+ const event = newCustomEvent(validationErrors)
24
+ options.form.dispatchEvent(event)
25
+ }
26
+ }
27
+
17
28
  class BaseModel {
18
29
  static modelClassData () {
19
30
  throw new Error("modelClassData should be overriden by child")
@@ -177,7 +188,7 @@ class BaseModel {
177
188
  {}
178
189
  )
179
190
  } catch (error) {
180
- this.parseValidationErrors(error, options)
191
+ BaseModel.parseValidationErrors({error, model: this, options})
181
192
  throw error
182
193
  }
183
194
 
@@ -190,7 +201,7 @@ class BaseModel {
190
201
  }
191
202
 
192
203
  async createRaw (rawData, options = {}) {
193
- const objectData = this._objectDataFromGivenRawData(rawData, options)
204
+ const objectData = BaseModel._objectDataFromGivenRawData(rawData, options)
194
205
 
195
206
  let response
196
207
 
@@ -208,7 +219,7 @@ class BaseModel {
208
219
  {}
209
220
  )
210
221
  } catch (error) {
211
- this.parseValidationErrors(error, options)
222
+ BaseModel.parseValidationErrors({error, model: this, options})
212
223
  throw error
213
224
  }
214
225
 
@@ -284,7 +295,7 @@ class BaseModel {
284
295
  }
285
296
 
286
297
  handleResponseError (response) {
287
- this.parseValidationErrors(response)
298
+ BaseModel.parseValidationErrors({model: this, response})
288
299
  throw new new CustomError("Response wasn't successful", {model: this, response})
289
300
  }
290
301
 
@@ -299,33 +310,22 @@ class BaseModel {
299
310
  return false
300
311
  }
301
312
 
302
- parseValidationErrors (error, options) {
313
+ static parseValidationErrors ({error, model, options}) {
303
314
  if (!(error instanceof CustomError)) return
304
315
  if (!error.args.response.validation_errors) return
305
316
 
306
317
  const validationErrors = new ValidationErrors({
307
- model: this,
318
+ model,
308
319
  validationErrors: digg(error, "args", "response", "validation_errors")
309
320
  })
310
321
 
311
- this.sendValidationErrorsEvent(validationErrors, options)
322
+ sendValidationErrorsEvent(validationErrors, options)
312
323
 
313
324
  if (!options || options.throwValidationError != false) {
314
325
  throw new ValidationError(validationErrors, digg(error, "args"))
315
326
  }
316
327
  }
317
328
 
318
- sendValidationErrorsEvent (validationErrors, options) {
319
- if (options && options.form) {
320
- const event = this.newCustomEvent(validationErrors)
321
- options.form.dispatchEvent(event)
322
- }
323
- }
324
-
325
- newCustomEvent (validationErrors) {
326
- return new CustomEvent("validation-errors", {detail: validationErrors})
327
- }
328
-
329
329
  static humanAttributeName (attributeName) {
330
330
  const keyName = digg(this.modelClassData(), "i18nKey")
331
331
 
@@ -517,7 +517,7 @@ class BaseModel {
517
517
  {}
518
518
  )
519
519
  } catch (error) {
520
- this.parseValidationErrors(error, options)
520
+ BaseModel.parseValidationErrors({error, model: this, options})
521
521
  throw error
522
522
  }
523
523
 
@@ -549,7 +549,7 @@ class BaseModel {
549
549
  this.setNewModelData(newModel)
550
550
  }
551
551
 
552
- _objectDataFromGivenRawData (rawData, options) {
552
+ static _objectDataFromGivenRawData (rawData, options) {
553
553
  if (rawData instanceof FormData || rawData.nodeName == "FORM") {
554
554
  const formData = FormDataObjectizer.formDataFromObject(rawData, options)
555
555
 
@@ -560,8 +560,7 @@ class BaseModel {
560
560
  }
561
561
 
562
562
  async updateRaw (rawData, options = {}) {
563
- const objectData = this._objectDataFromGivenRawData(rawData, options)
564
-
563
+ const objectData = BaseModel._objectDataFromGivenRawData(rawData, options)
565
564
  let response
566
565
 
567
566
  try {
@@ -579,7 +578,7 @@ class BaseModel {
579
578
  {}
580
579
  )
581
580
  } catch (error) {
582
- this.parseValidationErrors(error, options)
581
+ BaseModel.parseValidationErrors({error, model: this, options})
583
582
  throw error
584
583
  }
585
584
 
@@ -636,8 +635,18 @@ class BaseModel {
636
635
  return this.uniqueKeyValue
637
636
  }
638
637
 
639
- static _callCollectionCommand (args, commandArgs) {
640
- return CommandsPool.addCommand(args, commandArgs)
638
+ static async _callCollectionCommand (args, commandArgs) {
639
+ const formOrDataObject = args.args
640
+
641
+ try {
642
+ return await CommandsPool.addCommand(args, commandArgs)
643
+ } catch (error) {
644
+ if (formOrDataObject.nodeName == "FORM") {
645
+ BaseModel.parseValidationErrors({error, options: {form: formOrDataObject}})
646
+ }
647
+
648
+ throw error
649
+ }
641
650
  }
642
651
 
643
652
  _callMemberCommand (args, commandArgs) {
@@ -61,18 +61,17 @@ module.exports = class ApiMakerCommandsPool {
61
61
 
62
62
  this.pool[id] = {resolve, reject}
63
63
 
64
- if (!this.poolData[commandType])
65
- this.poolData[commandType] = {}
66
-
67
- if (!this.poolData[commandType][collectionName])
68
- this.poolData[commandType][collectionName] = {}
69
-
70
- if (!this.poolData[commandType][collectionName][commandName])
71
- this.poolData[commandType][collectionName][commandName] = {}
64
+ if (!this.poolData[commandType]) this.poolData[commandType] = {}
65
+ if (!this.poolData[commandType][collectionName]) this.poolData[commandType][collectionName] = {}
66
+ if (!this.poolData[commandType][collectionName][commandName]) this.poolData[commandType][collectionName][commandName] = {}
72
67
 
73
68
  let args
74
69
 
75
- if (data.args instanceof FormData) {
70
+ if (data.args?.nodeName == "FORM") {
71
+ const formData = new FormData(data.args)
72
+
73
+ args = FormDataObjectizer.toObject(formData)
74
+ } else if (data.args instanceof FormData) {
76
75
  args = FormDataObjectizer.toObject(data.args)
77
76
  } else {
78
77
  args = Serializer.serialize(data.args)
@@ -1,8 +1,12 @@
1
+ const {digg} = require("diggerize")
1
2
  const SourceMapsLoader = require("./source-maps-loader.cjs")
2
3
 
3
4
  module.exports = class ErrorLogger {
4
5
  constructor () {
6
+ this.debug = true
7
+ this.errorOccurred = false
5
8
  this.errors = []
9
+ this.isHandlingError = false
6
10
  this.sourceMapsLoader = new SourceMapsLoader()
7
11
  this.sourceMapsLoader.loadSourceMapsForScriptTags((script) => {
8
12
  const src = script.getAttribute("src")
@@ -23,8 +27,22 @@ module.exports = class ErrorLogger {
23
27
  return this.errors
24
28
  }
25
29
 
30
+ hasErrorOccurred() {
31
+ return digg(this, "errorOccurred")
32
+ }
33
+
34
+ isLoadingSourceMaps() {
35
+ return digg(this, "sourceMapsLoader", "isLoadingSourceMaps")
36
+ }
37
+
38
+ isWorkingOnError() {
39
+ return digg(this, "isHandlingError") || this.isLoadingSourceMaps()
40
+ }
41
+
26
42
  connectOnError () {
27
43
  global.addEventListener("error", (event) => {
44
+ this.errorOccurred = true
45
+
28
46
  if (!this.isHandlingError) {
29
47
  this.isHandlingError = true
30
48
  this.onError(event).finally(() => {
@@ -36,6 +54,8 @@ module.exports = class ErrorLogger {
36
54
 
37
55
  connectUnhandledRejection () {
38
56
  global.addEventListener("unhandledrejection", (event) => {
57
+ this.errorOccurred = true
58
+
39
59
  if (!this.isHandlingError) {
40
60
  this.isHandlingError = true
41
61
  this.onUnhandledRejection(event).finally(() => {
@@ -46,7 +66,8 @@ module.exports = class ErrorLogger {
46
66
  }
47
67
 
48
68
  async onError (event) {
49
- await this.sourceMapsLoader.loadSourceMaps()
69
+ this.errorOccurred = true
70
+ await this.sourceMapsLoader.loadSourceMaps(event.error)
50
71
 
51
72
  if (event.error && event.error.stack) {
52
73
  const backtrace = this.sourceMapsLoader.parseStackTrace(event.error.stack)
@@ -66,7 +87,7 @@ module.exports = class ErrorLogger {
66
87
  }
67
88
 
68
89
  async onUnhandledRejection (event) {
69
- await this.sourceMapsLoader.loadSourceMaps()
90
+ await this.sourceMapsLoader.loadSourceMaps(event.reason)
70
91
 
71
92
  if (event.reason.stack) {
72
93
  const backtrace = this.sourceMapsLoader.parseStackTrace(event.reason.stack)
@@ -74,7 +95,7 @@ module.exports = class ErrorLogger {
74
95
  this.errors.push({
75
96
  errorClass: "UnhandledRejection",
76
97
  message: event.reason.message || "Unhandled promise rejection",
77
- backtrace: backtrace
98
+ backtrace
78
99
  })
79
100
  } else {
80
101
  this.errors.push({
package/src/link.jsx CHANGED
@@ -14,7 +14,7 @@ export default class Link extends React.PureComponent {
14
14
 
15
15
  if (onClick) onClick(e, ...restArgs)
16
16
 
17
- if (!e.defaultPrevented) {
17
+ if (!e.defaultPrevented && !e.ctrlKey && !e.metaKey) {
18
18
  e.preventDefault()
19
19
 
20
20
  const history = global.apiMakerConfigGlobal?.history
@@ -1,5 +1,6 @@
1
1
  const stackTraceParser = require("stacktrace-parser")
2
2
  const {SourceMapConsumer} = require("source-map")
3
+ const uniqunize = require("uniqunize")
3
4
 
4
5
  // Sometimes this needs to be called and sometimes not
5
6
  if (SourceMapConsumer.initialize) {
@@ -10,6 +11,8 @@ if (SourceMapConsumer.initialize) {
10
11
 
11
12
  module.exports = class SourceMapsLoader {
12
13
  constructor () {
14
+ this.debug = false
15
+ this.isLoadingSourceMaps = false
13
16
  this.sourceMaps = []
14
17
  this.srcLoaded = {}
15
18
  }
@@ -22,47 +25,93 @@ module.exports = class SourceMapsLoader {
22
25
  this.sourceMapForSourceCallback = callback
23
26
  }
24
27
 
25
- async loadSourceMaps () {
26
- const scripts = document.querySelectorAll("script")
27
- const promises = []
28
+ getSources(error) {
29
+ let sources = this.getSourcesFromScripts()
28
30
 
29
- for (const script of scripts) {
30
- const src = this.loadSourceMapsForScriptTagsCallback(script)
31
+ if (error) sources = sources.concat(this.getSourcesFromError(error))
32
+
33
+ return uniqunize(sources, (source) => source.originalUrl)
34
+ }
31
35
 
32
- if (src && !this.srcLoaded[src]) {
33
- this.srcLoaded[src] = true
36
+ async loadSourceMaps (error) {
37
+ this.isLoadingSourceMaps = true
34
38
 
35
- const promise = this.loadSourceMapForSource(src)
36
- promises.push(promise)
39
+ try {
40
+ const promises = []
41
+ const sources = this.getSources(error)
42
+
43
+ for(const source of sources) {
44
+ if (source.originalUrl && !this.srcLoaded[source.originalUrl]) {
45
+ this.srcLoaded[source.originalUrl] = true
46
+
47
+ const promise = this.loadSourceMapForSource(source)
48
+ promises.push(promise)
49
+ }
37
50
  }
51
+
52
+ await Promise.all(promises)
53
+ } finally {
54
+ this.isLoadingSourceMaps = false
38
55
  }
56
+ }
57
+
58
+ getSourcesFromError(error) {
59
+ const stack = stackTraceParser.parse(error.stack)
60
+ const sources = []
61
+
62
+ for (const trace of stack) {
63
+ const file = trace.file
39
64
 
40
- await Promise.all(promises)
65
+ if (file != "\u003Canonymous>") {
66
+ const sourceMapUrl = this.getMapURL({src: file})
67
+
68
+ if (sourceMapUrl) sources.push({originalUrl: file, sourceMapUrl})
69
+ }
70
+ }
71
+
72
+ return sources
73
+ }
74
+
75
+ getSourcesFromScripts() {
76
+ const scripts = document.querySelectorAll("script")
77
+ const sources = []
78
+
79
+ for (const script of scripts) {
80
+ const sourceMapUrl = this.getMapURL({script, src: script.src})
81
+
82
+ if (sourceMapUrl) sources.push({originalUrl: script.src, sourceMapUrl})
83
+ }
84
+
85
+ return sources
41
86
  }
42
87
 
43
- async loadSourceMapForSource (src) {
88
+ getMapURL({script, src}) {
44
89
  const url = this.loadUrl(src)
45
90
  const originalUrl = `${url.origin}${url.pathname}`
46
91
 
47
- let mapUrl
48
-
49
92
  if (this.sourceMapForSourceCallback) {
50
93
  // Use custom callback to resolve which map-file to download
51
- mapUrl = this.sourceMapForSourceCallback({src, url})
52
- } else {
94
+ return this.sourceMapForSourceCallback({originalUrl, script, src, url})
95
+ } else if (this.includeMapURL(src)) {
53
96
  // Default to original URL with '.map' appended
54
- mapUrl = `${originalUrl}.map`
97
+ return `${originalUrl}.map`
55
98
  }
99
+ }
56
100
 
101
+ includeMapURL(src) {
102
+ return src.includes("/packs/") || src.includes("/assets/")
103
+ }
104
+
105
+ async loadSourceMapForSource ({originalUrl, sourceMapUrl}) {
57
106
  const xhr = new XMLHttpRequest()
58
107
 
59
- xhr.open("GET", mapUrl, true)
108
+ xhr.open("GET", sourceMapUrl, true)
60
109
 
61
110
  await this.loadXhr(xhr)
62
111
 
63
112
  const consumer = await new SourceMapConsumer(xhr.responseText)
64
113
 
65
- this.sourceMaps.push({consumer, originalUrl, src})
114
+ this.sourceMaps.push({consumer, originalUrl})
66
115
  }
67
116
 
68
117
  loadUrl (url) {
@@ -90,6 +139,7 @@ module.exports = class SourceMapsLoader {
90
139
 
91
140
  for (const trace of stack) {
92
141
  const sourceMapData = this.sourceMaps.find((sourceMapData) => sourceMapData.originalUrl == trace.file)
142
+
93
143
  let filePath, fileString, original
94
144
 
95
145
  if (sourceMapData) {
@@ -100,7 +150,7 @@ module.exports = class SourceMapsLoader {
100
150
  }
101
151
 
102
152
  if (original && original.source) {
103
- filePath = original.source.replace(/^webpack:\/\/\//, "")
153
+ filePath = original.source.replace(/^webpack:\/\/(app|)\//, "")
104
154
  fileString = `${filePath}:${original.line}`
105
155
 
106
156
  if (original.column) {