Repository navigation
fix(portal): keep the preview up and report a broken specification while serving - #434
Open
saeedjamshaid wants to merge 7 commits into
Open
saeedjamshaid wants to merge 7 commits into
saeedjamshaid wants to merge 7 commits into
Conversation
Under `vite dev`, one document saved half written failed the module every route imports, so every page of the preview answered 500 until it was fixed. The preview now leaves that document's reference pages out and serves the rest; a build still fails on it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… document cannot be read Startup read only the documents at the top of `spec/`, so a split specification whose `$ref` named a missing or half-written file passed the check, then failed late in the build or rendered with that reference empty. The files each document refers to are now followed as the portal's bundler follows them, each read once and in parallel, and one that is missing or unreadable is refused, naming the file that refers to it. A document that does not parse is reported with the parser's reason, which carries its line and column. A table of cases holds the check to `bundleSpec`. The preview's dev-only handling in `openApiSource` is inlined. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…runs A specification saved with a mistake left its reference out of the preview and said nothing. Each save in `spec/` is now checked as `portal generate` checks it: a mistake is reported with the reason, the next good save says it is fixed, and a document added or removed is warned of once, since the preview serves only the documents it started with. The live preview note says so. The "refused, then fixed once" state the content and config previews each kept is one type now, and the sentences the watch messages shared live once in the prompts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…ec-errors #405 added the same `resolveSpecs` for quickstart, so one is kept for both callers, and the test this branch had for it gives way to the ones #405 brought. `specRejected` drops the `offerQuickstart` option #405 removed from `reportSourceProblem`. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…w's allow list Vite resolves a symlink before comparing a requested file against `server.fs.allow`, and the static directory was listed as written. A project reached through a symlink, as anything under macOS's `/tmp` or `/var` is, had a static file asked for before its page refused with 403, which is the request apimatic-io#2287 is about. The directory is now named by its real path, as the dependency directories beside it already are. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…the review The check read a file by its extension, and took the `$id`s a `$ref` may name from the file the `$ref` sat in, so a referenced `.json` holding YAML, or a `$ref` naming an `$id` of the root document, was refused although the portal builds it. Every file is now read as the bundler reads it, by what it holds, and one the bundler fails on or reads as nothing is refused with the reason. The `$id`s a reference may name are the root document's, as in the bundler. A document gone from `spec/` mid-save is reported as unreadable rather than left out, which had the preview warn that it was removed. `specs()` is back within Sonar's cognitive complexity limit, the watch messages say what the preview leaves out, and a test replaces the comment on the order in which `PreviewConfig.show` accepts a refusal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
… the preview's messages The `$ref` walk leaves the source context for `SpecBundle`, a plain type that records each file read and lists the ones still to read, while the context reads them a level at a time. A spec problem's reason is a kind the prompt words, so a document gone mid-save is "no longer there" rather than an ENOENT message, and a missing referenced file is a `MissingFile`, which names its spelling on disk in another case. The 50 characters the bundler looks at for JSON are a named constant, held to the bundler by a row of its table. The preview's watch messages are one prompt each, keyed by what is watched, and each preview type's answer goes straight to its prompt. A save of `apimatic.json` that throws now says its changes could not be checked, and a lost watch on it no longer says "further edits". Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
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.



The problem
Under
portal serve, a specification saved half written, a broken or missing file of a split specification, or a deleted specification made every address of the preview answer 500, Markdown pages included. The terminal said nothing, and the open tab needed F5 once the file was fixed.Before the preview starts, and in
portal generate, only the documents at the top ofspec/were checked. A file that a$refnamed, missing or half written, passed the check and failed the build later, and a document that did not parse was reported with no reason.What changes
vite dev,openApiSource()loads each document on its own and leaves out the reference pages of one that fails, so the rest of the portal is served. A build still fails on it.$refnames, is read by what it holds, as@scalar/json-magicreads it: JSON, else YAML when the text holds a key and does not open as JSON does within its first 50 characters. One the bundler fails on, or reads as nothing (an empty file, one holding only comments), is refused asunreadableSpec, with the reason: the parser's own words for a syntax error, and the CLI's for the rest, such as "it is empty". The parser used to be picked by the file's extension.dev: a.jsonfile holding YAML is accepted, as the portal builds it; an empty, comment-only or key-less file at the top ofspec/is refused, where it was ignored (an empty.jsonalready was).$ref. The files each document refers to are followed as the bundler follows them, each read once per document, a level of references at a time and in parallel within a level. One that is missing is refused asmissingSpecReference, and one that cannot be read asunreadableSpec, each naming the file that refers to it. A missing file that is on disk in another case, as a file system that matches case misses it, is named as it is spelt.$refon any object or list, resolved from the folder of the file it is written in, but not past a$ref's siblings orx-ext/x-ext-urls. A$refthat names an$idof the root document names a schema, not a file, in every file the document is bundled from.bundleSpecand the check on the same files, so the two cannot drift apart. Each row says whether the bundler builds, fails, or reads a file as nothing, which leaves its reference empty; the check accepts only what builds.SpecBundlerecords each file read and lists the ones still to read, and answers the document's operations; the source context does the reading.OpenApiDocument.parsereturns aResultcarrying the parser's message on one line, with its line and column.spec/is checked while serving, against the same rules:portal generatereports it, and the next save that fixes it says so once;spec/or taken out of it is warned of once, since the preview serves only the documents it started with;PreviewRefusalreplaces the flagPreviewContentandPreviewConfigeach kept. A message the watches ofapimatic.json,content/andspec/share is one prompt, keyed by what is watched, and what each preview says after an accepted save is decided in its prompt. Two sentences change forapimatic.json: a fault while checking a save now says its changes "could not be checked" (it said "could not be applied to the preview"), and a lost watch no longer says "further edits".server.fs.allow, as the dependency directories already are: Vite resolves a symlink before comparing, so under macOS's/tmpor/vara static file asked for before its page, as Safari does in apimatic-io issue 2287, was refused with 403. The serve e2e test, now run on a copy of the fixture in the temp directory, found it on macOS.devreformattedsrc/actions/action-result.tsandsrc/prompts/api/transform.ts: lint-staged ran Prettier over them. Nothing else in them changed.What it prints
Testing
pnpm test: 1864 passing, with the source and the tests type-checked and ESLint clean. New tests cover each$refrule, how a file is read, the bundler table,SpecBundle, the messages, the two preview state types, and the spec watch inportal serveon a copy of the fixture.APIMATIC_E2E=1serve and build: 64 passing. The new serve test saves a specification half written, checks that its reference is left out while a Markdown page is still served, and that the reference comes back once the file is fixed.portal servesessions, with a browser tab left open, on a single-file specification and on a split one in a folder named with a space and an accent: a half-written root document, a renamed, added or deleted document, a missing$ref'd file, half-written YAML and JSON in referenced files, and CTRL+C. All were reported as above, and the open tab recovered without F5. These ran before 865ac82 and ecd4b0e, which changed how a file is read and some of the wording.Not in this PR
operationId, is still not reported while serving. Its reference is left out rather than failing every page.$refnames outsidesrc/specare checked, but saving one is not watched.$refbelow an$idis not checked: the bundler resolves it against the$id, which names no folder of the specification, so it is left to the build.🤖 Generated with Claude Code