Repository navigation
Release 2.0.0-beta.5 - #432
Merged
Merged
Conversation
The API playground's OAuth sign-in (authorization code and implicit flows) now redirects to `<portal url>/oauth/callback` from every endpoint page, so portal owners register one redirect URI with their provider (Slack, for example) instead of every endpoint page's URL. Refs apimatic/apimatic-io#2255. fumadocs-openapi 12.1 added `oauthRedirectUrl` for this ([fuma-nama/fumadocs#3611](fuma-nama/fumadocs#3611)), with a `createOAuthHandler()` route that needs a server. Published portals are static files, so a prerendered page does the same in the browser: it sends the provider's answer back to the page that started the sign-in, or stays to show the provider's error. It refuses a starting page on another site, and forgets the starting page once read. When it can't tell where the sign-in started, it links to the portal's home page. The CLI now refuses a content page at `/oauth/callback`, which the template's route would hide, and its reserved-address error now says such a page would be served "where the portal puts pages of its own". Not done here: - Sign-in has been tried against a mock provider, not a real one yet. - The callback URL and its home-page link ignore a base path for now; both need one once portals can be hosted under a path (apimatic-io#2275). - Portal-owner docs for the single redirect URI. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com> Co-authored-by: Muhammad Rafay Nadeem <muhammad.nadeem@apimatic.io>
Follow-up to #418, which was approved on the condition that its review comments are addressed in a separate PR. Every comment is addressed here. ## Changes - **Real paths for the dependencies and the Vite binary** (finding 3). The package lookup answers canonical paths, so a Windows 8.3 short name or a symlinked install can no longer leave the entry's `/@fs/` import refused in every browser. The new unit test fails without the change on a pnpm checkout. - **The narrowest directory holding the dependencies** (finding 1). The allow list took the outermost `node_modules` above each linked package: every global package under an npm global install, and only each package's own directory under a pnpm global install, where 69 of the page's 120 `/@fs/` files fell outside it. It now takes the directory all the linked installations share: the CLI's own `node_modules` under npm, the `.pnpm` or `links` store under pnpm. Where the installations share nothing short of the disk's root, as with an `npm link`ed dependency on another drive, each is listed on its own rather than widening to the root. Unit tests cover the four layouts in the review's table and the divergent case. - **Vite's default workspace root is kept** (finding 5), and the project directory is `portalProjectDirectory` after the glossary (inline comment). - **Nothing is skipped** (finding 9, tightened in review). A missing `node_modules` or a link leading nowhere stops the config load with its own error, naming the path, rather than surfacing later as a blank page. - **Serve tests check what came back** (finding 7): a JavaScript content type for the dependency file and `image/png` for the static image, since a missing file answers 200 with the fallback page. Cleanup only removes what set-up made (finding 10). - **One-line comments**, as the review's table asks. ## Recommendation 5: `Cache-Control: no-store`, tested in Safari Tested on macOS, Safari, from the `dev` commit before #418 so the bug could show. Control: the first preview loaded and the next preview on the same port went blank. With `no-store` on the page: every run blank. With `no-store` on every module too: first run loaded, every later run blank, Safari restarted between. In Web Inspector the entry module, `virtual:tanstack-start-dev-client-entry`, showed `(memory)` as its transfer size in every case, on reload too. Safari serves the module from its memory cache whatever the header says, which confirms finding 6's premise and rules out the header as a fix. The allow list stays. ## Verification - Full suite, both end-to-end suites, lint and type check pass. - Replaying the review's measurement: the page's 120 `/@fs/` files, asked of a fresh server before anything else, are all served from a real `npm install -g` and a real `pnpm add -g` (pnpm 11, `links` store). The old boundary refused 69 under pnpm. - A build of this branch at 7754fb5 on macOS, Safari, with the stale cache from earlier previews in place: quickstart, two repeat previews, a page with a static image over two previews, and a second quickstart all loaded. The commits since restructure the fold, add the root guard and let the lookup throw; the unit and serve tests cover them, and on a project linked like the CLI links it the old and new lookup answer the same allow list. ## Note on Windows CI As finding 8 says, on `windows-latest` the test project lands inside the repository, which Vite's default already trusts, so the serve tests pass there with or without the allow list. They guard it on macOS and Linux. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5.1 <noreply@anthropic.com>
…dopted projects (#405) ## Summary `apimatic api validate` works inside a project without `--file` or `--url`: it zips `<input>/src/spec/` and validates the whole folder. `quickstart` validates an adopted project the same way, and keeps the project's own `apimatic.json`. ## `api validate` - **No flags:** zips everything in `<input>/src/spec/` and validates it. `-i`/`--input` is new and defaults to `./`. A spec split across files stays together with what it `$ref`s, and findings name the file inside the archive (`schemas/pet.yaml:1:1`). A single document is labelled with its own name instead of `UntitledAPI`. - **Flags:** `--file`, `--url` and `-i` are mutually exclusive (`[--file <value> | --url <value> | -i <value>]`). Each is refused, by name, when given empty or blank, so `--file "$SPEC" -i "$DIR"` with `SPEC` unset points at `--file`. - **Refused before anything is uploaded:** - a missing or empty `spec/` - a `spec/` that cannot be read, with the reason - a symlink or junction anywhere in `spec/`, each one named (the zip library used to crash on a linked folder) - a `--file` that cannot be read, in `api transform` too (it used to throw `ENOENT` with no outro) - **`--url` downloads** are named by `Content-Disposition`, or by the URL path without its query string. `sanitizeFilename` now strips path separators as it was meant to, so names like `../../escaped.json` or `specs/openapi.json` stay inside the temp directory. ## `quickstart` **Adopted project** (`src/spec/` holds anything): - Validates all of `spec/`, as `api validate` does. It used to upload only the portal's document, so a split spec failed quickstart and passed `api validate`. - Requires `src/apimatic.json`, as valid JSON in the schema version it reads. A missing file, one that is not valid JSON, or one such as `"schemaVersion": 2` stops it before validating, and the refusal says why: "it is not valid JSON", or the version it does not read. It no longer creates the file. - Checks `spec/` as the portal build does (`resolveSpecs()`), so Swagger 2.0 is refused with the build's `api transform` command before anything is written. - Uses `apimatic.json` as it is, adding only these: - `portal.site.name` when missing, named after the first spec `resolveSpecs()` returns (the whole `site` when the block has none) - the placeholder `plugin` block when there is none. An existing block is left alone, malformed or not, for the backend to report. - `languages`, asked for only when the file names none (no block, or `{}`, by the rule the build applies), and only after the additions above. Choosing none cancels and leaves those additions in place. A block of the wrong shape is not asked about or written to, and is left for the build to report. - Writes `content/index.md` and `content/nav.json` only when `content/` is missing. **New project:** a spec the user names is copied or downloaded into a `user-spec/` temp folder, apart from the sample's `sample/`, so the two never share a path. **Validation failure note:** names the command that validates the same spec: `apimatic api validate` for an adopted project, or `--file=<path>` / `--url=<url>` on its own line for a named one. The OpenAPI 3.x refusal names a named spec by its file name, not the wizard's temporary copy. When `apimatic.json` or its `portal` block is missing, `portal generate` and `portal serve` now say "Run `apimatic quickstart` in an empty directory with a sample spec to see an example of a valid portal." <details> <summary>Messages</summary> ```text $ apimatic api validate --file "" Error: Parsing --file The value is empty. Give a value, or leave the flag out. $ apimatic api validate --file does-not-exist.json ■ 'C:\…\does-not-exist.json' does not exist or could not be read. $ apimatic api validate # spec/ missing or empty ■ No API specification found in 'C:\…\src\spec'. Add yours there, point --input at the directory that holds 'src', or give a spec with --file or --url. $ apimatic api validate # a symlink in spec/ ■ 'schemas' in 'C:\…\src\spec' is a symlink, which cannot be uploaded for validation. Replace it with a copy of the files it points to. $ apimatic quickstart # spec/ filled, no apimatic.json ■ 'C:\…\src\spec' already holds files, but 'C:\…\src' has no 'apimatic.json'. │ Add the project's 'apimatic.json' there, or run apimatic quickstart from a directory with no 'src' to start a new portal. $ apimatic quickstart # spec/ filled, "schemaVersion": 2 ■ The 'apimatic.json' in 'C:\…\src' cannot be used: its 'schemaVersion' is 2, which this version of the CLI does not read; it reads 1. ``` </details> ## Code changes - `ResourceInput` includes `ProjectContext`, built by `createResourceInput` when no flag is given. `ResourceContext.resolveTo(input, tempDirectory)` turns any input into the one file to upload: `spec/` zipped, a URL downloaded, or a file copied. - `ValidateAction.execute` takes an input or an already-resolved `ResourceContext`, so quickstart validates the copy it scaffolds from. It returns `ActionResult<void, ValidateActionFailure>`, whose error is `'invalid'` or `'unchecked'`, in place of `SpecCheck` and `onChecked`. Quickstart treats a failure with no error as `'unchecked'`. - `api transform` still requires `--file` or `--url` (`createFileOrUrlInput`), since it names its output after the input file. - `CONTEXT.md` adds **Spec directory**. `.ai/skills/action.md` resolves through `ResourceContext.resolveTo` and reports with `specUnavailable`. - `commands/api/validate.ts`, `resource-input.ts`, `resource-context.ts`, `actions/api/transform.ts`, `flags-provider.ts` and `file-download-service.ts` switch to single quotes; they had never been through Prettier. - The README's `api validate` section is updated by hand from the 120-column `--help`, and its "Upgrading from 1.x" section is removed: it sent upgraders to run quickstart in a project that has no `apimatic.json`, which quickstart now refuses. ## Verification **`api validate` against the live service** - A two-file spec with a cross-file `$ref` passes with no flags; `--file` on its main document fails with "Reference could not be resolved". - `-i test/resources/portal-inputs/default` gives the same findings as `--file` on its one document. - A junction in `spec/`, a missing `--file`, and an empty `--file`, `--url` or `-i` each fail with their message and exit 1. - `--url` names carrying `../`, `../../../../`, `..\..\`, `nested/dir/` or `..%2F` are all written inside the temp directory. Before the fix, the deeper ones escaped it and a folder name failed with `ENOENT`. **`quickstart` against the live service** (adopted unless noted) - Template `v2` (`"site": {}`, three languages, no plugin): gains `site.name` and the placeholder plugin, `content/` and every other value stay as they were, no languages question, and the preview serves. - Two specs with `"site": {}`: named after the first spec, and the preview serves. - A malformed `plugin` block is left as written, and the backend reports `'pluginId' must be lower-case kebab-case`. - `{}`: asked for languages once `portal.site`, the placeholder plugin and `content/` are written. The choice is recorded and the preview serves. - `"languages": { "typescript": true }`: no languages question, and the preview reports `'languages.typescript' is not a JSON object.` `"schemaVersion": 2` is refused before step 1, by version, and a truncated `apimatic.json` as "not valid JSON", each with the file untouched and nothing written. - A read-only `src/` stops with "'apimatic.json' could not be written", and nothing is written. - A two-file spec passes validation and the `spec/` check. An invalid spec, a `spec/` holding only a `README.md`, Swagger 2.0, and a missing `apimatic.json` each stop with their message and leave `src/` untouched. - New project from a URL: still asks for languages, records them, and the preview serves. **Tests:** `pnpm test` gives 1666 passing, 46 pending, and `eslint src test` is clean. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
Co-authored-by: Claude Opus 5.5 <noreply@anthropic.com>
|
MuHamza30
approved these changes
Oct 9, 2026
Contributor
|
🎉 This PR is included in version 2.0.0-beta.5 🎉 The release is available on: Your semantic-release bot 📦🚀 |
Contributor
|
🎉 This PR is included in version 2.0.0 🎉 The release is available on: Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.



Promotes dev to beta, expected to publish 2.0.0-beta.5 to the npm beta dist-tag as a GitHub prerelease. The run commits nothing back to beta; the tag goes on this merge commit.
Merge with Create a merge commit.
What releases
api validateandquickstartavoids mutating adopted projects (feat(api): flaglessapi validateandquickstartavoids mutating adopted projects #405)🤖 Generated with Claude Code