Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

extend config with detected defaults #199

Merged
merged 8 commits into from
May 25, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions changelog.md
Original file line number Diff line number Diff line change
@@ -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`
Expand Down
52 changes: 23 additions & 29 deletions src/config/config.ts
Original file line number Diff line number Diff line change
@@ -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,
Expand All @@ -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';

/*

Expand All @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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<GroConfigCreatorOptions, 'config'>).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;
Expand All @@ -191,11 +182,14 @@ export const toConfig = async (
configOrCreator: GroConfigPartial | GroConfigCreator,
options: GroConfigCreatorOptions,
path: string,
baseConfig?: GroConfig,
): Promise<GroConfig> => {
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) {
Expand Down
17 changes: 12 additions & 5 deletions src/publish.task.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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<TaskArgs> = {
description: 'bump version, publish to npm, and sync to GitHub',
dev: false,
run: async ({fs, args, log, invokeTask, dev}): Promise<void> => {
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');
}
Expand Down Expand Up @@ -60,14 +61,20 @@ export const task: Task<TaskArgs> = {
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);
},
};

Expand Down