@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.
- package/lib/commands/actions/plugin/build-command/action.js +137 -0
- package/lib/commands/actions/plugin/build-command/command.js +17 -0
- package/lib/commands/builders/packages.js +252 -0
- package/lib/commands/builders/tasks/dts.js +199 -0
- package/lib/commands/builders/tasks/index.js +29 -0
- package/lib/commands/builders/tasks/vite.js +144 -0
- package/lib/commands/index.js +1 -0
- package/lib/commands/utils/helpers.js +53 -1
- package/lib/commands/utils/logger.js +97 -0
- package/lib/commands/utils/pkg.js +421 -0
- package/lib/services/entity-service/types/params/filters/index.d.ts +9 -24
- package/lib/types/core/attributes/timestamp.d.ts +1 -1
- package/lib/types/core/strapi/index.d.ts +1 -1
- package/package.json +21 -16
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const fs = require('fs/promises');
|
|
4
|
+
const boxen = require('boxen');
|
|
5
|
+
const chalk = require('chalk');
|
|
6
|
+
const ora = require('ora');
|
|
7
|
+
const { createLogger } = require('../../../utils/logger');
|
|
8
|
+
const { notifyExperimentalCommand } = require('../../../utils/helpers');
|
|
9
|
+
const {
|
|
10
|
+
loadPkg,
|
|
11
|
+
validatePkg,
|
|
12
|
+
validateExportsOrdering,
|
|
13
|
+
getExportExtensionMap,
|
|
14
|
+
} = require('../../../utils/pkg');
|
|
15
|
+
const { createBuildContext, createBuildTasks } = require('../../../builders/packages');
|
|
16
|
+
const { buildTaskHandlers } = require('../../../builders/tasks');
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
*
|
|
20
|
+
* @param {object} args
|
|
21
|
+
* @param {boolean} args.force
|
|
22
|
+
* @param {boolean} args.debug
|
|
23
|
+
*/
|
|
24
|
+
module.exports = async ({ force, debug }) => {
|
|
25
|
+
const logger = createLogger({ debug, timestamp: false });
|
|
26
|
+
try {
|
|
27
|
+
/**
|
|
28
|
+
* Notify users this is an experimental command and get them to approve first
|
|
29
|
+
* this can be opted out by setting the argument --yes
|
|
30
|
+
*/
|
|
31
|
+
await notifyExperimentalCommand({ force });
|
|
32
|
+
|
|
33
|
+
const cwd = process.cwd();
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Load the closest package.json and then verify the structure against what we expect.
|
|
37
|
+
*/
|
|
38
|
+
const packageJsonLoader = ora('Verifying package.json \n').start();
|
|
39
|
+
|
|
40
|
+
const rawPkg = await loadPkg({ cwd, logger }).catch((err) => {
|
|
41
|
+
packageJsonLoader.fail();
|
|
42
|
+
logger.error(err.message);
|
|
43
|
+
logger.debug(`Path checked – ${cwd}`);
|
|
44
|
+
process.exit(1);
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
const validatedPkg = await validatePkg({
|
|
48
|
+
pkg: rawPkg,
|
|
49
|
+
}).catch((err) => {
|
|
50
|
+
packageJsonLoader.fail();
|
|
51
|
+
logger.error(err.message);
|
|
52
|
+
process.exit(1);
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Validate the exports of the package incl. the order of the
|
|
57
|
+
* exports within the exports map if applicable
|
|
58
|
+
*/
|
|
59
|
+
const packageJson = await validateExportsOrdering({ pkg: validatedPkg, logger }).catch(
|
|
60
|
+
(err) => {
|
|
61
|
+
packageJsonLoader.fail();
|
|
62
|
+
logger.error(err.message);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
);
|
|
66
|
+
|
|
67
|
+
packageJsonLoader.succeed('Verified package.json');
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* We create tasks based on the exports of the package.json
|
|
71
|
+
* their handlers are then ran in the order of the exports map
|
|
72
|
+
* and results are logged to see gradual progress.
|
|
73
|
+
*/
|
|
74
|
+
|
|
75
|
+
const buildContextLoader = ora('Creating build context \n').start();
|
|
76
|
+
|
|
77
|
+
const extMap = getExportExtensionMap();
|
|
78
|
+
|
|
79
|
+
const ctx = await createBuildContext({
|
|
80
|
+
cwd,
|
|
81
|
+
extMap,
|
|
82
|
+
logger,
|
|
83
|
+
pkg: packageJson,
|
|
84
|
+
}).catch((err) => {
|
|
85
|
+
buildContextLoader.fail();
|
|
86
|
+
logger.error(err.message);
|
|
87
|
+
process.exit(1);
|
|
88
|
+
});
|
|
89
|
+
|
|
90
|
+
logger.debug('Build context: \n', ctx);
|
|
91
|
+
|
|
92
|
+
const buildTasks = await createBuildTasks(ctx);
|
|
93
|
+
|
|
94
|
+
buildContextLoader.succeed('Created build context');
|
|
95
|
+
|
|
96
|
+
/**
|
|
97
|
+
* If the distPath already exists, clean it
|
|
98
|
+
*/
|
|
99
|
+
try {
|
|
100
|
+
logger.debug(`Cleaning dist folder: ${ctx.distPath}`);
|
|
101
|
+
await fs.rm(ctx.distPath, { recursive: true, force: true });
|
|
102
|
+
logger.debug('Cleaned dist folder');
|
|
103
|
+
} catch {
|
|
104
|
+
// do nothing, it will fail if the folder does not exist
|
|
105
|
+
logger.debug('There was no dist folder to clean');
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
for (const task of buildTasks) {
|
|
109
|
+
/**
|
|
110
|
+
* @type {import('../../../builders/tasks').TaskHandler<any>}
|
|
111
|
+
*/
|
|
112
|
+
const handler = buildTaskHandlers[task.type];
|
|
113
|
+
handler.print(ctx, task);
|
|
114
|
+
|
|
115
|
+
await handler.run(ctx, task).catch((err) => {
|
|
116
|
+
if (err instanceof Error) {
|
|
117
|
+
logger.error(err.message);
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
process.exit(1);
|
|
121
|
+
});
|
|
122
|
+
}
|
|
123
|
+
} catch (err) {
|
|
124
|
+
logger.error(
|
|
125
|
+
'There seems to be an unexpected error, try again with --debug for more information \n'
|
|
126
|
+
);
|
|
127
|
+
console.log(
|
|
128
|
+
chalk.red(
|
|
129
|
+
boxen(err.stack, {
|
|
130
|
+
padding: 1,
|
|
131
|
+
align: 'left',
|
|
132
|
+
})
|
|
133
|
+
)
|
|
134
|
+
);
|
|
135
|
+
process.exit(1);
|
|
136
|
+
}
|
|
137
|
+
};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { forceOption } = require('../../../utils/commander');
|
|
4
|
+
const { getLocalScript } = require('../../../utils/helpers');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* `$ strapi plugin:build`
|
|
8
|
+
* @param {import('../../../../types/core/commands').AddCommandOptions} options
|
|
9
|
+
*/
|
|
10
|
+
module.exports = ({ command }) => {
|
|
11
|
+
command
|
|
12
|
+
.command('plugin:build')
|
|
13
|
+
.description('Bundle your strapi plugin for publishing.')
|
|
14
|
+
.addOption(forceOption)
|
|
15
|
+
.option('-d, --debug', 'Enable debugging mode with verbose logs', false)
|
|
16
|
+
.action(getLocalScript('plugin/build-command'));
|
|
17
|
+
};
|
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const browserslistToEsbuild = require('browserslist-to-esbuild');
|
|
5
|
+
|
|
6
|
+
const { parseExports } = require('../utils/pkg');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @typedef {Object} BuildContextArgs
|
|
10
|
+
* @property {string} cwd
|
|
11
|
+
* @property {import('../utils/pkg').ExtMap} extMap
|
|
12
|
+
* @property {import('../utils/logger').Logger} logger
|
|
13
|
+
* @property {import('../utils/pkg').PackageJson} pkg
|
|
14
|
+
*/
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* @typedef {Object} Targets
|
|
18
|
+
* @property {string[]} node
|
|
19
|
+
* @property {string[]} web
|
|
20
|
+
* @property {string[]} *
|
|
21
|
+
*/
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* @typedef {Object} BuildContext
|
|
25
|
+
* @property {string} cwd
|
|
26
|
+
* @property {import('../utils/pkg').Export[]} exports
|
|
27
|
+
* @property {string[]} external
|
|
28
|
+
* @property {import('../utils/pkg').ExtMap} extMap
|
|
29
|
+
* @property {import('../utils/logger').Logger} logger
|
|
30
|
+
* @property {import('../utils/pkg').PackageJson} pkg
|
|
31
|
+
* @property {Targets} targets
|
|
32
|
+
*/
|
|
33
|
+
|
|
34
|
+
const DEFAULT_BROWSERS_LIST_CONFIG = [
|
|
35
|
+
'last 3 major versions',
|
|
36
|
+
'Firefox ESR',
|
|
37
|
+
'last 2 Opera versions',
|
|
38
|
+
'not dead',
|
|
39
|
+
'node 16.0.0',
|
|
40
|
+
];
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* @description Create a build context for the pipeline we're creating,
|
|
44
|
+
* this is shared among tasks so they all use the same settings for core pieces
|
|
45
|
+
* such as a target, distPath, externals etc.
|
|
46
|
+
*
|
|
47
|
+
* @type {(args: BuildContextArgs) => Promise<BuildContext>}
|
|
48
|
+
*/
|
|
49
|
+
const createBuildContext = async ({ cwd, extMap, logger, pkg }) => {
|
|
50
|
+
const targets = {
|
|
51
|
+
'*': browserslistToEsbuild(pkg.browserslist ?? DEFAULT_BROWSERS_LIST_CONFIG),
|
|
52
|
+
node: browserslistToEsbuild(['node 16.0.0']),
|
|
53
|
+
web: ['esnext'],
|
|
54
|
+
};
|
|
55
|
+
|
|
56
|
+
const exports = parseExports({ extMap, pkg }).reduce((acc, x) => {
|
|
57
|
+
const { _path: exportPath, ...exportEntry } = x;
|
|
58
|
+
|
|
59
|
+
return { ...acc, [exportPath]: exportEntry };
|
|
60
|
+
}, {});
|
|
61
|
+
|
|
62
|
+
const external = [
|
|
63
|
+
...(pkg.dependencies ? Object.keys(pkg.dependencies) : []),
|
|
64
|
+
...(pkg.peerDependencies ? Object.keys(pkg.peerDependencies) : []),
|
|
65
|
+
];
|
|
66
|
+
|
|
67
|
+
const outputPaths = Object.values(exports)
|
|
68
|
+
.flatMap((exportEntry) => {
|
|
69
|
+
return [exportEntry.import, exportEntry.require].filter(Boolean);
|
|
70
|
+
})
|
|
71
|
+
.map((p) => path.resolve(cwd, p));
|
|
72
|
+
|
|
73
|
+
const distPath = findCommonDirPath(outputPaths);
|
|
74
|
+
|
|
75
|
+
if (distPath === cwd) {
|
|
76
|
+
throw new Error(
|
|
77
|
+
'all output files must share a common parent directory which is not the root package directory'
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
if (!distPath) {
|
|
82
|
+
throw new Error("could not detect 'dist' path");
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
return {
|
|
86
|
+
logger,
|
|
87
|
+
cwd,
|
|
88
|
+
pkg,
|
|
89
|
+
exports,
|
|
90
|
+
external,
|
|
91
|
+
distPath,
|
|
92
|
+
targets,
|
|
93
|
+
extMap,
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
/**
|
|
98
|
+
* @type {(containerPath: string, itemPath: string) => boolean}
|
|
99
|
+
*/
|
|
100
|
+
const pathContains = (containerPath, itemPath) => {
|
|
101
|
+
return !path.relative(containerPath, itemPath).startsWith('..');
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
/**
|
|
105
|
+
* @type {(filePaths: string[]) => string | undefined}
|
|
106
|
+
*/
|
|
107
|
+
const findCommonDirPath = (filePaths) => {
|
|
108
|
+
/**
|
|
109
|
+
* @type {string | undefined}
|
|
110
|
+
*/
|
|
111
|
+
let commonPath;
|
|
112
|
+
|
|
113
|
+
for (const filePath of filePaths) {
|
|
114
|
+
let dirPath = path.dirname(filePath);
|
|
115
|
+
|
|
116
|
+
if (!commonPath) {
|
|
117
|
+
commonPath = dirPath;
|
|
118
|
+
// eslint-disable-next-line no-continue
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
while (dirPath !== commonPath) {
|
|
123
|
+
dirPath = path.dirname(dirPath);
|
|
124
|
+
|
|
125
|
+
if (dirPath === commonPath) {
|
|
126
|
+
break;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (pathContains(dirPath, commonPath)) {
|
|
130
|
+
commonPath = dirPath;
|
|
131
|
+
break;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
if (dirPath === '.') return undefined;
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return commonPath;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* @typedef {import('./tasks/vite').ViteTask | import('./tasks/dts').DtsTask} BuildTask
|
|
143
|
+
*/
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* @description Create the build tasks for the pipeline, this
|
|
147
|
+
* comes from the exports map we've created in the build context.
|
|
148
|
+
* But handles each export line uniquely with space to add more
|
|
149
|
+
* as the standard develops.
|
|
150
|
+
*
|
|
151
|
+
* @type {(args: BuildContext) => Promise<BuildTask[]>}
|
|
152
|
+
*/
|
|
153
|
+
const createBuildTasks = async (ctx) => {
|
|
154
|
+
/**
|
|
155
|
+
* @type {BuildTask[]}
|
|
156
|
+
*/
|
|
157
|
+
const tasks = [];
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* @type {import('./tasks/dts').DtsTask}
|
|
161
|
+
*/
|
|
162
|
+
const dtsTask = {
|
|
163
|
+
type: 'build:dts',
|
|
164
|
+
entries: [],
|
|
165
|
+
};
|
|
166
|
+
|
|
167
|
+
/**
|
|
168
|
+
* @type {Record<string, import('./tasks/vite').ViteTask>}
|
|
169
|
+
*/
|
|
170
|
+
const viteTasks = {};
|
|
171
|
+
|
|
172
|
+
const createViteTask = (format, runtime, { output, ...restEntry }) => {
|
|
173
|
+
const buildId = `${format}:${output}`;
|
|
174
|
+
|
|
175
|
+
if (viteTasks[buildId]) {
|
|
176
|
+
viteTasks[buildId].entries.push(restEntry);
|
|
177
|
+
|
|
178
|
+
if (output !== viteTasks[buildId].output) {
|
|
179
|
+
ctx.logger.warn(
|
|
180
|
+
'Multiple entries with different outputs for the same format are not supported. The first output will be used.'
|
|
181
|
+
);
|
|
182
|
+
}
|
|
183
|
+
} else {
|
|
184
|
+
viteTasks[buildId] = {
|
|
185
|
+
type: 'build:js',
|
|
186
|
+
format,
|
|
187
|
+
output,
|
|
188
|
+
runtime,
|
|
189
|
+
entries: [restEntry],
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
};
|
|
193
|
+
|
|
194
|
+
const exps = Object.entries(ctx.exports).map(([exportPath, exportEntry]) => ({
|
|
195
|
+
...exportEntry,
|
|
196
|
+
_path: exportPath,
|
|
197
|
+
}));
|
|
198
|
+
|
|
199
|
+
for (const exp of exps) {
|
|
200
|
+
if (exp.types) {
|
|
201
|
+
const importId = path.join(ctx.pkg.name, exp._path);
|
|
202
|
+
|
|
203
|
+
dtsTask.entries.push({
|
|
204
|
+
importId,
|
|
205
|
+
exportPath: exp._path,
|
|
206
|
+
sourcePath: exp.source,
|
|
207
|
+
targetPath: exp.types,
|
|
208
|
+
});
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
/**
|
|
212
|
+
* @type {keyof Target}
|
|
213
|
+
*/
|
|
214
|
+
// eslint-disable-next-line no-nested-ternary
|
|
215
|
+
const runtime = exp._path.includes('strapi-admin')
|
|
216
|
+
? 'web'
|
|
217
|
+
: exp._path.includes('strapi-server')
|
|
218
|
+
? 'node'
|
|
219
|
+
: '*';
|
|
220
|
+
|
|
221
|
+
if (exp.require) {
|
|
222
|
+
/**
|
|
223
|
+
* register CJS task
|
|
224
|
+
*/
|
|
225
|
+
createViteTask('cjs', runtime, {
|
|
226
|
+
path: exp._path,
|
|
227
|
+
entry: exp.source,
|
|
228
|
+
output: exp.require,
|
|
229
|
+
});
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
if (exp.import) {
|
|
233
|
+
/**
|
|
234
|
+
* register ESM task
|
|
235
|
+
*/
|
|
236
|
+
createViteTask('es', runtime, {
|
|
237
|
+
path: exp._path,
|
|
238
|
+
entry: exp.source,
|
|
239
|
+
output: exp.import,
|
|
240
|
+
});
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
tasks.push(dtsTask, ...Object.values(viteTasks));
|
|
245
|
+
|
|
246
|
+
return tasks;
|
|
247
|
+
};
|
|
248
|
+
|
|
249
|
+
module.exports = {
|
|
250
|
+
createBuildContext,
|
|
251
|
+
createBuildTasks,
|
|
252
|
+
};
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const path = require('path');
|
|
4
|
+
const chalk = require('chalk');
|
|
5
|
+
const ora = require('ora');
|
|
6
|
+
const ts = require('typescript');
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* @description Load a tsconfig.json file and return the parsed config
|
|
10
|
+
*
|
|
11
|
+
* @internal
|
|
12
|
+
*
|
|
13
|
+
* @type {(args: { cwd: string; path: string }) => Promise<ts.ParsedCommandLine>)}
|
|
14
|
+
*/
|
|
15
|
+
const loadTsConfig = async ({ cwd, path }) => {
|
|
16
|
+
const configPath = ts.findConfigFile(cwd, ts.sys.fileExists, path);
|
|
17
|
+
|
|
18
|
+
if (!configPath) {
|
|
19
|
+
throw new TSConfigNotFoundError(`could not find a valid '${path}'`);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
const configFile = ts.readConfigFile(configPath, ts.sys.readFile);
|
|
23
|
+
|
|
24
|
+
return ts.parseJsonConfigFileContent(configFile.config, ts.sys, cwd);
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
class TSConfigNotFoundError extends Error {
|
|
28
|
+
// eslint-disable-next-line no-useless-constructor
|
|
29
|
+
constructor(message, options) {
|
|
30
|
+
super(message, options);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
get code() {
|
|
34
|
+
return 'TS_CONFIG_NOT_FOUND';
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
/**
|
|
39
|
+
* @description
|
|
40
|
+
*
|
|
41
|
+
* @internal
|
|
42
|
+
*
|
|
43
|
+
* @type {(args: { cwd: string; logger: import('../../utils/logger').Logger; outDir: string; tsconfig: ts.ParsedCommandLine }) => Promise<void>}
|
|
44
|
+
*/
|
|
45
|
+
const buildTypes = ({ cwd, logger, outDir, tsconfig }) => {
|
|
46
|
+
const compilerOptions = {
|
|
47
|
+
...tsconfig.options,
|
|
48
|
+
declaration: true,
|
|
49
|
+
declarationDir: outDir,
|
|
50
|
+
emitDeclarationOnly: true,
|
|
51
|
+
noEmit: false,
|
|
52
|
+
outDir,
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
const program = ts.createProgram(tsconfig.fileNames, compilerOptions);
|
|
56
|
+
|
|
57
|
+
const emitResult = program.emit();
|
|
58
|
+
|
|
59
|
+
const allDiagnostics = ts.getPreEmitDiagnostics(program).concat(emitResult.diagnostics);
|
|
60
|
+
|
|
61
|
+
for (const diagnostic of allDiagnostics) {
|
|
62
|
+
if (diagnostic.file && diagnostic.start) {
|
|
63
|
+
const { line, character } = ts.getLineAndCharacterOfPosition(
|
|
64
|
+
diagnostic.file,
|
|
65
|
+
diagnostic.start
|
|
66
|
+
);
|
|
67
|
+
const message = ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n');
|
|
68
|
+
|
|
69
|
+
const file = path.relative(cwd, diagnostic.file.fileName);
|
|
70
|
+
|
|
71
|
+
const output = [
|
|
72
|
+
`${chalk.cyan(file)}:${chalk.cyan(line + 1)}:${chalk.cyan(character + 1)} - `,
|
|
73
|
+
`${chalk.gray(`TS${diagnostic.code}:`)} ${message}`,
|
|
74
|
+
].join('');
|
|
75
|
+
|
|
76
|
+
if (diagnostic.category === ts.DiagnosticCategory.Error) {
|
|
77
|
+
logger.error(output);
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
if (diagnostic.category === ts.DiagnosticCategory.Warning) {
|
|
81
|
+
logger.warn(output);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (diagnostic.category === ts.DiagnosticCategory.Message) {
|
|
85
|
+
logger.info(output);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
if (diagnostic.category === ts.DiagnosticCategory.Suggestion) {
|
|
89
|
+
logger.info(output);
|
|
90
|
+
}
|
|
91
|
+
} else {
|
|
92
|
+
logger.info(ts.flattenDiagnosticMessageText(diagnostic.messageText, '\n'));
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
if (emitResult.emitSkipped) {
|
|
97
|
+
const errors = allDiagnostics.filter((diag) => diag.category === ts.DiagnosticCategory.Error);
|
|
98
|
+
|
|
99
|
+
if (errors.length) {
|
|
100
|
+
throw new Error('Failed to compile TypeScript definitions');
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
};
|
|
104
|
+
|
|
105
|
+
/**
|
|
106
|
+
* @typedef {Object} DtsTaskEntry
|
|
107
|
+
* @property {string} exportPath
|
|
108
|
+
* @property {string} sourcePath
|
|
109
|
+
* @property {string} targetPath
|
|
110
|
+
*/
|
|
111
|
+
|
|
112
|
+
/**
|
|
113
|
+
* @typedef {Object} DtsTask
|
|
114
|
+
* @property {"build:dts"} type
|
|
115
|
+
* @property {DtsTaskEntry[]} entries
|
|
116
|
+
*/
|
|
117
|
+
|
|
118
|
+
/**
|
|
119
|
+
* @type {import('./index').TaskHandler<DtsTask>}
|
|
120
|
+
*/
|
|
121
|
+
const dtsTask = {
|
|
122
|
+
_spinner: null,
|
|
123
|
+
print(ctx, task) {
|
|
124
|
+
const entries = [
|
|
125
|
+
' entries:',
|
|
126
|
+
...task.entries.map((entry) =>
|
|
127
|
+
[
|
|
128
|
+
` – `,
|
|
129
|
+
chalk.green(`${entry.importId} `),
|
|
130
|
+
`${chalk.cyan(entry.sourcePath)} ${chalk.gray('→')} ${chalk.cyan(entry.targetPath)}`,
|
|
131
|
+
].join('')
|
|
132
|
+
),
|
|
133
|
+
'',
|
|
134
|
+
];
|
|
135
|
+
|
|
136
|
+
this._spinner = ora(`Building type files:\n`).start();
|
|
137
|
+
|
|
138
|
+
ctx.logger.log([...entries].join('\n'));
|
|
139
|
+
},
|
|
140
|
+
async run(ctx, task) {
|
|
141
|
+
try {
|
|
142
|
+
await Promise.all(
|
|
143
|
+
task.entries.map(async (entry) => {
|
|
144
|
+
const config = await loadTsConfig({
|
|
145
|
+
/**
|
|
146
|
+
* TODO: this will not scale and assumes all project sourcePaths are `src/index.ts`
|
|
147
|
+
* so we can go back to the "root" of the project...
|
|
148
|
+
*/
|
|
149
|
+
cwd: path.join(ctx.cwd, entry.sourcePath, '..', '..'),
|
|
150
|
+
path: 'tsconfig.build.json',
|
|
151
|
+
}).catch((err) => {
|
|
152
|
+
if (err instanceof TSConfigNotFoundError) {
|
|
153
|
+
return undefined;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
throw err;
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
if (config) {
|
|
160
|
+
ctx.logger.debug(`TS config for '${entry.sourcePath}': \n`, config);
|
|
161
|
+
} else {
|
|
162
|
+
ctx.logger.warn(
|
|
163
|
+
`You've added a types entry but no tsconfig.json was found for ${entry.targetPath}. Skipping...`
|
|
164
|
+
);
|
|
165
|
+
|
|
166
|
+
return;
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const { outDir } = config.raw.compilerOptions;
|
|
170
|
+
|
|
171
|
+
if (!outDir) {
|
|
172
|
+
throw new Error("tsconfig.json is missing 'compilerOptions.outDir'");
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
await buildTypes({
|
|
176
|
+
cwd: ctx.cwd,
|
|
177
|
+
logger: ctx.logger,
|
|
178
|
+
outDir: path.relative(ctx.cwd, outDir),
|
|
179
|
+
tsconfig: config,
|
|
180
|
+
});
|
|
181
|
+
})
|
|
182
|
+
);
|
|
183
|
+
|
|
184
|
+
await this.success(ctx, task);
|
|
185
|
+
} catch (err) {
|
|
186
|
+
this.fail(ctx, task, err);
|
|
187
|
+
}
|
|
188
|
+
},
|
|
189
|
+
async success() {
|
|
190
|
+
this._spinner.succeed('Built type files');
|
|
191
|
+
},
|
|
192
|
+
async fail(ctx, task, err) {
|
|
193
|
+
this._spinner.fail('Failed to build type files');
|
|
194
|
+
|
|
195
|
+
throw err;
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
module.exports = { dtsTask };
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
const { dtsTask } = require('./dts');
|
|
4
|
+
const { viteTask } = require('./vite');
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* @template Task
|
|
8
|
+
* @param {Task}
|
|
9
|
+
* @returns {Task}
|
|
10
|
+
*
|
|
11
|
+
* @typedef {Object} TaskHandler
|
|
12
|
+
* @property {(ctx: import("../packages").BuildContext, task: Task) => import('ora').Ora} print
|
|
13
|
+
* @property {(ctx: import("../packages").BuildContext, task: Task) => Promise<void>} run
|
|
14
|
+
* @property {(ctx: import("../packages").BuildContext, task: Task) => Promise<void>} success
|
|
15
|
+
* @property {(ctx: import("../packages").BuildContext, task: Task, err: unknown) => Promise<void>} fail
|
|
16
|
+
* @property {import('ora').Ora | null} _spinner
|
|
17
|
+
*/
|
|
18
|
+
|
|
19
|
+
/**
|
|
20
|
+
* @type {{ "build:js": TaskHandler<import("./vite").ViteTask>; "build:dts": TaskHandler<import("./dts").DtsTask>; }}}
|
|
21
|
+
*/
|
|
22
|
+
const buildTaskHandlers = {
|
|
23
|
+
'build:js': viteTask,
|
|
24
|
+
'build:dts': dtsTask,
|
|
25
|
+
};
|
|
26
|
+
|
|
27
|
+
module.exports = {
|
|
28
|
+
buildTaskHandlers,
|
|
29
|
+
};
|