Skip to content

Commit d245844

Browse files
authored
Client parity follow-ups (re-target to main): unify client, TODOs, tests, CI, versions (#87)
* fix: Restore client parity with server (#75, #76, #77) - fix(vscode #75): escape nested template literals in endpointTesterPanel so the webview HTML literal no longer desyncs the parser; build @flapi/shared automatically (shared prepare + extension prebuild) so EndpointConfig types resolve. Extension builds and typechecks again (broken since 2025-11-02). - feat(cli #76): add commands for server capabilities that had no CLI surface: health, config env, config filesystem, endpoints parameters, cache audit [path], cache gc. - fix(cli #77): FlapiApiClient.testEndpoint targets the real /template/test route instead of the non-existent /test (would 404). - docs: add CLIENT_PARITY_AUDIT.md documenting findings and resolution. * refactor: Unify extension on shared API client; cleanup; version align (#81, #83, #85) - refactor(vscode #83): delete the extension's duplicate FlapiApiClient and point extension.ts + yamlValidator at @flapi/shared's client; add slug-based validateEndpointConfig/reloadEndpointConfig and X-Config-Token to setToken. Fixes the local client's broken base-URL (it read non-existent flapi.host/port). - fix(vscode #81): remove dead 'Variables provider' editor-change handler. - chore(#85): align cli, @flapi/shared, and the extension to 26.6.13. * feat(vscode): resolve {{include}} directives and add endpoint picker (#79, #80) - feat(#80): add a pure extendedYaml resolver that inlines {{include:<section> from <file>}} directives from sibling workspace files; CodeLens now uses it instead of stripping includes and parsing blindly. - feat(#79): when multiple endpoints reference one SQL template, show a QuickPick selector instead of silently using the first. * test+ci: Add VSCode extension test suite and a clients CI gate (#82, #84) - test(vscode #84): set up Vitest and cover the pure logic — extended-YAML include resolution and endpoint-pick label building (12 tests). - ci(#82): add .github/workflows/clients.yaml that builds @flapi/shared, builds and tests the CLI, and typechecks/builds/tests the extension on every PR that touches cli/. This would have caught #75. * chore: Sync cli + shared lockfiles to 26.6.13 (#85) Keeps package-lock.json in step with the version bump so 'npm ci' (used by the new clients CI gate) doesn't fail on a version mismatch.
1 parent d6adfb1 commit d245844

18 files changed

Lines changed: 2017 additions & 306 deletions

.github/workflows/clients.yaml

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
name: Clients (CLI + VSCode)
2+
3+
# Compile/test gate for the TypeScript packages under cli/. This exists so a broken
4+
# build (like the extension being uncompilable for months) is caught on every PR.
5+
6+
on:
7+
push:
8+
branches: [ main ]
9+
paths:
10+
- 'cli/**'
11+
- '.github/workflows/clients.yaml'
12+
pull_request:
13+
branches: [ main ]
14+
paths:
15+
- 'cli/**'
16+
- '.github/workflows/clients.yaml'
17+
18+
concurrency:
19+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
20+
cancel-in-progress: true
21+
22+
jobs:
23+
shared:
24+
runs-on: ubuntu-latest
25+
steps:
26+
- uses: actions/checkout@v4
27+
- uses: actions/setup-node@v4
28+
with:
29+
node-version: '22'
30+
- name: Build @flapi/shared
31+
working-directory: cli/shared
32+
run: |
33+
npm ci
34+
npm run build
35+
36+
cli:
37+
runs-on: ubuntu-latest
38+
steps:
39+
- uses: actions/checkout@v4
40+
- uses: actions/setup-node@v4
41+
with:
42+
node-version: '22'
43+
- name: Build & test flapii CLI
44+
working-directory: cli
45+
run: |
46+
npm ci
47+
npm run build
48+
npm test
49+
50+
vscode-extension:
51+
runs-on: ubuntu-latest
52+
steps:
53+
- uses: actions/checkout@v4
54+
- uses: actions/setup-node@v4
55+
with:
56+
node-version: '22'
57+
- name: Build, typecheck & test the VSCode extension
58+
working-directory: cli/vscode-extension
59+
run: |
60+
npm ci
61+
npm run typecheck
62+
npm run build
63+
npm test

cli/package-lock.json

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "flapii",
3-
"version": "0.1.0",
3+
"version": "26.6.13",
44
"description": "CLI client for flapi ConfigService",
55
"license": "MIT",
66
"type": "module",

cli/shared/package-lock.json

Lines changed: 2 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

cli/shared/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@flapi/shared",
3-
"version": "0.1.0",
3+
"version": "26.6.13",
44
"type": "module",
55
"main": "dist/index.js",
66
"types": "dist/index.d.ts",

cli/shared/src/apiClient.ts

Lines changed: 44 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import axios from 'axios';
22
import type { AxiosInstance, AxiosRequestConfig, InternalAxiosRequestConfig } from 'axios';
33
import { pathToSlug, slugToPath } from './lib/url';
4+
import type { ValidationResult, ReloadResult } from './lib/types';
45

56
/**
67
* Configuration options for FlapiApiClient
@@ -188,8 +189,14 @@ export class FlapiApiClient {
188189
/**
189190
* Update authentication token
190191
*/
191-
setToken(token: string) {
192-
this.client.defaults.headers.common['Authorization'] = `Bearer ${token}`;
192+
setToken(token: string | undefined) {
193+
if (token) {
194+
this.client.defaults.headers.common['Authorization'] = `Bearer ${token}`;
195+
this.client.defaults.headers.common['X-Config-Token'] = token;
196+
} else {
197+
delete this.client.defaults.headers.common['Authorization'];
198+
delete this.client.defaults.headers.common['X-Config-Token'];
199+
}
193200
if (this.debug) {
194201
console.log('[FlapiAPI] Token updated');
195202
}
@@ -347,6 +354,41 @@ export class FlapiApiClient {
347354
const response = await this.client.get('/api/v1/_config/endpoints');
348355
return response.data;
349356
}
357+
358+
/**
359+
* Validate raw endpoint YAML for an already-encoded endpoint slug.
360+
* A 400 (invalid config) is returned as a normalized result rather than thrown.
361+
*/
362+
async validateEndpointConfig(slug: string, yamlContent: string): Promise<ValidationResult> {
363+
const response = await this.client.post(
364+
`/api/v1/_config/endpoints/${encodeURIComponent(slug)}/validate`,
365+
yamlContent,
366+
{
367+
headers: { 'Content-Type': 'application/x-yaml' },
368+
validateStatus: (status) => status < 500,
369+
},
370+
);
371+
const result = response.data ?? {};
372+
return {
373+
valid: result.valid ?? false,
374+
errors: result.errors ?? [],
375+
warnings: result.warnings ?? [],
376+
};
377+
}
378+
379+
/**
380+
* Reload an endpoint configuration from disk by already-encoded slug.
381+
*/
382+
async reloadEndpointConfig(slug: string): Promise<ReloadResult> {
383+
const response = await this.client.post(
384+
`/api/v1/_config/endpoints/${encodeURIComponent(slug)}/reload`,
385+
);
386+
const result = response.data ?? {};
387+
return {
388+
success: result.success ?? false,
389+
message: result.message ?? '',
390+
};
391+
}
350392
}
351393

352394
/**

0 commit comments

Comments
 (0)