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