@flarum/cli 2.0.0-beta.1 → 2.0.0-beta.13

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 (29) hide show
  1. package/README.md +45 -9
  2. package/boilerplate/skeleton/extension/.gitattributes +1 -0
  3. package/boilerplate/skeleton/extension/.github/workflows/backend.yml +1 -1
  4. package/boilerplate/skeleton/extension/.github/workflows/frontend.yml +1 -1
  5. package/boilerplate/skeleton/extension/extend.php +2 -2
  6. package/boilerplate/skeleton/extension/gitignore +12 -0
  7. package/boilerplate/skeleton/extension/js/.bundlewatch.config.json +8 -0
  8. package/boilerplate/skeleton/extension/js/admin.ts +2 -0
  9. package/boilerplate/skeleton/extension/js/forum.ts +2 -0
  10. package/boilerplate/skeleton/extension/js/gitignore +9 -0
  11. package/boilerplate/skeleton/extension/js/package.json +3 -3
  12. package/boilerplate/skeleton/extension/js/src/admin/index.ts +5 -0
  13. package/boilerplate/skeleton/extension/js/src/common/index.ts +5 -0
  14. package/boilerplate/skeleton/extension/js/src/forum/index.ts +5 -0
  15. package/lib/base-command.d.ts +2 -0
  16. package/lib/base-command.js +28 -32
  17. package/lib/boilersmith/io.d.ts +8 -4
  18. package/lib/boilersmith/io.js +33 -8
  19. package/lib/boilersmith/scaffolding/audit-step-factory.js +7 -0
  20. package/lib/boilersmith/scaffolding/infra-step-factory.js +1 -1
  21. package/lib/boilersmith/scaffolding/module.d.ts +17 -3
  22. package/lib/boilersmith/scaffolding/module.js +10 -5
  23. package/lib/commands/infra.d.ts +1 -1
  24. package/lib/steps/gen-ext-scaffolder.d.ts +1 -1
  25. package/lib/steps/gen-ext-scaffolder.js +97 -11
  26. package/lib/steps/js/base.js +3 -2
  27. package/lib/steps/update/js-imports.js +4 -3
  28. package/oclif.manifest.json +1 -1
  29. package/package.json +7 -9
package/README.md CHANGED
@@ -37,7 +37,7 @@ $ npm install -g @flarum/cli
37
37
  $ flarum-cli COMMAND
38
38
  running command...
39
39
  $ flarum-cli (-v|--version|version)
40
- @flarum/cli/2.0.0-beta.1 linux-x64 node-v16.13.0
40
+ @flarum/cli/2.0.0-beta.13 linux-x64 node-v16.13.0
41
41
  $ flarum-cli --help [COMMAND]
42
42
  USAGE
43
43
  $ flarum-cli COMMAND
@@ -61,8 +61,9 @@ flarum-cli --help
61
61
 
62
62
  # Commands
63
63
  * `flarum-cli help [COMMAND]`
64
- * `flarum-cli infra backend-testing [PATH]`
65
64
  * `flarum-cli init [PATH]`
65
+ * `flarum-cli infra [MODULE] [PATH]`
66
+ * `flarum-cli audit infra [--monorepo] [--fix]`
66
67
  * `flarum-cli make backend api-controller [PATH]`
67
68
  * `flarum-cli make backend api-serializer [PATH]`
68
69
  * `flarum-cli make backend api-serializer-attributes [PATH]`
@@ -83,6 +84,8 @@ flarum-cli --help
83
84
  * `flarum-cli make frontend model [PATH]`
84
85
  * `flarum-cli update js-imports [PATH]`
85
86
 
87
+ All commands can use a `--no-interaction` flag to proceed with defaults when possible.
88
+
86
89
  ## For Maintainers
87
90
 
88
91
  This section is for maintainers of the flarum-cli codebase.
@@ -99,7 +102,7 @@ The base command is implemented at [src/base-command.ts](https://github.com/flar
99
102
  3. Confirm we are in the right directory
100
103
  4. Confirm that files will be overwritten / clear files as needed
101
104
  5. Run a set of registered steps
102
- 6. Tell the user which steps ran
105
+ 6. Tell the user which steps ran, or display any errors
103
106
  7. Show a goodbye message
104
107
 
105
108
  Actual functionality is implemented at the step layer.
@@ -117,7 +120,7 @@ More documentation (and functionality!) will be added later.
117
120
 
118
121
  #### What are steps?
119
122
 
120
- Steps represent granular operations. Some are bigger and some are smaller, but they include:
123
+ Steps represent meaningful, granular operations. Some are bigger and some are smaller, but they include:
121
124
 
122
125
  - Initializing an extension from boilerplate
123
126
  - Updating some part of an extension from boilerplate (like adding backend testing)
@@ -132,9 +135,10 @@ If some subtask might be needed by multiple commands, that should be a step too.
132
135
  The actual logic of a step is implemented in the async `run` method. This method takes:
133
136
 
134
137
  - An in-memory filesystem object (through `mem-fs`)
135
- - A path provider, which is a class that can be used to get paths relative to the extension root, the working directory, the requested directory, and the CLI's boilerplate directory
136
- - A param provider, which can be used to prompt the user for parameters. We'll discuss this more soon.
137
- - A "php provider", which can be used to interact with the PHP subsystem to add extenders to extend.php.
138
+ - A paths object, which is a class that can be used to get paths relative to the extension root, the working directory, the requested directory (if the command was run with the `path` arg specified), and the monorepo directory (if in a subdirectory of a monorepo).
139
+ - An `io` instance, which can be used to prompt the user for input or display outputs / errors.
140
+ - An object of "providers", which represent additional functionality. For Flarum commands, these are:
141
+ - A "php provider", which can be used to interact with the PHP subsystem to add extenders to extend.php.
138
142
 
139
143
  Steps should modify the in-memory filesystem with their changes and return it.
140
144
 
@@ -214,8 +218,6 @@ Steps for generating extenders should use `src/steps/extenders/base`, where all
214
218
 
215
219
  Steps for generating templates from php stubs should use `src/steps/stubs/php-base`, where they just need to describe what stub file they use, which params they need, and a recommended namespace where the generated file should be placed.
216
220
 
217
- Steps for `infra` operations (copying over some portion of the default skeleton, for operations like adding/updating backend testing or TypeScript config) shouls use `src/steps/infra/base`, where all they need to indicate is a list of files from the boilerplate they copy over, and an object describing which JSON config keys should be copied from the boilerplate to the extension for various JSON files.
218
-
219
221
  ### Testing
220
222
 
221
223
  Most of this architecture was driven by TDD and BDD development, allowing for a highly decoupled system.
@@ -225,3 +227,37 @@ Any additions of steps, modifications of providers, or changes of functionality
225
227
  The 3 base step types actually provide a simple interface to generate test cases. See the relevant test files for more info.
226
228
 
227
229
  Since commands directly affect the filesystem, unit tests for them aren't really possible. It would also be quite complex to unit test all commands in addition to all steps. For this reason, commands should be manually tested, but unit tests are not currently required.
230
+
231
+ ### Monorepo Support
232
+
233
+ Flarum CLI was designed with monorepos in mind.
234
+ When registering a step, you can provide it an array of subdirectories to run it in.
235
+ For each of these subdirectories, an instance of the step will run with the `paths` object returning the subdirectory as `package()`, and the original root directory as `monorepo()`.
236
+
237
+ A monorepo should have a `flarum-monorepo.json` file in the root directory with the following (optional) keys:
238
+
239
+ - `packages.core`: a path to Flarum Core, if present.
240
+ - `packages.extensions`: an array of paths to Flarum extensions.
241
+ - `packages.composer`: an array of paths to non-extension PHP Composer packages published on Packagist.
242
+ - `packages.npm`: an array of paths to non-extension JS/TS packages published on NPM.
243
+
244
+ ### Scaffolding Generation
245
+
246
+ One powerful use-case of Flarum CLI is creating new extensions, and keeping infrastructure in sync for existing extensions.
247
+ For example, if managing 100 extensions, making sure the prettier config is consistent for all of them can be very tedious. Additionally, it can be annoying to have to add TypeScript config to every extension, and it's easy to make mistakes.
248
+
249
+ For this purpose, Flarum CLI's `Scaffolder` system formalizes the concepts of initializing and updating extension infrastructure.
250
+
251
+ At the core level, there's a boilerplate directory (`boilerplate/skeleton/extension`) that contains the scaffolding for a new extension.
252
+
253
+ The scaffolder receives a set of modules, which represent some aspect of infrastructure (e.g. JS, TypeScript, Backend Testing, etc).
254
+ Modules can be updatable (e.g. TypeScript) or not (e.g. the core setup of an `extend.php` file).
255
+ They can also be togglable (e.g. JS), or not, in which case they are always on.
256
+
257
+ Modules own files in the scaffolding directory, as well as keys in JSON config files. Every file and key must belong to at least one module. If any keys in a JSON config file belong to a module, all keys must belong to a module; if no keys are owned, the config file is treated like any other file.
258
+
259
+ Modules also have template params, which are used as variables in the scaffolding.
260
+
261
+ There's a lot more features and guaruntees than that, see the `Module` interface for more information.
262
+
263
+ The main benefit to this system is that given this scaffolding / module setup, it is possible to generate steps to initialize a new extension, update/add a module to an existing extension, or audit an extension for any outdated infrastructure. This is how the `init`, `infra`, and `audit infra` commands are implemented.
@@ -13,5 +13,6 @@ tests export-ignore
13
13
  js/dist/* -diff
14
14
  js/dist/* linguist-generated
15
15
  js/dist-typings/* linguist-generated
16
+ js/yarn.lock -diff
16
17
 
17
18
  * text=auto eol=lf
@@ -1,4 +1,4 @@
1
- name: PHP
1
+ name: <%= params.extensionName %> PHP
2
2
 
3
3
  on: [workflow_dispatch, push, pull_request]
4
4
 
@@ -1,4 +1,4 @@
1
- name: JS
1
+ name: <%= params.extensionName %> JS
2
2
 
3
3
  on: [workflow_dispatch, push, pull_request]
4
4
 
@@ -14,10 +14,10 @@ namespace <%= params.packageNamespace %>;
14
14
  use Flarum\Extend;
15
15
 
16
16
  return [
17
- <% if (modules.js || modules.css) { %>(new Extend\Frontend('forum'))
17
+ <% if (modules.forum) { %>(new Extend\Frontend('forum'))
18
18
  <% if (modules.js) { %>->js(__DIR__.'/js/dist/forum.js')<% if (!modules.css) { %>,<% } %><% } %>
19
19
  <% if (modules.css) { %>->css(__DIR__.'/less/forum.less'),<% } %><% } %>
20
- <% if (modules.js || modules.css) { %>(new Extend\Frontend('admin'))
20
+ <% if (modules.admin) { %>(new Extend\Frontend('admin'))
21
21
  <% if (modules.js) { %>->js(__DIR__.'/js/dist/admin.js')<% if (!modules.css) { %>,<% } %><% } %>
22
22
  <% if (modules.css) { %>->css(__DIR__.'/less/admin.less'),<% } %><% } %>
23
23
  <% if (modules.locale) { %>new Extend\Locales(__DIR__.'/locale'),<% } %>
@@ -0,0 +1,12 @@
1
+ /vendor
2
+ composer.lock
3
+ composer.phar
4
+
5
+ .DS_Store
6
+ Thumbs.db
7
+ tests/.phpunit.result.cache
8
+ /tests/integration/tmp
9
+ .vagrant
10
+ .idea/*
11
+ .vscode
12
+ js/coverage-ts
@@ -0,0 +1,8 @@
1
+ {
2
+ "files": [
3
+ {
4
+ "path": "./dist/*.js"
5
+ }
6
+ ],
7
+ "defaultCompression": "gzip"
8
+ }
@@ -0,0 +1,2 @@
1
+ <% if (modules.jsCommon) { %>export * from './src/common';
2
+ <% } %>export * from './src/admin';
@@ -0,0 +1,2 @@
1
+ <% if (modules.jsCommon) { %>export * from './src/common';
2
+ <% } %>export * from './src/forum';
@@ -0,0 +1,9 @@
1
+ .pnp.*
2
+ .yarn/*
3
+ !.yarn/patches
4
+ !.yarn/plugins
5
+ !.yarn/releases
6
+ !.yarn/sdks
7
+ !.yarn/versions
8
+
9
+ node_modules
@@ -8,10 +8,10 @@
8
8
  "@flarum/prettier-config": "^1.0.0",
9
9
  "flarum-tsconfig": "^1.0.2",
10
10
  "flarum-webpack-config": "^2.0.0",
11
- "prettier": "^2.4.1",
12
- "typescript": "^4.4.4",
11
+ "prettier": "^2.5.1",
12
+ "typescript": "^4.5.4",
13
13
  "typescript-coverage-report": "^0.6.1",
14
- "webpack": "^5.61.0",
14
+ "webpack": "^5.65.0",
15
15
  "webpack-cli": "^4.9.1"
16
16
  },
17
17
  "scripts": {
@@ -0,0 +1,5 @@
1
+ import app from 'flarum/admin/app';
2
+
3
+ app.initializers.add('<%= params.packageName %>', () => {
4
+ console.log('[<%= params.packageName %>] Hello, admin!');
5
+ });
@@ -0,0 +1,5 @@
1
+ import app from 'flarum/common/app';
2
+
3
+ app.initializers.add('<%= params.packageName %>', () => {
4
+ console.log('[<%= params.packageName %>] Hello, forum and admin!');
5
+ });
@@ -0,0 +1,5 @@
1
+ import app from 'flarum/forum/app';
2
+
3
+ app.initializers.add('<%= params.packageName %>', () => {
4
+ console.log('[<%= params.packageName %>] Hello, forum!');
5
+ });
@@ -1,4 +1,5 @@
1
1
  import { Command, Interfaces } from '@oclif/core';
2
+ import { IO } from 'boilersmith/io';
2
3
  import { StepManager } from 'boilersmith/step-manager';
3
4
  import { FlarumProviders } from './providers';
4
5
  export declare enum LocationType {
@@ -23,6 +24,7 @@ export default abstract class BaseCommand extends Command {
23
24
  protected goodbyeMessage(): string;
24
25
  protected additionalPreRunChecks(_extRoot: string): Promise<void>;
25
26
  protected abstract steps(stepManager: StepManager<FlarumProviders>): StepManager<FlarumProviders>;
27
+ protected genIO(): IO;
26
28
  protected monorepoPaths(options: {
27
29
  includeCore: boolean;
28
30
  includeExtensions: boolean;
@@ -5,7 +5,6 @@ const tslib_1 = require("tslib");
5
5
  const core_1 = require("@oclif/core");
6
6
  const cli_ux_1 = (0, tslib_1.__importDefault)(require("cli-ux"));
7
7
  const node_path_1 = require("node:path");
8
- const prompts_1 = (0, tslib_1.__importDefault)(require("prompts"));
9
8
  const globby_1 = (0, tslib_1.__importDefault)(require("globby"));
10
9
  const node_child_process_1 = require("node:child_process");
11
10
  const node_fs_1 = require("node:fs");
@@ -14,6 +13,7 @@ const step_manager_1 = require("boilersmith/step-manager");
14
13
  const paths_1 = require("boilersmith/paths");
15
14
  const php_provider_1 = require("./providers/php-provider");
16
15
  const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
16
+ const errors_1 = require("@oclif/errors");
17
17
  var LocationType;
18
18
  (function (LocationType) {
19
19
  LocationType[LocationType["FLARUM_EXTENSION"] = 0] = "FLARUM_EXTENSION";
@@ -41,9 +41,7 @@ class BaseCommand extends core_1.Command {
41
41
  const rootData = await this.getFlarumExtensionRoot(path || process.cwd());
42
42
  extRoot = rootData.path;
43
43
  this.locationType = rootData.type;
44
- if (!this.flags.defaults) {
45
- await this.confirmExtDir(extRoot);
46
- }
44
+ await this.confirmExtDir(extRoot);
47
45
  }
48
46
  else {
49
47
  extRoot = path || process.cwd();
@@ -55,7 +53,7 @@ class BaseCommand extends core_1.Command {
55
53
  });
56
54
  const phpProvider = new php_provider_1.PhpSubsystemProvider((0, node_path_1.resolve)(__dirname, '../php-subsystem/index.php'));
57
55
  const out = await this.steps(new step_manager_1.StepManager())
58
- .run(paths, new io_1.PromptsIO(), { php: phpProvider }, this.dry);
56
+ .run(paths, this.genIO(), { php: phpProvider }, this.dry);
59
57
  const errorMessages = out.messages.filter(m => m.type === 'error');
60
58
  this.log('\n\n');
61
59
  if (out.succeeded && errorMessages.length === 0) {
@@ -116,6 +114,9 @@ class BaseCommand extends core_1.Command {
116
114
  // ----------------------------------------------------------------
117
115
  // Confirmation
118
116
  // ----------------------------------------------------------------
117
+ genIO() {
118
+ return new io_1.PromptsIO({}, [], this.flags['no-interaction'], errors_1.exit);
119
+ }
119
120
  monorepoPaths(options) {
120
121
  try {
121
122
  const monorepoConfig = (0, node_fs_1.readFileSync)((0, node_path_1.resolve)(process.cwd(), 'flarum-monorepo.json'));
@@ -161,30 +162,26 @@ class BaseCommand extends core_1.Command {
161
162
  - Flarum monorepos must have a valid 'flarum-monorepo.json' file`);
162
163
  }
163
164
  async confirmExtDir(extRoot) {
164
- const response = await (0, prompts_1.default)([
165
- {
166
- name: 'verify',
167
- type: 'confirm',
168
- message: `Work in Flarum package located at ${(0, node_path_1.resolve)(extRoot)}?`,
169
- initial: true,
170
- },
171
- ], io_1.PROMPTS_OPTIONS);
172
- if (!response.verify)
165
+ const verify = await this.genIO().getParam({
166
+ name: 'verify',
167
+ type: 'confirm',
168
+ message: `Work in Flarum package located at ${(0, node_path_1.resolve)(extRoot)}?`,
169
+ initial: true,
170
+ });
171
+ if (!verify)
173
172
  this.exit();
174
173
  }
175
174
  async ensureComposerInstallRan(extRoot) {
176
175
  if ((0, node_fs_1.existsSync)((0, node_path_1.resolve)(extRoot, 'vendor/flarum/core/composer.json')))
177
176
  return;
178
177
  this.log("This command requires `composer install` to have been ran in your extension's root directory.");
179
- const response = await (0, prompts_1.default)([
180
- {
181
- name: 'composer',
182
- type: 'confirm',
183
- message: 'Would you like me to take care of that for you?',
184
- initial: true,
185
- },
186
- ], io_1.PROMPTS_OPTIONS);
187
- if (response.composer) {
178
+ const composer = await this.genIO().getParam({
179
+ name: 'composer',
180
+ type: 'confirm',
181
+ message: 'Would you like me to take care of that for you?',
182
+ initial: true,
183
+ });
184
+ if (composer) {
188
185
  cli_ux_1.default.action.start('Installing composer packages');
189
186
  (0, node_child_process_1.execSync)('composer install', { cwd: extRoot });
190
187
  cli_ux_1.default.action.stop();
@@ -204,14 +201,13 @@ class BaseCommand extends core_1.Command {
204
201
  const empty = files.length === 0 || (files.length === 1 && files[0] === '.git');
205
202
  if (empty)
206
203
  return false;
207
- const response = await (0, prompts_1.default)([
208
- {
209
- name: 'overwrite',
210
- type: 'confirm',
211
- message: confirmationMessage,
212
- },
213
- ], io_1.PROMPTS_OPTIONS);
214
- if (response.overwrite === false)
204
+ const overwrite = await this.genIO().getParam({
205
+ name: 'overwrite',
206
+ type: 'confirm',
207
+ message: confirmationMessage,
208
+ initial: true,
209
+ });
210
+ if (overwrite === false)
215
211
  this.exit();
216
212
  return true;
217
213
  }
@@ -222,7 +218,7 @@ class BaseCommand extends core_1.Command {
222
218
  }
223
219
  exports.default = BaseCommand;
224
220
  BaseCommand.flags = {
225
- defaults: core_1.Flags.boolean({ char: 'd', description: 'Assume default responses to prompts where possible.', default: false }),
221
+ 'no-interaction': core_1.Flags.boolean({ char: 'n', description: 'Do not ask any interactive questions, assume defaults. When impossible, error.', default: false }),
226
222
  help: core_1.Flags.help({ char: 'h' }),
227
223
  };
228
224
  BaseCommand.args = [
@@ -1,4 +1,4 @@
1
- import { Options, PromptObject } from 'prompts';
1
+ import { PromptObject } from 'prompts';
2
2
  export declare type ParamDef<N extends string = string> = Omit<PromptObject<N>, 'name'> & {
3
3
  name: N;
4
4
  };
@@ -29,12 +29,15 @@ export interface IO {
29
29
  getOutput(): Message[];
30
30
  newInstance(cache: Record<string, unknown>, messages: Message[]): IO;
31
31
  }
32
- export declare const PROMPTS_OPTIONS: Options;
32
+ declare type OnCancel = () => void;
33
33
  export declare class PromptsIO implements IO {
34
34
  supportsAnsiColor: boolean;
35
35
  private cache;
36
36
  private messages;
37
- constructor(initial?: Record<string, unknown>, messages?: Message[]);
37
+ private noInteraction;
38
+ private onCancel?;
39
+ private prev?;
40
+ constructor(initial?: Record<string, unknown>, messages?: Message[], noInteraction?: boolean, onCancel?: OnCancel);
38
41
  getParam<T>(paramDef: ParamDef): Promise<T>;
39
42
  hasCached(name: string): boolean;
40
43
  /**
@@ -44,7 +47,8 @@ export declare class PromptsIO implements IO {
44
47
  info(message: string, immediate: boolean): void;
45
48
  warning(message: string, immediate: boolean): void;
46
49
  error(message: string, immediate: false): void;
47
- error(message: string, immediate: true): void;
50
+ error(message: string, immediate: true): never;
48
51
  getOutput(): Message[];
49
52
  newInstance(cache: Record<string, unknown>, messages: Message[]): PromptsIO;
50
53
  }
54
+ export {};
@@ -1,27 +1,52 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PromptsIO = exports.PROMPTS_OPTIONS = void 0;
3
+ exports.PromptsIO = void 0;
4
4
  const tslib_1 = require("tslib");
5
5
  const prompts_1 = (0, tslib_1.__importDefault)(require("prompts"));
6
- const errors_1 = require("@oclif/errors");
7
6
  const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
8
- exports.PROMPTS_OPTIONS = { onCancel: () => (0, errors_1.exit)() };
9
7
  class PromptsIO {
10
- constructor(initial = {}, messages = []) {
8
+ constructor(initial = {}, messages = [], noInteraction = false, onCancel = () => {
9
+ throw new Error('EEXIT: 0');
10
+ }) {
11
11
  this.supportsAnsiColor = true;
12
12
  this.cache = new Map();
13
- this.messages = [];
14
13
  this.cache = new Map(Object.entries(initial));
15
14
  this.messages = messages;
15
+ this.noInteraction = noInteraction;
16
+ this.onCancel = onCancel;
16
17
  }
17
18
  async getParam(paramDef) {
19
+ var _a, _b, _c;
18
20
  const paramName = paramDef.name;
19
21
  if (this.cache.has(paramName)) {
20
22
  return this.cache.get(paramName);
21
23
  }
22
- const res = (await (0, prompts_1.default)(paramDef, exports.PROMPTS_OPTIONS));
23
- const resValue = res[paramName];
24
+ let resValue;
25
+ if (this.noInteraction) {
26
+ if (paramDef.initial && paramDef.initial instanceof Function) {
27
+ resValue = paramDef.initial((_a = this.prev) === null || _a === void 0 ? void 0 : _a.val, this.cache, (_b = this.prev) === null || _b === void 0 ? void 0 : _b.prompt);
28
+ }
29
+ else if (paramDef.type === 'confirm' || paramDef.type === 'toggle') {
30
+ resValue = ((_c = paramDef.initial) !== null && _c !== void 0 ? _c : false);
31
+ }
32
+ else if ('initial' in paramDef) {
33
+ resValue = paramDef.initial;
34
+ }
35
+ else {
36
+ return this.error(`No-Interaction mode is on, but input is required for param "${paramName}".`, true);
37
+ }
38
+ }
39
+ else {
40
+ const res = (await (0, prompts_1.default)(paramDef, {
41
+ onCancel: this.onCancel,
42
+ }));
43
+ resValue = res[paramName];
44
+ }
24
45
  this.cache.set(paramName, resValue);
46
+ this.prev = {
47
+ val: resValue,
48
+ prompt: paramDef,
49
+ };
25
50
  return resValue;
26
51
  }
27
52
  hasCached(name) {
@@ -66,7 +91,7 @@ class PromptsIO {
66
91
  return this.messages;
67
92
  }
68
93
  newInstance(cache, messages) {
69
- return new PromptsIO(cache, messages);
94
+ return new PromptsIO(cache, messages, this.noInteraction, this.onCancel);
70
95
  }
71
96
  }
72
97
  exports.PromptsIO = PromptsIO;
@@ -43,6 +43,13 @@ function auditStepFactory(dry, scaffoldDir, modules, templateParams, excludeScaf
43
43
  }
44
44
  }
45
45
  }
46
+ if (!dry) {
47
+ for (const m of modules) {
48
+ if (moduleStatusCache && m.updatable && (actionableModules.includes(m) || m.togglable)) {
49
+ (0, module_1.setModuleValue)(m, actionableModules.includes(m), _fs, paths, moduleStatusCache);
50
+ }
51
+ }
52
+ }
46
53
  return _fs;
47
54
  },
48
55
  exposes: modules.map(m => `modules.${m.name}`),
@@ -19,7 +19,7 @@ function infraStepFactory(scaffoldDir, moduleName, modules, templateParams, excl
19
19
  }
20
20
  const excludeScaffolding = excludeScaffoldingFunc ? excludeScaffoldingFunc(fs, paths) : [];
21
21
  const initializing = !modulesEnabled[module.name];
22
- (0, module_1.applyModule)(module, modulesEnabled, paramVals, scaffoldDir, fs, paths, excludeScaffolding, initializing);
22
+ (0, module_1.applyModule)(module, Object.assign(Object.assign({}, modulesEnabled), { [module.name]: true }), paramVals, scaffoldDir, fs, paths, excludeScaffolding, initializing);
23
23
  if (moduleStatusCache) {
24
24
  (0, module_1.setModuleValue)(module, true, fs, paths, moduleStatusCache);
25
25
  }
@@ -7,11 +7,19 @@ interface FileOwnership {
7
7
  */
8
8
  path: string;
9
9
  /**
10
- * If any of the needed modules aren't enabled, the file won't be updated.
10
+ * Where the file should go. Defaults to path.
11
11
  */
12
- needsOtherModules?: string[];
12
+ destPath?: string;
13
13
  /**
14
- * If in a monorepo, should the file be placed relative to the monorepo root?
14
+ * Depends on other modules being enabled (or disabled).
15
+ */
16
+ moduleDeps?: (string | {
17
+ module: string;
18
+ enabled: boolean;
19
+ })[];
20
+ /**
21
+ * If in a monorepo, should the file be placed relative to the monorepo root, and if so, where?
22
+ * If provided, takes priority over destPath.
15
23
  */
16
24
  monorepoPath?: string;
17
25
  }
@@ -55,6 +63,12 @@ interface TogglableModule<N extends string> extends CommonModule<N> {
55
63
  * Can only be enabled if these other modules are enabled.
56
64
  */
57
65
  dependsOn: string[];
66
+ /**
67
+ * On an existing installation, if no information about whether this
68
+ * module is enabled or disabled is cached, infer whether it's enabled
69
+ * based on the current installation's state.
70
+ */
71
+ inferEnabled?: (fs: Store, paths: Paths) => Promise<boolean | undefined>;
58
72
  }
59
73
  export declare type Module<N extends string = string> = UntoggleableModule<N> | TogglableModule<N>;
60
74
  export declare type ModuleStatusCache<N extends string> = {
@@ -43,12 +43,13 @@ async function promptModulesEnabled(modules, io) {
43
43
  }
44
44
  exports.promptModulesEnabled = promptModulesEnabled;
45
45
  async function currModulesEnabled(modules, fs, paths, cache) {
46
+ var _a, _b;
46
47
  const modulesEnabled = {};
47
48
  for (const m of modules) {
48
49
  if (m.togglable) {
49
50
  // eslint-disable-next-line no-await-in-loop
50
- const cacheVal = await (cache === null || cache === void 0 ? void 0 : cache.get(m, fs, paths));
51
- modulesEnabled[m.name] = cacheVal !== null && cacheVal !== void 0 ? cacheVal : m.defaultEnabled;
51
+ const isEnabled = (_a = await (cache === null || cache === void 0 ? void 0 : cache.get(m, fs, paths))) !== null && _a !== void 0 ? _a : await ((_b = m.inferEnabled) === null || _b === void 0 ? void 0 : _b.call(m, fs, paths));
52
+ modulesEnabled[m.name] = isEnabled !== null && isEnabled !== void 0 ? isEnabled : m.defaultEnabled;
52
53
  }
53
54
  else {
54
55
  modulesEnabled[m.name] = true;
@@ -91,10 +92,14 @@ async function applyModule(module, modulesEnabled, paramVals, scaffoldDir, fs, p
91
92
  const tplDataFlat = Object.assign(Object.assign({}, (0, rename_keys_1.renameKeys)(tplData.modules, k => `modules.${k}`)), (0, rename_keys_1.renameKeys)(tplData.params, k => `params.${k}`));
92
93
  for (const file of module.filesToReplace) {
93
94
  const path = typeof file === 'string' ? file : file.path;
94
- const needsOtherModules = typeof file === 'string' ? [] : (_a = file.needsOtherModules) !== null && _a !== void 0 ? _a : [];
95
- if (!excludeFiles.includes(path) && !needsOtherModules.some(dep => !modulesEnabled[dep])) {
95
+ const moduleDeps = typeof file === 'string' ? [] : (_a = file.moduleDeps) !== null && _a !== void 0 ? _a : [];
96
+ if (!excludeFiles.includes(path) && !moduleDeps.some(dep => {
97
+ const depName = typeof dep === 'string' ? dep : dep.module;
98
+ const enabled = modulesEnabled[depName];
99
+ return typeof dep === 'string' || dep.enabled ? !enabled : enabled;
100
+ })) {
96
101
  const copyToIfMonorepo = typeof file !== 'string' && file.monorepoPath ? paths.monorepo((0, clone_and_fill_1.cloneAndFill)(file.monorepoPath, tplDataFlat)) : undefined;
97
- const copyTo = copyToIfMonorepo !== null && copyToIfMonorepo !== void 0 ? copyToIfMonorepo : paths.package(path);
102
+ const copyTo = copyToIfMonorepo !== null && copyToIfMonorepo !== void 0 ? copyToIfMonorepo : paths.package(typeof file !== 'string' && file.destPath ? (0, clone_and_fill_1.cloneAndFill)(file.destPath, tplDataFlat) : path);
98
103
  fsEditor.copyTpl((0, node_path_1.resolve)(scaffoldDir, path), copyTo, tplData);
99
104
  }
100
105
  }
@@ -13,7 +13,7 @@ export default class Infra extends BaseCommand {
13
13
  name: string;
14
14
  description: string;
15
15
  required: boolean;
16
- options: ("core" | "icon" | "js" | "jsCommon" | "css" | "locale" | "gitConf" | "githubActions" | "prettier" | "typescript" | "bundlewatch" | "backendTesting" | "editorConfig" | "styleci")[];
16
+ options: ("core" | "icon" | "admin" | "forum" | "js" | "jsCommon" | "css" | "locale" | "gitConf" | "githubActions" | "prettier" | "typescript" | "bundlewatch" | "backendTesting" | "editorConfig" | "styleci")[];
17
17
  })[];
18
18
  protected steps(stepManager: StepManager<FlarumProviders>): StepManager<FlarumProviders>;
19
19
  protected additionalPreRunChecks(extRoot: string): Promise<void>;
@@ -1,6 +1,6 @@
1
1
  import { Scaffolder } from 'boilersmith/scaffolding/scaffolder';
2
2
  export declare const EXTENSION_PARAMS: readonly ["packageName", "packageDescription", "packageNamespace", "authorName", "authorEmail", "extensionName", "licenseType", "mainGitBranch", "licenseText", "packageNamespaceEscapedSlash", "extensionId", "year", "backendDirectory", "frontendDirectory"];
3
3
  export declare type ExtensionParams = typeof EXTENSION_PARAMS[number];
4
- export declare const EXTENSION_MODULES: readonly ["core", "icon", "js", "jsCommon", "css", "locale", "gitConf", "githubActions", "prettier", "typescript", "bundlewatch", "backendTesting", "editorConfig", "styleci"];
4
+ export declare const EXTENSION_MODULES: readonly ["core", "icon", "admin", "forum", "js", "jsCommon", "css", "locale", "gitConf", "githubActions", "prettier", "typescript", "bundlewatch", "backendTesting", "editorConfig", "styleci"];
5
5
  export declare type ExtensionModules = typeof EXTENSION_MODULES[number];
6
6
  export declare function genExtScaffolder(): Scaffolder<ExtensionParams, ExtensionModules>;
@@ -5,6 +5,7 @@ const tslib_1 = require("tslib");
5
5
  const scaffolder_1 = require("boilersmith/scaffolding/scaffolder");
6
6
  const chalk_1 = (0, tslib_1.__importDefault)(require("chalk"));
7
7
  const mem_fs_editor_1 = require("mem-fs-editor");
8
+ const node_fs_1 = require("node:fs");
8
9
  const node_path_1 = require("node:path");
9
10
  const simple_git_1 = (0, tslib_1.__importDefault)(require("simple-git"));
10
11
  const simple_1 = (0, tslib_1.__importDefault)(require("spdx-license-list/simple"));
@@ -119,6 +120,8 @@ function paramNamesToDef(name) {
119
120
  getCurrVal: async (fs, paths) => {
120
121
  var _a, _b, _c;
121
122
  const json = (0, composer_1.getComposerJson)(fs, paths);
123
+ if (json.name === 'flarum/core')
124
+ return 'Core';
122
125
  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
126
  },
124
127
  };
@@ -199,6 +202,8 @@ function paramNamesToDef(name) {
199
202
  exports.EXTENSION_MODULES = [
200
203
  'core',
201
204
  'icon',
205
+ 'admin',
206
+ 'forum',
202
207
  'js',
203
208
  'jsCommon',
204
209
  'css',
@@ -224,9 +229,12 @@ function moduleNameToDef(name) {
224
229
  'extend.php',
225
230
  'README.md',
226
231
  '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'] },
232
+ { path: 'js/src/admin/index.js', moduleDeps: ['js', 'admin', { module: 'typescript', enabled: false }] },
233
+ { path: 'js/src/forum/index.js', moduleDeps: ['js', 'forum', { module: 'typescript', enabled: false }] },
234
+ { path: 'js/src/common/index.js', moduleDeps: ['js', 'jsCommon', { module: 'typescript', enabled: false }] },
235
+ { path: 'js/src/admin/index.ts', moduleDeps: ['js', 'admin', { module: 'typescript', enabled: true }] },
236
+ { path: 'js/src/forum/index.ts', moduleDeps: ['js', 'forum', { module: 'typescript', enabled: true }] },
237
+ { path: 'js/src/common/index.ts', moduleDeps: ['js', 'jsCommon', { module: 'typescript', enabled: true }] },
230
238
  ],
231
239
  jsonToAugment: {
232
240
  'composer.json': [
@@ -268,6 +276,46 @@ function moduleNameToDef(name) {
268
276
  },
269
277
  needsTemplateParams: [],
270
278
  };
279
+ case 'admin':
280
+ return {
281
+ name,
282
+ updatable: true,
283
+ defaultEnabled: true,
284
+ dependsOn: [],
285
+ togglable: true,
286
+ shortDescription: 'Admin Frontend',
287
+ filesToReplace: [
288
+ { path: 'js/admin.js', moduleDeps: ['js', { module: 'typescript', enabled: false }] },
289
+ { path: 'js/admin.ts', moduleDeps: ['js', { module: 'typescript', enabled: true }] },
290
+ ],
291
+ jsonToAugment: {},
292
+ needsTemplateParams: [],
293
+ inferEnabled: async (_fs, paths) => {
294
+ if (!(0, node_fs_1.existsSync)(paths.package('js')))
295
+ undefined;
296
+ return (0, node_fs_1.existsSync)(paths.package('js/src/admin'));
297
+ },
298
+ };
299
+ case 'forum':
300
+ return {
301
+ name,
302
+ updatable: true,
303
+ defaultEnabled: true,
304
+ dependsOn: [],
305
+ togglable: true,
306
+ shortDescription: 'Forum Frontend',
307
+ filesToReplace: [
308
+ { path: 'js/forum.js', moduleDeps: ['js', { module: 'typescript', enabled: false }] },
309
+ { path: 'js/forum.ts', moduleDeps: ['js', { module: 'typescript', enabled: true }] },
310
+ ],
311
+ jsonToAugment: {},
312
+ needsTemplateParams: [],
313
+ inferEnabled: async (_fs, paths) => {
314
+ if (!(0, node_fs_1.existsSync)(paths.package('js')))
315
+ undefined;
316
+ return (0, node_fs_1.existsSync)(paths.package('js/src/forum'));
317
+ },
318
+ };
271
319
  case 'js':
272
320
  return {
273
321
  name,
@@ -277,7 +325,13 @@ function moduleNameToDef(name) {
277
325
  shortDescription: 'Javascript',
278
326
  longDescription: "Files, tools, and scripts to build Flarum's frontend.",
279
327
  dependsOn: [],
280
- filesToReplace: ['js/webpack.config.js', 'js/admin.js', 'js/forum.js'],
328
+ filesToReplace: [
329
+ 'js/webpack.config.js',
330
+ { path: 'js/admin.js', moduleDeps: ['admin', { module: 'typescript', enabled: false }] },
331
+ { path: 'js/forum.js', moduleDeps: ['forum', { module: 'typescript', enabled: false }] },
332
+ { path: 'js/admin.ts', moduleDeps: ['admin', { module: 'typescript', enabled: true }] },
333
+ { path: 'js/forum.ts', moduleDeps: ['forum', { module: 'typescript', enabled: true }] },
334
+ ],
281
335
  jsonToAugment: {
282
336
  'js/package.json': [
283
337
  'name',
@@ -291,19 +345,30 @@ function moduleNameToDef(name) {
291
345
  ],
292
346
  },
293
347
  needsTemplateParams: ['packageName'],
348
+ inferEnabled: async (_fs, paths) => {
349
+ return (0, node_fs_1.existsSync)(paths.package('js'));
350
+ },
294
351
  };
295
352
  case 'jsCommon':
296
353
  return {
297
354
  name,
298
- updatable: false,
355
+ updatable: true,
299
356
  togglable: true,
300
357
  defaultEnabled: true,
301
358
  shortDescription: 'JS common code',
302
359
  longDescription: 'Shared code between the forum and the admin frontends',
303
360
  dependsOn: ['js'],
304
- filesToReplace: [],
361
+ filesToReplace: [
362
+ { path: 'js/admin.js', moduleDeps: ['admin', { module: 'typescript', enabled: false }] },
363
+ { path: 'js/forum.js', moduleDeps: ['forum', { module: 'typescript', enabled: false }] },
364
+ { path: 'js/admin.ts', moduleDeps: ['admin', { module: 'typescript', enabled: true }] },
365
+ { path: 'js/forum.ts', moduleDeps: ['forum', { module: 'typescript', enabled: true }] },
366
+ ],
305
367
  jsonToAugment: {},
306
368
  needsTemplateParams: [],
369
+ inferEnabled: async (_fs, paths) => {
370
+ return (0, node_fs_1.existsSync)(paths.package('js/src/common'));
371
+ },
307
372
  };
308
373
  case 'css':
309
374
  return {
@@ -317,6 +382,9 @@ function moduleNameToDef(name) {
317
382
  filesToReplace: ['less/admin.less', 'less/forum.less'],
318
383
  jsonToAugment: {},
319
384
  needsTemplateParams: [],
385
+ inferEnabled: async (_fs, paths) => {
386
+ return (0, node_fs_1.existsSync)(paths.package('less'));
387
+ },
320
388
  };
321
389
  case 'locale':
322
390
  return {
@@ -330,6 +398,9 @@ function moduleNameToDef(name) {
330
398
  filesToReplace: ['locale/en.yml'],
331
399
  jsonToAugment: {},
332
400
  needsTemplateParams: [],
401
+ inferEnabled: async (_fs, paths) => {
402
+ return (0, node_fs_1.existsSync)(paths.package('locale'));
403
+ },
333
404
  };
334
405
  case 'gitConf':
335
406
  return {
@@ -340,7 +411,7 @@ function moduleNameToDef(name) {
340
411
  shortDescription: 'Git Configuration',
341
412
  longDescription: 'Git config files (e.g. .gitignore, .gitattributes).',
342
413
  dependsOn: [],
343
- filesToReplace: ['.gitignore', '.gitattributes'],
414
+ filesToReplace: [{ path: 'gitignore', destPath: '.gitignore' }, { path: 'js/gitignore', moduleDeps: ['js'], destPath: 'js/.gitignore' }, '.gitattributes'],
344
415
  jsonToAugment: {},
345
416
  needsTemplateParams: [],
346
417
  };
@@ -358,7 +429,7 @@ function moduleNameToDef(name) {
358
429
  { path: '.github/workflows/backend.yml', monorepoPath: '.github/workflows/${params.extensionId}-backend.yml' },
359
430
  ],
360
431
  jsonToAugment: {},
361
- needsTemplateParams: ['frontendDirectory', 'backendDirectory', 'mainGitBranch', 'extensionId'],
432
+ needsTemplateParams: ['frontendDirectory', 'backendDirectory', 'mainGitBranch', 'extensionId', 'extensionName'],
362
433
  };
363
434
  case 'prettier':
364
435
  return {
@@ -373,6 +444,12 @@ function moduleNameToDef(name) {
373
444
  'js/package.json': ['prettier', 'devDependencies.prettier', 'devDependencies.@flarum/prettier-config', 'scripts.format', 'scripts.format-check'],
374
445
  },
375
446
  needsTemplateParams: [],
447
+ inferEnabled: async (_fs, paths) => {
448
+ if (!(0, node_fs_1.existsSync)(paths.package('js/package.json'))) {
449
+ return false;
450
+ }
451
+ return (0, node_fs_1.readFileSync)('js/package.json').includes('prettier');
452
+ },
376
453
  };
377
454
  case 'typescript':
378
455
  return {
@@ -394,6 +471,9 @@ function moduleNameToDef(name) {
394
471
  ],
395
472
  },
396
473
  needsTemplateParams: [],
474
+ inferEnabled: async (_fs, paths) => {
475
+ return (0, node_fs_1.existsSync)(paths.package('js/tsconfig.json'));
476
+ },
397
477
  };
398
478
  case 'bundlewatch':
399
479
  return {
@@ -403,9 +483,12 @@ function moduleNameToDef(name) {
403
483
  defaultEnabled: false,
404
484
  shortDescription: 'Enable Bundlewatch Checks',
405
485
  dependsOn: ['js'],
406
- filesToReplace: [],
486
+ filesToReplace: ['js/.bundlewatch.config.json'],
407
487
  jsonToAugment: {},
408
488
  needsTemplateParams: [],
489
+ inferEnabled: async (_fs, paths) => {
490
+ return (0, node_fs_1.existsSync)(paths.package('js/.bundlewatch.config.json'));
491
+ },
409
492
  };
410
493
  case 'backendTesting':
411
494
  return {
@@ -437,6 +520,9 @@ function moduleNameToDef(name) {
437
520
  ],
438
521
  },
439
522
  needsTemplateParams: ['packageNamespaceEscapedSlash'],
523
+ inferEnabled: async (_fs, paths) => {
524
+ return (0, node_fs_1.existsSync)(paths.package('tests'));
525
+ },
440
526
  };
441
527
  case 'editorConfig':
442
528
  return {
@@ -473,9 +559,9 @@ function genExtScaffolder() {
473
559
  return cached;
474
560
  const moduleStatusCache = {
475
561
  get: async (module, fs, paths) => {
476
- var _a, _b, _c, _d;
562
+ var _a, _b, _c;
477
563
  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);
564
+ return !module.togglable || ((_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]);
479
565
  },
480
566
  set: async (module, enabled, fs, paths) => {
481
567
  const json = {
@@ -1,7 +1,8 @@
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
7
  const IMPORTS_REGEX = /((^import\s+(?:([\s\w*,{}]+)\s+from)?\s*["']?([\s\w./@\\-]+)\3?["']?\s*;?\s*)*)(.*)/m;
7
8
  const INIT_REGEX = /^(app\.initializers\.add\('[^']+',\s*\(\)\s*=>\s*{)$/m;
@@ -18,7 +19,7 @@ class BaseJsStep {
18
19
  frontends = ['admin', 'forum'];
19
20
  }
20
21
  for (const frontend of frontends) {
21
- const fsSrcFilePaths = glob_1.glob.sync(paths.package(`js/src/${frontend}/*.{js,jsx,ts,tsx}`));
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
@@ -1,7 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.UpdateJSImports = 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
7
  const CORE_JS_NAMESPACES = ['admin', 'common', 'forum'];
7
8
  const CORE_NAMESPACE_REGEX = new RegExp(`^(${CORE_JS_NAMESPACES.join('|')})/`);
@@ -18,7 +19,7 @@ class UpdateJSImports {
18
19
  const jsSrcDir = paths.package('vendor/flarum/core/js/src');
19
20
  const vendorRegex = new RegExp(`${jsSrcDir}/.*(js|jsx|ts|tsx)`);
20
21
  const fsVendorFilePaths = fs.all().map(file => file.path).filter(path => path && vendorRegex.test(path));
21
- const persistedVendorFilePaths = glob_1.glob.sync(`${jsSrcDir}/**/*.{js,jsx,ts,tsx}`);
22
+ const persistedVendorFilePaths = globby_1.default.sync(`${jsSrcDir}/**/*.{js,jsx,ts,tsx}`);
22
23
  for (const currPath of [...fsVendorFilePaths, ...persistedVendorFilePaths]) {
23
24
  const withNamespace = currPath.slice(jsSrcDir.length + 1).replace(/\.(js|jsx|ts|tsx)$/, '');
24
25
  const noNamespace = withNamespace.replace(CORE_NAMESPACE_REGEX, '');
@@ -26,7 +27,7 @@ class UpdateJSImports {
26
27
  }
27
28
  const srcRegex = new RegExp(`${paths.package('js/src')}/.*(js|jsx|ts|tsx)`);
28
29
  const fsSrcFilePaths = fs.all().map(file => file.path).filter(path => path && srcRegex.test(path));
29
- const persistedSrcFilePaths = glob_1.glob.sync(paths.package('js/src/**/*.{js,jsx,ts,tsx}'));
30
+ const persistedSrcFilePaths = globby_1.default.sync(paths.package('js/src/**/*.{js,jsx,ts,tsx}'));
30
31
  for (const match of [...fsSrcFilePaths, ...persistedSrcFilePaths]) {
31
32
  let fileCounted = false;
32
33
  const currContents = fsEditor.read(match);
@@ -1 +1 @@
1
- {"version":"2.0.0-beta.1","commands":{"infra":{"id":"infra","description":"Add/Update infrastructure to the latest scaffolding for some module in an extension. For example, you can use this to add/update TypeScript, backend testing, GitHub Actions, and other features.","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"monorepo":{"name":"monorepo","type":"boolean","char":"m","allowNo":false},"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"module","description":"The name of the module to enable/update.","required":true,"options":["core","icon","js","jsCommon","css","locale","gitConf","githubActions","prettier","typescript","bundlewatch","backendTesting","editorConfig","styleci"]},{"name":"path","description":"Where should this command be executed?"}]},"init":{"id":"init","description":"Create a new Flarum extension","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"audit:infra":{"id":"audit:infra","description":"Check for outdated config files, infrastructure, setup, etc.","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"fix":{"name":"fix","type":"boolean","char":"f","allowNo":false},"monorepo":{"name":"monorepo","type":"boolean","char":"m","allowNo":false},"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"update:js-imports":{"id":"update:js-imports","description":"Updates JS imports from core to use proper namespaces","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:api-controller":{"id":"make:backend:api-controller","description":"Generate an API controller class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:api-serializer-attributes":{"id":"make:backend:api-serializer-attributes","description":"Generate an API serializer attributes extender","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:api-serializer":{"id":"make:backend:api-serializer","description":"Generate an API serializer class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:command":{"id":"make:backend:command","description":"Generate a console command class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:event-listener":{"id":"make:backend:event-listener","description":"Generate an event listener class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:handler":{"id":"make:backend:handler","description":"Generate a domain logic handler class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:integration-test":{"id":"make:backend:integration-test","description":"Generate an integration test class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:job":{"id":"make:backend:job","description":"Generate a job class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:migration":{"id":"make:backend:migration","description":"Generate a migration","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:model":{"id":"make:backend:model","description":"Generate a model class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:policy":{"id":"make:backend:policy","description":"Generate a policy class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:repository":{"id":"make:backend:repository","description":"Generate a repository class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:route":{"id":"make:backend:route","description":"Generate a routes extender","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:service-provider":{"id":"make:backend:service-provider","description":"Generate a service provider class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:validator":{"id":"make:backend:validator","description":"Generate a validator class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:frontend:component":{"id":"make:frontend:component","description":"Generate a frontend component","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:frontend:modal":{"id":"make:frontend:modal","description":"Generate a modal component","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:frontend:model":{"id":"make:frontend:model","description":"Generate a model class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"defaults":{"name":"defaults","type":"boolean","char":"d","description":"Assume default responses to prompts where possible.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]}}}
1
+ {"version":"2.0.0-beta.13","commands":{"infra":{"id":"infra","description":"Add/Update infrastructure to the latest scaffolding for some module in an extension. For example, you can use this to add/update TypeScript, backend testing, GitHub Actions, and other features.","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"monorepo":{"name":"monorepo","type":"boolean","char":"m","allowNo":false},"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"module","description":"The name of the module to enable/update.","required":true,"options":["core","icon","admin","forum","js","jsCommon","css","locale","gitConf","githubActions","prettier","typescript","bundlewatch","backendTesting","editorConfig","styleci"]},{"name":"path","description":"Where should this command be executed?"}]},"init":{"id":"init","description":"Create a new Flarum extension","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"audit:infra":{"id":"audit:infra","description":"Check for outdated config files, infrastructure, setup, etc.","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"fix":{"name":"fix","type":"boolean","char":"f","allowNo":false},"monorepo":{"name":"monorepo","type":"boolean","char":"m","allowNo":false},"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"update:js-imports":{"id":"update:js-imports","description":"Updates JS imports from core to use proper namespaces","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:api-controller":{"id":"make:backend:api-controller","description":"Generate an API controller class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:api-serializer-attributes":{"id":"make:backend:api-serializer-attributes","description":"Generate an API serializer attributes extender","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:api-serializer":{"id":"make:backend:api-serializer","description":"Generate an API serializer class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:command":{"id":"make:backend:command","description":"Generate a console command class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:event-listener":{"id":"make:backend:event-listener","description":"Generate an event listener class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:handler":{"id":"make:backend:handler","description":"Generate a domain logic handler class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:integration-test":{"id":"make:backend:integration-test","description":"Generate an integration test class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:job":{"id":"make:backend:job","description":"Generate a job class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:migration":{"id":"make:backend:migration","description":"Generate a migration","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:model":{"id":"make:backend:model","description":"Generate a model class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:policy":{"id":"make:backend:policy","description":"Generate a policy class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:repository":{"id":"make:backend:repository","description":"Generate a repository class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:route":{"id":"make:backend:route","description":"Generate a routes extender","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:service-provider":{"id":"make:backend:service-provider","description":"Generate a service provider class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:backend:validator":{"id":"make:backend:validator","description":"Generate a validator class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:frontend:component":{"id":"make:frontend:component","description":"Generate a frontend component","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:frontend:modal":{"id":"make:frontend:modal","description":"Generate a modal component","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]},"make:frontend:model":{"id":"make:frontend:model","description":"Generate a model class","pluginName":"@flarum/cli","pluginType":"core","aliases":[],"flags":{"no-interaction":{"name":"no-interaction","type":"boolean","char":"n","description":"Do not ask any interactive questions, assume defaults. When impossible, error.","allowNo":false},"help":{"name":"help","type":"boolean","char":"h","description":"Show CLI help.","allowNo":false}},"args":[{"name":"path","description":"Where should this command be executed?"}]}}}
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@flarum/cli",
3
3
  "description": "A CLI for developing Flarum extensions",
4
- "version": "2.0.0-beta.1",
4
+ "version": "2.0.0-beta.13",
5
5
  "author": "Flarum Team",
6
6
  "bin": {
7
7
  "fl": "bin/run",
@@ -9,7 +9,8 @@
9
9
  },
10
10
  "bugs": "https://github.com/flarum/cli/issues",
11
11
  "devDependencies": {
12
- "@babel/core": "^7",
12
+ "@babel/core": "^7.0.0",
13
+ "@babel/preset-env": "^7.14.2",
13
14
  "@oclif/dev-cli": "^1.26.0",
14
15
  "@oclif/test": "^1.2.8",
15
16
  "@types/chai": "^4.2.20",
@@ -32,7 +33,6 @@
32
33
  "eslint-import-resolver-babel-module": "^5.3.1",
33
34
  "eslint-import-resolver-typescript": "^2.5.0",
34
35
  "eslint-plugin-import": "^2.25.3",
35
- "globby": "^10.0.2",
36
36
  "jest": "^27.4.5",
37
37
  "jest-extended": "^1.2.0",
38
38
  "ts-jest": "^27.1.2",
@@ -81,11 +81,13 @@
81
81
  },
82
82
  "audit": {
83
83
  "description": "Checks for potential errors / updatable parts of a Flarum extension."
84
+ },
85
+ "update": {
86
+ "description": "Helper commands to update extensions for new versions of Flarum Core."
84
87
  }
85
88
  },
86
89
  "plugins": [
87
90
  "@oclif/plugin-help",
88
- "@oclif/plugin-plugins",
89
91
  "@oclif/plugin-version"
90
92
  ]
91
93
  },
@@ -101,20 +103,16 @@
101
103
  },
102
104
  "types": "lib/index.d.ts",
103
105
  "dependencies": {
104
- "@babel/preset-env": "^7.14.2",
105
106
  "@oclif/core": "^1.0.11",
106
107
  "@oclif/errors": "^1.3.5",
107
108
  "@oclif/plugin-help": "^5",
108
- "@oclif/plugin-plugins": "^2.0.11",
109
109
  "@oclif/plugin-version": "^1",
110
110
  "chalk": "^2.4.2",
111
111
  "cli-ux": "^6.0.6",
112
112
  "ejs": "^3.1.6",
113
- "glob": "^7.1.6",
114
- "just-safe-get": "^2.1.2",
113
+ "globby": "^10.0.2",
115
114
  "mem-fs": "^2.2.1",
116
115
  "mem-fs-editor": "^8.0.0",
117
- "modern-async": "^1.0.2",
118
116
  "module-alias": "^2.2.2",
119
117
  "pick-deep": "^1.0.0",
120
118
  "pluralize": "^8.0.0",