Feat/spec asset hub#29
Merged
Merged
Conversation
Uploading an OpenAPI 3.x / Swagger 2.0 document into the Global Assets Files library now parses it once on upload and records a SpecAssetMeta summary (dialect, format, title, version, operationCount, warnings) on the asset. - shared: additive GlobalFileAsset.spec + SpecAssetMeta type (+ index export) - mock-server-core: browser-safe summarizeSpec() (detect dialect + count ops, no $ref resolution, no endpoint build) - ui-components: parse-on-upload in addGlobalFileAsset + fillGlobalFileAssetBytes; Assets-dock spec badge (SpecAssetBadge) + parsed summary in the file editor - mcp-server: assets.list_files envelope gains spec (null for ordinary files) - docs: CHANGELOG, mcp-tools-reference envelope, Help "Files" section Purely additive: existing assets and non-spec files are unaffected. Foundation for spec-driven mock servers (Increment B) and code-vs-spec drift.
Build a mock server from an uploaded spec asset (GlobalFileAsset) in two modes: "run live" (linked — endpoints derive from the asset, stay in sync, read-only) or "import & edit" (materialized — parsed into editable endpoints). - shared: MockServerSource `openapi-asset` variant + `isLinkedMockSource` - ui-components: `resolveMockEndpoints` (asset bytes -> parse); createMockServer handles both modes; `refreshMockServer`; linked read-only guards + auto-refresh of linked mocks when the asset changes; "From spec asset" modal tab; sidebar Refresh / Re-import actions + read-only indicator - mcp-server: `mock.refresh` tool + linked read-only guards on the 7 endpoint tools (catalog 94 -> 95) - vscode: mockYaml serializes the new source variant - docs: CHANGELOG, mcp-tools-reference, mock-server.md, Help; tool count reconciled across README / CLAUDE.md / AGENTS.md / docs Additive; existing mocks and sources are unaffected.
The editor's unified Import modal now recognises OpenAPI 3.x / Swagger 2.0 (auto-detect, or an explicit "OpenAPI / Swagger" source) — paste or upload a spec and it becomes a new folder with one request per operation (method, path, query/header/path params). The Global Assets spec editor gains an "Import to collection" button that imports straight from the stored asset. - shared: additive ApiRequest.specAssetId + operationId back-refs - ui-components: importOpenApiToCollection store action (reuses the mock resolver's parser dispatch); ImportModal OpenAPI source (sync detect via summarizeSpec, async import); Assets-dock "Import to collection" button - docs: CHANGELOG, Help import section Additive; existing requests and import formats are unaffected.
Every mock endpoint gains an "Add to collection" action (the mock sidebar's endpoint kebab) that creates a saved request from its method + path pattern + request-schema params — available even on read-only "run live" mocks. - ui-components: promoteMockEndpointToRequest store action; a shared requestShapeFromMockEndpoint mapper (also used by the OpenAPI importer so promoted + imported requests are identical); MocksSidebar "Add to collection" - mcp-server: mock.promote_endpoint tool (catalog 95 -> 96) - docs: CHANGELOG, mcp-tools-reference, Help; count reconciled across README / CLAUDE.md / AGENTS.md / docs Additive; existing mocks and requests are unaffected.
Promote the run-live (linked) mock path to a first-class, discoverable flow.
Previously "run live" was a radio buried in the New Mock Server modal, so a
contract server came out indistinguishable from a plain import.
- New "Serve OpenAPI contract" action in the Mocks header opens a dedicated
ServeContractModal: pick a spec asset, see a contract preview (title, version,
dialect, op count), name it, choose a port; creates a linked (read-only,
in-sync) mock and activates it so Start/Stop is right there.
- The unified "New Mock Server > From spec asset" path now always IMPORTS
(materialized/editable) and points to the new flow for run-live — removes the
confusing dual toggle that made this ambiguous.
- The mock panel shows a "Served directly from contract" callout + a friendly
source label ("OpenAPI contract (live)") for a linked mock.
- Store: mocksServeContractModalOpen + open/close actions (mirrors the create
modal). No new persisted shape or MCP tool — reuses createMockServer +
setMockServerDefaultPort. Additive; existing mocks and sources unaffected.
Tests: ServeContractModal (preview/create/port/validation/cancel/error),
sidebar 2-action menu, linked-mock panel callout, unified-modal import +
toggle-removal. Docs: CHANGELOG, mock-server.md, Help.
…sidebar names
A linked ("Serve OpenAPI contract") mock showed a read-only indicator but its
endpoint editor was fully interactive — the store rejected the edits, but the
inputs stayed enabled so it looked editable. Make read-only real:
- MockEndpointEditor wraps its header + node editor in <fieldset disabled> when
the mock is linked (isLinkedMockSource), disabling every native control at
once; the flow diagram stays enabled so the contract is still inspectable.
- The Monaco response-body editor isn't a form control, so it reads a new
MockReadOnlyContext (standalone module, no import cycle) to go read-only too.
- An explanatory banner points users to "New Mock Server -> From spec asset" for
an editable copy.
Also fix a sidebar bug: a long mock-server name (flex-1 without min-w-0) refused
to shrink and pushed the per-server actions (kebab) menu out of view. Add
min-w-0 so the existing truncate engages, plus shrink-0 on the row icons.
Tests: linked editor is read-only (banner + disabled controls); materialized
editor stays editable. Additive; materialized/manual/other mocks unaffected.
A "Serve OpenAPI contract" (linked, read-only) mock can now be unlocked for
editing in place, instead of re-creating it as a separate import.
- New convertMockToEditable(serverId) store action flips a linked openapi-asset
source to materialized: endpoints are preserved (already on the server, no
re-parse) and the spec link is kept, so "Re-import from spec" and asset-usage
tracking keep working. No-op for non-linked/manual/unknown mocks; success toast.
- Surfaced in all three read-only contexts: the Mocks sidebar kebab ("Convert
to editable mock"), the endpoint-editor read-only banner ("Convert to
editable", replacing the old import hint), and the panel's "Served directly
from contract" callout.
- Shorten the panel's source-kind label for a live contract from "OpenAPI
contract (live)" to "OpenAPI contract" (the callout already conveys liveness).
Tests: store flip preserves endpoints + unlocks editing + no-op cases; sidebar
action flips to materialized; banner button unlocks the editor. Docs: CHANGELOG,
mock-server.md, Help. Additive; other mocks unaffected.
…spec When a mock is served directly from an OpenAPI/Swagger contract, the user can now re-upload the modified spec from the mock itself and the endpoints update live — no hunting through Assets -> Files. - New reuploadMockSpec(serverId, file) store action: validates the file IS a spec first (a non-spec upload is rejected with an error toast, leaving the mock untouched), then replaces the backing asset's bytes via fillGlobalFileAssetBytes (re-parses the summary + auto-refreshes every linked mock reading it), and toasts the new endpoint count. No-op for non-openapi -asset mocks. - "Update spec..." file-picker surfaced in the panel's "Served directly from contract" callout and the sidebar kebab (linked mocks only). - Export the existing bytesFromFile helper (with its jsdom FileReader fallback) so validation reads bytes the same robust way as the rest of the app. Tests: replace+refresh, non-spec rejection, no-op manual, full sidebar upload flow, callout button presence. Docs: CHANGELOG, mock-server.md, Help. Additive.
…itor A live contract mock's editor was read-only via <fieldset disabled>, but the Add/Import/Remove CTAs were still visible (disabled, non-working) — confusing. Hide them in read-only mode and drop the empty-state "click Add ..." hints: - Rule overviews: "Add rule" / "Import rule" hidden; "No validation/response rules." without the click-to-add hint. - Request schema: "Derive from path" / "Add param" / row "Remove" hidden; "No <params>." without "Add one below." - Default response: "+ Header" / header "Remove" / "Add multiplier" hidden; the multipliers empty hint drops "Add one to repeat ...". All driven off the existing MockReadOnlyContext; inputs stay disabled+visible so the contract remains fully inspectable. (Rule-editor / form-data / attachment CTAs are unreachable for a spec-locked linked mock, so untouched.) Tests: read-only hides CTAs across the validation + default-response nodes and drops the hints; an editable mock keeps them. Additive.
…-mock option
Adding mock endpoints to a collection now produces runnable requests:
- A dedicated, activated "Mock" environment is ensured with MOCK_BASE_URL
(http://localhost) + MOCK_PORT (prefilled from the server's port, else 8080);
existing values are preserved on re-promote.
- Promoted request URLs are templated {{MOCK_BASE_URL}}:{{MOCK_PORT}}<path> so
they target the live mock and can be retargeted by editing the env.
- Requests land in a "<name> (mock)" folder (reused across repeated promotes).
- The server kebab gains "Add all to collection" (promoteMockToCollection) to
promote every endpoint at once, next to the per-endpoint "Add to collection".
requestShapeFromMockEndpoint gains an optional urlPrefix (import path unchanged).
The mock.promote_endpoint MCP tool still emits the basic mapping -- env/folder
auto-setup is UI-only for now.
Tests: env created+active+prefilled, folder created+reused, env-URL, whole-mock,
null cases. Docs: CHANGELOG, Help. Additive.
…e builder Prep for MCP + VS Code parity: the env + folder + templated-request logic that was inline in the web/desktop store now has one home, so all three surfaces behave identically. - @apicircle/shared: MOCK_ENV_NAME, MOCK_URL_PREFIX, mockEnvVarDefaults, mockFolderName, and requestShapeFromMockEndpoint (moved from ui-components). - @apicircle/core: buildMockPromotion(synced, mock, endpoints, opts) returns the ordered WorkspacePatch sequence (ensure the active "Mock" env, find-or-create the "<name> (mock)" folder, one templated request per endpoint) + folderId + requestIds. Pure; every surface applies it via its own applyMutation path. - ui-components: the two promote store actions now build patches via buildMockPromotion and apply them with applyMutation -- behavior-preserving (existing promote tests pass) and no more duplicated orchestration. Tests: new core buildMockPromotion suite (env/folder/request, port prefill + value preservation, folder reuse). Existing promote/import tests stay green. Additive; no shipped shape changed.
…ension
Brings the env + folder + templated-URL promotion (increment J) to the two
surfaces that lacked it, all through the shared core buildMockPromotion (K1).
MCP (catalog 96 -> 97):
- mock.promote_endpoint now ensures the active "Mock" env (MOCK_BASE_URL +
MOCK_PORT, prefilled from the mock's port else 8080), drops the request in a
"<name> (mock)" folder, and templates the URL
{{MOCK_BASE_URL}}:{{MOCK_PORT}}<path>.
- New mock.promote_to_collection tool promotes every endpoint at once.
- Count bumped across README (x3), mcp-server README (badge + heading), vscode
README, mcp-tools-reference (+ rows), context doc, AGENTS, CLAUDE.
VS Code:
- New "Add to Collection" (mock endpoint node) + "Add All to Collection" (mock
server node) commands via buildMockPromotion + active.apply, with command +
view/item/context menu manifest entries.
All three surfaces now produce identical results (same Mock env, "<name> (mock)"
folder, templated URLs). Tests: MCP promote tools + vscode commands. Docs:
CHANGELOG. Additive.
…quest shape
K2 changed `mock.promote_endpoint` to emit a runnable request (active "Mock"
env + "<name> (mock)" folder + templated `{{MOCK_BASE_URL}}:{{MOCK_PORT}}<path>`
URL) but only `mocks.test.ts` was updated — `mockRefresh.test.ts` still asserted
the old bare `/pets` path, so it failed under the full suite. Assert the new,
already-shipped-and-documented behavior instead (templated URL, folder, active
Mock env with MOCK_PORT=8080 for the portless linked mock).
`vsce package` was bundling the extension's `coverage/` report (137 files, ~7.7 MB of HTML) and the `.turbo/` cache into the marketplace `.vsix` because `.vscodeignore` didn't exclude them. Add both — the packaged extension drops from 167 files / 2.88 MB to 28 files / 1.74 MB, shipping only the runtime bundle, manifest, readme, changelog, license, media, schemas, and syntaxes.
Cut the 1.3.0 release. All workspace packages move to 1.3.0 in lockstep —
published: @apicircle/{shared,core,mock-server-core,mcp-server,cli} and the
apicircle-vscode extension; private: desktop, web, ui-components, git,
desktop-shell, e2e/*, examples (desktop-shell realigned from a stray 1.1.5).
Inter-package deps are workspace:*, so no dependency pins changed and the
lockfile is untouched.
- CHANGELOG.md: promote the accumulated "1.2.1 - Unreleased" block to
"1.3.0 - 2026-07-18" (the spec asset hub + Mock -> collection parity across
app / MCP / VS Code), and reconcile the promote_endpoint note now that the
MCP + VS Code surfaces reached parity (no longer "UI-only").
- apps/vscode/CHANGELOG.md: 1.3.0 entry for the Add to Collection / Add All to
Collection commands (the file the marketplace renders).
MCP catalog stays at 97 tools. Verified before cutting: pnpm check, lint,
build (10/10), knip (pre-existing baseline only), and the full unit suite
(~5450 tests) all green; the extension packages to a clean 1.74 MB VSIX.
E2E coverage (strict mode)
|
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.
Mock → collection parity across the MCP server + VS Code.