@flarum/cli 1.0.0 → 2.0.0-beta.4

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 (186) hide show
  1. package/README.md +2 -2
  2. package/bin/run +5 -3
  3. package/boilerplate/skeleton/extension/.gitattributes +16 -3
  4. package/boilerplate/skeleton/extension/.github/workflows/backend.yml +15 -0
  5. package/boilerplate/skeleton/extension/.github/workflows/frontend.yml +20 -0
  6. package/boilerplate/skeleton/extension/.styleci.yml +14 -0
  7. package/boilerplate/skeleton/extension/LICENSE.md +1 -0
  8. package/boilerplate/skeleton/extension/README.md +7 -7
  9. package/boilerplate/skeleton/extension/composer.json +11 -9
  10. package/boilerplate/skeleton/extension/extend.php +10 -10
  11. package/boilerplate/skeleton/extension/gitignore +13 -0
  12. package/boilerplate/skeleton/extension/js/admin.js +2 -1
  13. package/boilerplate/skeleton/extension/js/forum.js +2 -1
  14. package/boilerplate/skeleton/extension/js/package.json +13 -9
  15. package/boilerplate/skeleton/extension/js/src/admin/index.js +4 -2
  16. package/boilerplate/skeleton/extension/js/src/common/index.js +5 -0
  17. package/boilerplate/skeleton/extension/js/src/forum/index.js +4 -2
  18. package/boilerplate/skeleton/extension/js/tsconfig.json +6 -1
  19. package/boilerplate/skeleton/extension/locale/en.yml +1 -1
  20. package/boilerplate/stubs/migration.php +1 -1
  21. package/lib/base-command.d.ts +27 -6
  22. package/lib/base-command.js +131 -41
  23. package/lib/boilersmith/exposed-param-manager.d.ts +8 -0
  24. package/lib/boilersmith/exposed-param-manager.js +31 -0
  25. package/lib/boilersmith/io.d.ts +50 -0
  26. package/lib/boilersmith/io.js +72 -0
  27. package/lib/boilersmith/paths.d.ts +22 -0
  28. package/lib/boilersmith/paths.js +29 -0
  29. package/lib/boilersmith/scaffolding/audit-step-factory.d.ts +5 -0
  30. package/lib/boilersmith/scaffolding/audit-step-factory.js +54 -0
  31. package/lib/boilersmith/scaffolding/infra-step-factory.d.ts +5 -0
  32. package/lib/boilersmith/scaffolding/infra-step-factory.js +34 -0
  33. package/lib/boilersmith/scaffolding/init-step-factory.d.ts +5 -0
  34. package/lib/boilersmith/scaffolding/init-step-factory.js +34 -0
  35. package/lib/boilersmith/scaffolding/module.d.ts +73 -0
  36. package/lib/boilersmith/scaffolding/module.js +111 -0
  37. package/lib/boilersmith/scaffolding/scaffolder.d.ts +32 -0
  38. package/lib/boilersmith/scaffolding/scaffolder.js +203 -0
  39. package/lib/boilersmith/scaffolding/template-param.d.ts +23 -0
  40. package/lib/boilersmith/scaffolding/template-param.js +46 -0
  41. package/lib/boilersmith/step-manager.d.ts +85 -0
  42. package/lib/boilersmith/step-manager.js +234 -0
  43. package/lib/boilersmith/steps/stub-base.d.ts +53 -0
  44. package/lib/boilersmith/steps/stub-base.js +54 -0
  45. package/lib/{utils → boilersmith/utils}/clone-and-fill.d.ts +0 -0
  46. package/lib/{utils → boilersmith/utils}/clone-and-fill.js +2 -2
  47. package/lib/boilersmith/utils/cond-format.d.ts +1 -0
  48. package/lib/boilersmith/utils/cond-format.js +8 -0
  49. package/lib/boilersmith/utils/json-leaf-paths.d.ts +7 -0
  50. package/lib/boilersmith/utils/json-leaf-paths.js +17 -0
  51. package/lib/boilersmith/utils/read-tpl.d.ts +2 -0
  52. package/lib/boilersmith/utils/read-tpl.js +10 -0
  53. package/lib/boilersmith/utils/rename-keys.d.ts +1 -0
  54. package/lib/boilersmith/utils/rename-keys.js +7 -0
  55. package/lib/commands/audit/infra.d.ts +16 -0
  56. package/lib/commands/audit/infra.js +27 -0
  57. package/lib/commands/infra.d.ts +20 -0
  58. package/lib/commands/infra.js +55 -0
  59. package/lib/commands/init.d.ts +4 -3
  60. package/lib/commands/init.js +8 -6
  61. package/lib/commands/make/backend/api-controller.d.ts +4 -3
  62. package/lib/commands/make/backend/api-controller.js +3 -2
  63. package/lib/commands/make/backend/api-serializer-attributes.d.ts +4 -3
  64. package/lib/commands/make/backend/api-serializer-attributes.js +1 -1
  65. package/lib/commands/make/backend/api-serializer.d.ts +4 -3
  66. package/lib/commands/make/backend/api-serializer.js +3 -2
  67. package/lib/commands/make/backend/command.d.ts +4 -3
  68. package/lib/commands/make/backend/command.js +3 -2
  69. package/lib/commands/make/backend/event-listener.d.ts +4 -3
  70. package/lib/commands/make/backend/event-listener.js +3 -2
  71. package/lib/commands/make/backend/handler.d.ts +4 -3
  72. package/lib/commands/make/backend/handler.js +4 -3
  73. package/lib/commands/make/backend/integration-test.d.ts +4 -3
  74. package/lib/commands/make/backend/integration-test.js +3 -2
  75. package/lib/commands/make/backend/job.d.ts +4 -3
  76. package/lib/commands/make/backend/job.js +3 -2
  77. package/lib/commands/make/backend/migration.d.ts +4 -3
  78. package/lib/commands/make/backend/migration.js +3 -2
  79. package/lib/commands/make/backend/model.d.ts +4 -3
  80. package/lib/commands/make/backend/model.js +22 -21
  81. package/lib/commands/make/backend/policy.d.ts +4 -3
  82. package/lib/commands/make/backend/policy.js +3 -2
  83. package/lib/commands/make/backend/repository.d.ts +4 -3
  84. package/lib/commands/make/backend/repository.js +3 -2
  85. package/lib/commands/make/backend/route.d.ts +4 -3
  86. package/lib/commands/make/backend/route.js +1 -1
  87. package/lib/commands/make/backend/service-provider.d.ts +4 -3
  88. package/lib/commands/make/backend/service-provider.js +3 -2
  89. package/lib/commands/make/backend/validator.d.ts +4 -3
  90. package/lib/commands/make/backend/validator.js +3 -2
  91. package/lib/commands/make/frontend/component.d.ts +4 -3
  92. package/lib/commands/make/frontend/component.js +3 -2
  93. package/lib/commands/make/frontend/modal.d.ts +4 -3
  94. package/lib/commands/make/frontend/modal.js +3 -2
  95. package/lib/commands/make/frontend/model.d.ts +4 -3
  96. package/lib/commands/make/frontend/model.js +3 -2
  97. package/lib/commands/update/js-imports.d.ts +4 -3
  98. package/lib/commands/update/js-imports.js +1 -1
  99. package/lib/help.d.ts +5 -6
  100. package/lib/help.js +5 -4
  101. package/lib/index.d.ts +1 -1
  102. package/lib/index.js +3 -2
  103. package/lib/providers/index.d.ts +5 -0
  104. package/lib/providers/index.js +2 -0
  105. package/lib/{provider → providers}/php-provider.d.ts +0 -0
  106. package/lib/{provider → providers}/php-provider.js +2 -2
  107. package/lib/steps/extenders/api-serializer.js +2 -3
  108. package/lib/steps/extenders/base.d.ts +10 -10
  109. package/lib/steps/extenders/base.js +11 -11
  110. package/lib/steps/extenders/console-command.js +2 -3
  111. package/lib/steps/extenders/event.js +2 -3
  112. package/lib/steps/extenders/policy.js +2 -3
  113. package/lib/steps/extenders/route.js +2 -3
  114. package/lib/steps/extenders/service-provider.js +2 -3
  115. package/lib/steps/gen-ext-scaffolder.d.ts +6 -0
  116. package/lib/steps/gen-ext-scaffolder.js +510 -0
  117. package/lib/steps/js/base.d.ts +9 -9
  118. package/lib/steps/js/base.js +13 -12
  119. package/lib/steps/js/model.d.ts +5 -5
  120. package/lib/steps/js/model.js +8 -13
  121. package/lib/steps/misc/composer.d.ts +5 -6
  122. package/lib/steps/misc/composer.js +3 -3
  123. package/lib/steps/misc/git.d.ts +11 -0
  124. package/lib/steps/misc/git.js +20 -0
  125. package/lib/steps/misc/yarn.d.ts +5 -6
  126. package/lib/steps/misc/yarn.js +3 -3
  127. package/lib/steps/stubs/backend/api-controller.d.ts +1 -8
  128. package/lib/steps/stubs/backend/api-controller.js +2 -3
  129. package/lib/steps/stubs/backend/api-serializer.d.ts +4 -9
  130. package/lib/steps/stubs/backend/api-serializer.js +4 -4
  131. package/lib/steps/stubs/backend/command.d.ts +0 -5
  132. package/lib/steps/stubs/backend/command.js +1 -1
  133. package/lib/steps/stubs/backend/event-listener.d.ts +0 -5
  134. package/lib/steps/stubs/backend/event-listener.js +1 -1
  135. package/lib/steps/stubs/backend/handler-command.js +1 -1
  136. package/lib/steps/stubs/backend/handler.js +1 -1
  137. package/lib/steps/stubs/backend/migration.d.ts +4 -5
  138. package/lib/steps/stubs/backend/migration.js +8 -8
  139. package/lib/steps/stubs/backend/model.d.ts +4 -4
  140. package/lib/steps/stubs/backend/model.js +4 -4
  141. package/lib/steps/stubs/backend/policy.d.ts +0 -5
  142. package/lib/steps/stubs/backend/policy.js +1 -1
  143. package/lib/steps/stubs/backend/repository.d.ts +0 -5
  144. package/lib/steps/stubs/backend/repository.js +1 -1
  145. package/lib/steps/stubs/flarum-base.d.ts +9 -0
  146. package/lib/steps/stubs/flarum-base.js +10 -0
  147. package/lib/steps/stubs/frontend/component.js +0 -1
  148. package/lib/steps/stubs/frontend/modal.js +0 -1
  149. package/lib/steps/stubs/frontend/model.d.ts +4 -4
  150. package/lib/steps/stubs/frontend/model.js +3 -3
  151. package/lib/steps/stubs/js-base.d.ts +6 -7
  152. package/lib/steps/stubs/js-base.js +11 -16
  153. package/lib/steps/stubs/php-base.d.ts +7 -8
  154. package/lib/steps/stubs/php-base.js +12 -20
  155. package/lib/steps/update/js-imports.d.ts +5 -6
  156. package/lib/steps/update/js-imports.js +16 -19
  157. package/lib/utils/composer.d.ts +64 -0
  158. package/lib/utils/composer.js +8 -0
  159. package/lib/utils/migration.js +3 -3
  160. package/lib/utils/model-name.js +6 -6
  161. package/lib/utils/validation.d.ts +10 -7
  162. package/lib/utils/validation.js +9 -6
  163. package/oclif.manifest.json +1 -1
  164. package/package.json +55 -36
  165. package/php-subsystem/src/NodeVisitors/AddExtender.php +2 -1
  166. package/boilerplate/skeleton/extension/.github/workflows/build.yml +0 -32
  167. package/boilerplate/skeleton/extension/.github/workflows/lint.yml +0 -32
  168. package/boilerplate/skeleton/extension/.github/workflows/test.yml +0 -78
  169. package/lib/commands/infra/backend-testing.d.ts +0 -14
  170. package/lib/commands/infra/backend-testing.js +0 -26
  171. package/lib/provider/param-provider.d.ts +0 -15
  172. package/lib/provider/param-provider.js +0 -39
  173. package/lib/provider/path-provider.d.ts +0 -19
  174. package/lib/provider/path-provider.js +0 -24
  175. package/lib/steps/infra/backend-testing.d.ts +0 -8
  176. package/lib/steps/infra/backend-testing.js +0 -22
  177. package/lib/steps/infra/base.d.ts +0 -20
  178. package/lib/steps/infra/base.js +0 -36
  179. package/lib/steps/init/extension-skeleton.d.ts +0 -12
  180. package/lib/steps/init/extension-skeleton.js +0 -142
  181. package/lib/steps/step-manager.d.ts +0 -71
  182. package/lib/steps/step-manager.js +0 -173
  183. package/lib/steps/stubs/base.d.ts +0 -49
  184. package/lib/steps/stubs/base.js +0 -58
  185. package/lib/utils/extension-metadata.d.ts +0 -2
  186. package/lib/utils/extension-metadata.js +0 -21
@@ -0,0 +1,510 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.genExtScaffolder = exports.EXTENSION_MODULES = exports.EXTENSION_PARAMS = void 0;
4
+ const tslib_1 = require("tslib");
5
+ const scaffolder_1 = require("boilersmith/scaffolding/scaffolder");
6
+ const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
7
+ const mem_fs_editor_1 = require("mem-fs-editor");
8
+ const node_path_1 = require("node:path");
9
+ const simple_git_1 = (0, tslib_1.__importDefault)(require("simple-git"));
10
+ const simple_1 = (0, tslib_1.__importDefault)(require("spdx-license-list/simple"));
11
+ const composer_1 = require("../utils/composer");
12
+ function assertUnreachable(_x) {
13
+ throw new Error("Didn't expect to get here");
14
+ }
15
+ exports.EXTENSION_PARAMS = [
16
+ 'packageName',
17
+ 'packageDescription',
18
+ 'packageNamespace',
19
+ 'authorName',
20
+ 'authorEmail',
21
+ 'extensionName',
22
+ 'licenseType',
23
+ 'mainGitBranch',
24
+ 'licenseText',
25
+ 'packageNamespaceEscapedSlash',
26
+ 'extensionId',
27
+ 'year',
28
+ 'backendDirectory',
29
+ 'frontendDirectory',
30
+ ];
31
+ function paramNamesToDef(name) {
32
+ switch (name) {
33
+ case 'packageName':
34
+ return {
35
+ prompt: {
36
+ name,
37
+ type: 'text',
38
+ message: `Package ${chalk_1.default.dim('(vendor/extension-name)')}`,
39
+ validate: s => /^([\dA-Za-z-]{2,})\/([\dA-Za-z-]{2,})$/.test(s.trim()) || 'Invalid package name format',
40
+ format: s => s.toLowerCase(),
41
+ },
42
+ getCurrVal: async (fs, paths) => {
43
+ const json = (0, composer_1.getComposerJson)(fs, paths);
44
+ return json === null || json === void 0 ? void 0 : json.name;
45
+ },
46
+ };
47
+ case 'packageDescription':
48
+ return {
49
+ prompt: {
50
+ name,
51
+ type: 'text',
52
+ message: 'Package description',
53
+ },
54
+ getCurrVal: async (fs, paths) => {
55
+ var _a;
56
+ const json = (0, composer_1.getComposerJson)(fs, paths);
57
+ return (_a = json === null || json === void 0 ? void 0 : json.description) !== null && _a !== void 0 ? _a : '';
58
+ },
59
+ };
60
+ case 'packageNamespace':
61
+ return {
62
+ prompt: {
63
+ name,
64
+ type: 'text',
65
+ message: `Package namespace ${chalk_1.default.dim('(Vendor\\ExtensionName)')}`,
66
+ validate: s => /^([\dA-Za-z]+)\\([\dA-Za-z]+)$/.test(s.trim()) || 'Invalid namespace format',
67
+ format: (str) => str &&
68
+ str
69
+ .split('\\')
70
+ .map(s => s[0].toUpperCase() + s.slice(1))
71
+ .join('\\'),
72
+ },
73
+ getCurrVal: async (fs, paths) => {
74
+ var _a, _b, _c, _d, _e;
75
+ const json = (0, composer_1.getComposerJson)(fs, paths);
76
+ const namespace = (_e = ((_d = (_c = Object.keys((_b = (_a = json === null || json === void 0 ? void 0 : json.autoload) === null || _a === void 0 ? void 0 : _a['psr-4']) !== null && _b !== void 0 ? _b : {})) === null || _c === void 0 ? void 0 : _c[0]) !== null && _d !== void 0 ? _d : '')) === null || _e === void 0 ? void 0 : _e.slice(0, -1);
77
+ return namespace || '';
78
+ },
79
+ };
80
+ case 'authorName':
81
+ return {
82
+ prompt: {
83
+ name,
84
+ type: 'text',
85
+ message: 'Author name',
86
+ },
87
+ getCurrVal: async (fs, paths) => {
88
+ var _a, _b, _c;
89
+ const json = (0, composer_1.getComposerJson)(fs, paths);
90
+ return (_c = (_b = (_a = json.authors) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.name) !== null && _c !== void 0 ? _c : '';
91
+ },
92
+ };
93
+ case 'authorEmail':
94
+ return {
95
+ prompt: {
96
+ name,
97
+ type: 'text',
98
+ message: 'Author email',
99
+ validate: s => !s || /^[\w!#$%&*+./=?^`{|}~’-]+@[\dA-Za-z-]+(?:\.[\dA-Za-z-]+)*$/.test(s) || 'Invalid email format',
100
+ },
101
+ getCurrVal: async (fs, paths) => {
102
+ var _a, _b, _c;
103
+ const json = (0, composer_1.getComposerJson)(fs, paths);
104
+ return (_c = (_b = (_a = json.authors) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.email) !== null && _c !== void 0 ? _c : '';
105
+ },
106
+ };
107
+ case 'extensionName':
108
+ return {
109
+ prompt: {
110
+ name,
111
+ type: 'text',
112
+ message: 'Extension name',
113
+ validate: str => Boolean(str.trim()) || 'The extension name is required',
114
+ format: str => str
115
+ .split(' ')
116
+ .map((s) => (s.length > 3 ? s[0].toUpperCase() + s.slice(1) : s))
117
+ .join(' '),
118
+ },
119
+ getCurrVal: async (fs, paths) => {
120
+ var _a, _b, _c;
121
+ const json = (0, composer_1.getComposerJson)(fs, paths);
122
+ if (json.name === 'flarum/core')
123
+ return 'Core';
124
+ return (_c = (_b = (_a = json === null || json === void 0 ? void 0 : json.extra) === null || _a === void 0 ? void 0 : _a['flarum-extension']) === null || _b === void 0 ? void 0 : _b.title) !== null && _c !== void 0 ? _c : '';
125
+ },
126
+ };
127
+ case 'licenseType':
128
+ return {
129
+ prompt: {
130
+ name,
131
+ type: 'autocomplete',
132
+ message: 'License',
133
+ choices: [...simple_1.default].map(e => ({ title: e, value: e })),
134
+ },
135
+ getCurrVal: async (fs, paths) => {
136
+ var _a;
137
+ const json = (0, composer_1.getComposerJson)(fs, paths);
138
+ return (_a = json === null || json === void 0 ? void 0 : json.license) !== null && _a !== void 0 ? _a : '';
139
+ },
140
+ };
141
+ case 'licenseText':
142
+ return {
143
+ name,
144
+ uses: ['licenseType'],
145
+ compute: async (_paths, licenseType) => (licenseType ? require(`spdx-license-list/licenses/${licenseType}`).licenseText : ''),
146
+ };
147
+ case 'packageNamespaceEscapedSlash':
148
+ return {
149
+ name,
150
+ uses: ['packageNamespace'],
151
+ compute: async (_paths, packageNamespace) => packageNamespace.replace('\\', '\\\\'),
152
+ };
153
+ case 'extensionId':
154
+ return {
155
+ name,
156
+ uses: ['packageName'],
157
+ compute: async (_paths, packageName) => packageName.replace(/(flarum-ext-)|(flarum-)/, '').replace('/', '-'),
158
+ };
159
+ case 'year':
160
+ return {
161
+ name,
162
+ uses: [],
163
+ compute: async () => new Date().getFullYear().toString(),
164
+ };
165
+ case 'mainGitBranch':
166
+ return {
167
+ prompt: {
168
+ name,
169
+ type: 'text',
170
+ message: `Main git branch ${chalk_1.default.dim('(JS will automatically build when changes are pushed to GitHub on this branch)')}`,
171
+ // See https://stackoverflow.com/a/12093994/11091039
172
+ validate: s => /^(?!.*\/\.)(?!.*\.\.)(?!\/)(?!.*\/\/)(?!.*@{)(?!.*\\)[^\000-\037 *:?[^~\177]+(?<!\.lock)(?<!\/)(?<!\.)$/.test(s.trim()) || 'Invalid git branch',
173
+ initial: 'main',
174
+ },
175
+ getCurrVal: async () => {
176
+ var _a;
177
+ return (_a = (await (0, simple_git_1.default)().getConfig('init.defaultBranch')).value) !== null && _a !== void 0 ? _a : 'main';
178
+ },
179
+ };
180
+ case 'backendDirectory':
181
+ return {
182
+ name,
183
+ uses: [],
184
+ compute: async (paths) => {
185
+ const monorepoPath = paths.monorepo();
186
+ return monorepoPath ? paths.package().replace(monorepoPath, '.') : '.';
187
+ },
188
+ };
189
+ case 'frontendDirectory':
190
+ return {
191
+ name,
192
+ uses: [],
193
+ compute: async (paths) => {
194
+ const monorepoPath = paths.monorepo();
195
+ return monorepoPath ? paths.package().replace(monorepoPath, '.') + '/js' : './js';
196
+ },
197
+ };
198
+ }
199
+ return assertUnreachable(name);
200
+ }
201
+ exports.EXTENSION_MODULES = [
202
+ 'core',
203
+ 'icon',
204
+ 'js',
205
+ 'jsCommon',
206
+ 'css',
207
+ 'locale',
208
+ 'gitConf',
209
+ 'githubActions',
210
+ 'prettier',
211
+ 'typescript',
212
+ 'bundlewatch',
213
+ 'backendTesting',
214
+ 'editorConfig',
215
+ 'styleci',
216
+ ];
217
+ function moduleNameToDef(name) {
218
+ switch (name) {
219
+ case 'core':
220
+ return {
221
+ name,
222
+ updatable: false,
223
+ togglable: false,
224
+ shortDescription: 'Core Functionality',
225
+ filesToReplace: [
226
+ 'extend.php',
227
+ 'README.md',
228
+ 'LICENSE.md',
229
+ { path: 'js/src/admin/index.js', needsOtherModules: ['js'] },
230
+ { path: 'js/src/forum/index.js', needsOtherModules: ['js'] },
231
+ { path: 'js/src/common/index.js', needsOtherModules: ['js', 'jsCommon'] },
232
+ ],
233
+ jsonToAugment: {
234
+ 'composer.json': [
235
+ 'name',
236
+ 'description',
237
+ 'keywords',
238
+ 'type',
239
+ 'license',
240
+ 'require.flarum/core',
241
+ 'authors',
242
+ 'autoload.psr-4.${params.packageNamespaceEscapedSlash}\\',
243
+ 'extra.flarum-extension.title',
244
+ 'extra.flarum-extension.category',
245
+ ],
246
+ },
247
+ needsTemplateParams: [
248
+ 'packageName',
249
+ 'packageNamespace',
250
+ 'packageNamespaceEscapedSlash',
251
+ 'packageDescription',
252
+ 'extensionName',
253
+ 'licenseType',
254
+ 'licenseText',
255
+ 'authorName',
256
+ 'authorEmail',
257
+ 'extensionId',
258
+ 'year',
259
+ ],
260
+ };
261
+ case 'icon':
262
+ return {
263
+ name,
264
+ updatable: false,
265
+ togglable: false,
266
+ shortDescription: 'Extension Icon',
267
+ filesToReplace: [],
268
+ jsonToAugment: {
269
+ 'composer.json': ['extra.flarum-extension.icon.name', 'extra.flarum-extension.icon.color', 'extra.flarum-extension.icon.backgroundColor'],
270
+ },
271
+ needsTemplateParams: [],
272
+ };
273
+ case 'js':
274
+ return {
275
+ name,
276
+ updatable: true,
277
+ togglable: true,
278
+ defaultEnabled: true,
279
+ shortDescription: 'Javascript',
280
+ longDescription: "Files, tools, and scripts to build Flarum's frontend.",
281
+ dependsOn: [],
282
+ filesToReplace: ['js/webpack.config.js', 'js/admin.js', 'js/forum.js'],
283
+ jsonToAugment: {
284
+ 'js/package.json': [
285
+ 'name',
286
+ 'private',
287
+ 'devDependencies.flarum-webpack-config',
288
+ 'devDependencies.webpack',
289
+ 'devDependencies.webpack-cli',
290
+ 'scripts.dev',
291
+ 'scripts.build',
292
+ 'scripts.analyze',
293
+ ],
294
+ },
295
+ needsTemplateParams: ['packageName'],
296
+ };
297
+ case 'jsCommon':
298
+ return {
299
+ name,
300
+ updatable: false,
301
+ togglable: true,
302
+ defaultEnabled: true,
303
+ shortDescription: 'JS common code',
304
+ longDescription: 'Shared code between the forum and the admin frontends',
305
+ dependsOn: ['js'],
306
+ filesToReplace: [],
307
+ jsonToAugment: {},
308
+ needsTemplateParams: [],
309
+ };
310
+ case 'css':
311
+ return {
312
+ name,
313
+ updatable: false,
314
+ togglable: true,
315
+ defaultEnabled: true,
316
+ shortDescription: 'CSS',
317
+ longDescription: "LESS starter files for Flarum's frontend styling.",
318
+ dependsOn: [],
319
+ filesToReplace: ['less/admin.less', 'less/forum.less'],
320
+ jsonToAugment: {},
321
+ needsTemplateParams: [],
322
+ };
323
+ case 'locale':
324
+ return {
325
+ name,
326
+ updatable: false,
327
+ togglable: true,
328
+ defaultEnabled: true,
329
+ shortDescription: 'Locale',
330
+ longDescription: 'Translation starter files.',
331
+ dependsOn: [],
332
+ filesToReplace: ['locale/en.yml'],
333
+ jsonToAugment: {},
334
+ needsTemplateParams: [],
335
+ };
336
+ case 'gitConf':
337
+ return {
338
+ name,
339
+ updatable: true,
340
+ togglable: true,
341
+ defaultEnabled: true,
342
+ shortDescription: 'Git Configuration',
343
+ longDescription: 'Git config files (e.g. .gitignore, .gitattributes).',
344
+ dependsOn: [],
345
+ filesToReplace: [{ path: 'gitignore', destPath: '.gitignore' }, '.gitattributes'],
346
+ jsonToAugment: {},
347
+ needsTemplateParams: [],
348
+ };
349
+ case 'githubActions':
350
+ return {
351
+ name,
352
+ updatable: true,
353
+ togglable: true,
354
+ defaultEnabled: true,
355
+ shortDescription: 'GitHub Actions CI',
356
+ longDescription: 'Automatically run checks via GitHub Actions CI. Free for open source projects.',
357
+ dependsOn: [],
358
+ filesToReplace: [
359
+ { path: '.github/workflows/frontend.yml', monorepoPath: '.github/workflows/${params.extensionId}-frontend.yml' },
360
+ { path: '.github/workflows/backend.yml', monorepoPath: '.github/workflows/${params.extensionId}-backend.yml' },
361
+ ],
362
+ jsonToAugment: {},
363
+ needsTemplateParams: ['frontendDirectory', 'backendDirectory', 'mainGitBranch', 'extensionId', 'extensionName'],
364
+ };
365
+ case 'prettier':
366
+ return {
367
+ name,
368
+ updatable: true,
369
+ togglable: true,
370
+ defaultEnabled: true,
371
+ shortDescription: 'Auto-format frontend code with Prettier.',
372
+ dependsOn: ['js'],
373
+ filesToReplace: [],
374
+ jsonToAugment: {
375
+ 'js/package.json': ['prettier', 'devDependencies.prettier', 'devDependencies.@flarum/prettier-config', 'scripts.format', 'scripts.format-check'],
376
+ },
377
+ needsTemplateParams: [],
378
+ };
379
+ case 'typescript':
380
+ return {
381
+ name,
382
+ updatable: true,
383
+ togglable: true,
384
+ defaultEnabled: true,
385
+ shortDescription: 'Support TypeScript in frontend code.',
386
+ dependsOn: ['js'],
387
+ filesToReplace: ['js/tsconfig.json'],
388
+ jsonToAugment: {
389
+ 'js/package.json': [
390
+ 'prettier',
391
+ 'devDependencies.flarum-tsconfig',
392
+ 'devDependencies.typescript',
393
+ 'devDependencies.typescript-coverage-report',
394
+ 'scripts.check-typings',
395
+ 'scripts.check-typings-coverage',
396
+ ],
397
+ },
398
+ needsTemplateParams: [],
399
+ };
400
+ case 'bundlewatch':
401
+ return {
402
+ name,
403
+ updatable: true,
404
+ togglable: true,
405
+ defaultEnabled: false,
406
+ shortDescription: 'Enable Bundlewatch Checks',
407
+ dependsOn: ['js'],
408
+ filesToReplace: [],
409
+ jsonToAugment: {},
410
+ needsTemplateParams: [],
411
+ };
412
+ case 'backendTesting':
413
+ return {
414
+ name,
415
+ updatable: true,
416
+ togglable: true,
417
+ defaultEnabled: true,
418
+ shortDescription: 'Backend PHP unit and integration testing via PHPUnit.',
419
+ dependsOn: [],
420
+ filesToReplace: [
421
+ 'tests/phpunit.integration.xml',
422
+ 'tests/phpunit.unit.xml',
423
+ 'tests/fixtures/.gitkeep',
424
+ 'tests/integration/setup.php',
425
+ 'tests/unit/.gitkeep',
426
+ ],
427
+ jsonToAugment: {
428
+ 'composer.json': [
429
+ 'autoload-dev.psr-4.${params.packageNamespaceEscapedSlash}\\Tests\\',
430
+ 'scripts.test',
431
+ 'scripts.test:unit',
432
+ 'scripts.test:integration',
433
+ 'scripts.test:setup',
434
+ 'scripts-descriptions.test',
435
+ 'scripts-descriptions.test:unit',
436
+ 'scripts-descriptions.test:integration',
437
+ 'scripts-descriptions.test:setup',
438
+ 'require-dev.flarum/testing',
439
+ ],
440
+ },
441
+ needsTemplateParams: ['packageNamespaceEscapedSlash'],
442
+ };
443
+ case 'editorConfig':
444
+ return {
445
+ name,
446
+ updatable: true,
447
+ togglable: true,
448
+ defaultEnabled: true,
449
+ shortDescription: 'EditorConfig setup',
450
+ dependsOn: [],
451
+ filesToReplace: ['.editorconfig'],
452
+ jsonToAugment: {},
453
+ needsTemplateParams: [],
454
+ };
455
+ case 'styleci':
456
+ return {
457
+ name,
458
+ updatable: true,
459
+ togglable: true,
460
+ defaultEnabled: true,
461
+ shortDescription: 'StyleCI config file',
462
+ dependsOn: [],
463
+ filesToReplace: [
464
+ { path: '.styleci.yml', monorepoPath: '.styleci.yml' },
465
+ ],
466
+ jsonToAugment: {},
467
+ needsTemplateParams: [],
468
+ };
469
+ }
470
+ return assertUnreachable(name);
471
+ }
472
+ let cached;
473
+ function genExtScaffolder() {
474
+ if (cached)
475
+ return cached;
476
+ const moduleStatusCache = {
477
+ get: async (module, fs, paths) => {
478
+ var _a, _b, _c, _d;
479
+ const json = (0, composer_1.getComposerJson)(fs, paths);
480
+ return !module.togglable || ((_d = (_c = (_b = (_a = json === null || json === void 0 ? void 0 : json.extra) === null || _a === void 0 ? void 0 : _a['flarum-cli']) === null || _b === void 0 ? void 0 : _b.modules) === null || _c === void 0 ? void 0 : _c[module.name]) !== null && _d !== void 0 ? _d : module.defaultEnabled);
481
+ },
482
+ set: async (module, enabled, fs, paths) => {
483
+ const json = {
484
+ extra: {
485
+ 'flarum-cli': {
486
+ modules: {
487
+ [module.name]: enabled,
488
+ },
489
+ },
490
+ },
491
+ };
492
+ (0, mem_fs_editor_1.create)(fs).extendJSON(paths.package('composer.json'), json, undefined, 4);
493
+ },
494
+ };
495
+ const excludeScaffoldingFunc = (fs, paths) => {
496
+ var _a, _b, _c;
497
+ const json = (0, composer_1.getComposerJson)(fs, paths);
498
+ return (_c = (_b = (_a = json === null || json === void 0 ? void 0 : json.extra) === null || _a === void 0 ? void 0 : _a['flarum-cli']) === null || _b === void 0 ? void 0 : _b.excludeScaffolding) !== null && _c !== void 0 ? _c : [];
499
+ };
500
+ const scaffolder = new scaffolder_1.Scaffolder((0, node_path_1.resolve)(__dirname, '../../boilerplate/skeleton/extension'), moduleStatusCache, excludeScaffoldingFunc);
501
+ for (const name of exports.EXTENSION_MODULES) {
502
+ scaffolder.registerModule(moduleNameToDef(name));
503
+ }
504
+ for (const name of exports.EXTENSION_PARAMS) {
505
+ scaffolder.registerTemplateParam(paramNamesToDef(name));
506
+ }
507
+ cached = scaffolder;
508
+ return scaffolder;
509
+ }
510
+ exports.genExtScaffolder = genExtScaffolder;
@@ -1,15 +1,15 @@
1
1
  import { Store } from 'mem-fs';
2
- import { ParamProvider } from '../../provider/param-provider';
3
- import { PathProvider } from '../../provider/path-provider';
4
- import { PhpProvider } from '../../provider/php-provider';
5
- import { Step } from '../step-manager';
6
- export declare abstract class BaseJsStep implements Step {
2
+ import { IO } from 'boilersmith/io';
3
+ import { Paths } from 'boilersmith/paths';
4
+ import { Step } from 'boilersmith/step-manager';
5
+ import { FlarumProviders } from '../../providers';
6
+ export declare abstract class BaseJsStep implements Step<FlarumProviders> {
7
7
  abstract type: string;
8
8
  composable: boolean;
9
- run(fs: Store, pathProvider: PathProvider, paramProvider: ParamProvider, _phpProvider: PhpProvider): Promise<Store>;
10
- protected abstract getDefinition(paramProvider: ParamProvider): Promise<string>;
11
- protected abstract getImports(frontend: string, pathProvider: PathProvider, paramProvider: ParamProvider): Promise<string>;
9
+ run(fs: Store, paths: Paths, io: IO, _providers: FlarumProviders): Promise<Store>;
10
+ protected abstract getDefinition(io: IO): Promise<string>;
11
+ protected abstract getImports(frontend: string, paths: Paths, io: IO): Promise<string>;
12
12
  protected importPath(frontend: string, classNamespace: string): string;
13
13
  exposes: never[];
14
- getExposed(_pathProvider: PathProvider, _paramProvider: ParamProvider): Record<string, unknown>;
14
+ getExposed(_paths: Paths, _paramProvider: IO): Record<string, unknown>;
15
15
  }
@@ -1,37 +1,38 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.BaseJsStep = void 0;
4
- const glob_1 = require("glob");
4
+ const tslib_1 = require("tslib");
5
+ const globby_1 = (0, tslib_1.__importDefault)(require("globby"));
5
6
  const mem_fs_editor_1 = require("mem-fs-editor");
6
- const IMPORTS_REGEX = /((^import\s+(?:([\w,{}\s*]+)\s+from)?\s*(?:(?:["'])?([@\w\s\\/.-]+)\3?(?:["'])?)\s*;?\s*)*)(.*)/m;
7
- const INIT_REGEX = /^(app\.initializers\.add\('[^']+',\s*\(\)\s*=>\s*\{)$/m;
7
+ const IMPORTS_REGEX = /((^import\s+(?:([\s\w*,{}]+)\s+from)?\s*["']?([\s\w./@\\-]+)\3?["']?\s*;?\s*)*)(.*)/m;
8
+ const INIT_REGEX = /^(app\.initializers\.add\('[^']+',\s*\(\)\s*=>\s*{)$/m;
8
9
  class BaseJsStep {
9
10
  constructor() {
10
11
  this.composable = true;
11
12
  this.exposes = [];
12
13
  }
13
- async run(fs, pathProvider, paramProvider, _phpProvider) {
14
- const fsEditor = mem_fs_editor_1.create(fs);
15
- const frontend = await paramProvider.get({ name: 'frontend', type: 'text' });
14
+ async run(fs, paths, io, _providers) {
15
+ const fsEditor = (0, mem_fs_editor_1.create)(fs);
16
+ const frontend = await io.getParam({ name: 'frontend', type: 'text' });
16
17
  let frontends = [frontend];
17
18
  if (frontend === 'common') {
18
19
  frontends = ['admin', 'forum'];
19
20
  }
20
- frontends.forEach(frontend => {
21
- const fsSrcFilePaths = glob_1.glob.sync(pathProvider.ext(`js/src/${frontend}/*.{js,jsx,ts,tsx}`));
21
+ for (const frontend of frontends) {
22
+ const fsSrcFilePaths = globby_1.default.sync(paths.package(`js/src/${frontend}/*.{js,jsx,ts,tsx}`));
22
23
  fsSrcFilePaths.forEach(async (match) => {
23
24
  /**
24
25
  * @TODO look into using https://esprima.org/ instead
25
26
  */
26
27
  const currContents = fsEditor.read(match);
27
- const imports = await this.getImports(frontend, pathProvider, paramProvider);
28
- const definition = await this.getDefinition(paramProvider);
28
+ const imports = await this.getImports(frontend, paths, io);
29
+ const definition = await this.getDefinition(io);
29
30
  const newContents = currContents
30
31
  .replace(INIT_REGEX, `$1\n ${definition}\n`)
31
32
  .replace(IMPORTS_REGEX, `$1${imports}\n\n$5`);
32
33
  fsEditor.write(match, newContents);
33
34
  });
34
- });
35
+ }
35
36
  return fs;
36
37
  }
37
38
  importPath(frontend, classNamespace) {
@@ -39,7 +40,7 @@ class BaseJsStep {
39
40
  path = path.replace(`../${frontend}/`, './');
40
41
  return path;
41
42
  }
42
- getExposed(_pathProvider, _paramProvider) {
43
+ getExposed(_paths, _paramProvider) {
43
44
  return {};
44
45
  }
45
46
  }
@@ -1,10 +1,10 @@
1
- import { ParamProvider } from '../../provider/param-provider';
2
- import { PathProvider } from '../../provider/path-provider';
1
+ import { IO } from 'boilersmith/io';
2
+ import { Paths } from 'boilersmith/paths';
3
3
  import { BaseJsStep } from './base';
4
4
  export declare class GenerateModelDefinition extends BaseJsStep {
5
5
  type: string;
6
- protected getDefinition(paramProvider: ParamProvider): Promise<string>;
7
- protected getImports(frontend: string, pathProvider: PathProvider, paramProvider: ParamProvider): Promise<string>;
6
+ protected getDefinition(io: IO): Promise<string>;
7
+ protected getImports(frontend: string, paths: Paths, io: IO): Promise<string>;
8
8
  exposes: never[];
9
- getExposed(_pathProvider: PathProvider, _paramProvider: ParamProvider): Record<string, unknown>;
9
+ getExposed(_paths: Paths, _paramProvider: IO): Record<string, unknown>;
10
10
  }
@@ -8,24 +8,19 @@ class GenerateModelDefinition extends base_1.BaseJsStep {
8
8
  this.type = 'Generate JS Model Definition';
9
9
  this.exposes = [];
10
10
  }
11
- async getDefinition(paramProvider) {
12
- const className = await paramProvider.get({ name: 'className', type: 'text' });
13
- let modelType = await paramProvider.get({ name: 'modelType', type: 'text' });
14
- if (modelType.includes('-')) {
15
- modelType = `['${modelType}']`;
16
- }
17
- else {
18
- modelType = `.${modelType}`;
19
- }
11
+ async getDefinition(io) {
12
+ const className = await io.getParam({ name: 'className', type: 'text' });
13
+ let modelType = await io.getParam({ name: 'modelType', type: 'text' });
14
+ modelType = modelType.includes('-') ? `['${modelType}']` : `.${modelType}`;
20
15
  return `app.store.models${modelType} = ${className};`;
21
16
  }
22
- async getImports(frontend, pathProvider, paramProvider) {
23
- const className = await paramProvider.get({ name: 'className', type: 'text' });
24
- const classNamespace = await paramProvider.get({ name: 'classNamespace', type: 'text' });
17
+ async getImports(frontend, paths, io) {
18
+ const className = await io.getParam({ name: 'className', type: 'text' });
19
+ const classNamespace = await io.getParam({ name: 'classNamespace', type: 'text' });
25
20
  const importPath = this.importPath(frontend, classNamespace);
26
21
  return `import ${className} from '${importPath}';`;
27
22
  }
28
- getExposed(_pathProvider, _paramProvider) {
23
+ getExposed(_paths, _paramProvider) {
29
24
  return {};
30
25
  }
31
26
  }
@@ -1,12 +1,11 @@
1
1
  import { Store } from 'mem-fs';
2
- import { ParamProvider } from '../../provider/param-provider';
3
- import { PathProvider } from '../../provider/path-provider';
4
- import { PhpProvider } from '../../provider/php-provider';
5
- import { Step } from '../step-manager';
2
+ import { IO } from 'boilersmith/io';
3
+ import { Paths } from 'boilersmith/paths';
4
+ import { DefaultProviders, Step } from 'boilersmith/step-manager';
6
5
  export declare class ComposerInstall implements Step {
7
6
  type: string;
8
7
  composable: boolean;
9
- run(fs: Store, pathProvider: PathProvider, _paramProvider: ParamProvider, _phpProvider: PhpProvider): Promise<Store>;
8
+ run(fs: Store, paths: Paths, _paramProvider: IO, _providers: DefaultProviders): Promise<Store>;
10
9
  exposes: never[];
11
- getExposed(): {};
10
+ getExposed(): Record<string, unknown>;
12
11
  }