From f6634c72aac1c5b960f1f75726433b979589869f Mon Sep 17 00:00:00 2001 From: Ryan Atkinson <2608646+ryanatkn@users.noreply.github.com> Date: Mon, 24 May 2021 18:14:16 -0600 Subject: [PATCH] extend config with detected defaults (#199) --- changelog.md | 7 ++++++ src/config/config.ts | 52 ++++++++++++++++++++------------------------ src/publish.task.ts | 17 ++++++++++----- 3 files changed, 42 insertions(+), 34 deletions(-) diff --git a/changelog.md b/changelog.md index 18c596f77a..826452499e 100644 --- a/changelog.md +++ b/changelog.md @@ -1,5 +1,12 @@ # changelog +## 0.24.0 + +- **break**: extend config with detected defaults + ([#199](https://github.com/feltcoop/gro/pull/199)) +- improve `gro publish` errors and suport restricted packages + ([#199](https://github.com/feltcoop/gro/pull/199)) + ## 0.23.7 - fix `gro publish` arg forwarding to `npm version` diff --git a/src/config/config.ts b/src/config/config.ts index 6a578d60ac..f36ef5a0a9 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -1,4 +1,4 @@ -import {paths, groPaths, toBuildOutPath, CONFIG_BUILD_PATH, toImportId} from '../paths.js'; +import {paths, toBuildOutPath, CONFIG_BUILD_PATH} from '../paths.js'; import { isPrimaryBuildConfig, normalizeBuildConfigs, @@ -22,10 +22,11 @@ import type {EcmaScriptTarget} from '../build/tsBuildHelpers.js'; import {omitUndefined} from '../utils/object.js'; import type {ServedDirPartial} from '../build/servedDir.js'; import {DEFAULT_SERVER_HOST, DEFAULT_SERVER_PORT} from '../server/server.js'; -import type {Result} from '../utils/types.js'; +import type {Assignable, Result} from '../utils/types.js'; import {toArray} from '../utils/array.js'; import type {Filesystem} from '../fs/filesystem.js'; import {defaultAdapt} from '../adapt/defaultAdapt.js'; +import {config as createDefaultConfig} from './gro.config.default.js'; /* @@ -46,9 +47,6 @@ This choice keeps things simple and flexible because: */ -const FALLBACK_CONFIG_BASE_PATH = 'config/gro.config.default.ts'; -const FALLBACK_CONFIG_NAME = `gro/src/${FALLBACK_CONFIG_BASE_PATH}`; - export interface GroConfig { readonly builds: BuildConfig[]; readonly adapt: AdaptBuilds; @@ -85,6 +83,7 @@ export interface GroConfigCreatorOptions { readonly fs: Filesystem; readonly dev: boolean; readonly log: Logger; + readonly config: GroConfig; // default config is available for user config code } let cachedConfig: GroConfig | undefined; @@ -141,47 +140,39 @@ export const loadGroConfig = async ( } const log = new SystemLogger(printLogLabel('config')); - const options: GroConfigCreatorOptions = {fs, log, dev}; - + const options: GroConfigCreatorOptions = {fs, log, dev, config: null as any}; + const defaultConfig = await toConfig(createDefaultConfig, options, ''); + (options as Assignable).config = defaultConfig; const {configSourceId} = paths; - // TODO maybe refactor this to use `../fs/modules#loadModule`, duplicates some stuff - let configModule: GroConfigModule; - let modulePath: string; if (await fs.exists(configSourceId)) { // The project has a `gro.config.ts`, so import it. // If it's not already built, we need to bootstrap the config and use it to compile everything. - modulePath = configSourceId; const configBuildId = toBuildOutPath(dev, PRIMARY_NODE_BUILD_CONFIG.name, CONFIG_BUILD_PATH); if (!(await fs.exists(configBuildId))) { const {buildSourceDirectory} = await import('../build/buildSourceDirectory.js'); await buildSourceDirectory( fs, // TODO feels hacky, the `sourcemap` in particular - await toConfig({builds: [PRIMARY_NODE_BUILD_CONFIG], sourcemap: dev}, options, modulePath), + await toConfig( + {builds: [PRIMARY_NODE_BUILD_CONFIG], sourcemap: dev}, + options, + configSourceId, + ), dev, log, ); } - configModule = await import(configBuildId); + const configModule = await import(configBuildId); + const validated = validateConfigModule(configModule); + if (!validated.ok) { + throw Error(`Invalid Gro config module at '${configSourceId}': ${validated.reason}`); + } + cachedConfig = await toConfig(configModule.config, options, configSourceId, defaultConfig); } else { - // The project does not have a `gro.config.ts`, so use Gro's fallback default. - modulePath = FALLBACK_CONFIG_NAME; - configModule = await import( - toImportId( - `${groPaths.source}${FALLBACK_CONFIG_BASE_PATH}`, - dev, - PRIMARY_NODE_BUILD_CONFIG.name, - groPaths, - ) - ); + cachedConfig = defaultConfig; } - const validated = validateConfigModule(configModule); - if (!validated.ok) { - throw Error(`Invalid Gro config module at '${modulePath}': ${validated.reason}`); - } - cachedConfig = await toConfig(configModule.config, options, modulePath); cachedDev = dev; if (applyConfigToSystem) applyConfig(cachedConfig); return cachedConfig; @@ -191,11 +182,14 @@ export const toConfig = async ( configOrCreator: GroConfigPartial | GroConfigCreator, options: GroConfigCreatorOptions, path: string, + baseConfig?: GroConfig, ): Promise => { const configPartial = typeof configOrCreator === 'function' ? await configOrCreator(options) : configOrCreator; - const config = normalizeConfig(configPartial); + const extendedConfig = baseConfig ? {...baseConfig, ...configPartial} : configPartial; + + const config = normalizeConfig(extendedConfig); const validateResult = validateConfig(config); if (!validateResult.ok) { diff --git a/src/publish.task.ts b/src/publish.task.ts index 36ac6fd196..a18546c195 100644 --- a/src/publish.task.ts +++ b/src/publish.task.ts @@ -22,14 +22,15 @@ import {buildSourceDirectory} from './build/buildSourceDirectory.js'; export interface TaskArgs { _: string[]; branch?: string; - dry?: boolean; + dry?: boolean; // run without changing git or npm + restricted?: string; // if `true`, package is not public } export const task: Task = { description: 'bump version, publish to npm, and sync to GitHub', dev: false, run: async ({fs, args, log, invokeTask, dev}): Promise => { - const {branch = GIT_DEPLOY_BRANCH, dry = false} = args; + const {branch = GIT_DEPLOY_BRANCH, dry = false, restricted = false} = args; if (dev) { log.warn('building in development mode; normally this is only for diagnostics'); } @@ -60,14 +61,20 @@ export const task: Task = { return; } - await spawnProcess('npm', ['version', versionIncrement]); + const npmVersionResult = await spawnProcess('npm', ['version', versionIncrement]); + if (!npmVersionResult.ok) { + throw Error('npm version failed: no commits were made: see the error above'); + } await spawnProcess('git', ['push']); await spawnProcess('git', ['push', '--tags']); const publishArgs = ['publish']; if (!publishContext.previousChangelogVersion) { - publishArgs.push('--access', 'public'); + publishArgs.push('--access', restricted ? 'restricted' : 'public'); + } + const npmPublishResult = await spawnProcess('npm', publishArgs); + if (!npmPublishResult.ok) { + throw Error('npm publish failed: revert the version commits or run "npm publish" manually'); } - await spawnProcess('npm', publishArgs); }, };