mirror of
https://github.com/strapi/strapi.git
synced 2025-09-01 12:53:03 +00:00
feat(pack-up): enable config via nodeAPI & allow bundles to have own tsconfig (#18440)
* feat: add ability to pass config & have tsconfig per bundle * feat: use node:module builtinModules for node stuff * chore: remove builtins from externals
This commit is contained in:
parent
8632eeaf18
commit
25d1ceaa44
@ -10,6 +10,5 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
dist: './dist',
|
dist: './dist',
|
||||||
externals: ['node:fs', 'node:path'],
|
|
||||||
runtime: 'node',
|
runtime: 'node',
|
||||||
});
|
});
|
||||||
|
@ -10,6 +10,5 @@ export default defineConfig({
|
|||||||
},
|
},
|
||||||
],
|
],
|
||||||
dist: './dist',
|
dist: './dist',
|
||||||
externals: ['child_process', 'node:fs', 'node:path', 'os', 'path'],
|
|
||||||
runtime: 'node',
|
runtime: 'node',
|
||||||
});
|
});
|
||||||
|
@ -3,5 +3,4 @@ import { defineConfig } from '@strapi/pack-up';
|
|||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
runtime: 'node',
|
runtime: 'node',
|
||||||
externals: ['crypto', 'http', 'https', 'os', 'path', 'stream', 'zlib'],
|
|
||||||
});
|
});
|
||||||
|
@ -3,13 +3,6 @@ import { defineConfig } from '@strapi/pack-up';
|
|||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
externals: [
|
externals: [
|
||||||
'crypto',
|
|
||||||
'node:async_hooks',
|
|
||||||
'node:path',
|
|
||||||
'path',
|
|
||||||
'stream',
|
|
||||||
'timers',
|
|
||||||
'tty',
|
|
||||||
/**
|
/**
|
||||||
* Knex dependencies, if we don't mark these as external
|
* Knex dependencies, if we don't mark these as external
|
||||||
* they will be included in the bundle which means they
|
* they will be included in the bundle which means they
|
||||||
|
@ -2,6 +2,5 @@
|
|||||||
import { defineConfig } from '@strapi/pack-up';
|
import { defineConfig } from '@strapi/pack-up';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
externals: ['node:stream'],
|
|
||||||
runtime: 'node',
|
runtime: 'node',
|
||||||
});
|
});
|
||||||
|
@ -2,7 +2,6 @@
|
|||||||
import { defineConfig } from '@strapi/pack-up';
|
import { defineConfig } from '@strapi/pack-up';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
externals: ['crypto', 'fs', 'node:fs', 'node:os', 'node:path', 'node:readline', 'os', 'path'],
|
|
||||||
preserveModules: true,
|
preserveModules: true,
|
||||||
runtime: 'node',
|
runtime: 'node',
|
||||||
});
|
});
|
||||||
|
@ -9,6 +9,5 @@ export default defineConfig({
|
|||||||
import: './dist/plopfile.mjs',
|
import: './dist/plopfile.mjs',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
externals: ['node:path', 'path'],
|
|
||||||
runtime: 'node',
|
runtime: 'node',
|
||||||
});
|
});
|
||||||
|
@ -2,6 +2,5 @@
|
|||||||
import { defineConfig } from '@strapi/pack-up';
|
import { defineConfig } from '@strapi/pack-up';
|
||||||
|
|
||||||
export default defineConfig({
|
export default defineConfig({
|
||||||
externals: ['stream', 'fs', 'path'],
|
|
||||||
runtime: 'node',
|
runtime: 'node',
|
||||||
});
|
});
|
||||||
|
@ -10,7 +10,7 @@ export default defineConfig({
|
|||||||
require: './dist/cli.js',
|
require: './dist/cli.js',
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
externals: ['fs', 'path', 'child_process', 'fs/promises', 'module', 'os'],
|
externals: ['node:module'],
|
||||||
runtime: 'node',
|
runtime: 'node',
|
||||||
minify: false,
|
minify: false,
|
||||||
sourcemap: true,
|
sourcemap: true,
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { build as nodeBuild, BuildOptions } from '../../node/build';
|
import { build as nodeBuild, BuildCLIOptions } from '../../node/build';
|
||||||
import { handleError } from '../errors';
|
import { handleError } from '../errors';
|
||||||
|
|
||||||
export const build = async (options: Omit<BuildOptions, 'cwd'>) => {
|
export const build = async (options: BuildCLIOptions) => {
|
||||||
try {
|
try {
|
||||||
await nodeBuild(options);
|
await nodeBuild(options);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import { WatchOptions, watch as nodeWatch } from '../../node/watch';
|
import { WatchCLIOptions, watch as nodeWatch } from '../../node/watch';
|
||||||
import { handleError } from '../errors';
|
import { handleError } from '../errors';
|
||||||
|
|
||||||
export const watch = async (options: WatchOptions) => {
|
export const watch = async (options: WatchCLIOptions) => {
|
||||||
try {
|
try {
|
||||||
await nodeWatch(options);
|
await nodeWatch(options);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@ -4,7 +4,13 @@ export * from './node/check';
|
|||||||
export * from './node/init';
|
export * from './node/init';
|
||||||
|
|
||||||
export { defineConfig } from './node/core/config';
|
export { defineConfig } from './node/core/config';
|
||||||
export type { Config } from './node/core/config';
|
export type {
|
||||||
|
Config,
|
||||||
|
ConfigBundle,
|
||||||
|
ConfigOptions,
|
||||||
|
ConfigProperty,
|
||||||
|
ConfigPropertyResolver,
|
||||||
|
} from './node/core/config';
|
||||||
|
|
||||||
export { defineTemplate, definePackageFeature, definePackageOption } from './node/templates/create';
|
export { defineTemplate, definePackageFeature, definePackageOption } from './node/templates/create';
|
||||||
export type {
|
export type {
|
||||||
|
@ -4,7 +4,7 @@ import os from 'os';
|
|||||||
|
|
||||||
import { CommonCLIOptions } from '../types';
|
import { CommonCLIOptions } from '../types';
|
||||||
|
|
||||||
import { loadConfig } from './core/config';
|
import { loadConfig, type Config } from './core/config';
|
||||||
import { isError } from './core/errors';
|
import { isError } from './core/errors';
|
||||||
import { getExportExtensionMap, validateExportsOrdering } from './core/exports';
|
import { getExportExtensionMap, validateExportsOrdering } from './core/exports';
|
||||||
import { createLogger } from './core/logger';
|
import { createLogger } from './core/logger';
|
||||||
@ -13,14 +13,34 @@ import { createBuildContext } from './createBuildContext';
|
|||||||
import { BuildTask, createBuildTasks } from './createTasks';
|
import { BuildTask, createBuildTasks } from './createTasks';
|
||||||
import { TaskHandler, taskHandlers } from './tasks';
|
import { TaskHandler, taskHandlers } from './tasks';
|
||||||
|
|
||||||
export interface BuildOptions extends CommonCLIOptions {
|
interface BuildCLIOptions extends CommonCLIOptions {
|
||||||
cwd?: string;
|
|
||||||
minify?: boolean;
|
minify?: boolean;
|
||||||
sourcemap?: boolean;
|
sourcemap?: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const build = async (opts: BuildOptions = {}) => {
|
interface BuildWithConfigFile extends BuildCLIOptions {
|
||||||
const { silent, debug, cwd = process.cwd(), ...configOptions } = opts;
|
configFile?: true;
|
||||||
|
config?: never;
|
||||||
|
cwd?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface BuildWithoutConfigFile extends BuildCLIOptions {
|
||||||
|
configFile: false;
|
||||||
|
config?: Config;
|
||||||
|
cwd?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type BuildOptions = BuildWithConfigFile | BuildWithoutConfigFile;
|
||||||
|
|
||||||
|
const build = async (opts: BuildOptions = {}) => {
|
||||||
|
const {
|
||||||
|
silent,
|
||||||
|
debug,
|
||||||
|
cwd = process.cwd(),
|
||||||
|
configFile = true,
|
||||||
|
config: providedConfig,
|
||||||
|
...configOptions
|
||||||
|
} = opts;
|
||||||
|
|
||||||
const logger = createLogger({ silent, debug });
|
const logger = createLogger({ silent, debug });
|
||||||
|
|
||||||
@ -66,13 +86,18 @@ export const build = async (opts: BuildOptions = {}) => {
|
|||||||
|
|
||||||
packageJsonLoader.succeed('Verified package.json');
|
packageJsonLoader.succeed('Verified package.json');
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If configFile is true – which is the default, atempt to load the config
|
||||||
|
* otherwise if it's explicitly false then we suspect there might be a config passed
|
||||||
|
* in the options, so we'll use that instead.
|
||||||
|
*/
|
||||||
|
const config = configFile ? await loadConfig({ cwd, logger }) : providedConfig;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We create tasks based on the exports of the package.json
|
* We create tasks based on the exports of the package.json
|
||||||
* their handlers are then ran in the order of the exports map
|
* their handlers are then ran in the order of the exports map
|
||||||
* and results are logged to see gradual progress.
|
* and results are logged to see gradual progress.
|
||||||
*/
|
*/
|
||||||
const config = await loadConfig({ cwd, logger });
|
|
||||||
|
|
||||||
const buildContextLoader = ora(`Creating build context ${os.EOL}`).start();
|
const buildContextLoader = ora(`Creating build context ${os.EOL}`).start();
|
||||||
|
|
||||||
const extMap = getExportExtensionMap();
|
const extMap = getExportExtensionMap();
|
||||||
@ -126,3 +151,6 @@ export const build = async (opts: BuildOptions = {}) => {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { build };
|
||||||
|
export type { BuildOptions, BuildCLIOptions, BuildWithConfigFile, BuildWithoutConfigFile };
|
||||||
|
@ -70,6 +70,7 @@ interface ConfigBundle {
|
|||||||
import?: string;
|
import?: string;
|
||||||
require?: string;
|
require?: string;
|
||||||
runtime?: Runtime;
|
runtime?: Runtime;
|
||||||
|
tsconfig?: string;
|
||||||
types?: string;
|
types?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -99,6 +100,12 @@ interface ConfigOptions {
|
|||||||
preserveModules?: boolean;
|
preserveModules?: boolean;
|
||||||
sourcemap?: boolean;
|
sourcemap?: boolean;
|
||||||
runtime?: Runtime;
|
runtime?: Runtime;
|
||||||
|
/**
|
||||||
|
* @description path to the tsconfig file to use for the bundle.
|
||||||
|
*
|
||||||
|
* @default tsconfig.build.json
|
||||||
|
*/
|
||||||
|
tsconfig?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -128,4 +135,4 @@ export function resolveConfigProperty<T>(prop: ConfigProperty<T> | undefined, in
|
|||||||
}
|
}
|
||||||
|
|
||||||
export { loadConfig, defineConfig, CONFIG_FILE_NAMES };
|
export { loadConfig, defineConfig, CONFIG_FILE_NAMES };
|
||||||
export type { Config };
|
export type { Config, ConfigOptions, ConfigBundle, ConfigPropertyResolver, ConfigProperty };
|
||||||
|
@ -65,7 +65,7 @@ const createBuildContext = async ({
|
|||||||
}: BuildContextArgs): Promise<BuildContext> => {
|
}: BuildContextArgs): Promise<BuildContext> => {
|
||||||
const tsConfig = loadTsConfig({
|
const tsConfig = loadTsConfig({
|
||||||
cwd,
|
cwd,
|
||||||
path: 'tsconfig.build.json',
|
path: resolveConfigProperty(config.tsconfig, 'tsconfig.build.json'),
|
||||||
logger,
|
logger,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
@ -143,6 +143,7 @@ const createTasks =
|
|||||||
exportPath: bundle.source,
|
exportPath: bundle.source,
|
||||||
sourcePath: bundle.source,
|
sourcePath: bundle.source,
|
||||||
targetPath: bundle.types,
|
targetPath: bundle.types,
|
||||||
|
tsconfig: bundle.tsconfig,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ import { Observable } from 'rxjs';
|
|||||||
import ts from 'typescript';
|
import ts from 'typescript';
|
||||||
|
|
||||||
import { isError } from '../../core/errors';
|
import { isError } from '../../core/errors';
|
||||||
|
import { loadTsConfig } from '../../core/tsconfig';
|
||||||
|
|
||||||
import { printDiagnostic } from './diagnostic';
|
import { printDiagnostic } from './diagnostic';
|
||||||
import { DtsBaseTask } from './types';
|
import { DtsBaseTask } from './types';
|
||||||
@ -33,7 +34,18 @@ const dtsBuildTask: TaskHandler<DtsBuildTask> = {
|
|||||||
return new Observable((subscriber) => {
|
return new Observable((subscriber) => {
|
||||||
Promise.all(
|
Promise.all(
|
||||||
task.entries.map(async (entry) => {
|
task.entries.map(async (entry) => {
|
||||||
if (!ctx.ts) {
|
/**
|
||||||
|
* Entry level tsconfig's take precedence
|
||||||
|
*/
|
||||||
|
const tsconfig = entry.tsconfig
|
||||||
|
? loadTsConfig({
|
||||||
|
cwd: ctx.cwd,
|
||||||
|
path: entry.tsconfig,
|
||||||
|
logger: ctx.logger,
|
||||||
|
})
|
||||||
|
: ctx.ts;
|
||||||
|
|
||||||
|
if (!tsconfig) {
|
||||||
ctx.logger.warn(
|
ctx.logger.warn(
|
||||||
`You've added a types entry but no tsconfig.json was found for ${entry.targetPath}. Skipping...`
|
`You've added a types entry but no tsconfig.json was found for ${entry.targetPath}. Skipping...`
|
||||||
);
|
);
|
||||||
@ -41,7 +53,7 @@ const dtsBuildTask: TaskHandler<DtsBuildTask> = {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const program = ts.createProgram(ctx.ts.config.fileNames, ctx.ts.config.options);
|
const program = ts.createProgram(tsconfig.config.fileNames, tsconfig.config.options);
|
||||||
|
|
||||||
const emitResult = program.emit();
|
const emitResult = program.emit();
|
||||||
|
|
||||||
|
@ -3,6 +3,12 @@ interface DtsTaskEntry {
|
|||||||
exportPath: string;
|
exportPath: string;
|
||||||
sourcePath: string;
|
sourcePath: string;
|
||||||
targetPath: string;
|
targetPath: string;
|
||||||
|
/**
|
||||||
|
* Allow a particular task to have it's own tsconfig
|
||||||
|
* great for when you're creating a server & web bundle
|
||||||
|
* package.
|
||||||
|
*/
|
||||||
|
tsconfig?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface DtsBaseTask {
|
interface DtsBaseTask {
|
||||||
|
@ -4,6 +4,7 @@ import { Observable } from 'rxjs';
|
|||||||
import ts from 'typescript';
|
import ts from 'typescript';
|
||||||
|
|
||||||
import { isError } from '../../core/errors';
|
import { isError } from '../../core/errors';
|
||||||
|
import { loadTsConfig } from '../../core/tsconfig';
|
||||||
|
|
||||||
import { printDiagnostic } from './diagnostic';
|
import { printDiagnostic } from './diagnostic';
|
||||||
import { DtsBaseTask } from './types';
|
import { DtsBaseTask } from './types';
|
||||||
@ -36,7 +37,18 @@ const dtsWatchTask: TaskHandler<DtsWatchTask, ts.Diagnostic> = {
|
|||||||
return new Observable((subscriber) => {
|
return new Observable((subscriber) => {
|
||||||
Promise.all(
|
Promise.all(
|
||||||
task.entries.map(async (entry) => {
|
task.entries.map(async (entry) => {
|
||||||
if (!ctx.ts) {
|
/**
|
||||||
|
* Entry level tsconfig's take precedence
|
||||||
|
*/
|
||||||
|
const tsconfig = entry.tsconfig
|
||||||
|
? loadTsConfig({
|
||||||
|
cwd: ctx.cwd,
|
||||||
|
path: entry.tsconfig,
|
||||||
|
logger: ctx.logger,
|
||||||
|
})
|
||||||
|
: ctx.ts;
|
||||||
|
|
||||||
|
if (!tsconfig) {
|
||||||
ctx.logger.warn(
|
ctx.logger.warn(
|
||||||
`You've added a types entry but no tsconfig.json was found for ${entry.targetPath}. Skipping...`
|
`You've added a types entry but no tsconfig.json was found for ${entry.targetPath}. Skipping...`
|
||||||
);
|
);
|
||||||
@ -46,7 +58,7 @@ const dtsWatchTask: TaskHandler<DtsWatchTask, ts.Diagnostic> = {
|
|||||||
|
|
||||||
const compilerHost = ts.createWatchCompilerHost(
|
const compilerHost = ts.createWatchCompilerHost(
|
||||||
'tsconfig.build.json',
|
'tsconfig.build.json',
|
||||||
ctx.ts.config.options,
|
tsconfig.config.options,
|
||||||
ts.sys,
|
ts.sys,
|
||||||
ts.createEmitAndSemanticDiagnosticsBuilderProgram,
|
ts.createEmitAndSemanticDiagnosticsBuilderProgram,
|
||||||
(diagnostic) => {
|
(diagnostic) => {
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import react from '@vitejs/plugin-react';
|
import react from '@vitejs/plugin-react';
|
||||||
|
import { builtinModules } from 'node:module';
|
||||||
import path from 'path';
|
import path from 'path';
|
||||||
import { InlineConfig, createLogger } from 'vite';
|
import { InlineConfig, createLogger } from 'vite';
|
||||||
|
|
||||||
@ -82,7 +83,15 @@ const resolveViteConfig = (ctx: BuildContext, task: ViteBaseTask) => {
|
|||||||
|
|
||||||
const name = idParts[0].startsWith('@') ? `${idParts[0]}/${idParts[1]}` : idParts[0];
|
const name = idParts[0].startsWith('@') ? `${idParts[0]}/${idParts[1]}` : idParts[0];
|
||||||
|
|
||||||
if (name && external.includes(name)) {
|
const builtinModulesWithNodePrefix = [
|
||||||
|
...builtinModules,
|
||||||
|
...builtinModules.map((modName) => `node:${modName}`),
|
||||||
|
];
|
||||||
|
|
||||||
|
if (
|
||||||
|
(name && external.includes(name)) ||
|
||||||
|
(name && builtinModulesWithNodePrefix.includes(name))
|
||||||
|
) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ import { Observable, distinctUntilChanged, scan, startWith, switchMap } from 'rx
|
|||||||
|
|
||||||
import { CommonCLIOptions } from '../types';
|
import { CommonCLIOptions } from '../types';
|
||||||
|
|
||||||
import { CONFIG_FILE_NAMES, loadConfig } from './core/config';
|
import { CONFIG_FILE_NAMES, Config, loadConfig } from './core/config';
|
||||||
import { getExportExtensionMap, validateExportsOrdering } from './core/exports';
|
import { getExportExtensionMap, validateExportsOrdering } from './core/exports';
|
||||||
import { createLogger } from './core/logger';
|
import { createLogger } from './core/logger';
|
||||||
import { loadPkg, validatePkg } from './core/pkg';
|
import { loadPkg, validatePkg } from './core/pkg';
|
||||||
@ -12,12 +12,24 @@ import { createBuildContext } from './createBuildContext';
|
|||||||
import { WatchTask, createWatchTasks } from './createTasks';
|
import { WatchTask, createWatchTasks } from './createTasks';
|
||||||
import { TaskHandler, taskHandlers } from './tasks';
|
import { TaskHandler, taskHandlers } from './tasks';
|
||||||
|
|
||||||
export interface WatchOptions extends CommonCLIOptions {
|
interface WatchCLIOptions extends CommonCLIOptions {}
|
||||||
|
|
||||||
|
interface WatchOptionsWithoutConfig extends WatchCLIOptions {
|
||||||
|
configFile?: true;
|
||||||
|
config?: never;
|
||||||
cwd?: string;
|
cwd?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export const watch = async (opts: WatchOptions) => {
|
interface WatchOptionsWithConfig extends WatchCLIOptions {
|
||||||
const { silent, debug, cwd = process.cwd() } = opts;
|
configFile: false;
|
||||||
|
config?: Config;
|
||||||
|
cwd?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
type WatchOptions = WatchOptionsWithConfig | WatchOptionsWithoutConfig;
|
||||||
|
|
||||||
|
const watch = async (opts: WatchOptions) => {
|
||||||
|
const { silent, debug, cwd = process.cwd(), configFile = true, config: providedConfig } = opts;
|
||||||
|
|
||||||
const logger = createLogger({ silent, debug });
|
const logger = createLogger({ silent, debug });
|
||||||
|
|
||||||
@ -111,12 +123,17 @@ export const watch = async (opts: WatchOptions) => {
|
|||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If configFile is true – which is the default, atempt to load the config
|
||||||
|
* otherwise if it's explicitly false then we suspect there might be a config passed
|
||||||
|
* in the options, so we'll use that instead.
|
||||||
|
*/
|
||||||
|
const config = configFile ? await loadConfig({ cwd, logger }) : providedConfig;
|
||||||
/**
|
/**
|
||||||
* We create tasks based on the exports of the package.json
|
* We create tasks based on the exports of the package.json
|
||||||
* their handlers are then ran in the order of the exports map
|
* their handlers are then ran in the order of the exports map
|
||||||
* and results are logged to see gradual progress.
|
* and results are logged to see gradual progress.
|
||||||
*/
|
*/
|
||||||
const config = await loadConfig({ cwd, logger });
|
|
||||||
|
|
||||||
const extMap = getExportExtensionMap();
|
const extMap = getExportExtensionMap();
|
||||||
|
|
||||||
@ -154,3 +171,6 @@ export const watch = async (opts: WatchOptions) => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export { watch };
|
||||||
|
export type { WatchOptions, WatchOptionsWithConfig, WatchOptionsWithoutConfig, WatchCLIOptions };
|
||||||
|
Loading…
x
Reference in New Issue
Block a user