@flarum/cli 3.0.12 → 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 (66) hide show
  1. package/README.md +33 -1
  2. package/boilerplate/skeleton/extension/composer.json +4 -0
  3. package/boilerplate/skeleton/extension/js/package.json +4 -4
  4. package/boilerplate/skeleton/extension/js/tsconfig.json +3 -0
  5. package/boilerplate/skeleton/extension/js/tsconfig.test.json +1 -0
  6. package/boilerplate/stubs/backend/advanced-api-resource.php +3 -3
  7. package/boilerplate/stubs/backend/model-factory.php +17 -0
  8. package/boilerplate/stubs/backend/model.php +3 -0
  9. package/lib/base-command.d.ts +21 -3
  10. package/lib/base-command.js +52 -5
  11. package/lib/commands/make/backend/model.js +10 -0
  12. package/lib/commands/upgrade/2.0.d.ts +43 -0
  13. package/lib/commands/upgrade/2.0.js +128 -2
  14. package/lib/steps/gen-ext-scaffolder.d.ts +5 -0
  15. package/lib/steps/gen-ext-scaffolder.js +17 -2
  16. package/lib/steps/stubs/backend/advanced-api-resource.js +1 -1
  17. package/lib/steps/stubs/backend/model-factory.d.ts +24 -0
  18. package/lib/steps/stubs/backend/model-factory.js +33 -0
  19. package/lib/steps/upgrade/twopointoh/backend/email-views.js +22 -30
  20. package/lib/steps/upgrade/twopointoh/backend/extension-models.d.ts +30 -0
  21. package/lib/steps/upgrade/twopointoh/backend/extension-models.js +34 -0
  22. package/lib/steps/upgrade/twopointoh/backend/json-api.d.ts +6 -0
  23. package/lib/steps/upgrade/twopointoh/backend/json-api.js +14 -0
  24. package/lib/steps/upgrade/twopointoh/backend/misc.d.ts +6 -0
  25. package/lib/steps/upgrade/twopointoh/backend/misc.js +19 -7
  26. package/lib/steps/upgrade/twopointoh/backend/model-factories.d.ts +18 -0
  27. package/lib/steps/upgrade/twopointoh/backend/model-factories.js +73 -0
  28. package/lib/steps/upgrade/twopointoh/backend/phpunit.d.ts +2 -0
  29. package/lib/steps/upgrade/twopointoh/backend/phpunit.js +16 -8
  30. package/lib/steps/upgrade/twopointoh/backend/search.d.ts +9 -0
  31. package/lib/steps/upgrade/twopointoh/backend/search.js +28 -10
  32. package/lib/steps/upgrade/twopointoh/base.d.ts +38 -0
  33. package/lib/steps/upgrade/twopointoh/base.js +73 -12
  34. package/lib/steps/upgrade/twopointoh/dependencies.d.ts +58 -1
  35. package/lib/steps/upgrade/twopointoh/dependencies.js +342 -19
  36. package/lib/steps/upgrade/twopointoh/frontend/admin-extender.d.ts +86 -0
  37. package/lib/steps/upgrade/twopointoh/frontend/admin-extender.js +842 -0
  38. package/lib/steps/upgrade/twopointoh/frontend/code-splitting/usage-of-lazy-modules.js +110 -18
  39. package/lib/steps/upgrade/twopointoh/frontend/export-registry/import-ext.js +13 -16
  40. package/lib/steps/upgrade/twopointoh/frontend/misc.d.ts +23 -0
  41. package/lib/steps/upgrade/twopointoh/frontend/misc.js +147 -8
  42. package/lib/steps/upgrade/twopointoh/infra.d.ts +16 -1
  43. package/lib/steps/upgrade/twopointoh/infra.js +87 -5
  44. package/lib/steps/upgrade/twopointoh/step-failures.d.ts +8 -0
  45. package/lib/steps/upgrade/twopointoh/step-failures.js +6 -0
  46. package/lib/steps/upgrade/twopointoh/todos.d.ts +22 -0
  47. package/lib/steps/upgrade/twopointoh/todos.js +57 -0
  48. package/lib/steps/upgrade/twopointoh/typescript-4-9.d.ts +12 -0
  49. package/lib/steps/upgrade/twopointoh/typescript-4-9.js +200 -0
  50. package/lib/utils/ast.js +3 -2
  51. package/lib/utils/babel-ts.d.ts +9 -0
  52. package/lib/utils/babel-ts.js +18 -0
  53. package/lib/utils/composer.d.ts +5 -0
  54. package/lib/utils/composer.js +10 -1
  55. package/lib/utils/terminal.d.ts +13 -0
  56. package/lib/utils/terminal.js +26 -0
  57. package/oclif.manifest.json +1 -1
  58. package/package.json +1 -1
  59. package/php-subsystem/index.php +12 -0
  60. package/php-subsystem/src/NodeUtil.php +19 -9
  61. package/php-subsystem/src/NodeVisitors/AddExtender.php +49 -1
  62. package/php-subsystem/src/Upgrade/TwoPointOh/JsonApi.php +2 -20
  63. package/php-subsystem/src/Upgrade/TwoPointOh/Misc.php +13 -17
  64. package/php-subsystem/src/Upgrade/TwoPointOh/ModelFactories.php +943 -0
  65. package/php-subsystem/src/Upgrade/TwoPointOh/PhpUnit.php +476 -71
  66. package/php-subsystem/src/Upgrade/TwoPointOh/Search.php +97 -13
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": "3.0.12",
4
+ "version": "3.0.13",
5
5
  "author": "Flarum Team",
6
6
  "flarum": "2.x",
7
7
  "bin": {
@@ -45,6 +45,18 @@ try {
45
45
  $output = (new Flarum\CliPhpSubsystem\Upgrade\TwoPointOh\Search())->handle($input['file'], $input['code'] ?? null, $input['data'] ?? []);
46
46
  break;
47
47
 
48
+ case 'upgrade.2-0.migrations-schema':
49
+ $output = (new Flarum\CliPhpSubsystem\Upgrade\TwoPointOh\ModelFactories())->schema($input['data']['migrations'] ?? []);
50
+ break;
51
+
52
+ case 'upgrade.2-0.models':
53
+ $output = (new Flarum\CliPhpSubsystem\Upgrade\TwoPointOh\ModelFactories())->models($input['data']['files'] ?? []);
54
+ break;
55
+
56
+ case 'upgrade.2-0.model-factory':
57
+ $output = (new Flarum\CliPhpSubsystem\Upgrade\TwoPointOh\ModelFactories())->factory($input['file'], $input['code'], $input['data'] ?? []);
58
+ break;
59
+
48
60
  case 'upgrade.2-0.phpunit':
49
61
  $output = (new Flarum\CliPhpSubsystem\Upgrade\TwoPointOh\PhpUnit())->handle($input['file'], $input['code'] ?? null, $input['data'] ?? []);
50
62
  break;
@@ -55,18 +55,28 @@ class NodeUtil
55
55
  return true;
56
56
  }));
57
57
 
58
- $lastUseStatement = null;
58
+ usort($uses, fn ($a, $b) => strcasecmp($a->uses[0]->name->toString(), $b->uses[0]->name->toString()));
59
59
 
60
- foreach ($node->stmts as $index => $stmt) {
61
- if ($stmt instanceof \PhpParser\Node\Stmt\Use_) {
62
- $lastUseStatement = $index;
63
- } elseif (! is_null($lastUseStatement)) {
64
- break;
60
+ // Each goes where it sorts among the imports already there, as the
61
+ // Flarum StyleCI preset orders them, or after the last one.
62
+ foreach ($uses as $use) {
63
+ $lastUseStatement = null;
64
+ $position = null;
65
+
66
+ foreach ($node->stmts as $index => $stmt) {
67
+ if ($stmt instanceof \PhpParser\Node\Stmt\Use_) {
68
+ $lastUseStatement = $index;
69
+
70
+ if (is_null($position) && strcasecmp($stmt->uses[0]->name->toString(), $use->uses[0]->name->toString()) > 0) {
71
+ $position = $index;
72
+ }
73
+ } elseif (! is_null($lastUseStatement)) {
74
+ break;
75
+ }
65
76
  }
66
- }
67
77
 
68
- if (! is_null($lastUseStatement)) {
69
- array_splice($node->stmts, $lastUseStatement + 1, 0, $uses);
78
+ // Without any imports yet, it opens the namespace.
79
+ array_splice($node->stmts, $position ?? (is_null($lastUseStatement) ? 0 : $lastUseStatement + 1), 0, [$use]);
70
80
  }
71
81
  }
72
82
 
@@ -28,9 +28,57 @@ class AddExtender extends NodeVisitorAbstract
28
28
  $this->nameContext = $nameContext;
29
29
  }
30
30
 
31
+ /**
32
+ * The return statements whose array of extenders gets the new one.
33
+ *
34
+ * @var array<int, true>
35
+ */
36
+ protected $targets = [];
37
+
38
+ /**
39
+ * Picks the arrays of extenders the file returns: those returned outside any
40
+ * function, or failing that, from the fewest nested functions. An array a
41
+ * Conditional's closure returns is left alone, as it holds the extenders for
42
+ * when another extension is enabled.
43
+ */
44
+ public function beforeTraverse(array $nodes)
45
+ {
46
+ $returns = [];
47
+
48
+ $find = function (array $nodes, int $depth) use (&$find, &$returns) {
49
+ foreach ($nodes as $node) {
50
+ if (! $node instanceof Node) {
51
+ continue;
52
+ }
53
+
54
+ if ($node instanceof Node\Stmt\Return_ && $node->expr instanceof Node\Expr\Array_) {
55
+ $returns[] = [$node, $depth];
56
+ }
57
+
58
+ $nested = $node instanceof Node\FunctionLike ? $depth + 1 : $depth;
59
+
60
+ foreach ($node->getSubNodeNames() as $name) {
61
+ $find(is_array($node->$name) ? $node->$name : [$node->$name], $nested);
62
+ }
63
+ }
64
+ };
65
+
66
+ $find($nodes, 0);
67
+
68
+ $outermost = min(array_column($returns, 1) ?: [0]);
69
+
70
+ foreach ($returns as [$return, $depth]) {
71
+ if ($depth === $outermost) {
72
+ $this->targets[spl_object_id($return)] = true;
73
+ }
74
+ }
75
+
76
+ return null;
77
+ }
78
+
31
79
  public function leaveNode(Node $node)
32
80
  {
33
- if ($node instanceof Node\Stmt\Return_ && $node->expr instanceof Node\Expr\Array_) {
81
+ if ($node instanceof Node\Stmt\Return_ && $node->expr instanceof Node\Expr\Array_ && isset($this->targets[spl_object_id($node)])) {
34
82
  if (! isset($this->params['extender'])) {
35
83
  $params = json_encode($this->params);
36
84
  throw new \Exception("Invalid Extender Schema. Provided params: $params");
@@ -135,9 +135,9 @@ class JsonApi extends Replacement
135
135
 
136
136
  $traverser->addVisitor(new NodeVisitor\ParentConnectingVisitor());
137
137
 
138
+ // The TODO says what to write instead. Imports are left to whoever
139
+ // writes it: added now, they would go unused until then.
138
140
  $traverser->addVisitor(new class () extends \PhpParser\NodeVisitorAbstract {
139
- public $hasExtenders = false;
140
-
141
141
  const LINK_TO_DOCS = 'https://docs.flarum.org/2.x/extend/api#extending-api-resources';
142
142
  const COMMENT = '// @TODO: Replace with the new implementation '.self::LINK_TO_DOCS;
143
143
 
@@ -157,28 +157,10 @@ class JsonApi extends Replacement
157
157
  if ($parent) {
158
158
  $parent->setAttribute('comments', [new \PhpParser\Comment\Doc(self::COMMENT)]);
159
159
  }
160
-
161
- $this->hasExtenders = true;
162
160
  }
163
161
  }
164
162
  }
165
163
  }
166
-
167
- public function leaveNode(\PhpParser\Node $node)
168
- {
169
- if (! $this->hasExtenders) {
170
- return null;
171
- }
172
-
173
- if ($node instanceof \PhpParser\Node\Stmt\Namespace_) {
174
- NodeUtil::addUsesToNamespace($node, [
175
- 'Flarum\Api\Context',
176
- 'Flarum\Api\Endpoint',
177
- 'Flarum\Api\Resource',
178
- 'Flarum\Api\Schema',
179
- ]);
180
- }
181
- }
182
164
  });
183
165
 
184
166
  return new ReplacementResult($traverser->traverse($ast));
@@ -2,6 +2,7 @@
2
2
 
3
3
  namespace Flarum\CliPhpSubsystem\Upgrade\TwoPointOh;
4
4
 
5
+ use Flarum\CliPhpSubsystem\NodeUtil;
5
6
  use Flarum\CliPhpSubsystem\NodeVisitors\ChangeSignatures;
6
7
  use Flarum\CliPhpSubsystem\Upgrade\Replacement;
7
8
  use Flarum\CliPhpSubsystem\Upgrade\ReplacementResult;
@@ -198,7 +199,11 @@ class Misc extends Replacement
198
199
  if ($node instanceof \PhpParser\Node\Expr\MethodCall) {
199
200
  if ($class = $this->getClass($node)) {
200
201
  if ($class === 'Extend\Notification') {
201
- if ($node->name->name === 'type') {
202
+ // 1.x's second argument is the serializer. 2.x's is the
203
+ // drivers enabled by default, an array, which stays.
204
+ $serializer = $node->args[1]->value ?? null;
205
+
206
+ if ($node->name->name === 'type' && ($serializer instanceof \PhpParser\Node\Expr\ClassConstFetch || $serializer instanceof \PhpParser\Node\Scalar\String_)) {
202
207
  $args = $node->args;
203
208
  unset($args[1]);
204
209
  $node->args = array_values($args);
@@ -371,14 +376,13 @@ class Misc extends Replacement
371
376
 
372
377
  public function enterNode(Node $node)
373
378
  {
374
- // Does this class implement the Flarum\Notification\Blueprint\BlueprintInterface ?
379
+ // Does this class implement the Flarum\Notification\Blueprint\BlueprintInterface,
380
+ // and not yet the Flarum\Notification\AlertableInterface ?
375
381
  if ($node instanceof Node\Stmt\Class_) {
376
- foreach ($node->implements as $interface) {
377
- if ($interface->getAttribute('resolvedName')->name === 'Flarum\Notification\Blueprint\BlueprintInterface') {
378
- $this->valid = true;
379
- break;
380
- }
381
- }
382
+ $implements = array_map(fn ($interface) => $interface->getAttribute('resolvedName')->name, $node->implements);
383
+
384
+ $this->valid = in_array('Flarum\Notification\Blueprint\BlueprintInterface', $implements)
385
+ && ! in_array('Flarum\Notification\AlertableInterface', $implements);
382
386
  }
383
387
  }
384
388
 
@@ -389,15 +393,7 @@ class Misc extends Replacement
389
393
  }
390
394
 
391
395
  if ($node instanceof Node\Stmt\Namespace_) {
392
- // Add the Flarum\Notification\AlertableInterface import
393
- $node->stmts = array_merge(
394
- [
395
- new Node\Stmt\Use_([
396
- new Node\Stmt\UseUse(new Node\Name('Flarum\Notification\AlertableInterface'))
397
- ])
398
- ],
399
- $node->stmts
400
- );
396
+ NodeUtil::addUsesToNamespace($node, ['Flarum\Notification\AlertableInterface']);
401
397
  }
402
398
 
403
399
  if ($node instanceof \PhpParser\Node\Stmt\Class_) {