api_maker 0.0.1 → 0.0.2

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 (135) hide show
  1. checksums.yaml +4 -4
  2. data/app/api_maker/api_helpers/api_maker_helpers.rb +5 -0
  3. data/app/api_maker/services/can_can/load_abilities.rb +30 -0
  4. data/app/api_maker/services/devise/sign_in.rb +64 -0
  5. data/app/api_maker/services/devise/sign_out.rb +9 -0
  6. data/app/api_maker/services/models/find_or_create_by.rb +18 -0
  7. data/app/channels/api_maker/subscriptions_channel.rb +33 -2
  8. data/app/controllers/api_maker/base_controller.rb +7 -3
  9. data/app/controllers/api_maker/commands_controller.rb +26 -4
  10. data/app/controllers/api_maker/session_statuses_controller.rb +1 -1
  11. data/app/services/api_maker/abilities_loader.rb +104 -0
  12. data/app/services/api_maker/application_service.rb +2 -1
  13. data/app/services/api_maker/base_command.rb +248 -0
  14. data/app/services/api_maker/collection_command_service.rb +29 -15
  15. data/app/services/api_maker/collection_loader.rb +124 -0
  16. data/app/services/api_maker/command_failed_error.rb +3 -0
  17. data/app/services/api_maker/command_response.rb +17 -6
  18. data/app/services/api_maker/command_service.rb +3 -3
  19. data/app/services/api_maker/create_command.rb +11 -26
  20. data/app/services/api_maker/create_command_service.rb +3 -3
  21. data/app/services/api_maker/database_type.rb +9 -0
  22. data/app/services/api_maker/deep_merge_params.rb +26 -0
  23. data/app/services/api_maker/deserializer.rb +35 -0
  24. data/app/services/api_maker/destroy_command.rb +15 -21
  25. data/app/services/api_maker/destroy_command_service.rb +3 -3
  26. data/app/services/api_maker/generate_react_native_api_service.rb +3 -19
  27. data/app/services/api_maker/include_helpers.rb +17 -0
  28. data/app/services/api_maker/index_command.rb +8 -88
  29. data/app/services/api_maker/index_command_service.rb +5 -5
  30. data/app/services/api_maker/js_method_namer_service.rb +1 -1
  31. data/app/services/api_maker/locals_from_controller.rb +14 -0
  32. data/app/services/api_maker/member_command_service.rb +15 -13
  33. data/app/services/api_maker/model_classes_java_script_generator_service.rb +37 -0
  34. data/app/services/api_maker/model_content_generator_service.rb +17 -21
  35. data/app/services/api_maker/models/save.rb +29 -0
  36. data/app/services/api_maker/models_finder_service.rb +6 -2
  37. data/app/services/api_maker/models_generator_service.rb +6 -43
  38. data/app/services/api_maker/move_components_to_routes.rb +50 -0
  39. data/app/services/api_maker/primary_id_for_model.rb +6 -0
  40. data/app/services/api_maker/reset_indexed_db_service.rb +36 -0
  41. data/app/services/api_maker/routes_file_reloader.rb +20 -0
  42. data/app/services/api_maker/select_columns_on_collection.rb +78 -0
  43. data/app/services/api_maker/select_parser.rb +32 -0
  44. data/app/services/api_maker/service_command.rb +27 -0
  45. data/app/services/api_maker/service_command_service.rb +14 -0
  46. data/app/services/api_maker/simple_model_errors.rb +52 -0
  47. data/app/services/api_maker/update_command.rb +8 -24
  48. data/app/services/api_maker/update_command_service.rb +3 -3
  49. data/app/services/api_maker/valid_command.rb +4 -13
  50. data/app/services/api_maker/valid_command_service.rb +3 -3
  51. data/app/services/api_maker/validation_errors_generator_service.rb +146 -0
  52. data/app/views/api_maker/_data.html.erb +17 -11
  53. data/config/routes.rb +0 -2
  54. data/lib/api_maker/ability.rb +22 -7
  55. data/lib/api_maker/ability_loader.rb +9 -6
  56. data/lib/api_maker/base_collection_instance.rb +15 -0
  57. data/lib/api_maker/base_resource.rb +135 -9
  58. data/lib/api_maker/base_service.rb +14 -0
  59. data/lib/api_maker/collection_serializer.rb +95 -34
  60. data/lib/api_maker/command_spec_helper.rb +41 -11
  61. data/lib/api_maker/configuration.rb +31 -4
  62. data/lib/api_maker/expect_to_able_to_helper.rb +31 -0
  63. data/lib/api_maker/individual_command.rb +24 -9
  64. data/lib/api_maker/javascript/model-template.js.erb +39 -25
  65. data/lib/api_maker/javascript/models.js.erb +6 -0
  66. data/lib/api_maker/loader.rb +1 -1
  67. data/lib/api_maker/memory_storage.rb +1 -1
  68. data/lib/api_maker/model_extensions.rb +34 -18
  69. data/lib/api_maker/permitted_params_argument.rb +5 -1
  70. data/lib/api_maker/preloader.rb +71 -32
  71. data/lib/api_maker/preloader_base.rb +108 -0
  72. data/lib/api_maker/preloader_belongs_to.rb +34 -33
  73. data/lib/api_maker/preloader_has_many.rb +45 -39
  74. data/lib/api_maker/preloader_has_one.rb +30 -47
  75. data/lib/api_maker/railtie.rb +3 -11
  76. data/lib/api_maker/relationship_preloader.rb +42 -0
  77. data/lib/api_maker/resource_routing.rb +18 -4
  78. data/lib/api_maker/result_parser.rb +34 -20
  79. data/lib/api_maker/serializer.rb +53 -22
  80. data/lib/api_maker/spec_helper/browser_logs.rb +14 -0
  81. data/lib/api_maker/spec_helper/execute_collection_command.rb +46 -0
  82. data/lib/api_maker/spec_helper/execute_member_command.rb +52 -0
  83. data/lib/api_maker/spec_helper/expect_no_browser_errors.rb +18 -0
  84. data/lib/api_maker/spec_helper/wait_for_expect.rb +20 -0
  85. data/lib/api_maker/spec_helper/wait_for_flash_message.rb +21 -0
  86. data/lib/api_maker/spec_helper.rb +112 -48
  87. data/lib/api_maker/version.rb +1 -1
  88. data/lib/api_maker.rb +7 -3
  89. metadata +108 -89
  90. data/README.md +0 -476
  91. data/app/controllers/api_maker/devise_controller.rb +0 -60
  92. data/lib/api_maker/base_command.rb +0 -81
  93. data/lib/api_maker/javascript/api.js +0 -92
  94. data/lib/api_maker/javascript/base-model.js +0 -543
  95. data/lib/api_maker/javascript/bootstrap/attribute-row.jsx +0 -16
  96. data/lib/api_maker/javascript/bootstrap/attribute-rows.jsx +0 -47
  97. data/lib/api_maker/javascript/bootstrap/card.jsx +0 -79
  98. data/lib/api_maker/javascript/bootstrap/checkbox.jsx +0 -127
  99. data/lib/api_maker/javascript/bootstrap/checkboxes.jsx +0 -105
  100. data/lib/api_maker/javascript/bootstrap/live-table.jsx +0 -168
  101. data/lib/api_maker/javascript/bootstrap/money-input.jsx +0 -136
  102. data/lib/api_maker/javascript/bootstrap/radio-buttons.jsx +0 -80
  103. data/lib/api_maker/javascript/bootstrap/select.jsx +0 -168
  104. data/lib/api_maker/javascript/bootstrap/string-input.jsx +0 -203
  105. data/lib/api_maker/javascript/cable-connection-pool.js +0 -169
  106. data/lib/api_maker/javascript/cable-subscription-pool.js +0 -111
  107. data/lib/api_maker/javascript/cable-subscription.js +0 -33
  108. data/lib/api_maker/javascript/collection.js +0 -186
  109. data/lib/api_maker/javascript/commands-pool.js +0 -123
  110. data/lib/api_maker/javascript/custom-error.js +0 -14
  111. data/lib/api_maker/javascript/deserializer.js +0 -35
  112. data/lib/api_maker/javascript/devise.js.erb +0 -113
  113. data/lib/api_maker/javascript/error-logger.js +0 -119
  114. data/lib/api_maker/javascript/event-connection.jsx +0 -24
  115. data/lib/api_maker/javascript/event-created.jsx +0 -26
  116. data/lib/api_maker/javascript/event-destroyed.jsx +0 -26
  117. data/lib/api_maker/javascript/event-emitter-listener.jsx +0 -32
  118. data/lib/api_maker/javascript/event-listener.jsx +0 -41
  119. data/lib/api_maker/javascript/event-updated.jsx +0 -26
  120. data/lib/api_maker/javascript/form-data-to-object.js +0 -70
  121. data/lib/api_maker/javascript/included.js +0 -39
  122. data/lib/api_maker/javascript/key-value-store.js +0 -47
  123. data/lib/api_maker/javascript/logger.js +0 -23
  124. data/lib/api_maker/javascript/model-name.js +0 -21
  125. data/lib/api_maker/javascript/models-response-reader.js +0 -43
  126. data/lib/api_maker/javascript/paginate.jsx +0 -128
  127. data/lib/api_maker/javascript/params.js +0 -68
  128. data/lib/api_maker/javascript/resource-route.jsx +0 -75
  129. data/lib/api_maker/javascript/resource-routes.jsx +0 -36
  130. data/lib/api_maker/javascript/result.js +0 -25
  131. data/lib/api_maker/javascript/session-status-updater.js +0 -113
  132. data/lib/api_maker/javascript/sort-link.jsx +0 -88
  133. data/lib/api_maker/javascript/updated-attribute.jsx +0 -60
  134. data/lib/api_maker/preloader_through.rb +0 -101
  135. data/lib/api_maker/relationship_includer.rb +0 -42
@@ -1,168 +0,0 @@
1
- import PropTypes from "prop-types"
2
- import PropTypesExact from "prop-types-exact"
3
- import React from "react"
4
-
5
- const inflection = require("inflection")
6
-
7
- export default class BootstrapSelect extends React.Component {
8
- static propTypes = PropTypesExact({
9
- attribute: PropTypes.string,
10
- children: PropTypes.node,
11
- className: PropTypes.string,
12
- "data-controller": PropTypes.string,
13
- defaultValue: PropTypes.oneOfType([PropTypes.array, PropTypes.number, PropTypes.string]),
14
- description: PropTypes.node,
15
- disabled: PropTypes.bool,
16
- id: PropTypes.string,
17
- includeBlank: PropTypes.bool,
18
- hideSearch: PropTypes.bool,
19
- hint: PropTypes.node,
20
- hintBottom: PropTypes.node,
21
- label: PropTypes.node,
22
- labelContainerClassName: PropTypes.string,
23
- model: PropTypes.object,
24
- multiple: PropTypes.bool,
25
- name: PropTypes.string,
26
- placeholder: PropTypes.string,
27
- onChange: PropTypes.func,
28
- options: PropTypes.array,
29
- select2: PropTypes.bool,
30
- wrapperClassName: PropTypes.string,
31
- })
32
-
33
- componentDidMount() {
34
- if (this.props.select2 && this.props.onChange)
35
- $(this.refs.select).on("change", this.props.onChange)
36
-
37
- // Set default value to nothing when multiple
38
- if (this.props.select2 && this.props.multiple && !this.inputDefaultValue())
39
- $(this.refs.select).val("")
40
- }
41
-
42
- componentWillUnmount() {
43
- if (this.props.select2 && this.props.onChange)
44
- $(this.refs.select).off("change", this.props.onChange)
45
- }
46
-
47
- render() {
48
- return (
49
- <div className={this.wrapperClassName()}>
50
- {this.label() &&
51
- <div className={this.props.labelContainerClassName ? this.props.labelContainerClassName : null}>
52
- <label className={this.labelClassName()} htmlFor={this.inputId()}>
53
- {this.label()}
54
- </label>
55
- </div>
56
- }
57
- {this.props.description &&
58
- <div className="mb-4">
59
- {this.props.description}
60
- </div>
61
- }
62
- {this.props.hint &&
63
- <span className="form-text text-muted font-smoothing font-xs">
64
- {this.props.hint}
65
- </span>
66
- }
67
- <select
68
- data-controller={this.dataController()}
69
- data-hide-search={this.props.hideSearch}
70
- data-placeholder={this.props.placeholder}
71
- defaultValue={this.inputDefaultValue()}
72
- className={`form-control ${this.props.className}`}
73
- disabled={this.props.disabled}
74
- id={this.inputId()}
75
- multiple={this.props.multiple}
76
- name={this.inputName()}
77
- onChange={this.props.onChange}
78
- ref="select"
79
- >
80
- {this.includeBlank() &&
81
- <option />
82
- }
83
- {this.props.options && this.props.options.map(option => (
84
- <option key={`select-option-${option[1]}`} value={option[1]}>{option[0]}</option>
85
- ))}
86
- {this.props.children}
87
- </select>
88
- {this.props.hintBottom &&
89
- <span className="form-text text-muted font-smoothing font-xs">
90
- {this.props.hintBottom}
91
- </span>
92
- }
93
- </div>
94
- )
95
- }
96
-
97
- dataController() {
98
- if ("data-controller" in this.props) {
99
- return this.props["data-controller"]
100
- } else if (this.props.select2) {
101
- return "select2--default"
102
- }
103
- }
104
-
105
- includeBlank() {
106
- if (this.props.includeBlank || (this.props.placeholder && !this.props.multiple)) {
107
- return true
108
- } else {
109
- return false
110
- }
111
- }
112
-
113
- inputDefaultValue() {
114
- if ("defaultValue" in this.props) {
115
- return this.props.defaultValue
116
- } else if (this.props.selected) {
117
- return this.props.selected
118
- } else if (this.props.model) {
119
- if (!this.props.model[this.props.attribute])
120
- throw new Error(`No attribute by that name: ${this.props.attribute}`)
121
-
122
- return this.props.model[this.props.attribute]()
123
- }
124
- }
125
-
126
- inputId() {
127
- if ("id" in this.props) {
128
- return this.props.id
129
- } else if (this.props.model) {
130
- return `${this.props.model.modelClassData().paramKey}_${inflection.underscore(this.props.attribute)}`
131
- }
132
- }
133
-
134
- inputName() {
135
- if ("name" in this.props) {
136
- return this.props.name
137
- } else if (this.props.model) {
138
- return `${this.props.model.modelClassData().paramKey}[${inflection.underscore(this.props.attribute)}]`
139
- }
140
- }
141
-
142
- label() {
143
- if ("label" in this.props) {
144
- return this.props.label
145
- } else if (this.props.model) {
146
- let attributeMethodName = inflection.camelize(this.props.attribute.replace(/_id$/, ""), true)
147
- return this.props.model.modelClass().humanAttributeName(attributeMethodName)
148
- }
149
- }
150
-
151
- labelClassName() {
152
- let classNames = ["form-group-label"]
153
-
154
- if (this.props.labelClassName)
155
- classNames.push(this.props.labelClassName)
156
-
157
- return classNames.join(" ")
158
- }
159
-
160
- wrapperClassName() {
161
- let classNames = ["form-group", "component-bootstrap-select"]
162
-
163
- if (this.props.wrapperClassName)
164
- classNames.push(this.props.wrapperClassName)
165
-
166
- return classNames.join(" ")
167
- }
168
- }
@@ -1,203 +0,0 @@
1
- import MoneyInput from "./money-input"
2
- import PropTypes from "prop-types"
3
- import PropTypesExact from "prop-types-exact"
4
- import React from "react"
5
-
6
- const inflection = require("inflection")
7
-
8
- export default class BootstrapStringInput extends React.Component {
9
- static propTypes = PropTypesExact({
10
- append: PropTypes.node,
11
- attribute: PropTypes.string,
12
- autoComplete: PropTypes.oneOfType([PropTypes.bool, PropTypes.string]),
13
- className: PropTypes.string,
14
- currenciesCollection: PropTypes.array,
15
- currencyName: PropTypes.string,
16
- "data-controller": PropTypes.string,
17
- defaultValue: PropTypes.node,
18
- disabled: PropTypes.bool,
19
- hint: PropTypes.node,
20
- hintBottom: PropTypes.node,
21
- id: PropTypes.string,
22
- label: PropTypes.node,
23
- labelClassName: PropTypes.string,
24
- maxLength: PropTypes.number,
25
- model: PropTypes.object,
26
- name: PropTypes.string,
27
- onChange: PropTypes.func,
28
- onKeyUp: PropTypes.func,
29
- placeholder: PropTypes.node,
30
- rows: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
31
- step: PropTypes.number,
32
- small: PropTypes.bool,
33
- type: PropTypes.string,
34
- wrapperClassName: PropTypes.string
35
- })
36
-
37
- render() {
38
- return (
39
- <div className={this.wrapperClassName()} ref="wrapper">
40
- {this.label() &&
41
- <label className={this.labelClassName()} htmlFor={this.inputId()}>
42
- {this.label()}
43
- </label>
44
- }
45
- {this.props.hint &&
46
- <span className="form-text text-muted font-smoothing font-xs">
47
- {this.props.hint}
48
- </span>
49
- }
50
- {this.inputType() == "textarea" &&
51
- <textarea
52
- className={this.inputClassName()}
53
- data-controller={this.props["data-controller"]}
54
- defaultValue={this.inputDefaultValue()}
55
- id={this.inputId()}
56
- maxLength={this.props.maxLength}
57
- name={this.inputName()}
58
- onChange={this.props.onChange}
59
- onKeyUp={this.props.onKeyUp}
60
- placeholder={this.props.placeholder}
61
- ref="input"
62
- rows={this.props.rows}
63
- />
64
- }
65
- {this.inputType() == "money" &&
66
- <MoneyInput
67
- attribute={this.props.attribute}
68
- currenciesCollection={this.props.currenciesCollection}
69
- currencyName={this.props.currencyName}
70
- model={this.props.model}
71
- name={this.props.name}
72
- className={this.inputClassName()}
73
- onChange={this.props.onChange}
74
- placeholder={this.props.placeholder}
75
- small={this.props.small}
76
- ref="money"
77
- />
78
- }
79
- {this.inputType() != "textarea" && this.inputType() != "money" &&
80
- <div className="input-group">
81
- {this.props.prepend &&
82
- <div className="input-group-prepend">
83
- <span className="input-group-text">
84
- {this.props.prepend}
85
- </span>
86
- </div>
87
- }
88
- <input
89
- autoComplete={this.props.autoComplete}
90
- className={this.inputClassName()}
91
- data-controller={this.props["data-controller"]}
92
- defaultValue={this.inputDefaultValue()}
93
- disabled={this.props.disabled}
94
- id={this.inputId()}
95
- name={this.inputName()}
96
- onChange={this.props.onChange}
97
- onKeyUp={this.props.onKeyUp}
98
- placeholder={this.props.placeholder}
99
- ref="input"
100
- step={this.props.step}
101
- type={this.inputType()}
102
- />
103
- {this.props.append &&
104
- <div className="input-group-append">
105
- <span className="input-group-text">
106
- {this.props.append}
107
- </span>
108
- </div>
109
- }
110
- </div>
111
- }
112
- {this.props.hintBottom &&
113
- <span className="form-text text-muted font-smoothing font-xs">
114
- {this.props.hintBottom}
115
- </span>
116
- }
117
- </div>
118
- )
119
- }
120
-
121
- inputClassName() {
122
- var classNames = ["form-control"]
123
-
124
- if (this.props.className)
125
- classNames.push(this.props.className)
126
-
127
- return classNames.join(" ")
128
- }
129
-
130
- inputDefaultValue() {
131
- if ("defaultValue" in this.props) {
132
- return this.formatValue(this.props.defaultValue)
133
- } else if (this.props.model) {
134
- if (!this.props.model[this.props.attribute])
135
- throw new Error(`No such attribute: ${this.props.model.modelClassData().name}#${this.props.attribute}`)
136
-
137
- return this.formatValue(this.props.model[this.props.attribute]())
138
- }
139
- }
140
-
141
- formatValue(value) {
142
- // We need to use a certain format for datetime-local
143
- if (this.inputType() == "datetime-local" && value instanceof Date) {
144
- return I18n.strftime(value, "%Y-%m-%dT%H:%M:%S")
145
- } else if (this.inputType() == "date" && value instanceof Date) {
146
- return I18n.strftime(value, "%Y-%m-%d")
147
- }
148
-
149
- return value
150
- }
151
-
152
- inputId() {
153
- if ("id" in this.props) {
154
- return this.props.id
155
- } else if (this.props.model) {
156
- return `${this.props.model.modelClassData().paramKey}_${inflection.underscore(this.props.attribute)}`
157
- }
158
- }
159
-
160
- inputName() {
161
- if ("name" in this.props) {
162
- return this.props.name
163
- } else if (this.props.model) {
164
- return `${this.props.model.modelClassData().paramKey}[${inflection.underscore(this.props.attribute)}]`
165
- }
166
- }
167
-
168
- inputType() {
169
- if (this.props.type) {
170
- return this.props.type
171
- } else {
172
- return "text"
173
- }
174
- }
175
-
176
- label() {
177
- if (this.props.label === false) {
178
- return null
179
- } else if (this.props.label) {
180
- return this.props.label
181
- } else if (this.props.model) {
182
- return this.props.model.modelClass().humanAttributeName(this.props.attribute)
183
- }
184
- }
185
-
186
- labelClassName() {
187
- var classNames = []
188
-
189
- if (this.props.labelClassName)
190
- classNames.push(this.props.labelClassName)
191
-
192
- return classNames.join(" ")
193
- }
194
-
195
- wrapperClassName() {
196
- var classNames = ["form-group", "component-bootstrap-string-input"]
197
-
198
- if (this.props.wrapperClassName)
199
- classNames.push(this.props.wrapperClassName)
200
-
201
- return classNames.join(" ")
202
- }
203
- }
@@ -1,169 +0,0 @@
1
- import CableSubscriptionPool from "./cable-subscription-pool"
2
- import CableSubscription from "./cable-subscription"
3
-
4
- export default class ApiMakerCableConnectionPool {
5
- static current() {
6
- if (!window.apiMakerCableConnectionPool)
7
- window.apiMakerCableConnectionPool = new ApiMakerCableConnectionPool()
8
-
9
- return window.apiMakerCableConnectionPool
10
- }
11
-
12
- constructor() {
13
- this.connections = {}
14
- this.upcomingSubscriptionData = {}
15
- this.upcomingSubscriptions = []
16
- }
17
-
18
- connectCreated(modelName, callback) {
19
- if (!this.upcomingSubscriptionData[modelName])
20
- this.upcomingSubscriptionData[modelName] = {}
21
-
22
- if (!this.upcomingSubscriptionData[modelName]["creates"])
23
- this.upcomingSubscriptionData[modelName]["creates"] = true
24
-
25
- if (!this.upcomingSubscriptions[modelName])
26
- this.upcomingSubscriptions[modelName] = {}
27
-
28
- if (!this.upcomingSubscriptions[modelName]["creates"])
29
- this.upcomingSubscriptions[modelName]["creates"] = []
30
-
31
- var subscription = new CableSubscription({
32
- callback: callback,
33
- modelName: modelName
34
- })
35
-
36
- this.upcomingSubscriptions[modelName]["creates"].push(subscription)
37
-
38
- this.scheduleConnectUpcoming()
39
-
40
- return subscription
41
- }
42
-
43
- connectDestroyed(modelName, modelId, callback) {
44
- if (!this.upcomingSubscriptionData[modelName])
45
- this.upcomingSubscriptionData[modelName] = {}
46
-
47
- if (!this.upcomingSubscriptionData[modelName]["destroys"])
48
- this.upcomingSubscriptionData[modelName]["destroys"] = []
49
-
50
- if (!this.upcomingSubscriptionData[modelName]["destroys"].includes(modelId))
51
- this.upcomingSubscriptionData[modelName]["destroys"].push(modelId)
52
-
53
- if (!this.upcomingSubscriptions[modelName])
54
- this.upcomingSubscriptions[modelName] = {}
55
-
56
- if (!this.upcomingSubscriptions[modelName]["destroys"])
57
- this.upcomingSubscriptions[modelName]["destroys"] = {}
58
-
59
- if (!this.upcomingSubscriptions[modelName]["destroys"][modelId])
60
- this.upcomingSubscriptions[modelName]["destroys"][modelId] = []
61
-
62
- var subscription = new CableSubscription({
63
- callback: callback,
64
- modelName: modelName,
65
- modelId: modelId
66
- })
67
-
68
- this.upcomingSubscriptions[modelName]["destroys"][modelId].push(subscription)
69
-
70
- this.scheduleConnectUpcoming()
71
-
72
- return subscription
73
- }
74
-
75
- connectEvent(modelName, modelId, eventName, callback) {
76
- if (!this.upcomingSubscriptionData[modelName])
77
- this.upcomingSubscriptionData[modelName] = {}
78
-
79
- if (!this.upcomingSubscriptionData[modelName]["events"])
80
- this.upcomingSubscriptionData[modelName]["events"] = {}
81
-
82
- if (!this.upcomingSubscriptionData[modelName]["events"][eventName])
83
- this.upcomingSubscriptionData[modelName]["events"][eventName] = []
84
-
85
- if (!this.upcomingSubscriptionData[modelName]["events"][eventName].includes(modelId))
86
- this.upcomingSubscriptionData[modelName]["events"][eventName].push(modelId)
87
-
88
- if (!this.upcomingSubscriptions[modelName])
89
- this.upcomingSubscriptions[modelName] = {}
90
-
91
- if (!this.upcomingSubscriptions[modelName]["events"])
92
- this.upcomingSubscriptions[modelName]["events"] = {}
93
-
94
- if (!this.upcomingSubscriptions[modelName]["events"])
95
- this.upcomingSubscriptions[modelName]["events"] = {}
96
-
97
- if (!this.upcomingSubscriptions[modelName]["events"][modelId])
98
- this.upcomingSubscriptions[modelName]["events"][modelId] = {}
99
-
100
- if (!this.upcomingSubscriptions[modelName]["events"][modelId][eventName])
101
- this.upcomingSubscriptions[modelName]["events"][modelId][eventName] = []
102
-
103
- var subscription = new CableSubscription({
104
- callback: callback,
105
- modelName: modelName,
106
- modelId: modelId
107
- })
108
-
109
- this.upcomingSubscriptions[modelName]["events"][modelId][eventName].push(subscription)
110
-
111
- this.scheduleConnectUpcoming()
112
-
113
- return subscription
114
- }
115
-
116
- connectUpdate(modelName, modelId, callback) {
117
- if (!this.upcomingSubscriptionData[modelName])
118
- this.upcomingSubscriptionData[modelName] = {}
119
-
120
- if (!this.upcomingSubscriptionData[modelName]["updates"])
121
- this.upcomingSubscriptionData[modelName]["updates"] = []
122
-
123
- if (!this.upcomingSubscriptionData[modelName]["updates"].includes(modelId))
124
- this.upcomingSubscriptionData[modelName]["updates"].push(modelId)
125
-
126
- if (!this.upcomingSubscriptions[modelName])
127
- this.upcomingSubscriptions[modelName] = {}
128
-
129
- if (!this.upcomingSubscriptions[modelName]["updates"])
130
- this.upcomingSubscriptions[modelName]["updates"] = {}
131
-
132
- if (!this.upcomingSubscriptions[modelName]["updates"][modelId])
133
- this.upcomingSubscriptions[modelName]["updates"][modelId] = []
134
-
135
- var subscription = new CableSubscription({
136
- callback: callback,
137
- modelName: modelName,
138
- modelId: modelId
139
- })
140
-
141
- this.upcomingSubscriptions[modelName]["updates"][modelId].push(subscription)
142
-
143
- this.scheduleConnectUpcoming()
144
-
145
- return subscription
146
- }
147
-
148
- connectUpcoming() {
149
- var subscriptionData = this.upcomingSubscriptionData
150
- var subscriptions = this.upcomingSubscriptions
151
-
152
- this.upcomingSubscriptionData = {}
153
- this.upcomingSubscriptions = {}
154
-
155
- var cableSubscriptionPool = new CableSubscriptionPool({
156
- subscriptionData: subscriptionData,
157
- subscriptions: subscriptions
158
- })
159
-
160
- return cableSubscriptionPool
161
- }
162
-
163
- scheduleConnectUpcoming() {
164
- if (this.scheduleConnectUpcomingTimeout)
165
- clearTimeout(this.scheduleConnectUpcomingTimeout)
166
-
167
- this.scheduleConnectUpcomingTimeout = setTimeout(() => this.connectUpcoming(), 50)
168
- }
169
- }
@@ -1,111 +0,0 @@
1
- import CommandsPool from "./commands-pool"
2
- import Deserializer from "./deserializer"
3
- import Logger from "./logger"
4
-
5
- const inflection = require("inflection")
6
-
7
- export default class ApiMakerCableSubscriptionPool {
8
- constructor(props) {
9
- this.props = props
10
- this.activeSubscriptions = 0
11
- this.registerSubscriptions()
12
- this.connect()
13
- }
14
-
15
- connect() {
16
- var globalData = CommandsPool.current().globalRequestData
17
-
18
- this.subscription = App.cable.subscriptions.create(
19
- {channel: "ApiMaker::SubscriptionsChannel", global: globalData, subscription_data: this.props.subscriptionData},
20
- {received: (data) => this.onReceived(data)}
21
- )
22
- }
23
-
24
- onReceived(rawData) {
25
- var data = Deserializer.parse(rawData)
26
- var modelType = data.model_type
27
- var modelName = inflection.camelize(inflection.singularize(modelType.replace(/-/g, "_")))
28
- var modelId = data.model_id
29
- var modelInstance = data.model
30
- var subscriptions = this.props.subscriptions
31
-
32
- if (data.type == "update") {
33
- for(var subscription of subscriptions[modelName]["updates"][modelId]) {
34
- subscription.onReceived({model: modelInstance})
35
- }
36
- } else if (data.type == "create") {
37
- for(var subscription of subscriptions[modelName]["creates"]) {
38
- subscription.onReceived({model: modelInstance})
39
- }
40
- } else if (data.type == "destroy") {
41
- for(var subscription of subscriptions[modelName]["destroys"][modelId]) {
42
- subscription.onReceived({model: modelInstance})
43
- }
44
- } else if (data.type == "event") {
45
- for(var subscription of subscriptions[modelName]["events"][modelId][data.event_name]) {
46
- subscription.onReceived({
47
- args: data.args,
48
- eventName: data.event_name,
49
- model: modelInstance
50
- })
51
- }
52
- } else {
53
- throw new Error(`Unknown type: ${data.type}`)
54
- }
55
- }
56
-
57
- onUnsubscribe() {
58
- Logger.log(`activeSubscriptions before unsub: ${this.activeSubscriptions}`)
59
- this.activeSubscriptions -= 1
60
- Logger.log(`activeSubscriptions after unsub: ${this.activeSubscriptions}`)
61
-
62
- if (this.activeSubscriptions <= 0) {
63
- Logger.log("Unsubscribe from ActionCable subscription")
64
- this.subscription.unsubscribe()
65
- }
66
- }
67
-
68
- registerSubscriptions() {
69
- Logger.log(`registerSubscriptions: ${this.props.subscriptions.length}`)
70
- Logger.log(this.props.subscriptions)
71
-
72
- for(var modelName in this.props.subscriptions) {
73
- if (this.props.subscriptions[modelName]["creates"]) {
74
- for(var subscription of this.props.subscriptions[modelName]["creates"]) {
75
- this.connectUnsubscriptionForSubscription(subscription)
76
- }
77
- }
78
-
79
- if (this.props.subscriptions[modelName]["events"]) {
80
- for(var eventName in this.props.subscriptions[modelName]["events"]) {
81
- for(var modelId in this.props.subscriptions[modelName]["events"][eventName]) {
82
- for(var subscription of this.props.subscriptions[modelName]["events"][eventName][modelId]) {
83
- this.connectUnsubscriptionForSubscription(subscription)
84
- }
85
- }
86
- }
87
- }
88
-
89
- if (this.props.subscriptions[modelName]["updates"]) {
90
- for(var modelId in this.props.subscriptions[modelName]["updates"]) {
91
- for(var subscription of this.props.subscriptions[modelName]["updates"][modelId]) {
92
- this.connectUnsubscriptionForSubscription(subscription)
93
- }
94
- }
95
- }
96
- }
97
- }
98
-
99
- connectUnsubscriptionForSubscription(subscription) {
100
- Logger.log("Connecting to unsubscribe on subscription")
101
- Logger.log({ subscription })
102
-
103
- this.activeSubscriptions += 1
104
-
105
- subscription.onUnsubscribe(() => {
106
- Logger.log("Call onUnsubscribe on self")
107
-
108
- this.onUnsubscribe(subscription)
109
- })
110
- }
111
- }
@@ -1,33 +0,0 @@
1
- import Logger from "./logger"
2
-
3
- export default class ApiMakerCableSubscription {
4
- constructor(props) {
5
- this.props = props
6
- this.onUnsubscribeCallbacks = []
7
- this.subscribed = true
8
- }
9
-
10
- onReceived(data) {
11
- this.props.callback.apply(null, [data])
12
- }
13
-
14
- onUnsubscribe(callback) {
15
- this.onUnsubscribeCallbacks.push(callback)
16
- }
17
-
18
- unsubscribe() {
19
- if (!this.subscribed) {
20
- Logger.log("Unsubscribed already called")
21
- return
22
- }
23
-
24
- Logger.log(`Unsubscribe called: ${this.onUnsubscribeCallbacks.length}`)
25
-
26
- for(var onUnsubscribeCallback of this.onUnsubscribeCallbacks) {
27
- Logger.log("onUnsubscribe called for a callback")
28
- onUnsubscribeCallback.call()
29
- }
30
-
31
- this.subscribed = false
32
- }
33
- }