Skip to content

feat(cli): Project configuration API (replaces loadConfig)#3277

Merged
ejhammond merged 3 commits into
xds-unprefix-integrationfrom
astryx/project-config-api
Jun 30, 2026
Merged

feat(cli): Project configuration API (replaces loadConfig)#3277
ejhammond merged 3 commits into
xds-unprefix-integrationfrom
astryx/project-config-api

Conversation

@ejhammond

Copy link
Copy Markdown
Contributor

Summary

Introduces a Project class as the single API for reading resolved project
configuration, replacing loadConfig entirely. Previously nine+ call sites
each loaded the config and then independently fanned out to discovery helpers
(component ownership, templates, integration codemods). This centralizes all of
that behind one class.

The Project class (packages/cli/src/lib/project.mjs)

Project.load(cwd, { cache }) is the async factory (constructors can't be
async). It does exactly what loadConfig did — find the config sibling of the
nearest package.json, import + validate it, load the configured integrations
— and nothing more. Discovery is lazy and memoized.

  • config / integrations / loadedIntegrations / cwd — the raw surface.
  • components() / templates() / codemods(from, to) — memoized discovery
    that wraps the existing discovery functions (never reimplements them).
  • issuesUrl(ref) — routes core to config.issuesUrl (or the default tracker)
    and an integration package to its manifest issuesUrl.
  • issues() — the accumulated, deduped integration issues; when called
    directly it also validates any configured integration not yet visited by a
    discovery call, so the set is always complete on demand.

Lazy + memoized + skip-and-warn

load() does not validate integrations. As each discovery method runs it
guards per-integration work so one broken integration never throws out of
discovery — its contributions are skipped and any issue is collected into a
private set (the skip + warn policy). Memoization runs through a small pluggable
cache.

Pluggable cache

A tiny ConfigCache interface (get/set) with an in-memory default. Cache
keys are derived from a config-file content hash + cwd + discovery kind
(+args), e.g. codemods:<from>..<to>. The in-memory cache never busts, but the
hash is computed regardless so a future file-backed, hash-busting cache drops
in with no API change.

Migrating callers + removing loadConfig

Every caller now routes through Project.load: discover, doctor, layout,
template, component, swizzle, and the component/template command
wrappers. findConfigPath now lives in lib/project.mjs as the single home.
lib/config.mjs (loadConfig) is removed with no shim. Each command's existing
output/behavior is unchanged.

Upgrade error policy + --skip-codemod

  • Definition errors for an integration (bad manifest/export, duplicate ids,
    missing root) now skip that integration's codemods and warn, instead of
    hard-failing the upgrade. This reverses the previous hard-fail behavior.
  • Execution-time failures (a transform throwing while rewriting files) still
    abort the upgrade so a partial write never proceeds.
  • New variadic --skip-codemod <name...> flag excludes named codemods by the
    same identifier the run loop matches (core transform name, integration
    codemod id), so a user who hits an execution failure can re-run past it.

Tests

  • New project.test.mjs: load/config/integrations, discovery results,
    memoization (no re-walk), issue collection + dedupe, broken-integration skip,
    issuesUrl routing, shared-cache reuse.
  • New config-cache.test.mjs: cache get/set, content-hash stability/variance,
    key derivation.
  • New upgrade.integration-policy.test.mjs: broken integration is skipped (not
    a hard fail), a healthy integration codemod runs, and --skip-codemod
    excludes a named codemod.
  • Existing component/template/discover/doctor/upgrade/swizzle/integration tests
    updated where they referenced loadConfig directly or the old hard-fail
    policy.

Full CLI suite: 1583 passing.

@vercel

vercel Bot commented Jun 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
astryx Ready Ready Preview, Comment Jun 30, 2026 2:23pm

Request Review

@meta-cla meta-cla Bot added the CLA Signed This label is managed by the Meta Open Source bot. label Jun 30, 2026
@github-actions

github-actions Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

PR Analysis Report

📚 Storybook Preview

View Storybook for this PR
GitHub Pages may take up to a minute to hydrate after deploy.

🧪 Sandbox Preview

View Sandbox for this PR
GitHub Pages may take up to a minute to hydrate after deploy.

No new or modified components detected.

Bundle Size Summary

Package Size (ESM) Size (CJS) Gzipped
@astryxdesign/core N/A 4.6KB 0B

Accessibility Audit

Status: No accessibility violations detected.


Generated by PR Enrichment workflow | Storybook | Sandbox | View full report

github-actions Bot added a commit that referenced this pull request Jun 30, 2026
Introduce the Project class as a single, lazy, memoized entry point for
reading resolved project configuration and discovery (components, templates,
codemods) plus integration issue routing. Add a small pluggable cache
(InMemoryConfigCache) keyed by a config content hash + cwd + discovery kind.
Route every config/discovery read through Project.load: discover, doctor,
layout, template, component, swizzle, and the component/template command
wrappers. findConfigPath now lives in lib/project.mjs as the single home.
Removes lib/config.mjs (loadConfig) with no shim.
Upgrade now treats an integration definition error (bad manifest/export,
duplicate ids, missing root) as skip-and-warn rather than a hard failure,
while an execution-time codemod throw still aborts the run. Adds a variadic
--skip-codemod flag to exclude named codemods (core transform name or
integration codemod id) so users can re-run past a failed codemod.
@ejhammond ejhammond force-pushed the astryx/project-config-api branch from afdc265 to 47c92aa Compare June 30, 2026 14:19
github-actions Bot added a commit that referenced this pull request Jun 30, 2026
@ejhammond ejhammond merged commit 67f63ea into xds-unprefix-integration Jun 30, 2026
12 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

CLA Signed This label is managed by the Meta Open Source bot.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant