@flarum/cli 3.0.11 → 3.0.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 (76) hide show
  1. package/README.md +33 -1
  2. package/bin/libgit2.1.5.dylib +0 -0
  3. package/bin/splitsh-lite-darwin-arm64 +0 -0
  4. package/boilerplate/skeleton/extension/composer.json +4 -0
  5. package/boilerplate/skeleton/extension/js/package.json +5 -5
  6. package/boilerplate/skeleton/extension/js/tsconfig.json +3 -0
  7. package/boilerplate/skeleton/extension/js/tsconfig.test.json +1 -0
  8. package/boilerplate/skeleton/extension/phpstan.neon +0 -1
  9. package/boilerplate/skeleton/extension/tests/phpunit.integration.xml +1 -0
  10. package/boilerplate/skeleton/extension/tests/phpunit.unit.xml +2 -1
  11. package/boilerplate/stubs/backend/advanced-api-resource.php +3 -3
  12. package/boilerplate/stubs/backend/model-factory.php +17 -0
  13. package/boilerplate/stubs/backend/model.php +3 -0
  14. package/lib/base-command.d.ts +21 -3
  15. package/lib/base-command.js +52 -5
  16. package/lib/commands/make/backend/model.js +10 -0
  17. package/lib/commands/monorepo/split.js +1 -1
  18. package/lib/commands/upgrade/2.0.d.ts +43 -0
  19. package/lib/commands/upgrade/2.0.js +128 -2
  20. package/lib/steps/gen-ext-scaffolder.d.ts +5 -0
  21. package/lib/steps/gen-ext-scaffolder.js +17 -2
  22. package/lib/steps/monorepo/split.d.ts +2 -1
  23. package/lib/steps/monorepo/split.js +20 -5
  24. package/lib/steps/stubs/backend/advanced-api-resource.js +1 -1
  25. package/lib/steps/stubs/backend/model-factory.d.ts +24 -0
  26. package/lib/steps/stubs/backend/model-factory.js +33 -0
  27. package/lib/steps/upgrade/twopointoh/backend/email-views.js +22 -30
  28. package/lib/steps/upgrade/twopointoh/backend/extension-models.d.ts +30 -0
  29. package/lib/steps/upgrade/twopointoh/backend/extension-models.js +34 -0
  30. package/lib/steps/upgrade/twopointoh/backend/json-api.d.ts +6 -0
  31. package/lib/steps/upgrade/twopointoh/backend/json-api.js +14 -0
  32. package/lib/steps/upgrade/twopointoh/backend/misc.d.ts +6 -0
  33. package/lib/steps/upgrade/twopointoh/backend/misc.js +19 -7
  34. package/lib/steps/upgrade/twopointoh/backend/model-factories.d.ts +18 -0
  35. package/lib/steps/upgrade/twopointoh/backend/model-factories.js +73 -0
  36. package/lib/steps/upgrade/twopointoh/backend/phpunit-xml.d.ts +8 -0
  37. package/lib/steps/upgrade/twopointoh/backend/phpunit-xml.js +33 -0
  38. package/lib/steps/upgrade/twopointoh/backend/phpunit.d.ts +2 -0
  39. package/lib/steps/upgrade/twopointoh/backend/phpunit.js +34 -21
  40. package/lib/steps/upgrade/twopointoh/backend/search.d.ts +9 -0
  41. package/lib/steps/upgrade/twopointoh/backend/search.js +28 -10
  42. package/lib/steps/upgrade/twopointoh/base.d.ts +38 -0
  43. package/lib/steps/upgrade/twopointoh/base.js +122 -24
  44. package/lib/steps/upgrade/twopointoh/dependencies.d.ts +58 -1
  45. package/lib/steps/upgrade/twopointoh/dependencies.js +343 -15
  46. package/lib/steps/upgrade/twopointoh/frontend/admin-extender.d.ts +86 -0
  47. package/lib/steps/upgrade/twopointoh/frontend/admin-extender.js +842 -0
  48. package/lib/steps/upgrade/twopointoh/frontend/code-splitting/usage-of-lazy-modules.js +110 -18
  49. package/lib/steps/upgrade/twopointoh/frontend/export-registry/import-ext.js +13 -16
  50. package/lib/steps/upgrade/twopointoh/frontend/misc.d.ts +23 -0
  51. package/lib/steps/upgrade/twopointoh/frontend/misc.js +147 -8
  52. package/lib/steps/upgrade/twopointoh/infra.d.ts +16 -1
  53. package/lib/steps/upgrade/twopointoh/infra.js +87 -5
  54. package/lib/steps/upgrade/twopointoh/step-failures.d.ts +32 -0
  55. package/lib/steps/upgrade/twopointoh/step-failures.js +54 -0
  56. package/lib/steps/upgrade/twopointoh/todos.d.ts +22 -0
  57. package/lib/steps/upgrade/twopointoh/todos.js +57 -0
  58. package/lib/steps/upgrade/twopointoh/typescript-4-9.d.ts +12 -0
  59. package/lib/steps/upgrade/twopointoh/typescript-4-9.js +200 -0
  60. package/lib/utils/ast.js +5 -10
  61. package/lib/utils/babel-ts.d.ts +9 -0
  62. package/lib/utils/babel-ts.js +18 -0
  63. package/lib/utils/composer.d.ts +5 -0
  64. package/lib/utils/composer.js +10 -1
  65. package/lib/utils/terminal.d.ts +13 -0
  66. package/lib/utils/terminal.js +26 -0
  67. package/oclif.manifest.json +1 -1
  68. package/package.json +1 -1
  69. package/php-subsystem/index.php +12 -0
  70. package/php-subsystem/src/NodeUtil.php +19 -9
  71. package/php-subsystem/src/NodeVisitors/AddExtender.php +49 -1
  72. package/php-subsystem/src/Upgrade/TwoPointOh/JsonApi.php +2 -20
  73. package/php-subsystem/src/Upgrade/TwoPointOh/Misc.php +13 -17
  74. package/php-subsystem/src/Upgrade/TwoPointOh/ModelFactories.php +943 -0
  75. package/php-subsystem/src/Upgrade/TwoPointOh/PhpUnit.php +476 -71
  76. package/php-subsystem/src/Upgrade/TwoPointOh/Search.php +97 -13
package/README.md CHANGED
@@ -49,7 +49,7 @@ $ npm install -g @flarum/cli
49
49
  $ flarum-cli COMMAND
50
50
  running command...
51
51
  $ flarum-cli (-v|--version|version)
52
- @flarum/cli/3.0.11 linux-x64 node-v18.19.1
52
+ @flarum/cli/3.0.13 darwin-arm64 node-v26.11.1
53
53
  $ flarum-cli --help [COMMAND]
54
54
  USAGE
55
55
  $ flarum-cli COMMAND
@@ -132,6 +132,38 @@ The CLI has different types of commands for different tasks:
132
132
  **Code Updates**: These commands help update extensions for newer versions of Flarum.
133
133
 
134
134
  - `flarum-cli update js-imports [PATH]`: Adds admin/forum/common namespaces to all JS imports from flarum core.
135
+ - `flarum-cli upgrade 2.0 [PATH] [-n|--no-interaction] [--json] [--check] [--step <number>] [--force-steps]`: Upgrades a 1.x extension to Flarum 2.0, one step at a time, committing each step. Steps already committed are skipped, so running it again resumes where it stopped.
136
+
137
+ To drive the upgrade from another program, such as an AI agent, pass `--json`. It asks nothing, and prints a single JSON object when it finishes. It exits non-zero when the upgrade didn't complete:
138
+
139
+ ```json
140
+ {
141
+ "status": "failed",
142
+ "error": "1 file could not be upgraded by this step, so it made no changes. …",
143
+ "messages": [],
144
+ "steps": [
145
+ {
146
+ "step": 13,
147
+ "title": "Prepare for JSON:API changes.",
148
+ "status": "committed",
149
+ "commit": { "sha": "c63dd501…", "message": "chore(2.0): JSON:API changes" },
150
+ "notes": "Flarum 2.0 completely refactors the JSON:API implementation. …",
151
+ "todos": [{ "file": "extend.php", "line": 33, "text": "// @TODO: Replace with the new implementation …" }]
152
+ },
153
+ {
154
+ "step": 14,
155
+ "title": "Intervention Image Library v3",
156
+ "status": "failed",
157
+ "failures": [{ "file": "src/Thumbnailer.php", "reason": "Syntax error, unexpected '{' on line 15" }]
158
+ },
159
+ { "step": 15, "title": "Search & Filter API changes", "status": "not-run" }
160
+ ]
161
+ }
162
+ ```
163
+
164
+ Each step is `committed`, `no-changes`, `skipped` (committed by an earlier run), `failed` or `not-run`. A step that fails on some files lists them and makes no changes, so fix those files, commit, and run the command again. The `todos` are what the upgrade could not change itself: the `@TODO` comments the step's commit added, and work it can only point out, such as a file to add, which has a `line` of `null`. A `no-changes` step lists its `todos` too, when it has any.
165
+
166
+ To see what the upgrade would change without changing anything, pass `--check`, such as for an extension already on Flarum 2.0. The steps run on the extension's last commit, in a temporary git worktree that is removed afterwards, and none is skipped. With `--json`, a step that would change something is `would-change`, with the `files` and `diff` of the change, and the report's `check` names the commit checked and whether changes not yet committed were left out.
135
167
 
136
168
  _And of course, you can always use the help command to see a list of all available commands with their descriptions:_
137
169
 
Binary file
Binary file
@@ -49,7 +49,9 @@
49
49
  "@test:integration"
50
50
  ],
51
51
  "test:unit": "phpunit -c tests/phpunit.unit.xml",
52
+ "test:unit:filter": "phpunit -c tests/phpunit.unit.xml --filter",
52
53
  "test:integration": "phpunit -c tests/phpunit.integration.xml",
54
+ "test:integration:filter": "phpunit -c tests/phpunit.integration.xml --filter",
53
55
  "test:setup": "@php tests/integration/setup.php",
54
56
  "analyse:phpstan": "phpstan analyse",
55
57
  "clear-cache:phpstan": "phpstan clear-result-cache"
@@ -57,7 +59,9 @@
57
59
  "scripts-descriptions": {
58
60
  "test": "Runs all tests.",
59
61
  "test:unit": "Runs all unit tests.",
62
+ "test:unit:filter": "Runs unit tests whose name matches: composer test:unit:filter -- ClassName",
60
63
  "test:integration": "Runs all integration tests.",
64
+ "test:integration:filter": "Runs integration tests whose name matches: composer test:integration:filter -- ClassName",
61
65
  "test:setup": "Sets up a database for use with integration tests. Execute this only once.",
62
66
  "analyse:phpstan": "Run static analysis"
63
67
  },
@@ -7,14 +7,14 @@
7
7
  "dependencies": {
8
8
  },
9
9
  "devDependencies": {
10
- "@flarum/jest-config": "^1.0.1",
10
+ "@flarum/jest-config": "^2.0.0",
11
11
  "@flarum/prettier-config": "^1.0.0",
12
12
  "flarum-tsconfig": "^2.0.0",
13
- "flarum-webpack-config": "^3.0.0",
13
+ "flarum-webpack-config": "^3.0.7",
14
14
  "prettier": "^2.5.1",
15
- "typescript": "^4.5.4",
15
+ "typescript": "^4.9.5",
16
16
  "typescript-coverage-report": "^0.6.1",
17
- "webpack": "^5.65.0",
17
+ "webpack": "^5.104.1",
18
18
  "webpack-cli": "^4.9.1"
19
19
  },
20
20
  "scripts": {
@@ -25,7 +25,7 @@
25
25
  "format-check": "prettier --check src",
26
26
  "clean-typings": "npx rimraf dist-typings && mkdir dist-typings",
27
27
  "build-typings": "<%= params.jsPackageManager %> run clean-typings && ([ -e src/@types ] && cp -r src/@types dist-typings/@types || true) && tsc && <%= params.jsPackageManager %> run post-build-typings",
28
- "post-build-typings": "find dist-typings -type f -name '*.d.ts' -print0 | xargs -0 sed -i 's,../src/@types,@types,g'",
28
+ "post-build-typings": "find dist-typings -type f -name '*.d.ts' -print0 | xargs -0 sed -i.bak 's,../src/@types,@types,g' && find dist-typings -type f -name '*.d.ts.bak' -delete",
29
29
  "check-typings": "tsc --noEmit --emitDeclarationOnly false",
30
30
  "check-typings-coverage": "typescript-coverage-report",
31
31
  "test": "yarn node --experimental-vm-modules $(yarn bin jest)"
@@ -12,6 +12,9 @@
12
12
  "@types/**/*"
13
13
  ],
14
14
  "compilerOptions": {
15
+ // Only load the type packages the code imports. Others, such as the
16
+ // @types/node webpack brings along, use syntax TypeScript 4.9 can't read.
17
+ "types": [],
15
18
  // This will output typings to `dist-typings`
16
19
  "declarationDir": "./dist-typings",
17
20
  "baseUrl": ".",
@@ -3,6 +3,7 @@
3
3
  "include": ["tests/**/*"],
4
4
  "files": ["../../../node_modules/@flarum/jest-config/shims.d.ts"],
5
5
  "compilerOptions": {
6
+ "types": ["jest"],
6
7
  "strict": false,
7
8
  "noImplicitReturns": false,
8
9
  "noImplicitAny": false
@@ -8,5 +8,4 @@ parameters:
8
8
  - src
9
9
  excludePaths:
10
10
  - *.blade.php
11
- checkMissingIterableValueType: false
12
11
  databaseMigrationsPath: ['migrations']
@@ -6,6 +6,7 @@
6
6
  cacheDirectory=".phpunit.cache"
7
7
  backupStaticProperties="false"
8
8
  colors="true"
9
+ displayDetailsOnTestsThatTriggerWarnings="true"
9
10
  processIsolation="true"
10
11
  stopOnFailure="false"
11
12
  >
@@ -1,11 +1,12 @@
1
1
  <?xml version="1.0" encoding="UTF-8"?>
2
2
  <phpunit
3
3
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
4
- xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
4
+ xsi:noNamespaceSchemaLocation="../vendor/phpunit/phpunit/phpunit.xsd"
5
5
  backupGlobals="false"
6
6
  cacheDirectory=".phpunit.cache"
7
7
  backupStaticProperties="false"
8
8
  colors="true"
9
+ displayDetailsOnTestsThatTriggerWarnings="true"
9
10
  processIsolation="false"
10
11
  stopOnFailure="false"
11
12
  >
@@ -14,7 +14,7 @@ use Tobyz\JsonApiServer\Context as OriginalContext;
14
14
  /**
15
15
  * @extends <% if (modelClassName) { %>Resource\AbstractDatabaseResource<<%= modelClassName %>><% } else { %>Resource\AbstractResource<object><% } %>
16
16
  */
17
- class <%= className %> extends <% if (modelClassName) { %>Resource\AbstractDatabaseResource<% } else { %>Resource\AbstractResource<% if (interfaces.length > 0) %> implements <%= interfaces.join(', ') %><% } %>
17
+ class <%= className %> extends <% if (modelClassName) { %>Resource\AbstractDatabaseResource<% } else { %>Resource\AbstractResource<% if (interfaces.length > 0) { %> implements <%= interfaces.join(', ') %><% } %><% } %>
18
18
  {
19
19
  public function type(): string
20
20
  {
@@ -35,7 +35,7 @@ class <%= className %> extends <% if (modelClassName) { %>Resource\AbstractDatab
35
35
  {
36
36
  return [<% if (endpoints.includes('create')) { %>
37
37
  Endpoint\Create::make()<% if (modelClassName) { %>
38
- ->can('create<%= modelClassName %>'),<% } %><% } %><% if (endpoints.includes('update')) { %>
38
+ ->can('create<%= modelClassName %>')<% } %>,<% } %><% if (endpoints.includes('update')) { %>
39
39
  Endpoint\Update::make()
40
40
  ->can('update'),<% } %><% if (endpoints.includes('delete')) { %>
41
41
  Endpoint\Delete::make()
@@ -52,7 +52,7 @@ class <%= className %> extends <% if (modelClassName) { %>Resource\AbstractDatab
52
52
  return [
53
53
 
54
54
  /**
55
- * @todo migrate logic from old serializer and controllers to this API Resource.
55
+ * @TODO migrate logic from old serializer and controllers to this API Resource.
56
56
  * @see https://docs.flarum.org/2.x/extend/api#api-resources
57
57
  */
58
58
 
@@ -0,0 +1,17 @@
1
+ <?php
2
+
3
+ namespace <%= classNamespace %>;
4
+
5
+ use Illuminate\Database\Eloquent\Factories\Factory;
6
+
7
+ class <%= className %> extends Factory
8
+ {
9
+ // A default for each column, so tests only need to set the ones they care about.
10
+ // See https://docs.flarum.org/2.x/extend/testing#model-factories for more information.
11
+ public function definition(): array
12
+ {
13
+ return [
14
+ //
15
+ ];
16
+ }
17
+ }
@@ -5,9 +5,12 @@ namespace <%= classNamespace %>;
5
5
  use Flarum\Database\AbstractModel;
6
6
  use Flarum\Database\ScopeVisibilityTrait;
7
7
  use Flarum\Foundation\EventGeneratorTrait;
8
+ use Illuminate\Database\Eloquent\Factories\HasFactory;
8
9
 
9
10
  class <%= className %> extends AbstractModel
10
11
  {
12
+ use HasFactory;
13
+
11
14
  // See https://docs.flarum.org/2.x/extend/models.html#backend-models for more information.
12
15
  <% if (tableName) { %>
13
16
  protected $table = '<%= tableName %>';<% } %>
@@ -1,5 +1,5 @@
1
1
  import { Command, Interfaces } from '@oclif/core';
2
- import { IO } from 'boilersmith/io';
2
+ import { IO, Message } from 'boilersmith/io';
3
3
  import { StepManager } from 'boilersmith/step-manager';
4
4
  import { FlarumProviders } from './providers';
5
5
  export declare enum LocationType {
@@ -20,19 +20,37 @@ export default abstract class BaseCommand extends Command {
20
20
  protected skipFinalMessage: boolean;
21
21
  runSteps(steps: StepManager<FlarumProviders>): Promise<{
22
22
  succeeded: true;
23
- messages: import("boilersmith/io").Message[];
23
+ messages: Message[];
24
24
  stepsRan: string[];
25
25
  } | {
26
26
  succeeded: false;
27
27
  error: string;
28
28
  errorTrace?: string | undefined;
29
- messages: import("boilersmith/io").Message[];
29
+ messages: Message[];
30
30
  stepsRan: string[];
31
31
  e?: any;
32
32
  }>;
33
+ /**
34
+ * Where the steps run, which is where the command was asked to unless a
35
+ * command runs them somewhere else.
36
+ */
37
+ protected stepsPath(path: string | undefined): string | undefined;
33
38
  extRoot(path: string | undefined): Promise<string>;
34
39
  run(): Promise<void>;
35
40
  protected welcomeMessage(): string;
41
+ /**
42
+ * The result of a run with `--json`, for the program that started it.
43
+ */
44
+ protected jsonReport(succeeded: boolean, error: string | null, messages: Message[]): Record<string, unknown>;
45
+ /**
46
+ * Written by hand rather than returned from `run()`: oclif colours JSON it
47
+ * prints itself whenever the output is a terminal.
48
+ */
49
+ protected writeJson(report: Record<string, unknown>): void;
50
+ /**
51
+ * With `--json`, an error before or between steps is still reported as JSON.
52
+ */
53
+ catch(err: any): Promise<any>;
36
54
  protected goodbyeMessage(): string;
37
55
  protected additionalPreRunChecks(_extRoot: string): Promise<void>;
38
56
  protected abstract steps(stepManager: StepManager<FlarumProviders>, extRoot: string): StepManager<FlarumProviders>;
@@ -16,6 +16,7 @@ const chalk_1 = tslib_1.__importDefault(require("chalk"));
16
16
  const errors_1 = require("@oclif/errors");
17
17
  const monorepo_1 = require("./utils/monorepo");
18
18
  const mem_fs_1 = require("mem-fs");
19
+ const terminal_1 = require("./utils/terminal");
19
20
  var LocationType;
20
21
  (function (LocationType) {
21
22
  LocationType[LocationType["FLARUM_EXTENSION"] = 0] = "FLARUM_EXTENSION";
@@ -34,7 +35,7 @@ class BaseCommand extends core_1.Command {
34
35
  async runSteps(steps) {
35
36
  const { args } = await this.parse(this.constructor);
36
37
  this.args = args;
37
- const path = args.path;
38
+ const path = this.stepsPath(args.path);
38
39
  const paths = new paths_1.NodePaths({
39
40
  requestedDir: path,
40
41
  package: await this.extRoot(path),
@@ -42,6 +43,13 @@ class BaseCommand extends core_1.Command {
42
43
  const phpProvider = new php_provider_1.PhpSubsystemProvider((0, path_1.resolve)(__dirname, '../php-subsystem/index.php'));
43
44
  return steps.run(paths, this.genIO(), { php: phpProvider }, this.dry, args);
44
45
  }
46
+ /**
47
+ * Where the steps run, which is where the command was asked to unless a
48
+ * command runs them somewhere else.
49
+ */
50
+ stepsPath(path) {
51
+ return path;
52
+ }
45
53
  async extRoot(path) {
46
54
  let extRoot;
47
55
  if (this.requireExistingExtension) {
@@ -56,7 +64,7 @@ class BaseCommand extends core_1.Command {
56
64
  return extRoot;
57
65
  }
58
66
  async run() {
59
- var _a;
67
+ var _a, _b, _c;
60
68
  const { args, flags } = await this.parse(this.constructor);
61
69
  this.args = args;
62
70
  this.flags = flags;
@@ -70,6 +78,14 @@ class BaseCommand extends core_1.Command {
70
78
  await this.additionalPreRunChecks(extRoot);
71
79
  const out = await this.runSteps(this.steps(new step_manager_1.StepManager(), extRoot));
72
80
  const errorMessages = out.messages.filter((m) => m.type === 'error');
81
+ if (this.jsonEnabled()) {
82
+ const succeeded = out.succeeded && errorMessages.length === 0;
83
+ const error = out.succeeded ? (_b = (_a = errorMessages[0]) === null || _a === void 0 ? void 0 : _a.message) !== null && _b !== void 0 ? _b : null : out.error;
84
+ this.writeJson(this.jsonReport(succeeded, error, out.messages));
85
+ if (!succeeded)
86
+ process.exitCode = 1;
87
+ return;
88
+ }
73
89
  // this.log('\n\n');
74
90
  if (!this.skipFinalMessage && out.succeeded && errorMessages.length === 0) {
75
91
  this.log(chalk_1.default.bold(chalk_1.default.underline(chalk_1.default.green('Success! The following steps were completed:'))));
@@ -88,12 +104,12 @@ class BaseCommand extends core_1.Command {
88
104
  }
89
105
  }
90
106
  else if (!out.succeeded) {
91
- const prettyPrint = ((_a = out.e) === null || _a === void 0 ? void 0 : _a.code) === 'FL_ERR';
107
+ const prettyPrint = ((_c = out.e) === null || _c === void 0 ? void 0 : _c.code) === 'FL_ERR';
92
108
  if (!prettyPrint)
93
109
  this.log(chalk_1.default.bold(chalk_1.default.underline(chalk_1.default.red('Error occurred, and could not complete:'))));
94
110
  if (prettyPrint) {
95
111
  this.log('\n');
96
- this.log('\u001B[A => ' + chalk_1.default.bgRed.bold(' ERROR ') + ' ' + chalk_1.default.red(out.error));
112
+ this.log((0, terminal_1.overwrite)() + ' => ' + chalk_1.default.bgRed.bold(' ERROR ') + ' ' + chalk_1.default.red(out.error));
97
113
  }
98
114
  else {
99
115
  this.log(chalk_1.default.red(out.error));
@@ -130,6 +146,36 @@ class BaseCommand extends core_1.Command {
130
146
  welcomeMessage() {
131
147
  return '';
132
148
  }
149
+ /**
150
+ * The result of a run with `--json`, for the program that started it.
151
+ */
152
+ jsonReport(succeeded, error, messages) {
153
+ return {
154
+ status: succeeded ? 'succeeded' : 'failed',
155
+ error: error === null ? null : (0, terminal_1.stripAnsi)(error),
156
+ messages: messages.map((m) => (Object.assign(Object.assign({}, m), { message: (0, terminal_1.stripAnsi)(m.message) }))),
157
+ };
158
+ }
159
+ /**
160
+ * Written by hand rather than returned from `run()`: oclif colours JSON it
161
+ * prints itself whenever the output is a terminal.
162
+ */
163
+ writeJson(report) {
164
+ process.stdout.write(JSON.stringify(report, null, 2) + '\n');
165
+ }
166
+ /**
167
+ * With `--json`, an error before or between steps is still reported as JSON.
168
+ */
169
+ async catch(err) {
170
+ var _a, _b, _c;
171
+ if (!this.jsonEnabled())
172
+ return super.catch(err);
173
+ const code = (_b = (_a = err === null || err === void 0 ? void 0 : err.oclif) === null || _a === void 0 ? void 0 : _a.exit) !== null && _b !== void 0 ? _b : 1;
174
+ if (code === 0)
175
+ return;
176
+ process.exitCode = code;
177
+ this.writeJson(this.jsonReport(false, (_c = err === null || err === void 0 ? void 0 : err.message) !== null && _c !== void 0 ? _c : String(err), []));
178
+ }
133
179
  goodbyeMessage() {
134
180
  return 'Please make sure to check my work, adjust formatting, and test before committing!!!';
135
181
  }
@@ -140,7 +186,8 @@ class BaseCommand extends core_1.Command {
140
186
  // Confirmation
141
187
  // ----------------------------------------------------------------
142
188
  genIO() {
143
- return new io_1.PromptsIO(this.args, [], this.flags['no-interaction'], errors_1.exit);
189
+ // Nobody can answer a prompt when a program is reading the output.
190
+ return new io_1.PromptsIO(this.args, [], this.flags['no-interaction'] || this.jsonEnabled(), errors_1.exit);
144
191
  }
145
192
  monorepoPaths(options) {
146
193
  var _a, _b;
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  const tslib_1 = require("tslib");
4
4
  const base_command_1 = tslib_1.__importDefault(require("../../../base-command"));
5
5
  const model_1 = require("../../../steps/stubs/backend/model");
6
+ const model_factory_1 = require("../../../steps/stubs/backend/model-factory");
6
7
  const migration_1 = require("../../../steps/stubs/backend/migration");
7
8
  const api_resource_1 = require("../../../steps/stubs/backend/api-resource");
8
9
  const policy_1 = require("../../../steps/stubs/backend/policy");
@@ -16,8 +17,17 @@ class BackendModel extends base_command_1.default {
16
17
  });
17
18
  }
18
19
  static steps(stepManager, STUB_PATH, shouldRun, dependencies, predefinedDependencies) {
20
+ // The factory is not optional: the model uses HasFactory, which needs it.
19
21
  return stepManager
20
22
  .namedStep('backendModel', new model_1.GenerateModelStub(STUB_PATH, (0, gen_ext_scaffolder_1.genExtScaffolder)()), shouldRun, dependencies, predefinedDependencies)
23
+ .step(new model_factory_1.GenerateModelFactoryStub(STUB_PATH, (0, gen_ext_scaffolder_1.genExtScaffolder)()), {}, [
24
+ {
25
+ sourceStep: 'backendModel',
26
+ exposedName: 'className',
27
+ consumedName: 'className',
28
+ modifier: (modelClassName) => `${modelClassName}Factory`,
29
+ },
30
+ ])
21
31
  .step(new migration_1.GenerateMigrationStub(STUB_PATH, (0, gen_ext_scaffolder_1.genExtScaffolder)()), { optional: true, confirmationMessage: 'Generate corresponding Migration?', default: true }, [
22
32
  {
23
33
  sourceStep: 'backendModel',
@@ -10,7 +10,7 @@ class Split extends base_command_1.default {
10
10
  this.requireExistingExtension = false;
11
11
  }
12
12
  steps(stepManager) {
13
- return stepManager.step(new split_1.MonorepoSplit(this.flags.force));
13
+ return stepManager.step(new split_1.MonorepoSplit(this.flags.force, this.flags['no-interaction']));
14
14
  }
15
15
  }
16
16
  exports.default = Split;
@@ -1,17 +1,60 @@
1
1
  import { StepManager } from 'boilersmith/step-manager';
2
2
  import BaseCommand from '../../base-command';
3
3
  import { FlarumProviders } from '../../providers';
4
+ import { BaseUpgradeStep } from '../../steps/upgrade/twopointoh/base';
5
+ import { IO, Message } from 'boilersmith/io';
6
+ /**
7
+ * The temporary worktree a check runs the steps in, so the extension itself
8
+ * is never changed.
9
+ */
10
+ type Checkout = {
11
+ /** The repository the extension is in. */
12
+ repo: string;
13
+ worktree: string;
14
+ branch: string;
15
+ /** The extension's root inside the worktree. */
16
+ root: string;
17
+ /** What was checked. */
18
+ commit: string;
19
+ /** Whether the extension had changes not committed, which a check leaves out. */
20
+ dirty: boolean;
21
+ cwd: string;
22
+ };
4
23
  export default class TwoPointOh extends BaseCommand {
5
24
  static description: string;
25
+ static enableJsonFlag: boolean;
6
26
  static flags: {
27
+ json: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
7
28
  step: import("@oclif/core/lib/interfaces").OptionFlag<string | undefined>;
8
29
  'force-steps': import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
30
+ check: import("@oclif/core/lib/interfaces").BooleanFlag<boolean>;
9
31
  };
10
32
  static args: import("@oclif/core/lib/interfaces").Arg<any>[];
11
33
  protected requireExistingExtension: boolean;
12
34
  skipFinalMessage: boolean;
35
+ /**
36
+ * The steps this run was asked to take, in order.
37
+ */
38
+ protected scheduled: BaseUpgradeStep[];
39
+ protected checkout: Checkout | null;
40
+ run(): Promise<void>;
41
+ protected additionalPreRunChecks(extRoot: string): Promise<void>;
42
+ protected stepsPath(requested: string | undefined): string | undefined;
43
+ protected genIO(): IO;
44
+ protected createCheckout(extRoot: string): Promise<Checkout>;
45
+ /** Remove the worktree and its branch, saying so if it can't. */
46
+ protected removeCheckout(): Promise<void>;
47
+ /** What a step that committed in the worktree would change, from its commit. */
48
+ protected wouldChange(sha: string): {
49
+ files: string[];
50
+ diff: string;
51
+ };
13
52
  protected steps(steps: StepManager<FlarumProviders>, extRoot: string): StepManager<FlarumProviders>;
14
53
  private prepareSteps;
54
+ protected jsonReport(succeeded: boolean, error: string | null, messages: Message[]): Record<string, unknown>;
55
+ /** A step's outcome, as what it would change when checking. */
56
+ protected reported(step: BaseUpgradeStep): Record<string, unknown>;
15
57
  protected welcomeMessage(): string;
16
58
  protected goodbyeMessage(): string;
17
59
  }
60
+ export {};