@fleetbase/registry-bridge-engine 0.0.1

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 (211) hide show
  1. package/.php-cs-fixer.php +29 -0
  2. package/LICENSE.md +651 -0
  3. package/README.md +122 -0
  4. package/addon/adapters/registry-bridge.js +5 -0
  5. package/addon/adapters/registry-extension-bundle.js +1 -0
  6. package/addon/adapters/registry-extension.js +1 -0
  7. package/addon/components/extension-card.hbs +12 -0
  8. package/addon/components/extension-card.js +235 -0
  9. package/addon/components/extension-form.hbs +237 -0
  10. package/addon/components/extension-form.js +123 -0
  11. package/addon/components/extension-modal-title.hbs +14 -0
  12. package/addon/components/extension-modal-title.js +20 -0
  13. package/addon/components/extension-monetize-form.hbs +56 -0
  14. package/addon/components/extension-monetize-form.js +7 -0
  15. package/addon/components/extension-pending-publish-viewer.hbs +52 -0
  16. package/addon/components/extension-pending-publish-viewer.js +37 -0
  17. package/addon/components/extension-reviewer-control.hbs +68 -0
  18. package/addon/components/extension-reviewer-control.js +68 -0
  19. package/addon/components/modals/confirm-extension-purchase.hbs +5 -0
  20. package/addon/components/modals/confirm-extension-purchase.js +3 -0
  21. package/addon/components/modals/extension-details.hbs +69 -0
  22. package/addon/components/modals/extension-details.js +33 -0
  23. package/addon/components/modals/extension-purchase-form.hbs +5 -0
  24. package/addon/components/modals/extension-purchase-form.js +3 -0
  25. package/addon/components/modals/extension-uninstall.hbs +25 -0
  26. package/addon/components/modals/extension-uninstall.js +11 -0
  27. package/addon/components/modals/select-extension-bundle.hbs +43 -0
  28. package/addon/components/modals/select-extension-bundle.js +31 -0
  29. package/addon/components/progress-bar.hbs +12 -0
  30. package/addon/components/progress-bar.js +8 -0
  31. package/addon/controllers/application.js +6 -0
  32. package/addon/controllers/developers/analytics.js +26 -0
  33. package/addon/controllers/developers/extensions/edit/bundles.js +70 -0
  34. package/addon/controllers/developers/extensions/edit/index.js +3 -0
  35. package/addon/controllers/developers/extensions/edit/monetize.js +7 -0
  36. package/addon/controllers/developers/extensions/edit.js +107 -0
  37. package/addon/controllers/developers/extensions/index.js +3 -0
  38. package/addon/controllers/developers/extensions/new.js +32 -0
  39. package/addon/controllers/developers/payments/index.js +39 -0
  40. package/addon/controllers/developers/payments/onboard.js +67 -0
  41. package/addon/controllers/explore/category.js +22 -0
  42. package/addon/controllers/explore/index.js +15 -0
  43. package/addon/controllers/installed.js +86 -0
  44. package/addon/controllers/purchased.js +18 -0
  45. package/addon/engine.js +44 -0
  46. package/addon/models/registry-extension-bundle.js +62 -0
  47. package/addon/models/registry-extension.js +215 -0
  48. package/addon/routes/application.js +12 -0
  49. package/addon/routes/developers/analytics.js +10 -0
  50. package/addon/routes/developers/credentials.js +3 -0
  51. package/addon/routes/developers/extensions/edit/bundles.js +21 -0
  52. package/addon/routes/developers/extensions/edit/details.js +3 -0
  53. package/addon/routes/developers/extensions/edit/index.js +3 -0
  54. package/addon/routes/developers/extensions/edit/monetize.js +3 -0
  55. package/addon/routes/developers/extensions/edit.js +18 -0
  56. package/addon/routes/developers/extensions/index.js +10 -0
  57. package/addon/routes/developers/extensions/new.js +3 -0
  58. package/addon/routes/developers/extensions.js +3 -0
  59. package/addon/routes/developers/payments/index.js +26 -0
  60. package/addon/routes/developers/payments/onboard.js +21 -0
  61. package/addon/routes/developers/payments.js +3 -0
  62. package/addon/routes/developers.js +3 -0
  63. package/addon/routes/explore/category.js +27 -0
  64. package/addon/routes/explore/index.js +17 -0
  65. package/addon/routes/explore.js +3 -0
  66. package/addon/routes/installed.js +10 -0
  67. package/addon/routes/purchased.js +10 -0
  68. package/addon/routes.js +28 -0
  69. package/addon/serializers/registry-extension-bundle.js +15 -0
  70. package/addon/serializers/registry-extension.js +21 -0
  71. package/addon/services/stripe.js +83 -0
  72. package/addon/styles/registry-bridge-engine.css +142 -0
  73. package/addon/templates/application.hbs +26 -0
  74. package/addon/templates/developers/analytics.hbs +83 -0
  75. package/addon/templates/developers/credentials.hbs +1 -0
  76. package/addon/templates/developers/extensions/edit/bundles.hbs +71 -0
  77. package/addon/templates/developers/extensions/edit/details.hbs +16 -0
  78. package/addon/templates/developers/extensions/edit/index.hbs +1 -0
  79. package/addon/templates/developers/extensions/edit/monetize.hbs +3 -0
  80. package/addon/templates/developers/extensions/edit.hbs +48 -0
  81. package/addon/templates/developers/extensions/index.hbs +27 -0
  82. package/addon/templates/developers/extensions/new.hbs +39 -0
  83. package/addon/templates/developers/extensions.hbs +1 -0
  84. package/addon/templates/developers/payments/index.hbs +33 -0
  85. package/addon/templates/developers/payments/onboard.hbs +48 -0
  86. package/addon/templates/developers/payments.hbs +1 -0
  87. package/addon/templates/developers.hbs +1 -0
  88. package/addon/templates/explore/category.hbs +12 -0
  89. package/addon/templates/explore/index.hbs +12 -0
  90. package/addon/templates/explore.hbs +1 -0
  91. package/addon/templates/installed.hbs +32 -0
  92. package/addon/templates/purchased.hbs +34 -0
  93. package/app/adapters/registry-bridge.js +1 -0
  94. package/app/adapters/registry-extension-bundle.js +1 -0
  95. package/app/adapters/registry-extension.js +1 -0
  96. package/app/components/extension-card.js +1 -0
  97. package/app/components/extension-form.js +1 -0
  98. package/app/components/extension-modal-title.js +1 -0
  99. package/app/components/extension-monetize-form.js +1 -0
  100. package/app/components/extension-pending-publish-viewer.js +1 -0
  101. package/app/components/extension-reviewer-control.js +1 -0
  102. package/app/components/modals/confirm-extension-purchase.js +1 -0
  103. package/app/components/modals/extension-details.js +1 -0
  104. package/app/components/modals/extension-purchase-form.js +1 -0
  105. package/app/components/modals/extension-uninstall.js +1 -0
  106. package/app/components/modals/select-extension-bundle.js +1 -0
  107. package/app/components/progress-bar.js +1 -0
  108. package/app/controllers/application.js +1 -0
  109. package/app/controllers/developers/analytics.js +1 -0
  110. package/app/controllers/developers/extensions/edit/bundles.js +1 -0
  111. package/app/controllers/developers/extensions/edit/index.js +1 -0
  112. package/app/controllers/developers/extensions/edit/monetize.js +1 -0
  113. package/app/controllers/developers/extensions/edit.js +1 -0
  114. package/app/controllers/developers/extensions/index.js +1 -0
  115. package/app/controllers/developers/extensions/new.js +1 -0
  116. package/app/controllers/developers/payments/index.js +1 -0
  117. package/app/controllers/developers/payments/onboard.js +1 -0
  118. package/app/controllers/explore/category.js +1 -0
  119. package/app/controllers/explore/index.js +1 -0
  120. package/app/controllers/installed.js +1 -0
  121. package/app/controllers/purchased.js +1 -0
  122. package/app/models/registry-extension-bundle.js +1 -0
  123. package/app/models/registry-extension.js +1 -0
  124. package/app/routes/developers/analytics.js +1 -0
  125. package/app/routes/developers/credentials.js +1 -0
  126. package/app/routes/developers/extensions/edit/bundles.js +1 -0
  127. package/app/routes/developers/extensions/edit/details.js +1 -0
  128. package/app/routes/developers/extensions/edit/index.js +1 -0
  129. package/app/routes/developers/extensions/edit/monetize.js +1 -0
  130. package/app/routes/developers/extensions/edit.js +1 -0
  131. package/app/routes/developers/extensions/index.js +1 -0
  132. package/app/routes/developers/extensions/new.js +1 -0
  133. package/app/routes/developers/extensions.js +1 -0
  134. package/app/routes/developers/payments/index.js +1 -0
  135. package/app/routes/developers/payments/onboard.js +1 -0
  136. package/app/routes/developers/payments.js +1 -0
  137. package/app/routes/developers.js +1 -0
  138. package/app/routes/explore/category.js +1 -0
  139. package/app/routes/explore/index.js +1 -0
  140. package/app/routes/explore.js +1 -0
  141. package/app/routes/installed.js +1 -0
  142. package/app/routes/purchased.js +1 -0
  143. package/app/serializers/registry-extension-bundle.js +1 -0
  144. package/app/serializers/registry-extension.js +1 -0
  145. package/app/services/stripe.js +1 -0
  146. package/app/templates/developers/analytics.js +1 -0
  147. package/app/templates/developers/credentials.js +1 -0
  148. package/app/templates/developers/extensions/edit/bundles.js +1 -0
  149. package/app/templates/developers/extensions/edit/details.js +1 -0
  150. package/app/templates/developers/extensions/edit/index.js +1 -0
  151. package/app/templates/developers/extensions/edit/monetize.js +1 -0
  152. package/app/templates/developers/extensions/edit.js +1 -0
  153. package/app/templates/developers/extensions/index.js +1 -0
  154. package/app/templates/developers/extensions/new.js +1 -0
  155. package/app/templates/developers/extensions.js +1 -0
  156. package/app/templates/developers/payments/index.js +1 -0
  157. package/app/templates/developers/payments/onboard.js +1 -0
  158. package/app/templates/developers/payments.js +1 -0
  159. package/app/templates/developers.js +1 -0
  160. package/app/templates/explore/category.js +1 -0
  161. package/app/templates/explore/index.js +1 -0
  162. package/app/templates/explore.js +1 -0
  163. package/app/templates/installed.js +1 -0
  164. package/app/templates/purchased.js +1 -0
  165. package/composer.json +95 -0
  166. package/config/environment.js +28 -0
  167. package/extension.json +10 -0
  168. package/index.js +26 -0
  169. package/package.json +129 -0
  170. package/phpstan.neon.dist +8 -0
  171. package/phpunit.xml.dist +16 -0
  172. package/server/.gitattributes +14 -0
  173. package/server/config/registry-bridge.php +32 -0
  174. package/server/migrations/2024_03_19_060627_create_registry_users_table.php +42 -0
  175. package/server/migrations/2024_03_21_051614_create_registry_extensions_table.php +76 -0
  176. package/server/migrations/2024_03_25_044537_create_registry_extension_bundles_table.php +54 -0
  177. package/server/migrations/2024_03_29_072101_registry_extension_installs.php +35 -0
  178. package/server/migrations/2024_07_16_155000_create_registry_extension_purchases.php +41 -0
  179. package/server/seeders/ExtensionsCategorySeeder.php +359 -0
  180. package/server/src/Console/Commands/Initialize.php +35 -0
  181. package/server/src/Console/Commands/PostInstallExtension.php +84 -0
  182. package/server/src/Exceptions/InstallFailedException.php +21 -0
  183. package/server/src/Expansions/CategoryExpansion.php +30 -0
  184. package/server/src/Http/Controllers/Internal/v1/ExtensionInstallerController.php +153 -0
  185. package/server/src/Http/Controllers/Internal/v1/RegistryAuthController.php +230 -0
  186. package/server/src/Http/Controllers/Internal/v1/RegistryController.php +54 -0
  187. package/server/src/Http/Controllers/Internal/v1/RegistryExtensionBundleController.php +112 -0
  188. package/server/src/Http/Controllers/Internal/v1/RegistryExtensionController.php +257 -0
  189. package/server/src/Http/Controllers/Internal/v1/RegistryPaymentsController.php +227 -0
  190. package/server/src/Http/Controllers/RegistryBridgeController.php +13 -0
  191. package/server/src/Http/Filter/RegistryExtensionFilter.php +80 -0
  192. package/server/src/Http/Requests/AddRegistryUserRequest.php +47 -0
  193. package/server/src/Http/Requests/AuthenticateRegistryUserRequest.php +47 -0
  194. package/server/src/Http/Requests/CreateRegistryExtensionBundleRequest.php +42 -0
  195. package/server/src/Http/Requests/CreateRegistryExtensionRequest.php +31 -0
  196. package/server/src/Http/Requests/InstallExtensionRequest.php +30 -0
  197. package/server/src/Http/Requests/RegistryAuthRequest.php +46 -0
  198. package/server/src/Http/Requests/RegistryExtensionActionRequest.php +30 -0
  199. package/server/src/Http/Resources/RegistryUser.php +40 -0
  200. package/server/src/Models/RegistryExtension.php +656 -0
  201. package/server/src/Models/RegistryExtensionBundle.php +1015 -0
  202. package/server/src/Models/RegistryExtensionInstall.php +76 -0
  203. package/server/src/Models/RegistryExtensionPurchase.php +87 -0
  204. package/server/src/Models/RegistryUser.php +140 -0
  205. package/server/src/Providers/RegistryBridgeServiceProvider.php +117 -0
  206. package/server/src/Support/Bridge.php +53 -0
  207. package/server/src/Support/Utils.php +19 -0
  208. package/server/src/routes.php +58 -0
  209. package/server/tests/Feature.php +5 -0
  210. package/translations/en-us.yaml +119 -0
  211. package/tsconfig.declarations.json +10 -0
@@ -0,0 +1,62 @@
1
+ import Model, { attr, belongsTo } from '@ember-data/model';
2
+ import { computed } from '@ember/object';
3
+ import { format as formatDate, formatDistanceToNow, isValid as isValidDate } from 'date-fns';
4
+
5
+ export default class RegistryExtensionBundleModel extends Model {
6
+ /** @ids */
7
+ @attr('string') uuid;
8
+ @attr('string') company_uuid;
9
+ @attr('string') created_by_uuid;
10
+ @attr('string') extension_uuid;
11
+ @attr('string') bundle_uuid;
12
+ @attr('string') bundle_id;
13
+ @attr('string') public_id;
14
+
15
+ /** @relationships */
16
+ @belongsTo('file') bundle;
17
+
18
+ /** @attributes */
19
+ @attr('string') bundle_filename;
20
+ @attr('string') bundle_number;
21
+ @attr('string') version;
22
+ @attr('string') status;
23
+ @attr('object') meta;
24
+
25
+ /** @dates */
26
+ @attr('date') created_at;
27
+ @attr('date') updated_at;
28
+ @attr('date') deleted_at;
29
+
30
+ /** @computed */
31
+ @computed('updated_at') get updatedAgo() {
32
+ if (!isValidDate(this.updated_at)) {
33
+ return null;
34
+ }
35
+
36
+ return formatDistanceToNow(this.updated_at);
37
+ }
38
+
39
+ @computed('updated_at') get updatedAt() {
40
+ if (!isValidDate(this.updated_at)) {
41
+ return null;
42
+ }
43
+
44
+ return formatDate(this.updated_at, 'PP HH:mm');
45
+ }
46
+
47
+ @computed('created_at') get createdAgo() {
48
+ if (!isValidDate(this.created_at)) {
49
+ return null;
50
+ }
51
+
52
+ return formatDistanceToNow(this.created_at);
53
+ }
54
+
55
+ @computed('created_at') get createdAt() {
56
+ if (!isValidDate(this.created_at)) {
57
+ return null;
58
+ }
59
+
60
+ return formatDate(this.created_at, 'PP HH:mm');
61
+ }
62
+ }
@@ -0,0 +1,215 @@
1
+ import Model, { attr, belongsTo, hasMany } from '@ember-data/model';
2
+ import { action, computed } from '@ember/object';
3
+ import { getOwner } from '@ember/application';
4
+ import { format as formatDate, formatDistanceToNow, isValid as isValidDate } from 'date-fns';
5
+
6
+ export default class RegistryExtensionModel extends Model {
7
+ /** @ids */
8
+ @attr('string') uuid;
9
+ @attr('string') company_uuid;
10
+ @attr('string') created_by_uuid;
11
+ @attr('string') registry_user_uuid;
12
+ @attr('string') current_bundle_uuid;
13
+ @attr('string') next_bundle_uuid;
14
+ @attr('string') category_uuid;
15
+ @attr('string') icon_uuid;
16
+ @attr('string') public_id;
17
+ @attr('string') current_bundle_public_id;
18
+ @attr('string') next_bundle_public_id;
19
+ @attr('string') current_bundle_id;
20
+ @attr('string') next_bundle_id;
21
+
22
+ /** @relationships */
23
+ @belongsTo('company') company;
24
+ @belongsTo('user') created_by;
25
+ @belongsTo('category') category;
26
+ @belongsTo('registry-extension-bundle') current_bundle;
27
+ @belongsTo('registry-extension-bundle') next_bundle;
28
+ @belongsTo('file') icon;
29
+ @hasMany('file') screenshots;
30
+
31
+ /** @attributes */
32
+ @attr('string', { defaultValue: 'https://flb-assets.s3.ap-southeast-1.amazonaws.com/static/default-extension-icon.svg' }) icon_url;
33
+ @attr('string') name;
34
+ @attr('string') subtitle;
35
+ @attr('string') category_name;
36
+ @attr('string') publisher_name;
37
+ @attr('boolean') payment_required;
38
+ @attr('string') price;
39
+ @attr('string') sale_price;
40
+ @attr('boolean') on_sale;
41
+ @attr('boolean') subscription_required;
42
+ @attr('string', { defaultValue: 'flat_rate' }) subscription_model;
43
+ @attr('string', { defaultValue: 'monthly' }) subscription_billing_period;
44
+ @attr('string') subscription_amount;
45
+ @attr('array') subscription_tiers;
46
+ @attr('string', { defaultValue: 'USD' }) currency;
47
+ @attr('string') slug;
48
+ @attr('string', { defaultValue: '1.0.0' }) version;
49
+ @attr('string') fa_icon;
50
+ @attr('string') description;
51
+ @attr('string') current_bundle_filename;
52
+ @attr('string') next_bundle_filename;
53
+ @attr('string') promotional_text;
54
+ @attr('string') website_url;
55
+ @attr('string') repo_url;
56
+ @attr('string') support_url;
57
+ @attr('string') privacy_policy_url;
58
+ @attr('string') tos_url;
59
+ @attr('string') copyright;
60
+ @attr('string') primary_language;
61
+ @attr('array') tags;
62
+ @attr('array') languages;
63
+ @attr('object') meta;
64
+ @attr('boolean') core_service;
65
+ @attr('boolean') is_purchased;
66
+ @attr('boolean') is_installed;
67
+ @attr('string', { defaultValue: 'pending' }) status;
68
+
69
+ /** @dates */
70
+ @attr('date') created_at;
71
+ @attr('date') updated_at;
72
+ @attr('date') deleted_at;
73
+
74
+ /** @computed */
75
+ @computed('updated_at') get updatedAgo() {
76
+ if (!isValidDate(this.updated_at)) {
77
+ return null;
78
+ }
79
+
80
+ return formatDistanceToNow(this.updated_at);
81
+ }
82
+
83
+ @computed('updated_at') get updatedAt() {
84
+ if (!isValidDate(this.updated_at)) {
85
+ return null;
86
+ }
87
+
88
+ return formatDate(this.updated_at, 'MMMM, dd yyyy');
89
+ }
90
+
91
+ @computed('created_at') get createdAgo() {
92
+ if (!isValidDate(this.created_at)) {
93
+ return null;
94
+ }
95
+
96
+ return formatDistanceToNow(this.created_at);
97
+ }
98
+
99
+ @computed('created_at') get createdAt() {
100
+ if (!isValidDate(this.created_at)) {
101
+ return null;
102
+ }
103
+
104
+ return formatDate(this.created_at, 'MMMM, dd yyyy');
105
+ }
106
+
107
+ /** @methods */
108
+ /**
109
+ * Submits the registry extension for review.
110
+ *
111
+ * @return {Promise<RegistryExtensionModel>}
112
+ * @memberof RegistryExtensionModel
113
+ */
114
+ @action submitForReview(params = {}) {
115
+ const owner = getOwner(this);
116
+ const fetch = owner.lookup('service:fetch');
117
+
118
+ return fetch.post(`registry-extensions/${this.id}/submit`, params, { namespace: '~registry/v1', normalizeToEmberData: true, modelType: 'registry-extension' });
119
+ }
120
+
121
+ /**
122
+ * Submits the registry extension for approval.
123
+ *
124
+ * @return {Promise<RegistryExtensionModel>}
125
+ * @memberof RegistryExtensionModel
126
+ */
127
+ @action approve(params = {}) {
128
+ const owner = getOwner(this);
129
+ const fetch = owner.lookup('service:fetch');
130
+
131
+ return fetch.post('registry-extensions/approve', { id: this.id, ...params }, { namespace: '~registry/v1', normalizeToEmberData: true, modelType: 'registry-extension' });
132
+ }
133
+
134
+ /**
135
+ * Submits the registry extension for rejection.
136
+ *
137
+ * @return {Promise<RegistryExtensionModel>}
138
+ * @memberof RegistryExtensionModel
139
+ */
140
+ @action reject(params = {}) {
141
+ const owner = getOwner(this);
142
+ const fetch = owner.lookup('service:fetch');
143
+
144
+ return fetch.post('registry-extensions/reject', { id: this.id, ...params }, { namespace: '~registry/v1', normalizeToEmberData: true, modelType: 'registry-extension' });
145
+ }
146
+
147
+ /**
148
+ * Downloads the extension latest bundle Zip.
149
+ *
150
+ * @return {Promise<>}
151
+ * @memberof RegistryExtensionModel
152
+ */
153
+ @action downloadBundle() {
154
+ const owner = getOwner(this);
155
+ const fetch = owner.lookup('service:fetch');
156
+
157
+ return fetch.download('registry-extensions/download-bundle', { id: this.id }, { namespace: '~registry/v1', fileName: this.latest_bundle_filename, mimeType: 'application/x-zip' });
158
+ }
159
+
160
+ /**
161
+ * Install the extension.
162
+ *
163
+ * @return {Promise<>}
164
+ * @memberof RegistryExtensionModel
165
+ */
166
+ @action install() {
167
+ const owner = getOwner(this);
168
+ const fetch = owner.lookup('service:fetch');
169
+
170
+ return fetch.post('installer/install', { extension: this.public_id }, { namespace: '~registry/v1' });
171
+ }
172
+
173
+ /**
174
+ * Uninstall the extension.
175
+ *
176
+ * @return {Promise<>}
177
+ * @memberof RegistryExtensionModel
178
+ */
179
+ @action uninstall() {
180
+ const owner = getOwner(this);
181
+ const fetch = owner.lookup('service:fetch');
182
+
183
+ return fetch.post('installer/uninstall', { extension: this.public_id }, { namespace: '~registry/v1' });
184
+ }
185
+
186
+ /**
187
+ * Adds a new tag to the tags array.
188
+ *
189
+ * This method takes a tag and adds it to the 'tags' array property
190
+ * of the current instance. The 'pushObject' method is used, which is
191
+ * typically available in Ember.js or similar frameworks that extend
192
+ * JavaScript array functionalities.
193
+ *
194
+ * @param {string} tag - The tag to be added to the tags array.
195
+ */
196
+ @action addTag(tag) {
197
+ this.tags.push(tag);
198
+ this.tags = [...this.tags];
199
+ }
200
+
201
+ /**
202
+ * Removes a tag from the tags array at a specific index.
203
+ *
204
+ * This method takes an index and removes the element at that position
205
+ * from the 'tags' array property of the current instance. The 'removeAt'
206
+ * method is used, which is typically available in Ember.js or similar
207
+ * frameworks that provide extended array functionalities.
208
+ *
209
+ * @param {number} index - The index of the tag to be removed from the tags array.
210
+ */
211
+ @action removeTag(index) {
212
+ this.tags.removeAt(index);
213
+ this.tags = [...this.tags];
214
+ }
215
+ }
@@ -0,0 +1,12 @@
1
+ import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
3
+
4
+ export default class ApplicationRoute extends Route {
5
+ @service fetch;
6
+
7
+ async setupController(controller) {
8
+ super.setupController(...arguments);
9
+ // controller.categories = await this.store.query('category', { for: 'extension_category', core_category: 1 });
10
+ controller.categories = await this.fetch.get('categories', {}, { namespace: '~registry/v1', normalizeToEmberData: true, modelType: 'category' });
11
+ }
12
+ }
@@ -0,0 +1,10 @@
1
+ import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
3
+
4
+ export default class DevelopersAnalyticsRoute extends Route {
5
+ @service store;
6
+
7
+ model() {
8
+ return this.store.query('registry-extension', { is_author: 1 });
9
+ }
10
+ }
@@ -0,0 +1,3 @@
1
+ import Route from '@ember/routing/route';
2
+
3
+ export default class DevelopersCredentialsRoute extends Route {}
@@ -0,0 +1,21 @@
1
+ import Route from '@ember/routing/route';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { inject as service } from '@ember/service';
4
+
5
+ export default class DevelopersExtensionsEditBundlesRoute extends Route {
6
+ @service store;
7
+ @tracked extension;
8
+
9
+ beforeModel() {
10
+ this.extension = this.modelFor('developers.extensions.edit');
11
+ }
12
+
13
+ model() {
14
+ return this.store.query('registry-extension-bundle', { extension_uuid: this.extension.id });
15
+ }
16
+
17
+ setupController(controller) {
18
+ super.setupController(...arguments);
19
+ controller.extension = this.extension;
20
+ }
21
+ }
@@ -0,0 +1,3 @@
1
+ import Route from '@ember/routing/route';
2
+
3
+ export default class DevelopersExtensionsEditDetailsRoute extends Route {}
@@ -0,0 +1,3 @@
1
+ import Route from '@ember/routing/route';
2
+
3
+ export default class DevelopersExtensionsEditIndexRoute extends Route {}
@@ -0,0 +1,3 @@
1
+ import Route from '@ember/routing/route';
2
+
3
+ export default class DevelopersExtensionsEditMonetizeRoute extends Route {}
@@ -0,0 +1,18 @@
1
+ import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
3
+
4
+ export default class DevelopersExtensionsEditRoute extends Route {
5
+ @service store;
6
+
7
+ model(params) {
8
+ return this.store.queryRecord('registry-extension', { public_id: params.public_id, single: true });
9
+ }
10
+
11
+ setupController(controller) {
12
+ super.setupController(...arguments);
13
+ const isReady = controller.validateExtensionForReview();
14
+ if (isReady === true) {
15
+ controller.isReady = isReady;
16
+ }
17
+ }
18
+ }
@@ -0,0 +1,10 @@
1
+ import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
3
+
4
+ export default class DevelopersExtensionsIndexRoute extends Route {
5
+ @service store;
6
+
7
+ model() {
8
+ return this.store.query('registry-extension', { is_author: 1 });
9
+ }
10
+ }
@@ -0,0 +1,3 @@
1
+ import Route from '@ember/routing/route';
2
+
3
+ export default class DevelopersExtensionsNewRoute extends Route {}
@@ -0,0 +1,3 @@
1
+ import Route from '@ember/routing/route';
2
+
3
+ export default class DevelopersExtensionsRoute extends Route {}
@@ -0,0 +1,26 @@
1
+ import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
3
+
4
+ export default class DevelopersPaymentsIndexRoute extends Route {
5
+ @service fetch;
6
+
7
+ queryParams = {
8
+ page: { refreshModel: true },
9
+ limit: { refreshModel: true },
10
+ sort: { refreshModel: true },
11
+ query: { refreshModel: true },
12
+ };
13
+
14
+ model() {
15
+ return this.fetch.get('payments/author-received', {}, { namespace: '~registry/v1' });
16
+ }
17
+
18
+ async setupController(controller) {
19
+ try {
20
+ const { hasStripeConnectAccount } = await this.fetch.get('payments/has-stripe-connect-account', {}, { namespace: '~registry/v1' });
21
+ controller.hasStripeConnectAccount = hasStripeConnectAccount;
22
+ } catch (error) {
23
+ controller.hasStripeConnectAccount = false;
24
+ }
25
+ }
26
+ }
@@ -0,0 +1,21 @@
1
+ import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
3
+
4
+ export default class DevelopersPaymentsOnboardRoute extends Route {
5
+ @service fetch;
6
+ @service hostRouter;
7
+ @service notifications;
8
+
9
+ async beforeModel() {
10
+ try {
11
+ const { hasStripeConnectAccount } = await this.fetch.get('payments/has-stripe-connect-account', {}, { namespace: '~registry/v1' });
12
+ if (hasStripeConnectAccount) {
13
+ this.notifications.info('Your account is already enabled to accept payments.');
14
+ this.hostRouter.transitionTo('console.extensions.payments');
15
+ }
16
+ } catch (error) {
17
+ this.notifications.serverError(error);
18
+ this.hostRouter.transitionTo('console.extensions.payments');
19
+ }
20
+ }
21
+ }
@@ -0,0 +1,3 @@
1
+ import Route from '@ember/routing/route';
2
+
3
+ export default class DevelopersPaymentsRoute extends Route {}
@@ -0,0 +1,3 @@
1
+ import Route from '@ember/routing/route';
2
+
3
+ export default class DevelopersRoute extends Route {}
@@ -0,0 +1,27 @@
1
+ import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
3
+
4
+ export default class ExploreCategoryRoute extends Route {
5
+ @service store;
6
+
7
+ queryParams = {
8
+ query: {
9
+ refreshModel: false,
10
+ },
11
+ };
12
+
13
+ model({ slug }) {
14
+ return this.store.queryRecord('category', { slug, for: 'extension_category', core_category: 1, single: 1 });
15
+ }
16
+
17
+ async setupController(controller, model) {
18
+ super.setupController(...arguments);
19
+ const params = { explore: 1, category: model.id };
20
+ const query = controller.query;
21
+ if (query) {
22
+ params.query = controller.query;
23
+ }
24
+
25
+ controller.extensions = await this.store.query('registry-extension', params);
26
+ }
27
+ }
@@ -0,0 +1,17 @@
1
+ import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
3
+
4
+ export default class ExploreIndexRoute extends Route {
5
+ @service store;
6
+
7
+ queryParams = {
8
+ query: {
9
+ refreshModel: true,
10
+ },
11
+ };
12
+
13
+ model(params) {
14
+ const { query } = params;
15
+ return this.store.query('registry-extension', { explore: 1, query });
16
+ }
17
+ }
@@ -0,0 +1,3 @@
1
+ import Route from '@ember/routing/route';
2
+
3
+ export default class ExploreRoute extends Route {}
@@ -0,0 +1,10 @@
1
+ import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
3
+
4
+ export default class InstalledRoute extends Route {
5
+ @service fetch;
6
+
7
+ model(params = {}) {
8
+ return this.fetch.get('registry-extensions/installed', params, { namespace: '~registry/v1', normalizeToEmberData: true, modelType: 'registry-extension' });
9
+ }
10
+ }
@@ -0,0 +1,10 @@
1
+ import Route from '@ember/routing/route';
2
+ import { inject as service } from '@ember/service';
3
+
4
+ export default class PurchasedRoute extends Route {
5
+ @service fetch;
6
+
7
+ model(params = {}) {
8
+ return this.fetch.get('registry-extensions/purchased', params, { namespace: '~registry/v1', normalizeToEmberData: true, modelType: 'registry-extension' });
9
+ }
10
+ }
@@ -0,0 +1,28 @@
1
+ import buildRoutes from 'ember-engines/routes';
2
+
3
+ export default buildRoutes(function () {
4
+ this.route('installed');
5
+ this.route('purchased');
6
+ this.route('developers', function () {
7
+ this.route('extensions', function () {
8
+ this.route('index', { path: '/' });
9
+ this.route('new');
10
+ this.route('edit', { path: '/distribution/:public_id' }, function () {
11
+ this.route('index', { path: '/' });
12
+ this.route('details');
13
+ this.route('bundles');
14
+ this.route('monetize');
15
+ });
16
+ });
17
+ this.route('analytics');
18
+ this.route('payments', function () {
19
+ this.route('index', { path: '/' });
20
+ this.route('onboard');
21
+ });
22
+ this.route('credentials');
23
+ });
24
+ this.route('explore', { path: '/' }, function () {
25
+ this.route('index', { path: '/' });
26
+ this.route('category', { path: '/:slug' });
27
+ });
28
+ });
@@ -0,0 +1,15 @@
1
+ import ApplicationSerializer from '@fleetbase/ember-core/serializers/application';
2
+ import { EmbeddedRecordsMixin } from '@ember-data/serializer/rest';
3
+
4
+ export default class RegistryExtensionBundleSerializer extends ApplicationSerializer.extend(EmbeddedRecordsMixin) {
5
+ /**
6
+ * Embedded relationship attributes
7
+ *
8
+ * @var {Object}
9
+ */
10
+ get attrs() {
11
+ return {
12
+ bundle: { embedded: 'always' },
13
+ };
14
+ }
15
+ }
@@ -0,0 +1,21 @@
1
+ import ApplicationSerializer from '@fleetbase/ember-core/serializers/application';
2
+ import { EmbeddedRecordsMixin } from '@ember-data/serializer/rest';
3
+
4
+ export default class RegistryExtensionSerializer extends ApplicationSerializer.extend(EmbeddedRecordsMixin) {
5
+ /**
6
+ * Embedded relationship attributes
7
+ *
8
+ * @var {Object}
9
+ */
10
+ get attrs() {
11
+ return {
12
+ company: { embedded: 'always' },
13
+ created_by: { embedded: 'always' },
14
+ category: { embedded: 'always' },
15
+ icon: { embedded: 'always' },
16
+ current_bundle: { embedded: 'always' },
17
+ next_bundle: { embedded: 'always' },
18
+ screenshots: { embedded: 'always' },
19
+ };
20
+ }
21
+ }
@@ -0,0 +1,83 @@
1
+ import Service from '@ember/service';
2
+ import { tracked } from '@glimmer/tracking';
3
+ import { later } from '@ember/runloop';
4
+ import config from '../config/environment';
5
+
6
+ const STRIPE_JS_INITIALIZE_DELAY_MS = 900;
7
+ export default class StripeService extends Service {
8
+ @tracked stripe;
9
+ @tracked loaded = false;
10
+
11
+ constructor() {
12
+ super(...arguments);
13
+ this.loadAndInitialize();
14
+ }
15
+
16
+ async initEmbeddedCheckout() {
17
+ if (!this.stripe) {
18
+ await this.loadAndInitialize();
19
+ }
20
+
21
+ if (typeof this.stripe.initEmbeddedCheckout === 'function') {
22
+ return this.stripe.initEmbeddedCheckout(...arguments);
23
+ }
24
+
25
+ throw new Error('Stripe not initialized!');
26
+ }
27
+
28
+ getInstance() {
29
+ return this.stripe;
30
+ }
31
+
32
+ createStripeInstance(options = {}) {
33
+ this.stripe = Stripe(config.stripe.publishableKey, options);
34
+ return this.stripe;
35
+ }
36
+
37
+ async loadAndInitialize() {
38
+ return new Promise((resolve) => {
39
+ this.load(() => {
40
+ resolve(this.createStripeInstance());
41
+ });
42
+ });
43
+ }
44
+
45
+ load(callback = null) {
46
+ const stripeJs = document.querySelector('script[data-stripe-js="loaded"]');
47
+ if (stripeJs) {
48
+ later(
49
+ this,
50
+ () => {
51
+ if (typeof callback === 'function') {
52
+ callback();
53
+ }
54
+ },
55
+ STRIPE_JS_INITIALIZE_DELAY_MS
56
+ );
57
+ return;
58
+ }
59
+
60
+ // Create a new script element
61
+ const script = document.createElement('script');
62
+ script.src = 'https://js.stripe.com/v3/';
63
+ script.async = true;
64
+
65
+ // Use a data attribute to mark that the script is loaded
66
+ script.setAttribute('data-stripe-js', 'loaded');
67
+ script.onload = () => {
68
+ this.loaded = true;
69
+ later(
70
+ this,
71
+ () => {
72
+ if (typeof callback === 'function') {
73
+ callback();
74
+ }
75
+ },
76
+ STRIPE_JS_INITIALIZE_DELAY_MS
77
+ );
78
+ };
79
+
80
+ // Append the script to the document's head
81
+ document.head.appendChild(script);
82
+ }
83
+ }