Skip to content

Commit

Permalink
feat(strapi): add experimental plugin:watch:link command to CLI (#19143)
Browse files Browse the repository at this point in the history
* feat(strapi): add plugin:link-watch command to CLI

* chore: skip assertion of strapi project if its the plugin:init command

* fix: add yalc

* fix: add yalc files/folders to ignore list to avoid restarting strapi when using

* chore: don't use run-action on plugin:init

* chore: add yarn dlx command to yarn suggestion
  • Loading branch information
joshuaellis committed Jan 11, 2024
1 parent a3690b1 commit e1ede8c
Show file tree
Hide file tree
Showing 11 changed files with 368 additions and 20 deletions.
33 changes: 33 additions & 0 deletions docs/docs/docs/01-core/strapi/commands/plugin/05-link-watch.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
---
title: plugin:watch:link
description: An in depth look at the plugin:watch:link command of the Strapi CLI
tags:
- CLI
- commands
- plugins
---

The `plugin:watch:link` command recompiles your plugin and pushes those changes to your local yalc registry to simulate using your plugin as a node_module in another project.

## Usage

```bash
strapi plugin:watch:link
```

### Options

```bash
Recompiles your plugin automatically on changes and runs yalc push --publish

Options:
-d, --debug Enable debugging mode with verbose logs (default: false)
--silent Don't log anything (default: false)
-h, --help Display help for command
```
## Why yalc?
npm link & yarn link unfortunately can easily break the [rules of hooks](https://legacy.reactjs.org/docs/hooks-rules.html) due to the way packages are resolved using symlinks.
Yalc bypass this problem as it more closely resembles installing a dependency as normal.
2 changes: 2 additions & 0 deletions packages/core/admin/_internal/node/develop.ts
Original file line number Diff line number Diff line change
Expand Up @@ -290,6 +290,8 @@ const develop = async ({
'**/exports/**',
'**/dist/**',
'**/*.d.ts',
'**/.yalc/**',
'**/yalc.lock',
...strapiInstance.config.get('admin.watchIgnoreFiles', []),
],
})
Expand Down
4 changes: 4 additions & 0 deletions packages/core/strapi/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,7 @@
"ci-info": "3.8.0",
"cli-table3": "0.6.2",
"commander": "8.3.0",
"concurrently": "8.2.2",
"configstore": "5.0.1",
"copyfiles": "2.4.1",
"debug": "4.3.4",
Expand Down Expand Up @@ -163,6 +164,7 @@
"node-fetch": "2.7.0",
"node-machine-id": "1.1.12",
"node-schedule": "2.1.0",
"nodemon": "3.0.2",
"open": "8.4.0",
"ora": "5.4.1",
"outdent": "0.8.0",
Expand All @@ -172,6 +174,7 @@
"semver": "7.5.4",
"statuses": "2.0.1",
"typescript": "5.2.2",
"yalc": "1.0.0-pre.53",
"yup": "0.32.9"
},
"devDependencies": {
Expand All @@ -190,6 +193,7 @@
"@types/mime-types": "2.1.1",
"@types/node": "18.18.4",
"@types/node-schedule": "2.1.0",
"@types/nodemon": "1.19.6",
"@types/statuses": "2.0.1",
"eslint-config-custom": "4.17.0",
"supertest": "6.3.3",
Expand Down
12 changes: 6 additions & 6 deletions packages/core/strapi/src/commands/actions/plugin/init/action.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ interface ActionOptions extends Pick<InitOptions, 'silent' | 'debug'> {}
export default async (
packagePath: string,
{ silent, debug }: ActionOptions,
_cmd: unknown,
{ logger, cwd }: CLIContext
) => {
try {
Expand Down Expand Up @@ -240,6 +239,7 @@ const PLUGIN_TEMPLATE = defineTemplate(async ({ logger, gitConfig, packagePath }
scripts: {
build: 'strapi plugin:build',
watch: 'strapi plugin:watch',
'watch:link': 'strapi plugin:watch:link',
verify: 'strapi plugin:verify',
},
dependencies: {},
Expand Down Expand Up @@ -296,7 +296,7 @@ const PLUGIN_TEMPLATE = defineTemplate(async ({ logger, gitConfig, packagePath }
case 'client-code': {
if (answer) {
pkgJson.exports['./strapi-admin'] = {
source: './src/admin/index.js',
source: './admin/src/index.js',
import: './dist/admin/index.mjs',
require: './dist/admin/index.js',
default: './dist/admin/index.js',
Expand All @@ -310,7 +310,7 @@ const PLUGIN_TEMPLATE = defineTemplate(async ({ logger, gitConfig, packagePath }
};

pkgJson.devDependencies = {
...pkgJson.dependencies,
...pkgJson.devDependencies,
react: '*',
'react-dom': '*',
'react-router-dom': '5.3.4',
Expand All @@ -331,7 +331,7 @@ const PLUGIN_TEMPLATE = defineTemplate(async ({ logger, gitConfig, packagePath }
case 'server-code': {
if (answer) {
pkgJson.exports['./strapi-server'] = {
source: './src/server/index.js',
source: './server/src/index.js',
import: './dist/server/index.mjs',
require: './dist/server/index.js',
default: './dist/server/index.js',
Expand All @@ -356,7 +356,7 @@ const PLUGIN_TEMPLATE = defineTemplate(async ({ logger, gitConfig, packagePath }

if (isTypescript) {
if (isRecord(pkgJson.exports['./strapi-admin'])) {
pkgJson.exports['./strapi-admin'].source = './src/admin/index.ts';
pkgJson.exports['./strapi-admin'].source = './admin/src/index.ts';

pkgJson.exports['./strapi-admin'] = {
types: './dist/admin/src/index.d.ts',
Expand All @@ -382,7 +382,7 @@ const PLUGIN_TEMPLATE = defineTemplate(async ({ logger, gitConfig, packagePath }
}

if (isRecord(pkgJson.exports['./strapi-server'])) {
pkgJson.exports['./strapi-server'].source = './src/server/index.ts';
pkgJson.exports['./strapi-server'].source = './server/src/index.ts';

pkgJson.exports['./strapi-server'] = {
types: './dist/server/src/index.d.ts',
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
import type { StrapiCommand } from '../../../types';
import { runAction } from '../../../utils/helpers';
import action from './action';

/**
Expand All @@ -12,7 +11,9 @@ const command: StrapiCommand = ({ command, ctx }) => {
.argument('[path]', 'path to the plugin', './src/plugins/my-plugin')
.option('-d, --debug', 'Enable debugging mode with verbose logs', false)
.option('--silent', "Don't log anything", false)
.action((...args) => runAction('plugin:init', action)(...args, ctx));
.action((path, options) => {
return action(path, options, ctx);
});
};

export default command;
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@ const TYPESCRIPT: TemplateFile[] = [
export default {
register(app: any) {
app.addMenuLink({
to: \`/plugins/\${PluginIcon}\`,
to: \`/plugins/\${PLUGIN_ID}\`,
icon: PluginIcon,
intlLabel: {
id: \`\${PLUGIN_ID}.plugin.name\`,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
import boxen from 'boxen';
import chalk from 'chalk';
import concurrently from 'concurrently';
import fs from 'node:fs/promises';
import path from 'node:path';
import nodemon from 'nodemon';
import { outdent } from 'outdent';

import { notifyExperimentalCommand } from '../../../utils/helpers';
import { CLIContext } from '../../../types';
import { loadPkg, validatePkg } from '../../../utils/pkg';

interface ActionOptions {}

export default async (_opts: ActionOptions, _cmd: unknown, { cwd, logger }: CLIContext) => {
try {
/**
* Notify users this is an experimental command.
*/
await notifyExperimentalCommand('plugin:watch:link', { force: true });

const outDir = './dist';
const extensions = 'ts,js,png,svg,gif,jpeg,css';

nodemon({
watch: [outDir],
ext: extensions,
exec: 'yalc push --changed',
});

const folder = path.join(cwd, outDir);

if (!(await pathExists(folder))) {
await fs.mkdir(folder);
}

const pkg = await loadPkg({ cwd, logger });
const pkgJson = await validatePkg({ pkg });

concurrently(['npm run watch']);

nodemon
.on('start', () => {
logger.info(
outdent`
Watching ${outDir} for changes to files with extensions: ${extensions}
To use this package in Strapi, in a separate shell run:
cd /path/to/strapi/project
Then run one of the commands below based on the package manager used in that project:
## yarn
${chalk.greenBright(`yarn dlx yalc add --link ${pkgJson.name} && yarn install`)}
## npm
${chalk.greenBright(
`npx yalc add ${pkgJson.name} && npx yalc link ${pkgJson.name} && npm install`
)}
`.trimStart()
);
})
.on('quit', () => {
process.exit();
})
.on('restart', (files) => {
logger.info('Found changes in files:', chalk.magentaBright(files));
logger.info('Pushing new yalc package...');
});
} catch (err) {
logger.error(
'There seems to be an unexpected error, try again with --debug for more information \n'
);
if (err instanceof Error && err.stack) {
console.log(
chalk.red(
boxen(err.stack, {
padding: 1,
align: 'left',
})
)
);
}
process.exit(1);
}
};

/**
* @internal
*/
const pathExists = async (path: string) => {
try {
await fs.access(path);
return true;
} catch (error) {
return false;
}
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
import type { StrapiCommand } from '../../../types';
import { runAction } from '../../../utils/helpers';
import action from './action';

/**
* `$ strapi plugin:watch:link`
*/
const command: StrapiCommand = ({ command, ctx }) => {
command
.command('plugin:watch:link')
.description('Recompiles your plugin automatically on changes and runs yalc push --publish')
.option('-d, --debug', 'Enable debugging mode with verbose logs', false)
.option('--silent', "Don't log anything", false)
.action((...args) => runAction('plugin:watch:link', action)(...args, ctx));
};

export default command;
2 changes: 2 additions & 0 deletions packages/core/strapi/src/commands/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import watchAdminCommand from './actions/watch-admin/command';

import buildPluginCommand from './actions/plugin/build-command/command';
import initPluginCommand from './actions/plugin/init/command';
import linkWatchPluginCommand from './actions/plugin/link-watch/command';
import watchPluginCommand from './actions/plugin/watch/command';
import verifyPluginCommand from './actions/plugin/verify/command';

Expand Down Expand Up @@ -66,6 +67,7 @@ const strapiCommands = {
*/
buildPluginCommand,
initPluginCommand,
linkWatchPluginCommand,
watchPluginCommand,
verifyPluginCommand,
} as const;
Expand Down
1 change: 1 addition & 0 deletions packages/core/strapi/src/commands/utils/pkg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ interface Export {
}

const packageJsonSchema = yup.object({
name: yup.string().required(),
exports: yup.lazy((value) =>
yup
.object(
Expand Down
Loading

0 comments on commit e1ede8c

Please sign in to comment.