feat: scaffold React, Vue, Angular, and Nuxt apps from the CLI - #257
Conversation
|
@mridang must be a member of the zitadel team on Vercel to deploy. Learn more about collaboration on Vercel and other options here. |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5ddb010489
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Adds setup --framework react|vue|angular. Writes the SPA auth entry and a dev proxy that forwards /__nextgen to the backend and injects the project secret on /sessions/exchange. New file-writer ops: merge-vite-config (magicast) for React/Vue and merge-angular-proxy for Angular.
5ddb010 to
29c60fa
Compare
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Generalizes the edit op to a candidate-path list so the proxy merge finds
vite.config.{ts,mts,cts,js,mjs,cjs}. Adds a ViteSupport capability (shared
buildViteProxyOp) that React and Vue patchers implement, removing duplication.
Adds a Nuxt detector/scaffolder/patcher. Like Next, Nuxt proxies via server middleware: the patcher registers @zitadel/sdk-nuxt through a non-destructive nuxt.config.ts edit and writes login/register/profile pages plus plugins. Extracts shared magicast helpers used by the Vite and Nuxt config edits.
Add braces to every single-line guard in the SPA/Nuxt config patchers and emitted proxy templates. Resolve config files through a shared configCandidates() helper so vite.config and nuxt.config both accept the full ts/mts/cts/js/mjs/cjs set instead of a partial list. Raise E_VALIDATION when an existing modules/transpile value is not an array instead of a raw TypeError.
The proxy implementation (PROXY_PATH, PROXY_ENTRY_CODE, viteProxyEdit) and the FileOp wiring (ViteSupport, buildViteProxyOp) were split across two files but are one concern; vite-support already imported viteProxyEdit, so no extra coupling. Repoint the react/vue/angular template importers at vite-support.
PROXY_PATH (/__nextgen) is the shared proxy prefix every framework keys off, but it lived in vite-support, so non-Vite patchers (Angular) imported it from a Vite-named file. Move it to proxy.ts and drop the dead re-export in react/templates.
The react/vue/angular/nuxt patchers each carried a copy of the CLI-version to dist-tag helper. Replace all four with the shared npmDistTagForCliVersion from public-cli, which also falls back to "latest" instead of "alpha" for a stable CLI release. Next keeps its own helper: its fallback is the renderer's pinned dependency version (workspace:* for the lit renderer), not a dist tag.
doctor --fix now reclaims edit ops, so a removed /__nextgen proxy in vite.config/nuxt.config/angular.json is restored; the edits are idempotent. nuxtConfigEdit routes its object descents through ensureEditableObject, which throws a clean E_VALIDATION when runtimeConfig/build is not an inline object literal instead of a raw magicast TypeError. Replace the per-op overwrite flag with uniform conflict protection: the Angular and Nuxt scaffolders now remove their starter entry files (as React/Vue already did), so the patch writes into an absent path. Running setup on an existing app no longer silently clobbers a user's App entry — it raises E_CONFLICT like the Next patcher, recoverable with --force.
Wrap over-width single-line arrays/objects (Angular runCommand args, merge-env entries, the magicast import) to the repo's 100-col Prettier style.
Extract parseConfigModule so the Vite and Nuxt edits drop their duplicated let-mod try/catch. Rebuild the Next file/op lists immutably with conditional entries + filter instead of push. Add a README to each patcher dir (next, react, vue, angular, nuxt) describing what it writes and how its proxy reaches the backend, in one shared format.
There was a problem hiding this comment.
Pull request overview
Adds multi-framework scaffolding/patching to the CLI’s Orca system so zitadel setup can create and integrate React (Vite), Vue (Vite), Nuxt, and Angular apps, including framework-specific auth entry files and dev-time /__nextgen proxy wiring via a new generic edit file operation.
Changes:
- Added new scaffolders, detectors, and rule-based patchers for
nuxt,react,vue, andangular, and registered them in the Orca registries. - Introduced a generic
FileOpkind"edit"and executor support to enable non-destructive config edits (Vite/Nuxt via magicast; Angular via JSON edit). - Added framework templates/README docs plus unit tests for Nuxt config editing and Orca framework selection.
Reviewed changes
Copilot reviewed 38 out of 39 changed files in this pull request and generated 7 comments.
Show a summary per file
| File | Description |
|---|---|
| pnpm-lock.yaml | Adds magicast@0.3.5 and associated lockfile updates. |
| apps/cli/package.json | Declares magicast dependency for CLI config editing. |
| apps/cli/tests/unit/lib/orca/patchers/rule/reclaim.test.ts | Extends reclaim tests to include new edit ops. |
| apps/cli/tests/unit/lib/orca/patchers/rule/nuxt/nuxt-config.test.ts | Adds unit tests for Nuxt magicast config edit idempotency/validation. |
| apps/cli/tests/unit/lib/orca/index.test.ts | Verifies Orca selects new scaffolders/patchers and lists frameworks. |
| apps/cli/src/lib/orca/scaffolders/vue.ts | Adds Vue (Vite) scaffolder via create-vite. |
| apps/cli/src/lib/orca/scaffolders/react.ts | Adds React (Vite) scaffolder via create-vite. |
| apps/cli/src/lib/orca/scaffolders/nuxt.ts | Adds Nuxt scaffolder via nuxi init minimal template. |
| apps/cli/src/lib/orca/scaffolders/index.ts | Registers new scaffolders in the scaffolder registry. |
| apps/cli/src/lib/orca/scaffolders/angular.ts | Adds Angular scaffolder via Angular CLI. |
| apps/cli/src/lib/orca/patchers/rule/vue/templates.ts | Adds managed src/App.vue template using @zitadel/sdk-vue. |
| apps/cli/src/lib/orca/patchers/rule/vue/README.md | Documents Vue patcher behavior and dev proxy approach. |
| apps/cli/src/lib/orca/patchers/rule/vue/index.ts | Implements Vue rule patcher + shared Vite proxy edit op. |
| apps/cli/src/lib/orca/patchers/rule/vite-support.ts | Introduces shared Vite config proxy edit (magicast) and ViteSupport. |
| apps/cli/src/lib/orca/patchers/rule/reclaim.ts | Makes doctor --fix reclaim config edit ops. |
| apps/cli/src/lib/orca/patchers/rule/react/templates.ts | Adds managed src/App.tsx template using @zitadel/sdk-react. |
| apps/cli/src/lib/orca/patchers/rule/react/README.md | Documents React patcher behavior and dev proxy approach. |
| apps/cli/src/lib/orca/patchers/rule/react/index.ts | Implements React rule patcher + shared Vite proxy edit op. |
| apps/cli/src/lib/orca/patchers/rule/proxy.ts | Centralizes the framework-agnostic /__nextgen proxy path constant. |
| apps/cli/src/lib/orca/patchers/rule/nuxt/templates.ts | Adds managed Nuxt pages/plugins and SSR-safe auth seeding logic. |
| apps/cli/src/lib/orca/patchers/rule/nuxt/README.md | Documents Nuxt patcher and server-middleware proxy behavior. |
| apps/cli/src/lib/orca/patchers/rule/nuxt/nuxt-config.ts | Implements Nuxt config edit transform (magicast). |
| apps/cli/src/lib/orca/patchers/rule/nuxt/index.ts | Implements Nuxt rule patcher with nuxt.config edit + templates. |
| apps/cli/src/lib/orca/patchers/rule/next/README.md | Adds Next.js patcher README documenting what’s patched and proxy model. |
| apps/cli/src/lib/orca/patchers/rule/next/index.ts | Refactors Next patcher op/path assembly to a filtered-array style. |
| apps/cli/src/lib/orca/patchers/rule/magicast-config.ts | Adds shared magicast helpers for config editing and clean validation errors. |
| apps/cli/src/lib/orca/patchers/rule/file-writer/types.ts | Extends FileOp union with new edit op type. |
| apps/cli/src/lib/orca/patchers/rule/file-writer/index.ts | Adds executor support for edit (candidate resolution + idempotency + atomic write). |
| apps/cli/src/lib/orca/patchers/rule/config-paths.ts | Adds shared config filename candidate generation (*.{ts,mts,cts,js,mjs,cjs}). |
| apps/cli/src/lib/orca/patchers/rule/angular/templates.ts | Adds Angular managed root component, template, and proxy.conf.cjs. |
| apps/cli/src/lib/orca/patchers/rule/angular/README.md | Documents Angular patcher behavior and dev proxy wiring. |
| apps/cli/src/lib/orca/patchers/rule/angular/index.ts | Implements Angular rule patcher with angular.json edit + proxy conf. |
| apps/cli/src/lib/orca/patchers/rule/angular/angular-json.ts | Implements Angular angular.json edit transform for proxyConfig/port. |
| apps/cli/src/lib/orca/patchers/index.ts | Registers new patchers in the patcher registry. |
| apps/cli/src/lib/orca/detectors/vue.ts | Adds Vue (Vite) detector. |
| apps/cli/src/lib/orca/detectors/react.ts | Adds React (Vite) detector. |
| apps/cli/src/lib/orca/detectors/nuxt.ts | Adds Nuxt detector. |
| apps/cli/src/lib/orca/detectors/index.ts | Registers detectors and documents probe ordering to avoid mis-detection. |
| apps/cli/src/lib/orca/detectors/angular.ts | Adds Angular detector. |
Files not reviewed (1)
- pnpm-lock.yaml: Language not supported
Add @zitadel/shared-component-styles and @zitadel/design-tokens to the Nuxt build.transpile list, matching the repo's demo-nuxt config, so SSR builds don't fail on their untranspiled ESM. Stop setting server.host in the Vite config edit: it duplicated Vite's default and got in the way of opting into network binding; the issuer/origin requirement is about the port, which is still set.
Read ZITADEL_PROJECT_ID via loadEnv(process.cwd()) instead of dirname(fileURLToPath(import.meta.url)). Vite may bundle the config to a temp file whose import.meta.url no longer points at the project root, leaving the env unresolved; process.cwd() is Vite's own default env dir and reliably finds .env.local. Drops the now-unused node:url/node:path imports. Also note the package.json dev-script edit in the Angular patcher README.
viteProxyEdit and nuxtConfigEdit now track whether they actually add anything and return the source untouched when nothing is missing, so the file-writer skips the file instead of letting magicast reformat an already-patched config on re-runs / doctor --fix. ensureArrayItem now reports whether it added the item so the edits can detect a no-op.
--renderer is accepted for any framework and recorded in zitadel.json branding; only the Next patcher varies its generated templates by it. "Next.js only" overstated a restriction that doesn't exist and could mislead agents.
…ative Fail fast with E_VALIDATION when an existing Angular project is older than 17, since the generated templates use @if control flow that won't compile there. Skip the DevPortPrompt when --dev-port was passed so an interactive answer can't override the explicit flag.
Probe *.cts/*.cjs after the ESM extensions so a project whose only config is CommonJS is found, and reject CommonJS source (module.exports) in parseConfigModule with a clear "convert to ESM or edit manually" message instead of a misleading "file not found". configPattern still lists only the editable ESM extensions.
…mple The eject manual step no longer calls the generic dev script "Zitadel". Fix the configCandidates JSDoc example to show full filenames, and add the missing "that" to the proxy-imports comment.
The Vite/Nuxt parse and CommonJS-rejection errors built their label from the ESM-only configPattern, but the candidate list now also probes *.cjs/*.cts, so a CommonJS-config error cited a glob that didn't include the offending file. Use vite.config.* / nuxt.config.* labels (covering every candidate) and drop the now-unused configPattern helper.
Match `module.exports =` rather than any mention of `module.exports`, so an ESM config that references it in a comment or string isn't wrongly rejected as CommonJS.
…son eject step Broaden the CommonJS detection to also match `exports.<name> =` (e.g. `exports.default = ...`), so a CommonJS config using named exports is rejected instead of getting ESM imports injected. Word the eject manual step for angular.json specifically (remove the proxyConfig/port from the serve target) rather than calling it a generic configuration block.
Replace the raw-source regex with an AST walk that looks for a real top-level module.exports / exports.x assignment, so module.exports appearing in a comment or string literal in an otherwise-ESM config no longer trips a false positive.
The react/vue/nuxt READMEs only mentioned the framework-specific env var, but the base patcher also writes ZITADEL_PROJECT_ID/ISSUER/URL/ENVIRONMENT (which the dev proxy and Nuxt config read). Document those shared keys too.
# Conflicts: # apps/cli/README.md # apps/cli/src/commands/setup/index.ts # apps/cli/src/lib/orca/patchers/rule/next/index.ts
importIsPresent matched only the local identifier name, so a same-named import
from a different module (e.g. a loadEnv from elsewhere) would make the Vite
edit skip adding the real `import { loadEnv } from "vite"`. It now also matches
the source module when given, and the Vite call site passes the expected `from`.
Adds
setup --framework react|vue|angular|nuxt. Writes the SPA auth entry/pages and a dev proxy that forwards/__nextgento the backend and attaches ask_<project_id>bearer (fromZITADEL_PROJECT_ID) to the forwarded requests.New file-writer ops:
merge-vite-config(magicast, non-destructive) for React/Vue andmerge-angular-proxyfor Angular. Production still needs@zitadel/edge-proxy.