Skip to content

Commit

Permalink
Add support for loadConfig to resolver plugins (#8847)
Browse files Browse the repository at this point in the history
  • Loading branch information
devongovett committed Feb 28, 2023
1 parent 0cf2aff commit b549779
Show file tree
Hide file tree
Showing 9 changed files with 398 additions and 23 deletions.
4 changes: 2 additions & 2 deletions packages/core/core/src/ParcelConfig.js
Original file line number Diff line number Diff line change
Expand Up @@ -157,7 +157,7 @@ export default class ParcelConfig {
return Promise.all(plugins.map(p => this.loadPlugin<T>(p)));
}

async getResolvers(): Promise<Array<LoadedPlugin<Resolver>>> {
async getResolvers(): Promise<Array<LoadedPlugin<Resolver<mixed>>>> {
if (this.resolvers.length === 0) {
throw await this.missingPluginError(
this.resolvers,
Expand All @@ -166,7 +166,7 @@ export default class ParcelConfig {
);
}

return this.loadPlugins<Resolver>(this.resolvers);
return this.loadPlugins<Resolver<mixed>>(this.resolvers);
}

_getValidatorNodes(filePath: ProjectPath): $ReadOnlyArray<ParcelPluginNode> {
Expand Down
20 changes: 12 additions & 8 deletions packages/core/core/src/Transformation.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ export default class Transformation {
parcelConfig: ParcelConfig;
invalidations: Map<string, RequestInvalidation>;
invalidateOnFileCreate: Array<InternalFileCreateInvalidation>;
resolverRunner: ResolverRunner;

constructor({request, options, config, workerApi}: TransformationOpts) {
this.configs = new Map();
Expand All @@ -121,6 +122,11 @@ export default class Transformation {
this.invalidateOnFileCreate = [];
this.devDepRequests = new Map();
this.pluginDevDeps = [];
this.resolverRunner = new ResolverRunner({
config,
options,
previousDevDeps: request.devDeps,
});

this.pluginOptions = new PluginOptions(
optionsProxy(
Expand Down Expand Up @@ -195,9 +201,13 @@ export default class Transformation {
error = e;
}

let configRequests = getConfigRequests([...this.configs.values()]);
let configRequests = getConfigRequests([
...this.configs.values(),
...this.resolverRunner.configs.values(),
]);
let devDepRequests = getWorkerDevDepRequests([
...this.devDepRequests.values(),
...this.resolverRunner.devDepRequests.values(),
]);

// $FlowFixMe because of $$raw
Expand Down Expand Up @@ -657,11 +667,6 @@ export default class Transformation {
plugin: transformer.plugin,
})),
options: this.options,
resolverRunner: new ResolverRunner({
config: this.parcelConfig,
options: this.options,
}),

pluginOptions: this.pluginOptions,
workerApi: this.workerApi,
};
Expand Down Expand Up @@ -740,7 +745,7 @@ export default class Transformation {
to: string,
options?: ResolveOptions,
): Promise<FilePath> => {
let result = await pipeline.resolverRunner.resolve(
let result = await this.resolverRunner.resolve(
createDependency(this.options.projectRoot, {
env: asset.value.env,
specifier: to,
Expand Down Expand Up @@ -882,7 +887,6 @@ type Pipeline = {|
transformers: Array<TransformerWithNameAndConfig>,
options: ParcelOptions,
pluginOptions: PluginOptions,
resolverRunner: ResolverRunner,
workerApi: WorkerApi,
postProcess?: PostProcessFunc,
generate?: GenerateFunc,
Expand Down
100 changes: 97 additions & 3 deletions packages/core/core/src/requests/PathRequest.js
Original file line number Diff line number Diff line change
@@ -1,8 +1,19 @@
// @flow strict-local
import type {Diagnostic} from '@parcel/diagnostic';
import type {Async, FileCreateInvalidation, FilePath} from '@parcel/types';
import type {
Async,
FileCreateInvalidation,
FilePath,
Resolver,
} from '@parcel/types';
import type {StaticRunOpts} from '../RequestTracker';
import type {AssetGroup, Dependency, ParcelOptions} from '../types';
import type {
AssetGroup,
Config,
Dependency,
DevDepRequest,
ParcelOptions,
} from '../types';
import type {ConfigAndCachePath} from './ParcelConfigRequest';

import ThrowableDiagnostic, {errorToDiagnostic, md} from '@parcel/diagnostic';
Expand All @@ -22,8 +33,19 @@ import {
fromProjectPath,
fromProjectPathRelative,
toProjectPath,
toProjectPathUnsafe,
} from '../projectPath';
import {Priority} from '../types';
import {createBuildCache} from '../buildCache';
import type {LoadedPlugin} from '../ParcelConfig';
import {createConfig} from '../InternalConfig';
import {loadPluginConfig, runConfigRequest} from './ConfigRequest';
import {
createDevDependency,
getDevDepRequests,
invalidateDevDeps,
runDevDepRequest,
} from './DevDepRequest';

export type PathRequest = {|
id: string,
Expand Down Expand Up @@ -61,9 +83,12 @@ async function run({input, api, options}) {
await api.runRequest<null, ConfigAndCachePath>(createParcelConfigRequest()),
);
let config = getCachedParcelConfig(configResult, options);
let {devDeps, invalidDevDeps} = await getDevDepRequests(api);
invalidateDevDeps(invalidDevDeps, options, config);
let resolverRunner = new ResolverRunner({
options,
config,
previousDevDeps: devDeps,
});
let result: ResolverResult = await resolverRunner.resolve(input.dependency);

Expand All @@ -89,6 +114,14 @@ async function run({input, api, options}) {
}
}

for (let config of resolverRunner.configs.values()) {
await runConfigRequest(api, config);
}

for (let devDepRequest of resolverRunner.devDepRequests.values()) {
await runDevDepRequest(api, devDepRequest);
}

if (result.assetGroup) {
api.invalidateOnFileDelete(result.assetGroup.filePath);
return result.assetGroup;
Expand All @@ -105,6 +138,7 @@ async function run({input, api, options}) {
type ResolverRunnerOpts = {|
config: ParcelConfig,
options: ParcelOptions,
previousDevDeps: Map<string, string>,
|};

type ResolverResult = {|
Expand All @@ -115,15 +149,23 @@ type ResolverResult = {|
diagnostics?: Array<Diagnostic>,
|};

const configCache = createBuildCache();

export class ResolverRunner {
config: ParcelConfig;
options: ParcelOptions;
pluginOptions: PluginOptions;
previousDevDeps: Map<string, string>;
devDepRequests: Map<string, DevDepRequest>;
configs: Map<string, Config>;

constructor({config, options}: ResolverRunnerOpts) {
constructor({config, options, previousDevDeps}: ResolverRunnerOpts) {
this.config = config;
this.options = options;
this.pluginOptions = new PluginOptions(this.options);
this.previousDevDeps = previousDevDeps;
this.devDepRequests = new Map();
this.configs = new Map();
}

async getDiagnostic(
Expand Down Expand Up @@ -154,6 +196,44 @@ export class ResolverRunner {
return diagnostic;
}

async loadConfigs(
resolvers: Array<LoadedPlugin<Resolver<mixed>>>,
): Promise<void> {
for (let plugin of resolvers) {
// Only load config for a plugin once per build.
let config = configCache.get(plugin.name);
if (!config && plugin.plugin.loadConfig != null) {
config = createConfig({
plugin: plugin.name,
searchPath: toProjectPathUnsafe('index'),
});

await loadPluginConfig(plugin, config, this.options);
configCache.set(plugin.name, config);
this.configs.set(plugin.name, config);
}

if (config) {
for (let devDep of config.devDeps) {
let devDepRequest = await createDevDependency(
devDep,
this.previousDevDeps,
this.options,
);
this.runDevDepRequest(devDepRequest);
}

this.configs.set(plugin.name, config);
}
}
}

runDevDepRequest(devDepRequest: DevDepRequest) {
let {specifier, resolveFrom} = devDepRequest;
let key = `${specifier}:${fromProjectPathRelative(resolveFrom)}`;
this.devDepRequests.set(key, devDepRequest);
}

async resolve(dependency: Dependency): Promise<ResolverResult> {
let dep = new PublicDependency(dependency, this.options);
report({
Expand All @@ -163,6 +243,7 @@ export class ResolverRunner {
});

let resolvers = await this.config.getResolvers();
await this.loadConfigs(resolvers);

let pipeline;
let specifier;
Expand Down Expand Up @@ -201,6 +282,7 @@ export class ResolverRunner {
dependency: dep,
options: this.pluginOptions,
logger: new PluginLogger({origin: resolver.name}),
config: this.configs.get(resolver.name)?.result,
});

if (result) {
Expand Down Expand Up @@ -292,6 +374,18 @@ export class ResolverRunner {
}

break;
} finally {
// Add dev dependency for the resolver. This must be done AFTER running it due to
// the potential for lazy require() that aren't executed until the request runs.
let devDepRequest = await createDevDependency(
{
specifier: resolver.name,
resolveFrom: resolver.resolveFrom,
},
this.previousDevDeps,
this.options,
);
this.runDevDepRequest(devDepRequest);
}
}

Expand Down
Loading

0 comments on commit b549779

Please sign in to comment.