@strapi/strapi 4.13.3 → 4.14.0-alpha.0

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.
@@ -0,0 +1,144 @@
1
+ 'use strict';
2
+
3
+ const path = require('path');
4
+ const { build, createLogger } = require('vite');
5
+ const react = require('@vitejs/plugin-react');
6
+ const ora = require('ora');
7
+ const chalk = require('chalk');
8
+
9
+ /**
10
+ * @internal
11
+ *
12
+ * @type {(ctx: import('../packages').BuildContext, task: ViteTask) => import('vite').UserConfig}
13
+ */
14
+ const resolveViteConfig = (ctx, task) => {
15
+ const { cwd, distPath, targets, external, extMap, pkg } = ctx;
16
+ const { entries, format, output, runtime } = task;
17
+ const outputExt = extMap[pkg.type || 'commonjs'][format];
18
+ const outDir = path.relative(cwd, distPath);
19
+
20
+ const customLogger = createLogger();
21
+ customLogger.warn = (msg) => ctx.logger.warn(msg);
22
+ customLogger.warnOnce = (msg) => ctx.logger.warn(msg);
23
+ customLogger.error = (msg) => ctx.logger.error(msg);
24
+
25
+ /**
26
+ * @type {import('vite').InlineConfig}
27
+ */
28
+ const config = {
29
+ configFile: false,
30
+ root: cwd,
31
+ mode: 'production',
32
+ logLevel: 'warn',
33
+ clearScreen: false,
34
+ customLogger,
35
+ build: {
36
+ sourcemap: true,
37
+ /**
38
+ * The task runner will clear this for us
39
+ */
40
+ emptyOutDir: false,
41
+ target: targets[runtime],
42
+ outDir,
43
+ lib: {
44
+ entry: entries.map((e) => e.entry),
45
+ formats: [format],
46
+ /**
47
+ * this enforces the file name to match what the output we've
48
+ * determined from the package.json exports.
49
+ */
50
+ fileName() {
51
+ return `${path.relative(outDir, output).replace(/\.[^/.]+$/, '')}${outputExt}`;
52
+ },
53
+ },
54
+ rollupOptions: {
55
+ external,
56
+ output: {
57
+ chunkFileNames() {
58
+ const parts = outputExt.split('.');
59
+
60
+ if (parts.length === 3) {
61
+ return `_chunks/[name]-[hash].${parts[2]}`;
62
+ }
63
+
64
+ return `_chunks/[name]-[hash]${outputExt}`;
65
+ },
66
+ },
67
+ },
68
+ },
69
+ /**
70
+ * We _could_ omit this, but we'd need to introduce the
71
+ * concept of a custom config for the scripts straight away
72
+ *
73
+ * and since this is isolated to the Strapi CLI, we can make
74
+ * some assumptions and add some weight until we move it outside.
75
+ */
76
+ plugins: runtime === 'node' ? [] : [react()],
77
+ };
78
+
79
+ return config;
80
+ };
81
+
82
+ /**
83
+ * @typedef {Object} ViteTaskEntry
84
+ * @property {string} path
85
+ * @property {string} entry
86
+ */
87
+
88
+ /**
89
+ * @typedef {Object} ViteTask
90
+ * @property {"build:js"} type
91
+ * @property {ViteTaskEntry[]} entries
92
+ * @property {string} format
93
+ * @property {string} output
94
+ * @property {keyof import('../packages').Targets} runtime
95
+ */
96
+
97
+ /**
98
+ * @type {import('./index').TaskHandler<ViteTask>}
99
+ */
100
+ const viteTask = {
101
+ _spinner: null,
102
+ print(ctx, task) {
103
+ const targetLines = [
104
+ ' target:',
105
+ ...ctx.targets[task.runtime].map((t) => chalk.cyan(` - ${t}`)),
106
+ ];
107
+ const entries = [
108
+ ' entries:',
109
+ ...task.entries.map((entry) =>
110
+ [
111
+ ` – `,
112
+ chalk.green(`${path.join(ctx.pkg.name, entry.path)}: `),
113
+ `${chalk.cyan(entry.entry)} ${chalk.gray('→')} ${chalk.cyan(task.output)}`,
114
+ ].join('')
115
+ ),
116
+ ];
117
+
118
+ this._spinner = ora(`Building javascript files:\n`).start();
119
+
120
+ ctx.logger.log([` format: ${task.format}`, ...targetLines, ...entries].join('\n'));
121
+ },
122
+ async run(ctx, task) {
123
+ try {
124
+ const config = resolveViteConfig(ctx, task);
125
+ ctx.logger.debug('Vite config: \n', config);
126
+ await build(config);
127
+ await this.success(ctx, task);
128
+ } catch (err) {
129
+ this.fail(ctx, task, err);
130
+ }
131
+ },
132
+ async success() {
133
+ this._spinner.succeed('Built javascript files');
134
+ },
135
+ async fail(ctx, task, err) {
136
+ this._spinner.fail('Failed to build javascript files');
137
+
138
+ throw err;
139
+ },
140
+ };
141
+
142
+ module.exports = {
143
+ viteTask,
144
+ };
@@ -20,6 +20,7 @@ const strapiCommands = {
20
20
  install: require('./actions/install/command'),
21
21
  'middlewares/list': require('./actions/middlewares/list/command'),
22
22
  new: require('./actions/new/command'),
23
+ 'plugin/build': require('./actions/plugin/build-command/command'),
23
24
  'policies/list': require('./actions/policies/list/command'),
24
25
  report: require('./actions/report/command'),
25
26
  'routes/list': require('./actions/routes/list/command'),
@@ -8,6 +8,9 @@ const { yellow, red, green } = require('chalk');
8
8
  const { isString, isArray } = require('lodash/fp');
9
9
  const resolveCwd = require('resolve-cwd');
10
10
  const { has } = require('lodash/fp');
11
+ const { prompt } = require('inquirer');
12
+ const boxen = require('boxen');
13
+ const chalk = require('chalk');
11
14
 
12
15
  const bytesPerKb = 1024;
13
16
  const sizes = ['B ', 'KB', 'MB', 'GB', 'TB', 'PB'];
@@ -121,7 +124,10 @@ const assertCwdContainsStrapiProject = (name) => {
121
124
 
122
125
  try {
123
126
  const pkgJSON = require(`${process.cwd()}/package.json`);
124
- if (!has('dependencies.@strapi/strapi', pkgJSON)) {
127
+ if (
128
+ !has('dependencies.@strapi/strapi', pkgJSON) &&
129
+ !has('devDependencies.@strapi/strapi', pkgJSON)
130
+ ) {
125
131
  logErrorAndExit(name);
126
132
  }
127
133
  } catch (err) {
@@ -156,6 +162,51 @@ const getLocalScript =
156
162
  });
157
163
  };
158
164
 
165
+ /**
166
+ * @description Notify users this is an experimental command and get them to approve first
167
+ * this can be opted out by passing `yes` as a property of the args object.
168
+ *
169
+ * @type {(args?: { force?: boolean }) => Promise<void>}
170
+ *
171
+ * @example
172
+ * ```ts
173
+ * const { notifyExperimentalCommand } = require('../utils/helpers');
174
+ *
175
+ * const myCommand = async ({ force }) => {
176
+ * await notifyExperimentalCommand({ force });
177
+ * }
178
+ * ```
179
+ */
180
+ const notifyExperimentalCommand = async ({ force } = {}) => {
181
+ console.log(
182
+ boxen(
183
+ `The ${chalk.bold(
184
+ chalk.underline('plugin:build')
185
+ )} command is considered experimental, use at your own risk.`,
186
+ {
187
+ title: 'Warning',
188
+ padding: 1,
189
+ margin: 1,
190
+ align: 'center',
191
+ borderColor: 'yellow',
192
+ borderStyle: 'bold',
193
+ }
194
+ )
195
+ );
196
+
197
+ if (!force) {
198
+ const { confirmed } = await prompt({
199
+ type: 'confirm',
200
+ name: 'confirmed',
201
+ message: 'Do you want to continue?',
202
+ });
203
+
204
+ if (!confirmed) {
205
+ process.exit(0);
206
+ }
207
+ }
208
+ };
209
+
159
210
  module.exports = {
160
211
  exitWith,
161
212
  assertUrlHasProtocol,
@@ -163,4 +214,5 @@ module.exports = {
163
214
  readableBytes,
164
215
  getLocalScript,
165
216
  assertCwdContainsStrapiProject,
217
+ notifyExperimentalCommand,
166
218
  };
@@ -0,0 +1,97 @@
1
+ 'use strict';
2
+
3
+ const chalk = require('chalk');
4
+
5
+ /**
6
+ * @typedef {{ silent?: boolean; debug?: boolean; timestamp?: boolean; }} LoggerOptions
7
+ */
8
+
9
+ /**
10
+ * @typedef {object} Logger
11
+ * @property {number} warnings
12
+ * @property {number} errors
13
+ * @property {(...args: any[]) => void} debug
14
+ * @property {(...args: any[]) => void} info
15
+ * @property {(...args: any[]) => void} warn
16
+ * @property {(...args: any[]) => void} error
17
+ * @property {(...args: any[]) => void} log
18
+ */
19
+
20
+ /**
21
+ * @type {(options: LoggerOptions) => Logger}
22
+ */
23
+ const createLogger = (options = {}) => {
24
+ const { silent = false, debug = false, timestamp = true } = options;
25
+
26
+ const state = { errors: 0, warning: 0 };
27
+
28
+ return {
29
+ get warnings() {
30
+ return state.warning;
31
+ },
32
+
33
+ get errors() {
34
+ return state.errors;
35
+ },
36
+
37
+ debug(...args) {
38
+ if (silent || !debug) {
39
+ return;
40
+ }
41
+
42
+ console.log(
43
+ chalk.cyan(`[DEBUG]${timestamp ? `\t[${new Date().toISOString()}]` : ''}`),
44
+ ...args
45
+ );
46
+ },
47
+
48
+ info(...args) {
49
+ if (silent) {
50
+ return;
51
+ }
52
+
53
+ console.info(
54
+ chalk.blue(`[INFO]${timestamp ? `\t[${new Date().toISOString()}]` : ''}`),
55
+ ...args
56
+ );
57
+ },
58
+
59
+ log(...args) {
60
+ if (silent) {
61
+ return;
62
+ }
63
+
64
+ console.info(chalk.blue(`${timestamp ? `\t[${new Date().toISOString()}]` : ''}`), ...args);
65
+ },
66
+
67
+ warn(...args) {
68
+ state.warning += 1;
69
+
70
+ if (silent) {
71
+ return;
72
+ }
73
+
74
+ console.warn(
75
+ chalk.yellow(`[WARN]${timestamp ? `\t[${new Date().toISOString()}]` : ''}`),
76
+ ...args
77
+ );
78
+ },
79
+
80
+ error(...args) {
81
+ state.errors += 1;
82
+
83
+ if (silent) {
84
+ return;
85
+ }
86
+
87
+ console.error(
88
+ chalk.red(`[ERROR]${timestamp ? `\t[${new Date().toISOString()}]` : ''}`),
89
+ ...args
90
+ );
91
+ },
92
+ };
93
+ };
94
+
95
+ module.exports = {
96
+ createLogger,
97
+ };