Skip to content

Commit

Permalink
feat: allow meta.effect to change value of config
Browse files Browse the repository at this point in the history
  • Loading branch information
brillout committed Feb 24, 2025
1 parent e665697 commit 86fe9b4
Show file tree
Hide file tree
Showing 4 changed files with 60 additions and 15 deletions.
26 changes: 26 additions & 0 deletions test/playground/+config.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import type { Config } from 'vike/types'

export default {
meta: {
prerenderSetOverEffect: {
env: { config: true },
global: (value) => typeof value === 'object',
effect({ configValue }) {
return {
prerender: configValue as PrerenderConfig
}
}
}
}
} satisfies Config

type PrerenderConfig = Config['prerender']
declare global {
namespace Vike {
interface Config {
prerenderSetOverEffect?: PrerenderConfig
}
}
}

export {}
2 changes: 1 addition & 1 deletion test/playground/pages/+config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import vikeReact from 'vike-react/config'

export default {
title: 'Big Playground',
prerender: {
prerenderSetOverEffect: {
// TEST: prerender.noExtraDir
noExtraDir: true
},
Expand Down
43 changes: 30 additions & 13 deletions vike/node/plugin/plugins/importUserCode/v1-design/getVikeConfig.ts
Original file line number Diff line number Diff line change
Expand Up @@ -334,6 +334,7 @@ function getPageConfigsBuildTime(
if (sources.length === 0) return
pageConfigGlobal.configValueSources[configName] = sources
})
applyEffectsAll(pageConfigGlobal.configValueSources, configDefinitionsResolved.configDefinitionsGlobal)
assertPageConfigGlobal(pageConfigGlobal, plusFilesAll)

const pageConfigs: PageConfigBuildTime[] = objectEntries(configDefinitionsResolved.configDefinitionsLocal)
Expand All @@ -354,6 +355,7 @@ function getPageConfigsBuildTime(
const pageConfigRoute = determineRouteFilesystem(locationId, configValueSources)

applyEffectsAll(configValueSources, configDefinitionsLocal)

const configValuesComputed = getComputed(configValueSources, configDefinitionsLocal)

const pageConfig: PageConfigBuildTime = {
Expand Down Expand Up @@ -924,23 +926,26 @@ function applyEffectsAll(configValueSources: ConfigValueSources, configDefinitio
const source = configValueSources[configName]?.[0]
if (!source) return
// The config value is eagerly loaded since `configDef.env === 'config-only``
assert('value' in source)
assert('value' in source) // TODO/now: refactor all `'value' in`
// Call effect
const configModFromEffect = configDef.effect({
configValue: source.value,
configDefinedAt: getConfigDefinedAt('Config', configName, source.definedAtFilePath)
})
if (!configModFromEffect) return
assert(hasProp(source, 'value')) // We need to assume that the config value is loaded at build-time
applyEffect(configModFromEffect, configValueSources, configDef)
applyEffect(configModFromEffect, source, configValueSources, configName, configDef, configDefinitions)
})
}
function applyEffect(
configModFromEffect: Config,
source: ConfigValueSource,
configValueSources: ConfigValueSources,
configDefEffect: ConfigDefinitionInternal
configNameEffect: string,
configDefEffect: ConfigDefinitionInternal,
configDefinitions: ConfigDefinitions
) {
const notSupported = `Effects currently only supports modifying the the ${pc.cyan('env')} of a config.` as const
const notSupported =
`${pc.cyan('meta.effect')} currently only supports setting the value of a config, or modifying the ${pc.cyan('meta.env')} of a config.` as const
objectEntries(configModFromEffect).forEach(([configName, configValue]) => {
if (configName === 'meta') {
let configDefinedAt: Parameters<typeof assertMetaUsage>[1]
Expand All @@ -964,14 +969,26 @@ function applyEffect(
})
})
} else {
assertUsage(false, notSupported)
/* To implement being able to set a config value in an effect:
* - Copy and append definedAtFile.fileExportPathToShowToUser with ['meta', configName, 'effect']
* - Copying the definedAtFile of the config that defines the effect
* - Same precedence as the config that sets the value triggering the effect (not the config defining the effect)
* - Apply sortConfigValueSources() again?
configValueSources.push()
*/
const configDef = configDefinitions[configName]
assert(configDef)
assert(configDefEffect._userEffectDefinedAtFilePath)
const configValueSource: ConfigValueSource = {
definedAtFilePath: configDefEffect._userEffectDefinedAtFilePath!,
plusFile: source.plusFile,
locationId: source.locationId,
configEnv: configDef.env,
isOverriden: false, // TODO/now check
valueIsLoadedWithImport: false,
valueIsDefinedByPlusValueFile: false,
valueIsLoaded: true,
value: configValue
}
assertUsage(
!!configDef.global === !!configDefEffect.global,
`The configuration ${pc.cyan(configNameEffect)} has a ${pc.cyan('meta.effect')} that changes the configuration ${pc.cyan(configName)} and, consequently, both ${pc.cyan(configNameEffect)} and ${pc.cyan(configName)} must have the same ${pc.cyan('meta.global')} value.`
)
configValueSources[configName] ??= []
configValueSources[configName].push(configValueSource)
}
})
}
Expand Down
4 changes: 3 additions & 1 deletion vike/shared/page-configs/serialize/parsePageConfigs.ts
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,9 @@ function parseConfigValuesSerialized_tmp(configValuesSerialized: Record<string,
const { valueSerialized, ...common } = configValueSeriliazed
const { value, sideExports } = parseValueSerialized(valueSerialized, configName, () => {
assert(configValueSeriliazed.type !== 'computed')
return configValueSeriliazed.definedAtData
const { definedAtData } = configValueSeriliazed
const definedAtFile = Array.isArray(definedAtData) ? definedAtData[0]! : definedAtData
return definedAtFile
})
addSideExports(sideExports)
configValue = { value, ...common }
Expand Down

0 comments on commit 86fe9b4

Please sign in to comment.