@kaspernj/api-maker 1.0.271 → 1.0.273

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 (34) hide show
  1. package/__tests__/{cable-subscription-pool.test.js → cable-subscription-pool.test.mjs} +2 -1
  2. package/__tests__/{can-can.test.js → can-can.test.mjs} +1 -1
  3. package/__tests__/{routes-native.test.js → routes-native.test.mjs} +1 -0
  4. package/__tests__/{routes.test.js → routes.test.mjs} +1 -0
  5. package/jest.config.js +6 -1
  6. package/package.json +3 -3
  7. package/src/base-model.mjs +12 -20
  8. package/src/cable-connection-pool.mjs +12 -28
  9. package/src/cable-subscription-pool.mjs +20 -15
  10. package/src/cable-subscription.mjs +5 -3
  11. package/src/cache-key-generator.mjs +8 -3
  12. package/src/can-can.mjs +6 -8
  13. package/src/command-submit-data.mjs +2 -7
  14. package/src/error-logger.mjs +1 -3
  15. package/src/error-messages.mjs +1 -0
  16. package/src/event-destroyed.jsx +1 -3
  17. package/src/event-emitter-listener.jsx +1 -3
  18. package/src/event-listener.jsx +1 -3
  19. package/src/event-model-class.jsx +1 -3
  20. package/src/event-updated.jsx +1 -3
  21. package/src/logger.mjs +17 -14
  22. package/src/session-status-updater.mjs +3 -3
  23. package/src/source-maps-loader.mjs +5 -7
  24. package/src/table/table-settings.js +24 -7
  25. /package/__tests__/{base-model.test.js → base-model.test.mjs} +0 -0
  26. /package/__tests__/{cable-connection-pool.test.js → cable-connection-pool.test.mjs} +0 -0
  27. /package/__tests__/{collection.test.js → collection.test.mjs} +0 -0
  28. /package/__tests__/{custom-error.test.js → custom-error.test.mjs} +0 -0
  29. /package/__tests__/{model-name.test.js → model-name.test.mjs} +0 -0
  30. /package/__tests__/{model-prop-type.test.js → model-prop-type.test.mjs} +0 -0
  31. /package/__tests__/{params.test.js → params.test.mjs} +0 -0
  32. /package/__tests__/{serializer.test.js → serializer.test.mjs} +0 -0
  33. /package/__tests__/support/{task.js → task.mjs} +0 -0
  34. /package/__tests__/support/{user.js → user.mjs} +0 -0
@@ -1,7 +1,8 @@
1
+ import CableSubscriptionPool from "../src/cable-subscription-pool.mjs"
2
+
1
3
  jest.mock("@rails/actioncable", () => ({
2
4
  createConsumer: () => ({})
3
5
  }))
4
- import CableSubscriptionPool from "../src/cable-subscription-pool.mjs"
5
6
 
6
7
  describe("CableSubscriptionPool", () => {
7
8
  describe("onUnsubscribe", () => {
@@ -1,5 +1,6 @@
1
1
  import CanCan from "../src/can-can.mjs"
2
2
  import {jest} from "@jest/globals"
3
+ import Services from "../src/services.mjs"
3
4
 
4
5
  jest.mock("../src/services.mjs")
5
6
 
@@ -8,7 +9,6 @@ describe("CanCan", () => {
8
9
 
9
10
  describe("resetAbilities", () => {
10
11
  test("that reset abilities and load abilities not have concurrency issues", async () => {
11
- import Services from "../src/services.mjs"
12
12
  const mockedCurrent = jest.fn().mockReturnValue({
13
13
  sendRequest: async () => ({abilities: ["loaded"]})
14
14
  })
@@ -1,4 +1,5 @@
1
1
  import RoutesNative from "../src/routes-native.mjs"
2
+
2
3
  const testRoutes = () => ({
3
4
  routes: [
4
5
  {"name": "blank", "path": "/blank", "component": "blank"},
@@ -1,4 +1,5 @@
1
1
  import Routes from "../src/routes.mjs"
2
+
2
3
  const testRoutes = {
3
4
  routes: [
4
5
  {"name": "blank", "path": "/blank", "component": "blank"},
package/jest.config.js CHANGED
@@ -1,4 +1,9 @@
1
1
  export default {
2
2
  testRegex: "__tests__/.*\.test\.(m|)js$", // eslint-disable-line no-useless-escape
3
- transform: {}
3
+ "transformIgnorePatterns": [
4
+ "node_modules/(?!variables/.*)"
5
+ ],
6
+ "transform": {
7
+ "^.+\\.mjs?$": "babel-jest"
8
+ }
4
9
  }
package/package.json CHANGED
@@ -16,7 +16,7 @@
16
16
  ]
17
17
  },
18
18
  "name": "@kaspernj/api-maker",
19
- "version": "1.0.271",
19
+ "version": "1.0.273",
20
20
  "type": "module",
21
21
  "description": "",
22
22
  "main": "index.js",
@@ -33,14 +33,14 @@
33
33
  "scripts": {
34
34
  "eslint": "eslint --ext .mjs,.js,.jsx",
35
35
  "eslint-find-rules": "eslint-find-rules",
36
- "test": "jest"
36
+ "test": "node --experimental-vm-modules ./node_modules/.bin/jest"
37
37
  },
38
38
  "dependencies": {
39
39
  "@rails/actioncable": ">= 6.1.0",
40
40
  "clone-deep": ">= 4.0.1",
41
41
  "debounce": ">= 1.2.1",
42
42
  "diggerize": ">= 1.0.5",
43
- "epic-locks": ">= 1.0.1",
43
+ "epic-locks": ">= 1.0.2",
44
44
  "form-data-objectizer": ">= 1.0.0",
45
45
  "form-serialize": ">= 0.7.2",
46
46
  "format-number": ">= 3.0.0",
@@ -153,6 +153,14 @@ export default class BaseModel {
153
153
  return foundReflection
154
154
  }
155
155
 
156
+ static _token () {
157
+ const csrfTokenElement = document.querySelector("meta[name='csrf-token']")
158
+
159
+ if (csrfTokenElement) {
160
+ return csrfTokenElement.getAttribute("content")
161
+ }
162
+ }
163
+
156
164
  constructor (args = {}) {
157
165
  this.changes = {}
158
166
  this.newRecord = args.isNewRecord
@@ -718,9 +726,7 @@ export default class BaseModel {
718
726
  return {valid: response.valid, errors: response.errors}
719
727
  }
720
728
 
721
- modelClass () {
722
- return this.constructor
723
- }
729
+ modelClass = () => this.constructor
724
730
 
725
731
  preloadRelationship (relationshipName, model) {
726
732
  this.relationshipsCache[BaseModel.snakeCase(relationshipName)] = model
@@ -731,9 +737,7 @@ export default class BaseModel {
731
737
  this._markedForDestruction = true
732
738
  }
733
739
 
734
- markedForDestruction() {
735
- return this._markedForDestruction
736
- }
740
+ markedForDestruction = () => this._markedForDestruction
737
741
 
738
742
  uniqueKey () {
739
743
  if (!this.uniqueKeyValue) {
@@ -766,9 +770,7 @@ export default class BaseModel {
766
770
  }
767
771
  }
768
772
 
769
- _callMemberCommand (args, commandArgs) {
770
- return CommandsPool.addCommand(args, commandArgs)
771
- }
773
+ _callMemberCommand = (args, commandArgs) => CommandsPool.addCommand(args, commandArgs)
772
774
 
773
775
  static _postDataFromArgs (args) {
774
776
  let postData
@@ -959,15 +961,5 @@ export default class BaseModel {
959
961
  }
960
962
  }
961
963
 
962
- primaryKey () {
963
- return this.readAttributeUnderscore(this.constructor.primaryKey())
964
- }
965
-
966
- static _token () {
967
- const csrfTokenElement = document.querySelector("meta[name='csrf-token']")
968
-
969
- if (csrfTokenElement) {
970
- return csrfTokenElement.getAttribute("content")
971
- }
972
- }
964
+ primaryKey = () => this.readAttributeUnderscore(this.constructor.primaryKey())
973
965
  }
@@ -5,19 +5,17 @@ import {dig} from "diggerize"
5
5
  const shared = {}
6
6
 
7
7
  export default class ApiMakerCableConnectionPool {
8
+ cableSubscriptionPools = []
9
+ connections = {}
10
+ upcomingSubscriptionData = {}
11
+ upcomingSubscriptions = {}
12
+
8
13
  static current () {
9
14
  if (!shared.apiMakerCableConnectionPool) shared.apiMakerCableConnectionPool = new ApiMakerCableConnectionPool()
10
15
 
11
16
  return shared.apiMakerCableConnectionPool
12
17
  }
13
18
 
14
- constructor () {
15
- this.cableSubscriptionPools = []
16
- this.connections = {}
17
- this.upcomingSubscriptionData = {}
18
- this.upcomingSubscriptions = {}
19
- }
20
-
21
19
  connectEventToExistingSubscription ({path, subscription, value}) {
22
20
  for (const cableSubscriptionPool of this.cableSubscriptionPools) {
23
21
  if (!cableSubscriptionPool.isConnected()) {
@@ -103,27 +101,13 @@ export default class ApiMakerCableConnectionPool {
103
101
  return subscription
104
102
  }
105
103
 
106
- connectCreated (modelName, callback) {
107
- return this.connectModelEvent({callback, value: true, path: [modelName, "creates"]})
108
- }
109
-
110
- connectEvent (modelName, modelId, eventName, callback) {
111
- return this.connectModelEvent({callback, value: modelId, path: [modelName, "events", eventName]})
112
- }
113
-
114
- connectDestroyed (modelName, modelId, callback) {
115
- return this.connectModelEvent({callback, value: modelId, path: [modelName, "destroys"]})
116
- }
117
-
118
- connectModelClassEvent (modelName, eventName, callback) {
119
- return this.connectModelEvent({callback, value: eventName, path: [modelName, "model_class_events"]})
120
- }
121
-
122
- connectUpdate (modelName, modelId, callback) {
123
- return this.connectModelEvent({callback, value: modelId, path: [modelName, "updates"]})
124
- }
104
+ connectCreated = (modelName, callback) => this.connectModelEvent({callback, value: true, path: [modelName, "creates"]})
105
+ connectEvent = (modelName, modelId, eventName, callback) => this.connectModelEvent({callback, value: modelId, path: [modelName, "events", eventName]})
106
+ connectDestroyed = (modelName, modelId, callback) => this.connectModelEvent({callback, value: modelId, path: [modelName, "destroys"]})
107
+ connectModelClassEvent = (modelName, eventName, callback) => this.connectModelEvent({callback, value: eventName, path: [modelName, "model_class_events"]})
108
+ connectUpdate = (modelName, modelId, callback) => this.connectModelEvent({callback, value: modelId, path: [modelName, "updates"]})
125
109
 
126
- connectUpcoming () {
110
+ connectUpcoming = () => {
127
111
  const subscriptionData = this.upcomingSubscriptionData
128
112
  const subscriptions = this.upcomingSubscriptions
129
113
 
@@ -142,6 +126,6 @@ export default class ApiMakerCableConnectionPool {
142
126
  if (this.scheduleConnectUpcomingTimeout)
143
127
  clearTimeout(this.scheduleConnectUpcomingTimeout)
144
128
 
145
- this.scheduleConnectUpcomingTimeout = setTimeout(() => this.connectUpcoming(), 0)
129
+ this.scheduleConnectUpcomingTimeout = setTimeout(this.connectUpcoming, 0)
146
130
  }
147
131
  }
@@ -5,6 +5,8 @@ import {digg} from "diggerize"
5
5
  import * as inflection from "inflection"
6
6
  import Logger from "./logger.mjs"
7
7
 
8
+ const logger = new Logger({name: "ApiMaker / CableSubscriptionPool"})
9
+
8
10
  export default class ApiMakerCableSubscriptionPool {
9
11
  constructor () {
10
12
  this.activeSubscriptions = 0
@@ -14,6 +16,8 @@ export default class ApiMakerCableSubscriptionPool {
14
16
  connect (subscriptionData) {
15
17
  const globalData = CommandsPool.current().globalRequestData
16
18
 
19
+ logger.log(() => ["Creating subscription", {subscriptionData}])
20
+
17
21
  this.subscription = ChannelsConsumer.subscriptions.create(
18
22
  {
19
23
  channel: "ApiMaker::SubscriptionsChannel",
@@ -21,8 +25,9 @@ export default class ApiMakerCableSubscriptionPool {
21
25
  subscription_data: subscriptionData
22
26
  },
23
27
  {
24
- connected: () => this.onConnected(),
25
- received: (data) => this.onReceived(data)
28
+ connected: this.onConnected,
29
+ received: this.onReceived,
30
+ subscribed: this.onSubscribed
26
31
  }
27
32
  )
28
33
  this.connected = true
@@ -69,17 +74,15 @@ export default class ApiMakerCableSubscriptionPool {
69
74
  }
70
75
  }
71
76
 
72
- isConnected () {
73
- return digg(this, "connected")
74
- }
77
+ isConnected = () => digg(this, "connected")
75
78
 
76
- onConnected () {
79
+ onConnected = () => {
77
80
  this.forEachSubscription(({subscription}) => {
78
81
  subscription.events.emit("connected")
79
82
  })
80
83
  }
81
84
 
82
- onReceived (rawData) {
85
+ onReceived = (rawData) => {
83
86
  const data = Deserializer.parse(rawData)
84
87
  const {a: args, e: eventName, m: model, mi: modelId, mt: modelType, t: type} = data
85
88
  const subscriptions = digg(this, "subscriptions")
@@ -124,13 +127,17 @@ export default class ApiMakerCableSubscriptionPool {
124
127
  }
125
128
  }
126
129
 
130
+ onSubscribed = () => {
131
+ logger.log("onSubscribed")
132
+ }
133
+
127
134
  onUnsubscribe () {
128
- Logger.log(`activeSubscriptions before unsub: ${this.activeSubscriptions}`)
135
+ logger.log(() => `activeSubscriptions before unsub: ${this.activeSubscriptions}`)
129
136
  this.activeSubscriptions -= 1
130
- Logger.log(`activeSubscriptions after unsub: ${this.activeSubscriptions}`)
137
+ logger.log(() => `activeSubscriptions after unsub: ${this.activeSubscriptions}`)
131
138
 
132
139
  if (this.activeSubscriptions <= 0) {
133
- Logger.log("Unsubscribe from ActionCable subscription")
140
+ logger.log("Unsubscribe from ActionCable subscription")
134
141
  this.subscription.unsubscribe()
135
142
  this.connected = false
136
143
  }
@@ -139,8 +146,7 @@ export default class ApiMakerCableSubscriptionPool {
139
146
  registerSubscriptions (subscriptions) {
140
147
  this.subscriptions = subscriptions
141
148
 
142
- Logger.log(`registerSubscriptions: ${subscriptions.length}`)
143
- Logger.log(subscriptions)
149
+ logger.log(() => ["registerSubscriptions", {subscriptions}])
144
150
 
145
151
  for (const modelName in subscriptions) {
146
152
  if (subscriptions[modelName].creates) {
@@ -170,13 +176,12 @@ export default class ApiMakerCableSubscriptionPool {
170
176
  }
171
177
 
172
178
  connectUnsubscriptionForSubscription (subscription) {
173
- Logger.log("Connecting to unsubscribe on subscription")
174
- Logger.log({subscription})
179
+ logger.log(() => ["Connecting to unsubscribe on subscription", {subscription}])
175
180
 
176
181
  this.activeSubscriptions += 1
177
182
 
178
183
  subscription.events.addListener("unsubscribed", () => {
179
- Logger.log("Call onUnsubscribe on self")
184
+ logger.log("Call onUnsubscribe on self")
180
185
 
181
186
  this.onUnsubscribe(subscription)
182
187
  })
@@ -1,6 +1,8 @@
1
1
  import EventEmitter from "events"
2
2
  import Logger from "./logger.mjs"
3
3
 
4
+ const logger = new Logger({name: "ApiMaker / CableSubscription"})
5
+
4
6
  export default class ApiMakerCableSubscription {
5
7
  constructor () {
6
8
  this.events = new EventEmitter()
@@ -9,13 +11,13 @@ export default class ApiMakerCableSubscription {
9
11
 
10
12
  unsubscribe () {
11
13
  if (!this.subscribed) {
12
- Logger.log("Unsubscribed already called")
14
+ logger.log("Unsubscribed already called")
13
15
  return
14
16
  }
15
17
 
16
- Logger.log("Unsubscribe called for subscription")
18
+ logger.log("Unsubscribe called for subscription")
17
19
 
18
- this.events.emit("unsubscribed")
19
20
  this.subscribed = false
21
+ this.events.emit("unsubscribed")
20
22
  }
21
23
  }
@@ -45,17 +45,22 @@ export default class CacheKeyGenerator {
45
45
  const md5 = new SparkMD5()
46
46
 
47
47
  for (const model of this.allModels) {
48
- md5.append("-model-")
48
+ md5.append("--model--")
49
49
  md5.append(model.modelClassData().name)
50
- md5.append("-unique-key-")
50
+ md5.append("--unique-key--")
51
51
  md5.append(model.id() || model.uniqueKey())
52
+
53
+ if (model.markedForDestruction()) {
54
+ md5.append("--marked-for-destruction--")
55
+ }
56
+
52
57
  md5.append("-attributes-")
53
58
 
54
59
  const attributes = model.attributes()
55
60
 
56
61
  for (const attributeName in attributes) {
57
62
  md5.append(attributeName)
58
- md5.append("-attribute-")
63
+ md5.append("--attribute--")
59
64
  md5.append(`${model.readAttributeUnderscore(attributeName)}`)
60
65
  }
61
66
  }
package/src/can-can.mjs CHANGED
@@ -7,20 +7,18 @@ import Services from "./services.mjs"
7
7
  const shared = {}
8
8
 
9
9
  export default class ApiMakerCanCan {
10
+ abilities = []
11
+ abilitiesToLoad = []
12
+ abilitiesToLoadData = []
13
+ events = new EventEmitter()
14
+ lock = new ReadersWriterLock()
15
+
10
16
  static current () {
11
17
  if (!shared.currentApiMakerCanCan) shared.currentApiMakerCanCan = new ApiMakerCanCan()
12
18
 
13
19
  return shared.currentApiMakerCanCan
14
20
  }
15
21
 
16
- constructor () {
17
- this.abilities = []
18
- this.abilitiesToLoad = []
19
- this.abilitiesToLoadData = []
20
- this.events = new EventEmitter()
21
- this.lock = new ReadersWriterLock()
22
- }
23
-
24
22
  can (ability, subject) {
25
23
  let abilityToUse = inflection.underscore(ability)
26
24
  const foundAbility = this.findAbility(abilityToUse, subject)
@@ -7,13 +7,8 @@ export default class ApiMakerCommandSubmitData {
7
7
  this.jsonData = this.traverseObject(this.data, "json")
8
8
  }
9
9
 
10
- getFilesCount () {
11
- return this.filesCount
12
- }
13
-
14
- getJsonData () {
15
- return this.jsonData
16
- }
10
+ getFilesCount = () => this.filesCount
11
+ getJsonData = () => this.jsonData
17
12
 
18
13
  getRawData () {
19
14
  if (!this.rawData) {
@@ -28,9 +28,7 @@ export default class ErrorLogger {
28
28
  this.connectUnhandledRejection()
29
29
  }
30
30
 
31
- getErrors () {
32
- return this.errors
33
- }
31
+ getErrors = () => this.errors
34
32
 
35
33
  hasErrorOccurred() {
36
34
  return digg(this, "errorOccurred")
@@ -1,4 +1,5 @@
1
1
  import {digg} from "diggerize"
2
+
2
3
  const errorMessages = (args) => {
3
4
  if (typeof args.response == "object") {
4
5
  return digg(args, "response", "errors").map((error) => {
@@ -23,7 +23,5 @@ export default class ApiMakerEventDestroyed extends React.PureComponent {
23
23
  this.connectDestroyed = ModelEvents.connectDestroyed(this.props.model, this.props.onDestroyed)
24
24
  }
25
25
 
26
- render () {
27
- return null
28
- }
26
+ render = () => null
29
27
  }
@@ -26,7 +26,5 @@ export default class ApiMakerEventEmitterListener extends React.PureComponent {
26
26
  this.props.onCalled.apply(null, ...args)
27
27
  }
28
28
 
29
- render () {
30
- return null
31
- }
29
+ render = () => null
32
30
  }
@@ -32,7 +32,5 @@ export default class ApiMakerEventListener extends React.PureComponent {
32
32
  this.props.onCalled.apply(null, args)
33
33
  }
34
34
 
35
- render () {
36
- return null
37
- }
35
+ render = () => null
38
36
  }
@@ -24,7 +24,5 @@ export default class ApiMakerEventModelClass extends React.PureComponent {
24
24
  this.connection = ModelEvents.connectModelClass(this.props.modelClass, this.props.event, this.props.onCall)
25
25
  }
26
26
 
27
- render () {
28
- return null
29
- }
27
+ render = () => null
30
28
  }
@@ -68,7 +68,5 @@ export default class ApiMakerEventUpdated extends React.PureComponent {
68
68
  }
69
69
  }
70
70
 
71
- render () {
72
- return null
73
- }
71
+ render = () => null
74
72
  }
package/src/logger.mjs CHANGED
@@ -1,29 +1,32 @@
1
1
  const shared = {}
2
2
 
3
3
  export default class ApiMakerLogger {
4
- static current() {
5
- if (!shared.apiMakerLogger) {
6
- shared.apiMakerLogger = new ApiMakerLogger()
7
- // shared.apiMakerLogger.setDebug(true)
8
- }
4
+ static getGlobalDebug = () => shared.isDebugging
9
5
 
10
- return shared.apiMakerLogger
6
+ static setGlobalDebug(newValue) {
7
+ shared.isDebugging = newValue
11
8
  }
12
9
 
13
- static log(message) {
14
- ApiMakerLogger.current().log(message)
10
+ constructor(args = {}) {
11
+ this.name = args.name
15
12
  }
16
13
 
17
- log(message) {
18
- if (this.debug)
19
- console.log("ApiMaker", message)
14
+ debug(message) {
15
+ if (this.getDebug()) this.log(message)
20
16
  }
21
17
 
22
- getDebug() {
23
- return this.debug
18
+ log(message) {
19
+ if (!this.debug && !ApiMakerLogger.getGlobalDebug()) return
20
+ if (typeof message == "function") message = message()
21
+ if (!Array.isArray(message)) message = [message]
22
+ if (this.name) message.unshift(`${this.name}:`)
23
+
24
+ console.log(...message)
24
25
  }
25
26
 
27
+ getDebug = () => this.isDebugging
28
+
26
29
  setDebug(value) {
27
- this.debug = value
30
+ this.isDebugging = value
28
31
  }
29
32
  }
@@ -3,6 +3,8 @@ import * as inflection from "inflection"
3
3
  import Logger from "./logger.mjs"
4
4
  import wakeEvent from "wake-event"
5
5
 
6
+ const logger = new Logger({name: "ApiMaker / SessionStatusUpdater"})
7
+
6
8
  export default class ApiMakerSessionStatusUpdater {
7
9
  static current () {
8
10
  if (!globalThis.apiMakerSessionStatusUpdater)
@@ -27,9 +29,7 @@ export default class ApiMakerSessionStatusUpdater {
27
29
  wakeEvent(() => this.updateSessionStatus())
28
30
  }
29
31
 
30
- debug (message) {
31
- Logger.log(`API maker / SessionStatusUpdater: ${message}`)
32
- }
32
+ debug = (message) => logger.log(() => message)
33
33
 
34
34
  async sessionStatus () {
35
35
  return new Promise((resolve) => {
@@ -10,6 +10,8 @@ if (SourceMapConsumer.initialize) {
10
10
  })
11
11
  }
12
12
 
13
+ const logger = new Logger({name: "ApiMaker / SourceMapsLoader"})
14
+
13
15
  export default class SourceMapsLoader {
14
16
  constructor () {
15
17
  this.isLoadingSourceMaps = false
@@ -17,10 +19,6 @@ export default class SourceMapsLoader {
17
19
  this.srcLoaded = {}
18
20
  }
19
21
 
20
- debug(messageCallback) {
21
- if (Logger.current().getDebug()) Logger.log(`API maker / SourceMapsLoader: ${messageCallback.call()}`)
22
- }
23
-
24
22
  loadSourceMapsForScriptTags (callback) {
25
23
  this.loadSourceMapsForScriptTagsCallback = callback
26
24
  }
@@ -72,11 +70,11 @@ export default class SourceMapsLoader {
72
70
  const sourceMapUrl = this.getMapURL({src: file})
73
71
 
74
72
  if (sourceMapUrl) {
75
- this.debug(() => `Found source map from error: ${sourceMapUrl}`)
73
+ logger.debug(() => `Found source map from error: ${sourceMapUrl}`)
76
74
 
77
75
  sources.push({originalUrl: file, sourceMapUrl})
78
76
  } else {
79
- this.debug(() => `Coudn't get source map from: ${file}`)
77
+ logger.debug(() => `Coudn't get source map from: ${file}`)
80
78
  }
81
79
  }
82
80
  }
@@ -92,7 +90,7 @@ export default class SourceMapsLoader {
92
90
  const sourceMapUrl = this.getMapURL({script, src: script.src})
93
91
 
94
92
  if (sourceMapUrl) {
95
- this.debug(() => `Found source map from script: ${sourceMapUrl}`)
93
+ logger.debug(() => `Found source map from script: ${sourceMapUrl}`)
96
94
  sources.push({originalUrl: script.src, sourceMapUrl})
97
95
  }
98
96
  }
@@ -2,13 +2,28 @@ import columnIdentifier from "./column-identifier.mjs"
2
2
  import columnVisible from "./column-visible.mjs"
3
3
  import {digg} from "diggerize"
4
4
  import * as inflection from "inflection"
5
+ import {ReadersWriterLock} from "epic-locks"
5
6
  import {serialize as objectToFormData} from "object-to-formdata"
6
7
  import {TableSetting} from "../models.mjs.erb"
7
8
  import {v4 as uuidv4} from "uuid"
8
9
 
10
+ // Have a lock for each unique table identifier
11
+ const tableSettingsLocks = {}
12
+
9
13
  export default class ApiMakerTableSettings {
10
14
  constructor({table}) {
11
15
  this.table = table
16
+ this.setTableSettingsLock()
17
+ }
18
+
19
+ setTableSettingsLock() {
20
+ const identifier = this.identifier()
21
+
22
+ if (!(identifier in tableSettingsLocks)) {
23
+ tableSettingsLocks[identifier] = new ReadersWriterLock()
24
+ }
25
+
26
+ this.tableSettingsLock = digg(tableSettingsLocks, identifier)
12
27
  }
13
28
 
14
29
  columns = () => digg(this, "table", "columnsAsArray")()
@@ -51,15 +66,17 @@ export default class ApiMakerTableSettings {
51
66
  }
52
67
 
53
68
  loadExistingOrCreateTableSettings = async () => {
54
- let tableSetting = await this.loadTableSetting()
69
+ return await this.tableSettingsLock.write(async () => {
70
+ let tableSetting = await this.loadTableSetting()
55
71
 
56
- if (tableSetting) {
57
- tableSetting = await this.updateTableSetting(tableSetting)
58
- } else {
59
- tableSetting = await this.createInitialTableSetting()
60
- }
72
+ if (tableSetting) {
73
+ tableSetting = await this.updateTableSetting(tableSetting)
74
+ } else {
75
+ tableSetting = await this.createInitialTableSetting()
76
+ }
61
77
 
62
- return tableSetting
78
+ return tableSetting
79
+ })
63
80
  }
64
81
 
65
82
  loadTableSetting = async () => {
File without changes
File without changes
File without changes