@kaspernj/api-maker 1.0.245 → 1.0.247

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.245",
19
+ "version": "1.0.247",
20
20
  "type": "module",
21
21
  "description": "",
22
22
  "main": "index.js",
@@ -3,7 +3,7 @@ import SourceMapsLoader from "./source-maps-loader.mjs"
3
3
 
4
4
  export default class ErrorLogger {
5
5
  constructor () {
6
- this.debug = true
6
+ this.debugging = true
7
7
  this.errorOccurred = false
8
8
  this.errors = []
9
9
  this.isHandlingError = false
package/src/logger.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  const shared = {}
2
2
 
3
3
  export default class ApiMakerLogger {
4
- static current () {
4
+ static current() {
5
5
  if (!shared.apiMakerLogger) {
6
6
  shared.apiMakerLogger = new ApiMakerLogger()
7
7
  // shared.apiMakerLogger.setDebug(true)
@@ -10,16 +10,20 @@ export default class ApiMakerLogger {
10
10
  return shared.apiMakerLogger
11
11
  }
12
12
 
13
- static log (message) {
13
+ static log(message) {
14
14
  ApiMakerLogger.current().log(message)
15
15
  }
16
16
 
17
- log (message) {
17
+ log(message) {
18
18
  if (this.debug)
19
19
  console.log("ApiMaker", message)
20
20
  }
21
21
 
22
- setDebug (value) {
22
+ getDebug() {
23
+ return this.debug
24
+ }
25
+
26
+ setDebug(value) {
23
27
  this.debug = value
24
28
  }
25
29
  }
@@ -1,5 +1,6 @@
1
1
  import Devise from "./devise.mjs"
2
2
  import inflection from "inflection"
3
+ import Logger from "./logger.mjs"
3
4
  import wakeEvent from "wake-event"
4
5
 
5
6
  export default class ApiMakerSessionStatusUpdater {
@@ -11,7 +12,6 @@ export default class ApiMakerSessionStatusUpdater {
11
12
  }
12
13
 
13
14
  constructor (args = {}) {
14
- this.debugging = args.debug || false
15
15
  this.events = {}
16
16
  this.timeout = args.timeout || 600000
17
17
 
@@ -28,8 +28,7 @@ export default class ApiMakerSessionStatusUpdater {
28
28
  }
29
29
 
30
30
  debug (message) {
31
- if (this.debugging)
32
- console.log(`ApiMakerSessionStatusUpdater: ${message}`)
31
+ Logger.log(`API maker / SessionStatusUpdater: ${message}`)
33
32
  }
34
33
 
35
34
  async sessionStatus () {
@@ -1,4 +1,5 @@
1
1
  import * as stackTraceParser from "stacktrace-parser"
2
+ import Logger from "./logger.mjs"
2
3
  import {SourceMapConsumer} from "source-map"
3
4
  import uniqunize from "uniqunize"
4
5
 
@@ -11,12 +12,15 @@ if (SourceMapConsumer.initialize) {
11
12
 
12
13
  export default class SourceMapsLoader {
13
14
  constructor () {
14
- this.debug = false
15
15
  this.isLoadingSourceMaps = false
16
16
  this.sourceMaps = []
17
17
  this.srcLoaded = {}
18
18
  }
19
19
 
20
+ debug(messageCallback) {
21
+ if (Logger.current().getDebug()) Logger.log(`API maker / SourceMapsLoader: ${messageCallback.call()}`)
22
+ }
23
+
20
24
  loadSourceMapsForScriptTags (callback) {
21
25
  this.loadSourceMapsForScriptTagsCallback = callback
22
26
  }
@@ -25,15 +29,9 @@ export default class SourceMapsLoader {
25
29
  this.sourceMapForSourceCallback = callback
26
30
  }
27
31
 
28
- getSources(error) {
29
- let sources = this.getSourcesFromScripts()
30
-
31
- if (error) sources = sources.concat(this.getSourcesFromError(error))
32
-
33
- return uniqunize(sources, (source) => source.originalUrl)
34
- }
35
-
36
32
  async loadSourceMaps (error) {
33
+ if (!error) throw new Error("No error was given to SourceMapsLoader#loadSourceMaps")
34
+
37
35
  this.isLoadingSourceMaps = true
38
36
 
39
37
  try {
@@ -55,6 +53,14 @@ export default class SourceMapsLoader {
55
53
  }
56
54
  }
57
55
 
56
+ getSources(error) {
57
+ let sources = this.getSourcesFromScripts()
58
+
59
+ if (error) sources = sources.concat(this.getSourcesFromError(error))
60
+
61
+ return uniqunize(sources, (source) => source.originalUrl)
62
+ }
63
+
58
64
  getSourcesFromError(error) {
59
65
  const stack = stackTraceParser.parse(error.stack)
60
66
  const sources = []
@@ -65,7 +71,13 @@ export default class SourceMapsLoader {
65
71
  if (file != "\u003Canonymous>") {
66
72
  const sourceMapUrl = this.getMapURL({src: file})
67
73
 
68
- if (sourceMapUrl) sources.push({originalUrl: file, sourceMapUrl})
74
+ if (sourceMapUrl) {
75
+ this.debug(() => `Found source map from error: ${sourceMapUrl}`)
76
+
77
+ sources.push({originalUrl: file, sourceMapUrl})
78
+ } else {
79
+ this.debug(() => `Coudn't get source map from: ${file}`)
80
+ }
69
81
  }
70
82
  }
71
83
 
@@ -79,7 +91,10 @@ export default class SourceMapsLoader {
79
91
  for (const script of scripts) {
80
92
  const sourceMapUrl = this.getMapURL({script, src: script.src})
81
93
 
82
- if (sourceMapUrl) sources.push({originalUrl: script.src, sourceMapUrl})
94
+ if (sourceMapUrl) {
95
+ this.debug(() => `Found source map from script: ${sourceMapUrl}`)
96
+ sources.push({originalUrl: script.src, sourceMapUrl})
97
+ }
83
98
  }
84
99
 
85
100
  return sources
@@ -3,10 +3,10 @@ import BelongsToAttributeRow from "./belongs-to-attribute-row"
3
3
  import ConfigReader from "../config-reader"
4
4
  import {digg, digs} from "diggerize"
5
5
  import inflection from "inflection"
6
- import modelLoadWrapper from "../../model-load-wrapper"
7
6
  import PropTypes from "prop-types"
8
7
  import React from "react"
9
8
  import ShowNav from "../show-nav"
9
+ import withModel from "../../with-model"
10
10
 
11
11
  class ApiMakerSuperAdminShowPage extends React.PureComponent {
12
12
  static propTypes = {
@@ -58,7 +58,7 @@ const modelClassResolver = {callback: ({queryParams}) => {
58
58
  return modelClass
59
59
  }}
60
60
 
61
- export default modelLoadWrapper(
61
+ export default withModel(
62
62
  ApiMakerSuperAdminShowPage,
63
63
  modelClassResolver,
64
64
  ({modelClass}) => {
@@ -1,9 +1,9 @@
1
1
  import {digg, digs} from "diggerize"
2
- import modelLoadWrapper from "../model-load-wrapper"
3
2
  import PropTypes from "prop-types"
4
3
  import React from "react"
5
4
  import ModelClassTable from "./model-class-table"
6
5
  import ShowNav from "./show-nav"
6
+ import withModel from "../with-model"
7
7
 
8
8
  class ApiMakerSuperAdminShowReflectionPage extends React.PureComponent {
9
9
  static propTypes = {
@@ -55,7 +55,7 @@ const modelClassResolver = {callback: ({queryParams}) => {
55
55
  return modelClass
56
56
  }}
57
57
 
58
- export default modelLoadWrapper(
58
+ export default withModel(
59
59
  ApiMakerSuperAdminShowReflectionPage,
60
60
  modelClassResolver,
61
61
  {
@@ -0,0 +1,259 @@
1
+ import {debounce} from "debounce"
2
+ import {digg, digs} from "diggerize"
3
+ import EventCreated from "./event-created"
4
+ import EventDestroyed from "./event-destroyed"
5
+ import EventUpdated from "./event-updated"
6
+ import React from "react"
7
+ import Shape from "set-state-compare/src/shape"
8
+ import withQueryParams from "on-location-changed/src/with-query-params"
9
+
10
+ export default (WrappedComponent, withCollectionArgs) => withQueryParams(class ApiMakerWithCollection extends React.PureComponent {
11
+ constructor (props) {
12
+ super(props)
13
+
14
+ let queryName = withCollectionArgs.queryName
15
+
16
+ if (!queryName) queryName = digg(withCollectionArgs.modelClass.modelClassData(), "collectionKey")
17
+
18
+ this.shape = new Shape(this, {
19
+ models: undefined,
20
+ overallCount: undefined,
21
+ query: undefined,
22
+ queryName,
23
+ queryPerKey: `${queryName}_per`,
24
+ queryQName: `${queryName}_q`,
25
+ querySName: `${queryName}_s`,
26
+ queryPageName: `${queryName}_page`,
27
+ qParams: undefined,
28
+ result: undefined,
29
+ searchParams: undefined,
30
+ showNoRecordsAvailableContent: false,
31
+ showNoRecordsFoundContent: false
32
+ })
33
+ }
34
+
35
+ componentDidMount () {
36
+ this.loadQParams()
37
+ this.loadModels()
38
+
39
+ const {noRecordsAvailableContent} = digs(withCollectionArgs)
40
+
41
+ if (noRecordsAvailableContent) this.loadOverallCount()
42
+ }
43
+
44
+ componentDidUpdate(prevProps) {
45
+ const {queryPageName, queryPerKey, queryQName, querySName} = digs(this.shape, "queryPageName", "queryPerKey", "queryQName", "querySName")
46
+ let changed = false
47
+
48
+ // Only load models again if certain things in the URL changes
49
+ if (prevProps.queryParams[queryQName] != this.props.queryParams[queryQName]) {
50
+ changed = true
51
+ } else if (prevProps.queryParams[queryPageName] != this.props.queryParams[queryPageName]) {
52
+ changed = true
53
+ } else if (prevProps.queryParams[queryPerKey] != this.props.queryParams[queryPerKey]) {
54
+ changed = true
55
+ } else if (prevProps.queryParams[querySName] != this.props.queryParams[querySName]) {
56
+ changed = true
57
+ }
58
+
59
+ if (changed) {
60
+ this.loadQParams()
61
+ this.loadModels()
62
+ }
63
+ }
64
+
65
+ async loadOverallCount () {
66
+ const baseQuery = withCollectionArgs.collection || withCollectionArgs.modelClass.all()
67
+ const overallCount = await baseQuery.count()
68
+
69
+ this.shape.set({
70
+ overallCount,
71
+ showNoRecordsAvailableContent: this.showNoRecordsAvailableContent({overallCount}),
72
+ showNoRecordsFoundContent: this.showNoRecordsFoundContent({overallCount})
73
+ })
74
+ }
75
+
76
+ hasQParams() {
77
+ const {queryParams} = digs(this.props, "queryParams")
78
+ const {queryQName} = digs(this.shape, "queryQName")
79
+
80
+ if (queryQName in queryParams) return true
81
+
82
+ return false
83
+ }
84
+
85
+ qParams() {
86
+ const {queryParams} = digs(this.props, "queryParams")
87
+ const {queryQName} = digs(this.shape, "queryQName")
88
+
89
+ if (this.hasQParams()) return JSON.parse(digg(queryParams, queryQName))
90
+
91
+ return {}
92
+ }
93
+
94
+ loadQParams () {
95
+ const {queryParams} = digs(this.props, "queryParams")
96
+ const {querySName} = digs(this.shape, "querySName")
97
+ const qParams = this.hasQParams() ? this.qParams() : Object.assign({}, withCollectionArgs.defaultParams)
98
+ const searchParams = []
99
+
100
+ if (queryParams[querySName]) {
101
+ for (const rawSearchParam of queryParams[querySName]) {
102
+ const parsedSearchParam = JSON.parse(rawSearchParam)
103
+
104
+ searchParams.push(parsedSearchParam)
105
+ }
106
+ }
107
+
108
+ this.shape.set({qParams, searchParams})
109
+ }
110
+
111
+ loadModels = async () => {
112
+ const {queryParams} = digs(this.props, "queryParams")
113
+ const {abilities, collection, groupBy, modelClass, onModelsLoaded, preloads, select, selectColumns} = withCollectionArgs
114
+ const {
115
+ qParams,
116
+ queryPageName,
117
+ queryPerKey,
118
+ queryQName,
119
+ searchParams
120
+ } = digs(
121
+ this.shape,
122
+ "qParams",
123
+ "queryPageName",
124
+ "queryPerKey",
125
+ "queryQName",
126
+ "searchParams"
127
+ )
128
+ const page = queryParams[queryPageName] || 1
129
+ let per = queryParams[queryPerKey] || 30
130
+
131
+ if (per == "all") {
132
+ per = 999_999_999
133
+ } else {
134
+ per = Number(per)
135
+ }
136
+
137
+ let query = collection?.clone() || modelClass.ransack()
138
+
139
+ if (groupBy) query = query.groupBy(...groupBy)
140
+
141
+ query = query
142
+ .ransack(qParams)
143
+ .search(searchParams)
144
+ .searchKey(queryQName)
145
+ .page(page)
146
+ .pageKey(queryPageName)
147
+ .per(per)
148
+ .perKey(queryPerKey)
149
+ .preload(preloads)
150
+ .select(select)
151
+
152
+ if (abilities) query = query.abilities(abilities)
153
+ if (selectColumns) query = query.selectColumns(selectColumns)
154
+
155
+ const result = await query.result()
156
+ const models = result.models()
157
+
158
+ if (onModelsLoaded) {
159
+ onModelsLoaded({
160
+ models,
161
+ qParams,
162
+ query,
163
+ result
164
+ })
165
+ }
166
+
167
+ this.shape.set({
168
+ query,
169
+ result,
170
+ models: result.models(),
171
+ showNoRecordsAvailableContent: this.showNoRecordsAvailableContent({models}),
172
+ showNoRecordsFoundContent: this.showNoRecordsFoundContent({models})
173
+ })
174
+ }
175
+
176
+ loadModelsDebounce = debounce(digg(this, "loadModels"))
177
+ onModelCreated = digg(this, "loadModels")
178
+
179
+ onModelDestroyed = ({destroyedModel}) => {
180
+ const {models} = digs(this.shape, "models")
181
+
182
+ this.shape.set({
183
+ models: models.filter((model) => model.id() != destroyedModel.id())
184
+ })
185
+ }
186
+
187
+ onModelUpdated = ({model: updatedModel}) => {
188
+ const {models} = digs(this.shape, "models")
189
+ const foundModel = models.find((model) => model.id() == updatedModel.id())
190
+
191
+ if (foundModel) this.loadModelsDebounce()
192
+ }
193
+
194
+ showNoRecordsAvailableContent (args) {
195
+ const {noRecordsAvailableContent} = withCollectionArgs
196
+ let models, overallCount
197
+
198
+ if (args.models !== undefined) {
199
+ models = args.models
200
+ } else if (this.shape.models !== undefined) {
201
+ models = this.shape.models
202
+ }
203
+
204
+ if (args.overallCount !== undefined) {
205
+ overallCount = args.overallCount
206
+ } else if (this.shape.overallCount !== undefined) {
207
+ overallCount = this.shape.overallCount
208
+ }
209
+
210
+ if (models === undefined || overallCount === undefined || noRecordsAvailableContent === undefined) return false
211
+ if (models.length === 0 && overallCount === 0 && noRecordsAvailableContent) return true
212
+ }
213
+
214
+ showNoRecordsFoundContent (args) {
215
+ const {noRecordsAvailableContent, noRecordsFoundContent} = withCollectionArgs
216
+ let models, overallCount
217
+
218
+ if (args.models !== undefined) {
219
+ models = args.models
220
+ } else if (this.shape.models !== undefined) {
221
+ models = this.shape.models
222
+ }
223
+
224
+ if (args.overallCount !== undefined) {
225
+ overallCount = args.overallCount
226
+ } else if (this.shape.overallCount !== undefined) {
227
+ overallCount = this.shape.overallCount
228
+ }
229
+
230
+ if (models === undefined || noRecordsFoundContent === undefined) return false
231
+
232
+ // Dont show noRecordsAvailableContent together with noRecordsAvailableContent
233
+ if (models.length === 0 && overallCount === 0 && noRecordsAvailableContent) return false
234
+ if (models.length === 0 && noRecordsFoundContent) return true
235
+ }
236
+
237
+ render() {
238
+ const {modelClass} = digs(withCollectionArgs, "modelClass")
239
+ const {onModelCreated, onModelDestroyed, onModelUpdated} = digs(this, "onModelCreated", "onModelDestroyed", "onModelUpdated")
240
+ const {models} = digs(this.shape, "models")
241
+ const modelsArgName = inflection.camelize(digg(withCollectionArgs.modelClass.modelClassData(), "pluralName"), true)
242
+ const forwardArgs = {}
243
+
244
+ forwardArgs[modelsArgName] = models
245
+
246
+ return (
247
+ <>
248
+ <EventCreated modelClass={modelClass} onCreated={onModelCreated} />
249
+ {models && models.map((model) =>
250
+ <React.Fragment key={model.id()}>
251
+ <EventDestroyed model={model} onDestroyed={onModelDestroyed} />
252
+ <EventUpdated model={model} onUpdated={onModelUpdated} />
253
+ </React.Fragment>
254
+ )}
255
+ <WrappedComponent {...forwardArgs} {...this.props} />
256
+ </>
257
+ )
258
+ }
259
+ })
@@ -6,7 +6,7 @@ import React from "react"
6
6
  import withQueryParams from "on-location-changed/src/with-query-params"
7
7
 
8
8
  export default (WrappedComponent, modelClassArg, argsArg = {}) => {
9
- class ModelLoadWrapper extends React.PureComponent {
9
+ class ApiMakerWithModel extends React.PureComponent {
10
10
  static propTypes = {
11
11
  queryParams: PropTypes.object
12
12
  }
@@ -135,5 +135,5 @@ export default (WrappedComponent, modelClassArg, argsArg = {}) => {
135
135
  onUpdated = this.loadExistingModel
136
136
  }
137
137
 
138
- return withQueryParams(ModelLoadWrapper)
138
+ return withQueryParams(ApiMakerWithModel)
139
139
  }