Migrate to Vite+ unified toolchain (#428)

This commit is contained in:
Gregory Schier
2026-03-13 09:27:56 -07:00
committed by GitHub
parent aed7bd12ea
commit 45262edfbd
166 changed files with 1762 additions and 1519 deletions

View File

@@ -14,17 +14,20 @@ jobs:
runs-on: macos-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
- uses: voidzero-dev/setup-vp@v1
with:
node-version: '24'
cache: true
- uses: dtolnay/rust-toolchain@stable
- uses: Swatinem/rust-cache@v2
with:
shared-key: ci
cache-on-failure: true
- run: npm ci
- run: vp install
- run: npm run bootstrap
- run: npm run lint
- name: Run JS Tests
run: npm test
run: vp test
- name: Run Rust Tests
run: cargo test --all

View File

@@ -50,8 +50,11 @@ jobs:
- name: Checkout yaakapp/app
uses: actions/checkout@v4
- name: Setup Node
uses: actions/setup-node@v4
- name: Setup Vite+
uses: voidzero-dev/setup-vp@v1
with:
node-version: '24'
cache: true
- name: install Rust stable
uses: dtolnay/rust-toolchain@stable
@@ -87,13 +90,13 @@ jobs:
echo $dir >> $env:GITHUB_PATH
& $exe --version
- run: npm ci
- run: vp install
- run: npm run bootstrap
env:
YAAK_TARGET_ARCH: ${{ matrix.yaak_arch }}
- run: npm run lint
- name: Run JS Tests
run: npm test
run: vp test
- name: Run Rust Tests
run: cargo test --all --exclude yaak-cli

1
.node-version Normal file
View File

@@ -0,0 +1 @@
24.14.0

1
.vite-hooks/pre-commit Normal file
View File

@@ -0,0 +1 @@
vp lint

View File

@@ -1,3 +1,3 @@
{
"recommendations": ["biomejs.biome", "rust-lang.rust-analyzer", "bradlc.vscode-tailwindcss"]
"recommendations": ["rust-lang.rust-analyzer", "bradlc.vscode-tailwindcss", "VoidZero.vite-plus-extension-pack"]
}

View File

@@ -1,6 +1,8 @@
{
"editor.defaultFormatter": "biomejs.biome",
"editor.defaultFormatter": "oxc.oxc-vscode",
"editor.formatOnSave": true,
"biome.enabled": true,
"biome.lint.format.enable": true
"editor.formatOnSaveMode": "file",
"editor.codeActionsOnSave": {
"source.fixAll.oxc": "explicit"
}
}

View File

@@ -1,55 +0,0 @@
{
"$schema": "https://biomejs.dev/schemas/2.3.13/schema.json",
"linter": {
"enabled": true,
"rules": {
"recommended": true,
"a11y": {
"useKeyWithClickEvents": "off"
}
}
},
"formatter": {
"enabled": true,
"indentStyle": "space",
"indentWidth": 2,
"lineWidth": 100,
"bracketSpacing": true
},
"css": {
"parser": {
"tailwindDirectives": true
},
"linter": {
"enabled": false
}
},
"javascript": {
"formatter": {
"quoteStyle": "single",
"jsxQuoteStyle": "double",
"trailingCommas": "all",
"semicolons": "always"
}
},
"files": {
"includes": [
"**",
"!**/node_modules",
"!**/dist",
"!**/build",
"!target",
"!scripts",
"!crates",
"!crates-tauri",
"!src-web/tailwind.config.cjs",
"!src-web/postcss.config.cjs",
"!src-web/vite.config.ts",
"!src-web/routeTree.gen.ts",
"!packages/plugin-runtime-types/lib",
"!**/bindings",
"!flatpak",
"!npm"
]
}
}

View File

@@ -29,7 +29,7 @@ export function useLicense() {
await queryClient.invalidateQueries({ queryKey: CHECK_QUERY_KEY });
});
return () => {
unlisten.then((fn) => fn());
void unlisten.then((fn) => fn());
};
}, []);

View File

@@ -89,8 +89,8 @@ export const gitMutations = (dir: string, callbacks: GitCallbacks) => {
const handleError = (err: unknown) => {
showToast({
id: `${err}`,
message: `${err}`,
id: err instanceof Error ? err.message : String(err),
message: err instanceof Error ? err.message : String(err),
color: 'danger',
timeout: 5000,
});
@@ -186,16 +186,16 @@ export const gitMutations = (dir: string, callbacks: GitCallbacks) => {
}
if (result.type === 'uncommitted_changes') {
callbacks.promptUncommittedChanges().then(async (strategy) => {
void callbacks.promptUncommittedChanges().then(async (strategy) => {
if (strategy === 'cancel') return;
await invoke('cmd_git_reset_changes', { dir });
return invoke<PullResult>('cmd_git_pull', { dir });
}).then(async () => { onSuccess(); await callbacks.forceSync(); }, handleError);
}).then(async () => { await onSuccess(); await callbacks.forceSync(); }, handleError);
}
if (result.type === 'diverged') {
callbacks.promptDiverged(result).then((strategy) => {
void callbacks.promptDiverged(result).then((strategy) => {
if (strategy === 'cancel') return;
if (strategy === 'force_reset') {
@@ -211,7 +211,7 @@ export const gitMutations = (dir: string, callbacks: GitCallbacks) => {
remote: result.remote,
branch: result.branch,
});
}).then(async () => { onSuccess(); await callbacks.forceSync(); }, handleError);
}).then(async () => { await onSuccess(); await callbacks.forceSync(); }, handleError);
}
return result;

View File

@@ -88,6 +88,7 @@ export function getAnyModel(
): AnyModel | null {
let data = mustStore().get(modelStoreDataAtom);
for (const t of Object.keys(data)) {
// oxlint-disable-next-line no-explicit-any
let v = (data as any)[t]?.[id];
if (v?.model === t) return v;
}

View File

@@ -39,7 +39,7 @@ export function watchWorkspaceFiles(
channel,
});
unlistenPromise.then(({ unlistenEvent }) => {
void unlistenPromise.then(({ unlistenEvent }) => {
addWatchKey(unlistenEvent);
});
@@ -53,7 +53,7 @@ export function watchWorkspaceFiles(
}
function unlistenToWatcher(unlistenEvent: string) {
emit(unlistenEvent).then(() => {
void emit(unlistenEvent).then(() => {
removeWatchKey(unlistenEvent);
});
}

View File

@@ -1,4 +1,6 @@
const { execSync } = require('node:child_process');
const fs = require('node:fs');
const path = require('node:path');
if (process.env.SKIP_WASM_BUILD === '1') {
console.log('Skipping wasm-pack build (SKIP_WASM_BUILD=1)');
@@ -6,3 +8,20 @@ if (process.env.SKIP_WASM_BUILD === '1') {
}
execSync('wasm-pack build --target bundler', { stdio: 'inherit' });
// Rewrite the generated entry to use Vite's ?init import style instead of
// the ES Module Integration style that wasm-pack generates, which Vite/rolldown
// does not support in production builds.
const entry = path.join(__dirname, 'pkg', 'yaak_templates.js');
fs.writeFileSync(
entry,
[
'import init from "./yaak_templates_bg.wasm?init";',
'export * from "./yaak_templates_bg.js";',
'import * as bg from "./yaak_templates_bg.js";',
'const instance = await init({ "./yaak_templates_bg.js": bg });',
'bg.__wbg_set_wasm(instance.exports);',
'instance.exports.__wbindgen_start();',
'',
].join('\n'),
);

View File

@@ -1,5 +1,6 @@
import * as wasm from "./yaak_templates_bg.wasm";
import init from "./yaak_templates_bg.wasm?init";
export * from "./yaak_templates_bg.js";
import { __wbg_set_wasm } from "./yaak_templates_bg.js";
__wbg_set_wasm(wasm);
wasm.__wbindgen_start();
import * as bg from "./yaak_templates_bg.js";
const instance = await init({ "./yaak_templates_bg.js": bg });
bg.__wbg_set_wasm(instance.exports);
instance.exports.__wbindgen_start();

2576
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@@ -63,7 +63,7 @@
"src-web"
],
"scripts": {
"prepare": "husky",
"prepare": "vp config",
"init": "npm install && npm run bootstrap",
"start": "npm run app-dev",
"app-build": "tauri build",
@@ -83,27 +83,27 @@
"vendor:vendor-protoc": "node scripts/vendor-protoc.cjs",
"vendor:vendor-node": "node scripts/vendor-node.cjs",
"lint": "run-p lint:*",
"lint:biome": "biome lint",
"lint:extra": "npm run --workspaces --if-present lint",
"format": "biome format --write .",
"lint:vp": "vp lint",
"lint:workspaces": "npm run --workspaces --if-present lint",
"replace-version": "node scripts/replace-version.cjs",
"tauri": "tauri",
"tauri-before-build": "npm run bootstrap",
"tauri-before-dev": "node scripts/run-workspaces-dev.mjs"
},
"overrides": {
"js-yaml": "^4.1.1"
"js-yaml": "^4.1.1",
"vite": "npm:@voidzero-dev/vite-plus-core@latest",
"vitest": "npm:@voidzero-dev/vite-plus-test@latest"
},
"devDependencies": {
"@biomejs/biome": "^2.3.13",
"@tauri-apps/cli": "^2.9.6",
"@yaakapp/cli": "^0.5.1",
"dotenv-cli": "^11.0.0",
"husky": "^9.1.7",
"nodejs-file-downloader": "^4.13.0",
"npm-run-all": "^4.1.5",
"typescript": "^5.8.3",
"vitest": "^3.2.4"
"vite-plus": "latest",
"vitest": "npm:@voidzero-dev/vite-plus-test@latest"
},
"dependencies": {
"@codemirror/lang-go": "^6.0.1",
@@ -111,5 +111,6 @@
"@codemirror/lang-php": "^6.0.2",
"@codemirror/lang-python": "^6.2.1",
"@codemirror/legacy-modes": "^6.5.2"
}
},
"packageManager": "npm@11.11.1"
}

View File

@@ -1,7 +1,7 @@
// biome-ignore lint/suspicious/noExplicitAny: none
// oxlint-disable-next-line no-explicit-any
export function debounce(fn: (...args: any[]) => void, delay = 500) {
let timer: ReturnType<typeof setTimeout>;
// biome-ignore lint/suspicious/noExplicitAny: none
// oxlint-disable-next-line no-explicit-any
const result = (...args: any[]) => {
clearTimeout(timer);
timer = setTimeout(() => fn(...args), delay);

View File

@@ -16,7 +16,7 @@ type AddDynamicMethod<T> = {
) => MaybePromise<Partial<T> | null | undefined>;
};
// biome-ignore lint/suspicious/noExplicitAny: distributive conditional type pattern
// oxlint-disable-next-line no-explicit-any -- distributive conditional type pattern
type AddDynamic<T> = T extends any
? T extends { inputs?: FormInput[] }
? Omit<T, 'inputs'> & {

View File

@@ -42,7 +42,7 @@ type AddDynamicMethod<T> = {
) => MaybePromise<Partial<T> | null | undefined>;
};
// biome-ignore lint/suspicious/noExplicitAny: distributive conditional type pattern
// oxlint-disable-next-line no-explicit-any -- distributive conditional type pattern
type AddDynamic<T> = T extends any
? T extends { inputs?: FormInput[] }
? Omit<T, 'inputs'> & {

View File

@@ -9,7 +9,7 @@ type AddDynamicMethod<T> = {
) => MaybePromise<Partial<T> | null | undefined>;
};
// biome-ignore lint/suspicious/noExplicitAny: distributive conditional type pattern
// oxlint-disable-next-line no-explicit-any -- distributive conditional type pattern
type AddDynamic<T> = T extends any
? T extends { inputs?: FormInput[] }
? Omit<T, 'inputs'> & {

View File

@@ -91,7 +91,7 @@ export class PluginInstance {
);
} catch (err: unknown) {
await ctx.toast.show({
message: `Failed to initialize plugin ${this.#workerData.bootRequest.dir.split('/').pop()}: ${err}`,
message: `Failed to initialize plugin ${this.#workerData.bootRequest.dir.split('/').pop()}: ${err instanceof Error ? err.message : String(err)}`,
color: 'notice',
icon: 'alert_triangle',
timeout: 30000,
@@ -328,7 +328,8 @@ export class PluginInstance {
payload.values = applyFormInputDefaults(args, payload.values);
const resolvedArgs = await applyDynamicFormInput(ctx, args, payload);
const resolvedActions: HttpAuthenticationAction[] = [];
for (const { onSelect, ...action } of actions ?? []) {
// oxlint-disable-next-line unbound-method
for (const { onSelect: _onSelect, ...action } of actions ?? []) {
resolvedActions.push(action);
}
@@ -474,7 +475,7 @@ export class PluginInstance {
{
type: 'call_template_function_response',
value: null,
error: `${err}`.replace(/^Error:\s*/g, ''),
error: (err instanceof Error ? err.message : String(err)).replace(/^Error:\s*/g, ''),
},
replyId,
);
@@ -483,7 +484,7 @@ export class PluginInstance {
}
}
} catch (err) {
const error = `${err}`.replace(/^Error:\s*/g, '');
const error = (err instanceof Error ? err.message : String(err)).replace(/^Error:\s*/g, '');
console.log('Plugin call threw exception', payload.type, '→', error);
this.#sendPayload(context, { type: 'error_response', error }, replyId);
return;
@@ -909,7 +910,7 @@ export class PluginInstance {
render: async (args: TemplateRenderRequest) => {
const payload = { type: 'template_render_request', ...args } as const;
const result = await this.#sendForReply<TemplateRenderResponse>(context, payload);
// biome-ignore lint/suspicious/noExplicitAny: That's okay
// oxlint-disable-next-line no-explicit-any -- That's okay
return result.data as any;
},
},
@@ -972,8 +973,8 @@ export class PluginInstance {
function stripDynamicCallbacks(inputs: { dynamic?: unknown }[]): FormInput[] {
return inputs.map((input) => {
// biome-ignore lint/suspicious/noExplicitAny: stripping dynamic from union type
const { dynamic, ...rest } = input as any;
// oxlint-disable-next-line no-explicit-any -- stripping dynamic from union type
const { dynamic: _dynamic, ...rest } = input as any;
if ('inputs' in rest && Array.isArray(rest.inputs)) {
rest.inputs = stripDynamicCallbacks(rest.inputs);
}

View File

@@ -1,3 +1,4 @@
/* oxlint-disable unbound-method */
import process from 'node:process';
export function interceptStdout(intercept: (text: string) => string) {
@@ -24,5 +25,5 @@ export function interceptStdout(intercept: (text: string) => string) {
}
function interceptor(text: string, fn: (text: string) => string) {
return fn(text).replace(/\n$/, '') + (fn(text) && /\n$/.test(text) ? '\n' : '');
return fn(text).replace(/\n$/, '') + (fn(text) && text.endsWith('\n') ? '\n' : '');
}

View File

@@ -1,7 +1,7 @@
import { applyFormInputDefaults } from '@yaakapp-internal/lib/templateFunction';
import type { CallTemplateFunctionArgs } from '@yaakapp-internal/plugins';
import type { Context, DynamicTemplateFunctionArg } from '@yaakapp/api';
import { describe, expect, test } from 'vitest';
import { describe, expect, test } from 'vite-plus/test';
import { applyDynamicFormInput } from '../src/common';
describe('applyFormInputDefaults', () => {

View File

@@ -10,11 +10,7 @@
"moduleResolution": "node16",
"resolveJsonModule": true,
"sourceMap": true,
"outDir": "build",
"baseUrl": ".",
"paths": {
"*": ["node_modules/*", "src/types/*"]
}
"outDir": "build"
},
"include": ["src"]
}

View File

@@ -12,7 +12,7 @@
"scripts": {
"build": "yaakcli build",
"dev": "yaakcli dev",
"test": "vitest --run tests"
"test": "vp test --run tests"
},
"dependencies": {
"@faker-js/faker": "^10.1.0"

View File

@@ -1,4 +1,4 @@
import { describe, expect, it } from 'vitest';
import { describe, expect, it } from 'vite-plus/test';
describe('template-function-faker', () => {
it('exports all expected template functions', async () => {
@@ -13,6 +13,7 @@ describe('template-function-faker', () => {
it('renders date results as unquoted ISO strings', async () => {
const { plugin } = await import('../src/index');
const fn = plugin.templateFunctions?.find((fn) => fn.name === 'faker.date.future');
// oxlint-disable-next-line unbound-method
const onRender = fn?.onRender;
expect(onRender).toBeTypeOf('function');

View File

@@ -173,7 +173,7 @@ function toHarRequest(request: Partial<HttpRequest>) {
return har;
}
function maybeParseJSON<T>(v: unknown, fallback: T): T | unknown {
function maybeParseJSON<T>(v: unknown, fallback: T): unknown {
if (typeof v !== 'string') return fallback;
try {
return JSON.parse(v);
@@ -305,7 +305,7 @@ export const plugin: PluginDefinition = {
});
} catch (err) {
await ctx.toast.show({
message: `Failed to generate snippet: ${err}`,
message: `Failed to generate snippet: ${err instanceof Error ? err.message : String(err)}`,
icon: 'alert_triangle',
color: 'danger',
});

View File

@@ -15,7 +15,7 @@ export const plugin: PluginDefinition = {
mcpServer = createMcpServer({ yaak: ctx }, serverPort);
} catch (err) {
console.error('Failed to start MCP server:', err);
ctx.toast.show({
void ctx.toast.show({
message: `Failed to start MCP Server: ${err instanceof Error ? err.message : String(err)}`,
icon: 'alert_triangle',
color: 'danger',

View File

@@ -30,7 +30,7 @@ export function createMcpServer(ctx: McpServerContext, port: number) {
if (!mcpServer.isConnected()) {
// Connect the mcp with the transport
await mcpServer.connect(transport);
ctx.yaak.toast.show({
void ctx.yaak.toast.show({
message: `MCP Server connected`,
icon: 'info',
color: 'info',
@@ -48,7 +48,7 @@ export function createMcpServer(ctx: McpServerContext, port: number) {
},
(info) => {
console.log('Started MCP server on ', info.address);
ctx.yaak.toast.show({
void ctx.yaak.toast.show({
message: `MCP Server running on http://127.0.0.1:${info.port}`,
icon: 'info',
color: 'secondary',

View File

@@ -12,6 +12,6 @@
"scripts": {
"build": "yaakcli build",
"dev": "yaakcli dev",
"test": "vitest --run tests"
"test": "vp test --run tests"
}
}

View File

@@ -1,4 +1,4 @@
import { describe, expect, test } from 'vitest';
import { describe, expect, test } from 'vite-plus/test';
import { convertToCurl } from '../src';
describe('exporter-curl', () => {

View File

@@ -12,6 +12,6 @@
"scripts": {
"build": "yaakcli build",
"dev": "yaakcli dev",
"test": "vitest --run tests"
"test": "vp test --run tests"
}
}

View File

@@ -1,4 +1,4 @@
import { describe, expect, test } from 'vitest';
import { describe, expect, test } from 'vite-plus/test';
import { convert } from '../src';
describe('exporter-curl', () => {

View File

@@ -12,6 +12,6 @@
"scripts": {
"build": "yaakcli build",
"dev": "yaakcli dev",
"test": "vitest --run tests"
"test": "vp test --run tests"
}
}

View File

@@ -1,5 +1,5 @@
import type { Context } from '@yaakapp/api';
import { describe, expect, test } from 'vitest';
import { describe, expect, test } from 'vite-plus/test';
import { plugin } from '../src';
const ctx = {} as Context;

View File

@@ -12,6 +12,6 @@
"scripts": {
"build": "yaakcli build",
"dev": "yaakcli dev",
"test": "vitest --run tests"
"test": "vp test --run tests"
}
}

View File

@@ -1,5 +1,5 @@
import type { Context } from '@yaakapp/api';
import { describe, expect, test } from 'vitest';
import { describe, expect, test } from 'vite-plus/test';
import { plugin } from '../src';
const ctx = {} as Context;

View File

@@ -12,7 +12,7 @@
"scripts": {
"build": "yaakcli build",
"dev": "yaakcli dev",
"test": "vitest --run tests"
"test": "vp test --run tests"
},
"dependencies": {
"httpntlm": "^1.8.13"

View File

@@ -1,5 +1,5 @@
import type { Context } from '@yaakapp/api';
import { beforeEach, describe, expect, test, vi } from 'vitest';
import { beforeEach, describe, expect, test, vi } from 'vite-plus/test';
const ntlmMock = vi.hoisted(() => ({
createType1Message: vi.fn(),
@@ -17,6 +17,7 @@ describe('auth-ntlm', () => {
ntlmMock.parseType2Message.mockReset();
ntlmMock.createType3Message.mockReset();
ntlmMock.createType1Message.mockReturnValue('NTLM TYPE1');
// oxlint-disable-next-line no-explicit-any
ntlmMock.parseType2Message.mockReturnValue({} as any);
ntlmMock.createType3Message.mockReturnValue('NTLM TYPE3');
});

View File

@@ -12,7 +12,7 @@
"scripts": {
"build": "yaakcli build",
"dev": "yaakcli dev",
"test": "vitest --run tests"
"test": "vp test --run tests"
},
"dependencies": {
"jsonwebtoken": "^9.0.2"

View File

@@ -71,7 +71,7 @@ export async function fetchAccessToken(
throw new Error(`Failed to fetch access token with status=${resp.status} and body=${body}`);
}
// biome-ignore lint/suspicious/noExplicitAny: none
// oxlint-disable-next-line no-explicit-any
let response: any;
try {
response = JSON.parse(body);

View File

@@ -91,7 +91,7 @@ export async function getOrRefreshAccessToken(
throw new Error(`Failed to refresh access token with status=${resp.status} and body=${body}`);
}
// biome-ignore lint/suspicious/noExplicitAny: none
// oxlint-disable-next-line no-explicit-any
let response: any;
try {
response = JSON.parse(body);

View File

@@ -148,7 +148,7 @@ async function getCodeViaEmbeddedBrowser(
const authorizationUrlStr = authorizationUrl.toString();
console.log('[oauth2] Authorizing via embedded browser', authorizationUrlStr);
// biome-ignore lint/suspicious/noAsyncPromiseExecutor: Required for this pattern
// oxlint-disable-next-line no-async-promise-executor -- Required for this pattern
return new Promise<string>(async (resolve, reject) => {
let foundCode = false;
const { close } = await ctx.window.openUrl({

View File

@@ -53,6 +53,7 @@ function buildClientAssertionJwt(params: {
signingKey = secret;
} else if (trimmed.startsWith('{')) {
// Looks like JSON - treat as JWK. There is surely a better way to detect JWK vs a raw secret, but this should work in most cases.
// oxlint-disable-next-line no-explicit-any
let jwk: any;
try {
jwk = JSON.parse(trimmed);

View File

@@ -105,7 +105,7 @@ async function getTokenViaEmbeddedBrowser(
const authorizationUrlStr = authorizationUrl.toString();
console.log('[oauth2] Authorizing via embedded browser (implicit)', authorizationUrlStr);
// biome-ignore lint/suspicious/noAsyncPromiseExecutor: Required for this pattern
// oxlint-disable-next-line no-async-promise-executor -- Required for this pattern
return new Promise<AccessToken>(async (resolve, reject) => {
let foundAccessToken = false;
const { close } = await ctx.window.openUrl({

View File

@@ -590,11 +590,11 @@ export const plugin: PluginDefinition = {
credentialsInBody,
});
} else {
throw new Error(`Invalid grant type ${grantType}`);
throw new Error(`Invalid grant type ${String(grantType)}`);
}
const headerName = stringArg(values, 'headerName') || 'Authorization';
const headerValue = `${headerPrefix} ${token.response[tokenName]}`.trim();
const headerValue = `${headerPrefix} ${token.response[tokenName] ?? ''}`.trim();
return { setHeaders: [{ name: headerName, value: headerValue }] };
},
},

View File

@@ -1,4 +1,4 @@
import { describe, expect, test } from 'vitest';
import { describe, expect, test } from 'vite-plus/test';
import { extractCode } from '../src/util';
describe('extractCode', () => {

View File

@@ -11,7 +11,7 @@ export const plugin: PluginDefinition = {
const filtered = JSONPath({ path: args.filter, json: parsed });
return { content: JSON.stringify(filtered, null, 2) };
} catch (err) {
return { content: '', error: `Invalid filter: ${err}` };
return { content: '', error: `Invalid filter: ${err instanceof Error ? err.message : String(err)}` };
}
},
},

View File

@@ -1,3 +1,4 @@
/* oxlint-disable no-base-to-string */
import { DOMParser } from '@xmldom/xmldom';
import type { PluginDefinition } from '@yaakapp/api';
import xpath from 'xpath';
@@ -7,7 +8,7 @@ export const plugin: PluginDefinition = {
name: 'XPath',
description: 'Filter XPath',
onFilter(_ctx, args) {
// biome-ignore lint/suspicious/noExplicitAny: none
// oxlint-disable-next-line no-explicit-any
const doc: any = new DOMParser().parseFromString(args.payload, 'text/xml');
try {
const result = xpath.select(args.filter, doc, false);
@@ -17,7 +18,7 @@ export const plugin: PluginDefinition = {
// Not sure what cases this happens in (?)
return { content: String(result) };
} catch (err) {
return { content: '', error: `Invalid filter: ${err}` };
return { content: '', error: `Invalid filter: ${err instanceof Error ? err.message : String(err)}` };
}
},
},

View File

@@ -7,7 +7,7 @@
"scripts": {
"build": "yaakcli build",
"dev": "yaakcli dev",
"test": "vitest --run tests"
"test": "vp test --run tests"
},
"dependencies": {
"shlex": "^3.0.0"

View File

@@ -48,7 +48,7 @@ export const plugin: PluginDefinition = {
name: 'cURL',
description: 'Import cURL commands',
onImport(_ctx: Context, args: { text: string }) {
// biome-ignore lint/suspicious/noExplicitAny: none
// oxlint-disable-next-line no-explicit-any
return convertCurl(args.text) as any;
},
},

View File

@@ -1,5 +1,5 @@
import type { HttpRequest, Workspace } from '@yaakapp/api';
import { describe, expect, test } from 'vitest';
import { describe, expect, test } from 'vite-plus/test';
import { convertCurl } from '../src';
describe('importer-curl', () => {

View File

@@ -7,7 +7,7 @@
"scripts": {
"build": "yaakcli build",
"dev": "yaakcli dev",
"test": "vitest --run tests"
"test": "vp test --run tests"
},
"dependencies": {
"yaml": "^2.4.2"

View File

@@ -30,7 +30,7 @@ export function deleteUndefinedAttrs<T>(obj: T): T {
/** Recursively render all nested object properties */
export function convertTemplateSyntax<T>(obj: T): T {
if (typeof obj === 'string') {
// biome-ignore lint/suspicious/noTemplateCurlyInString: Yaak template syntax
// oxlint-disable-next-line no-template-curly-in-string -- Yaak template syntax
return obj.replaceAll(/{{\s*(_\.)?([^}]+)\s*}}/g, '${[$2]}') as T;
}
if (Array.isArray(obj) && obj != null) {

View File

@@ -1,4 +1,4 @@
// biome-ignore-all lint/suspicious/noExplicitAny: too flexible for strict types
/* oxlint-disable no-explicit-any */
import type { PartialImportResources } from '@yaakapp/api';
import { convertId, convertTemplateSyntax, isJSObject } from './common';
@@ -203,7 +203,7 @@ function importEnvironment(
variables: Object.entries(e.data).map(([name, value]) => ({
enabled: true,
name,
value: `${value}`,
value: String(value),
})),
};
}

View File

@@ -1,4 +1,4 @@
// biome-ignore-all lint/suspicious/noExplicitAny: too flexible for strict types
/* oxlint-disable no-explicit-any */
import type { PartialImportResources } from '@yaakapp/api';
import { convertId, convertTemplateSyntax, isJSObject } from './common';
@@ -261,7 +261,7 @@ function importFolder(
variables: Object.entries(f.environment ?? {}).map(([name, value]) => ({
enabled: true,
name,
value: `${value}`,
value: String(value),
})),
};
}
@@ -308,7 +308,7 @@ function importEnvironment(
variables: Object.entries(e.data ?? {}).map(([name, value]) => ({
enabled: true,
name,
value: `${value}`,
value: String(value),
})),
};
}

View File

@@ -1,6 +1,6 @@
import * as fs from 'node:fs';
import * as path from 'node:path';
import { describe, expect, test } from 'vitest';
import { describe, expect, test } from 'vite-plus/test';
import YAML from 'yaml';
import { convertInsomnia } from '../src';

View File

@@ -7,7 +7,7 @@
"scripts": {
"build": "yaakcli build",
"dev": "yaakcli dev",
"test": "vitest --run tests"
"test": "vp test --run tests"
},
"dependencies": {
"openapi-to-postmanv2": "^5.8.0",

View File

@@ -14,11 +14,11 @@ export const plugin: PluginDefinition = {
};
export async function convertOpenApi(contents: string): Promise<ImportPluginResponse | undefined> {
// biome-ignore lint/suspicious/noExplicitAny: none
// oxlint-disable-next-line no-explicit-any
let postmanCollection: any;
try {
postmanCollection = await new Promise((resolve, reject) => {
// biome-ignore lint/suspicious/noExplicitAny: none
// oxlint-disable-next-line no-explicit-any
convert({ type: 'string', data: contents }, {}, (err, result: any) => {
if (err != null) reject(err);

View File

@@ -1,6 +1,6 @@
import * as fs from 'node:fs';
import * as path from 'node:path';
import { describe, expect, test } from 'vitest';
import { describe, expect, test } from 'vite-plus/test';
import { convertOpenApi } from '../src';
describe('importer-openapi', () => {

View File

@@ -8,6 +8,6 @@
"scripts": {
"build": "yaakcli build",
"dev": "yaakcli dev",
"test": "vitest --run tests"
"test": "vp test --run tests"
}
}

View File

@@ -1,3 +1,4 @@
/* oxlint-disable no-base-to-string */
import type {
Context,
Environment,
@@ -84,7 +85,7 @@ function parseJSONToRecord<T>(jsonStr: string): Record<string, T> | null {
}
}
function toRecord<T>(value: Record<string, T> | unknown): Record<string, T> {
function toRecord<T>(value: unknown): Record<string, T> {
if (value && typeof value === 'object' && !Array.isArray(value)) {
return value as Record<string, T>;
}

View File

@@ -1,6 +1,6 @@
import * as fs from 'node:fs';
import * as path from 'node:path';
import { describe, expect, test } from 'vitest';
import { describe, expect, test } from 'vite-plus/test';
import { convertPostmanEnvironment } from '../src';
describe('importer-postman-environment', () => {

View File

@@ -8,6 +8,6 @@
"scripts": {
"build": "yaakcli build",
"dev": "yaakcli dev",
"test": "vitest --run tests"
"test": "vp test --run tests"
}
}

View File

@@ -1,3 +1,4 @@
/* oxlint-disable no-base-to-string */
import type {
Context,
Environment,
@@ -158,7 +159,7 @@ export function convertPostman(contents: string): ImportPluginResponse | undefin
return { resources };
}
function convertUrl(rawUrl: string | unknown): Pick<HttpRequest, 'url' | 'urlParameters'> {
function convertUrl(rawUrl: unknown): Pick<HttpRequest, 'url' | 'urlParameters'> {
if (typeof rawUrl === 'string') {
return { url: rawUrl, urlParameters: [] };
}
@@ -172,7 +173,7 @@ function convertUrl(rawUrl: string | unknown): Pick<HttpRequest, 'url' | 'urlPar
}
if ('host' in url) {
v += `${Array.isArray(url.host) ? url.host.join('.') : url.host}`;
v += `${Array.isArray(url.host) ? url.host.join('.') : String(url.host)}`;
}
if ('port' in url && typeof url.port === 'string') {
@@ -489,7 +490,7 @@ function parseJSONToRecord<T>(jsonStr: string): Record<string, T> | null {
}
}
function toRecord<T>(value: Record<string, T> | unknown): Record<string, T> {
function toRecord<T>(value: unknown): Record<string, T> {
if (value && typeof value === 'object' && !Array.isArray(value)) {
return value as Record<string, T>;
}

View File

@@ -1,6 +1,6 @@
import * as fs from 'node:fs';
import * as path from 'node:path';
import { describe, expect, test } from 'vitest';
import { describe, expect, test } from 'vite-plus/test';
import { convertPostman } from '../src';
describe('importer-postman', () => {

View File

@@ -7,6 +7,6 @@
"scripts": {
"build": "yaakcli build",
"dev": "yaakcli dev",
"test": "vitest --run tests"
"test": "vp test --run tests"
}
}

View File

@@ -11,7 +11,7 @@ export const plugin: PluginDefinition = {
};
export function migrateImport(contents: string) {
// biome-ignore lint/suspicious/noExplicitAny: none
// oxlint-disable-next-line no-explicit-any
let parsed: any;
try {
parsed = JSON.parse(contents);

View File

@@ -1,4 +1,4 @@
import { describe, expect, test } from 'vitest';
import { describe, expect, test } from 'vite-plus/test';
import { migrateImport } from '../src';
describe('importer-yaak', () => {

View File

@@ -55,7 +55,8 @@ async function op(
}
}
return { client: _clients[hash], clientHash: hash };
// oxlint-disable-next-line no-non-null-assertion
return { client: _clients[hash]!, clientHash: hash };
}
async function getValue(
@@ -123,7 +124,7 @@ export const plugin: PluginDefinition = {
{
name: 'token',
type: 'text',
// biome-ignore lint/suspicious/noTemplateCurlyInString: Yaak template syntax
// oxlint-disable-next-line no-template-curly-in-string -- Yaak template syntax
defaultValue: '${[1PASSWORD_TOKEN]}',
dynamic(_ctx, args) {
switch (args.values.authMethod) {

View File

@@ -53,7 +53,7 @@ export const plugin: PluginDefinition = {
type: 'text',
name: 'namespace',
label: 'Namespace',
// biome-ignore lint/suspicious/noTemplateCurlyInString: Yaak template syntax
// oxlint-disable-next-line no-template-curly-in-string -- Yaak template syntax
defaultValue: '${[ctx.workspace()]}',
optional: true,
},

View File

@@ -7,6 +7,6 @@
"scripts": {
"build": "yaakcli build",
"dev": "yaakcli dev",
"test": "vitest --run tests"
"test": "vp test --run tests"
}
}

View File

@@ -1,5 +1,5 @@
import type { Context } from '@yaakapp/api';
import { describe, expect, it } from 'vitest';
import { describe, expect, it } from 'vite-plus/test';
import { plugin } from '../src';
describe('regex.match', () => {

View File

@@ -7,7 +7,7 @@
"scripts": {
"build": "yaakcli build",
"dev": "yaakcli dev",
"test": "vitest --run tests"
"test": "vp test --run tests"
},
"dependencies": {
"@date-fns/tz": "^1.4.1",

View File

@@ -1,5 +1,5 @@
import { tz } from '@date-fns/tz';
import { describe, expect, it } from 'vitest';
import { describe, expect, it } from 'vite-plus/test';
import { calculateDatetime, formatDatetime } from '../src';
describe('formatDatetime', () => {

View File

@@ -1,3 +1,4 @@
/* oxlint-disable no-base-to-string */
import { DOMParser } from '@xmldom/xmldom';
import type { CallTemplateFunctionArgs, Context, PluginDefinition } from '@yaakapp/api';
import xpath from 'xpath';
@@ -68,7 +69,7 @@ export function filterXPath(
result: XPathResult,
join: string | null,
): string {
// biome-ignore lint/suspicious/noExplicitAny: none
// oxlint-disable-next-line no-explicit-any
const doc: any = new DOMParser().parseFromString(body, 'text/xml');
const items = xpath.select(path, doc, false);

View File

@@ -12,7 +12,7 @@ execSync('cargo install wasm-pack --locked', { stdio: 'inherit' });
function tryExecSync(cmd) {
try {
return execSync(cmd, { stdio: 'pipe' }).toString('utf-8');
} catch (_) {
} catch {
return '';
}
}

View File

@@ -52,7 +52,7 @@ for (const ws of workspacesWithDev) {
// Cleanup function to kill all children
function cleanup() {
for (const { ws, child } of children) {
for (const { child } of children) {
if (child.exitCode === null) {
// Process still running
if (process.platform === 'win32') {

View File

@@ -105,7 +105,7 @@ rmSync(tmpDir, { recursive: true, force: true });
function tryExecSync(cmd) {
try {
return execSync(cmd, { stdio: 'pipe' }).toString('utf-8');
} catch (_) {
} catch {
return '';
}
}

View File

@@ -106,7 +106,7 @@ mkdirSync(dstDir, { recursive: true });
function tryExecSync(cmd) {
try {
return execSync(cmd, { stdio: 'pipe' }).toString('utf-8');
} catch (_) {
} catch {
return '';
}
}

View File

@@ -143,7 +143,7 @@ export const syncWorkspace = createFastMutation<
}
return (
// biome-ignore lint/suspicious/noArrayIndexKey: none
// oxlint-disable-next-line react/no-array-index-key
<TableRow key={i}>
<TableCell className="text-text-subtle">{model}</TableCell>
<TruncatedWideTableCell>{name}</TruncatedWideTableCell>

View File

@@ -19,7 +19,7 @@ export const openWorkspaceFromSyncDir = createFastMutation<void, void, string>({
await applySync(workspace.id, dir, ops);
router.navigate({
await router.navigate({
to: '/workspaces/$workspaceId',
params: { workspaceId: workspace.id },
});

View File

@@ -1,6 +1,7 @@
import type { DnsOverride, Workspace } from '@yaakapp-internal/models';
import { patchModel } from '@yaakapp-internal/models';
import { useCallback, useId, useMemo } from 'react';
import { fireAndForget } from '../lib/fireAndForget';
import { Button } from './core/Button';
import { Checkbox } from './core/Checkbox';
import { IconButton } from './core/IconButton';
@@ -29,7 +30,7 @@ export function DnsOverridesEditor({ workspace }: Props) {
const handleChange = useCallback(
(overrides: DnsOverride[]) => {
patchModel(workspace, { settingDnsOverrides: overrides });
fireAndForget(patchModel(workspace, { settingDnsOverrides: overrides }));
},
[workspace],
);

View File

@@ -512,16 +512,14 @@ function HttpRequestArg({
help={arg.description}
value={value}
disabled={arg.disabled}
options={[
...httpRequests.map((r) => {
options={httpRequests.map((r) => {
return {
label:
buildRequestBreadcrumbs(r, folders).join(' / ') +
(r.id === activeHttpRequest?.id ? ' (current)' : ''),
value: r.id,
};
}),
]}
})}
/>
);
}

View File

@@ -9,6 +9,7 @@ import {
useEnvironmentsBreakdown,
} from '../hooks/useEnvironmentsBreakdown';
import { deleteModelWithConfirm } from '../lib/deleteModelWithConfirm';
import { fireAndForget } from '../lib/fireAndForget';
import { jotaiStore } from '../lib/jotai';
import { isBaseEnvironment, isSubEnvironment } from '../lib/model_util';
import { resolvedModelName } from '../lib/resolvedModelName';
@@ -112,7 +113,7 @@ function EnvironmentEditDialogSidebar({
const treeRef = useRef<TreeHandle>(null);
const { baseEnvironment, baseEnvironments } = useEnvironmentsBreakdown();
// biome-ignore lint/correctness/useExhaustiveDependencies: none
// oxlint-disable-next-line react-hooks/exhaustive-deps
useLayoutEffect(() => {
if (selectedEnvironmentId == null) return;
treeRef.current?.selectItem(selectedEnvironmentId);
@@ -199,7 +200,7 @@ function EnvironmentEditDialogSidebar({
// Not sure why this is needed, but without it the
// edit input blurs immediately after opening.
requestAnimationFrame(() => {
actions['sidebar.selected.rename'].cb(items);
fireAndForget(actions['sidebar.selected.rename'].cb(items));
});
},
},

View File

@@ -55,7 +55,7 @@ function ExportDataDialogContent({
const handleToggleAll = () => {
setSelectedWorkspaces(
// biome-ignore lint/performance/noAccumulatingSpread: none
// oxlint-disable-next-line no-accumulating-spread
allSelected ? {} : workspaces.reduce((acc, w) => ({ ...acc, [w.id]: true }), {}),
);
};

View File

@@ -8,6 +8,7 @@ import { allRequestsAtom } from '../hooks/useAllRequests';
import { useFolderActions } from '../hooks/useFolderActions';
import { useLatestHttpResponse } from '../hooks/useLatestHttpResponse';
import { sendAnyHttpRequest } from '../hooks/useSendAnyHttpRequest';
import { fireAndForget } from '../lib/fireAndForget';
import { showDialog } from '../lib/dialog';
import { resolvedModelName } from '../lib/resolvedModelName';
import { router } from '../lib/router';
@@ -45,7 +46,7 @@ export function FolderLayout({ folder, style }: Props) {
}, [folder.id, folders, requests]);
const handleSendAll = useCallback(() => {
sendAllAction?.call(folder);
if (sendAllAction) fireAndForget(sendAllAction.call(folder));
}, [sendAllAction, folder]);
return (

View File

@@ -103,7 +103,7 @@ function GrpcProtoSelectionDialogWithRequest({ request }: Props & { request: Grp
Found services{' '}
{services?.slice(0, 5).map((s, i) => {
return (
<span key={s.name + s.methods.join(',')}>
<span key={s.name + s.methods.map((m) => m.name).join(',')}>
<InlineCode>{s.name}</InlineCode>
{i === services.length - 1 ? '' : i === services.length - 2 ? ' and ' : ', '}
</span>
@@ -119,7 +119,7 @@ function GrpcProtoSelectionDialogWithRequest({ request }: Props & { request: Grp
Server reflection found services
{services?.map((s, i) => {
return (
<span key={s.name + s.methods.join(',')}>
<span key={s.name + s.methods.map((m) => m.name).join(',')}>
<InlineCode>{s.name}</InlineCode>
{i === services.length - 1 ? '' : i === services.length - 2 ? ' and ' : ', '}
</span>
@@ -144,7 +144,7 @@ function GrpcProtoSelectionDialogWithRequest({ request }: Props & { request: Grp
{protoFiles.map((f, i) => {
const parts = f.split('/');
return (
// biome-ignore lint/suspicious/noArrayIndexKey: none
// oxlint-disable-next-line react/no-array-index-key
<tr key={f + i} className="group">
<td>
<Icon icon={f.endsWith('.proto') ? 'file_code' : 'folder_code'} />

View File

@@ -50,7 +50,7 @@ export function GrpcResponsePane({ style, methodType, activeRequest }: Props) {
);
// Set the active message to the first message received if unary
// biome-ignore lint/correctness/useExhaustiveDependencies: none
// oxlint-disable-next-line react-hooks/exhaustive-deps
useEffect(() => {
if (events.length === 0 || activeEvent != null || methodType !== 'unary') {
return;

View File

@@ -13,9 +13,9 @@ export function ImportCurlButton() {
const importCurl = useImportCurl();
const [isLoading, setIsLoading] = useState(false);
// biome-ignore lint/correctness/useExhaustiveDependencies: none
// oxlint-disable-next-line react-hooks/exhaustive-deps
useEffect(() => {
readText().then(setClipboardText);
readText().then(setClipboardText).catch(() => {});
}, [focused]);
if (!clipboardText?.trim().startsWith('curl ')) {

View File

@@ -2,6 +2,7 @@ import { linter } from '@codemirror/lint';
import type { HttpRequest } from '@yaakapp-internal/models';
import { patchModel } from '@yaakapp-internal/models';
import { useCallback, useMemo } from 'react';
import { fireAndForget } from '../lib/fireAndForget';
import { useKeyValue } from '../hooks/useKeyValue';
import { textLikelyContainsJsonComments } from '../lib/jsonComments';
import { Banner } from './core/Banner';
@@ -58,12 +59,12 @@ export function JsonBodyEditor({ forceUpdateKey, heightMode, request }: Props) {
} else {
delete newBody.sendJsonComments;
}
patchModel(request, { body: newBody });
fireAndForget(patchModel(request, { body: newBody }));
}, [request, autoFix]);
const handleDropdownOpen = useCallback(() => {
if (!bannerDismissed) {
setBannerDismissed(true);
fireAndForget(setBannerDismissed(true));
}
}, [bannerDismissed, setBannerDismissed]);

View File

@@ -102,7 +102,7 @@ const markdownComponents: Partial<Components> = {
language={match[1]}
style={prismTheme}
>
{String(children).replace(/\n$/, '')}
{String(children as string).replace(/\n$/, '')}
</SyntaxHighlighter>
) : (
<code {...extraProps} ref={ref} className={className}>

View File

@@ -5,6 +5,7 @@ import { getRecentCookieJars } from '../hooks/useRecentCookieJars';
import { getRecentEnvironments } from '../hooks/useRecentEnvironments';
import { getRecentRequests } from '../hooks/useRecentRequests';
import { useRecentWorkspaces } from '../hooks/useRecentWorkspaces';
import { fireAndForget } from '../lib/fireAndForget';
import { router } from '../lib/router';
export function RedirectToLatestWorkspace() {
@@ -20,7 +21,7 @@ export function RedirectToLatestWorkspace() {
return;
}
(async () => {
fireAndForget((async () => {
const workspaceId = recentWorkspaces[0] ?? workspaces[0]?.id ?? 'n/a';
const environmentId = (await getRecentEnvironments(workspaceId))[0] ?? null;
const cookieJarId = (await getRecentCookieJars(workspaceId))[0] ?? null;
@@ -34,7 +35,7 @@ export function RedirectToLatestWorkspace() {
console.log('Redirecting to workspace', params, search);
await router.navigate({ to: '/workspaces/$workspaceId', params, search });
})();
})());
}, [recentWorkspaces, workspaces, workspaces.length]);
return null;

View File

@@ -130,7 +130,7 @@ export function ResponseCookies({ response }: Props) {
) : (
<KeyValueRows>
{sentCookies.map((cookie, i) => (
// biome-ignore lint/suspicious/noArrayIndexKey: none
// oxlint-disable-next-line react/no-array-index-key
<KeyValueRow labelColor="primary" key={i} label={cookie.name}>
{cookie.value}
</KeyValueRow>
@@ -153,7 +153,7 @@ export function ResponseCookies({ response }: Props) {
) : (
<div className="flex flex-col gap-4">
{receivedCookies.map((cookie, i) => (
// biome-ignore lint/suspicious/noArrayIndexKey: none
// oxlint-disable-next-line react/no-array-index-key
<div key={i} className="flex flex-col gap-1">
<div className="flex items-center gap-2 my-1">
<span

View File

@@ -62,7 +62,7 @@ export function ResponseHeaders({ response }: Props) {
) : (
<KeyValueRows>
{requestHeaders.map((h, i) => (
// biome-ignore lint/suspicious/noArrayIndexKey: none
// oxlint-disable-next-line react/no-array-index-key
<KeyValueRow labelColor="primary" key={i} label={h.name}>
{h.value}
</KeyValueRow>
@@ -84,7 +84,7 @@ export function ResponseHeaders({ response }: Props) {
) : (
<KeyValueRows>
{responseHeaders.map((h, i) => (
// biome-ignore lint/suspicious/noArrayIndexKey: none
// oxlint-disable-next-line react/no-array-index-key
<KeyValueRow labelColor="info" key={i} label={h.name}>
{h.value}
</KeyValueRow>

View File

@@ -7,7 +7,7 @@ import { VStack } from './core/Stacks';
export default function RouteError({ error }: { error: unknown }) {
console.log('Error', error);
const stringified = JSON.stringify(error);
// biome-ignore lint/suspicious/noExplicitAny: none
// oxlint-disable-next-line no-explicit-any
const message = (error as any).message ?? stringified;
const stack =
typeof error === 'object' && error != null && 'stack' in error ? String(error.stack) : null;

View File

@@ -238,7 +238,7 @@ export function SettingsCertificates() {
<VStack space={3}>
{certificates.map((cert, index) => (
<CertificateEditor
// biome-ignore lint/suspicious/noArrayIndexKey: Index is fine here
// oxlint-disable-next-line react/no-array-index-key
key={index}
certificate={cert}
index={index}

View File

@@ -43,6 +43,7 @@ import { useSidebarHidden } from '../hooks/useSidebarHidden';
import { getWebsocketRequestActions } from '../hooks/useWebsocketRequestActions';
import { deepEqualAtom } from '../lib/atoms';
import { deleteModelWithConfirm } from '../lib/deleteModelWithConfirm';
import { fireAndForget } from '../lib/fireAndForget';
import { jotaiStore } from '../lib/jotai';
import { resolvedModelName } from '../lib/resolvedModelName';
import { isSidebarFocused } from '../lib/scopes';
@@ -439,7 +440,7 @@ function Sidebar({ className }: { className?: string }) {
leftSlot: <Icon icon="arrow_right_circle" />,
hidden: workspaces.length <= 1 || requestItems.length === 0 || requestItems.length !== items.length,
onSelect: () => {
actions['sidebar.selected.move'].cb(items);
fireAndForget(actions['sidebar.selected.move'].cb(items));
},
},
{

View File

@@ -141,7 +141,7 @@ function InitializedTemplateFunctionDialog({
});
const tooLarge = rendered.data ? rendered.data.length > 10000 : false;
// biome-ignore lint/correctness/useExhaustiveDependencies: Only update this on rendered data change to keep secrets hidden on input change
// oxlint-disable-next-line react-hooks/exhaustive-deps -- Only update this on rendered data change to keep secrets hidden on input change
const dataContainsSecrets = useMemo(() => {
for (const [name, value] of Object.entries(argValues)) {
const arg = templateFunction.data?.args.find((a) => 'name' in a && a.name === name);

View File

@@ -127,7 +127,7 @@ export function WorkspaceEncryptionSetting({ size, expanded, onDone, onEnabledEn
await enableEncryption(workspaceMeta.workspaceId);
setJustEnabledEncryption(true);
} catch (err) {
setError(`Failed to enable encryption: ${err}`);
setError(`Failed to enable encryption: ${err instanceof Error ? err.message : String(err)}`);
}
}}
>
@@ -285,7 +285,7 @@ function HighlightedKey({ keyText, show }: { keyText: string; show: boolean }) {
keyText.split('').map((c, i) => {
return (
<span
// biome-ignore lint/suspicious/noArrayIndexKey: it's fine
// oxlint-disable-next-line react/no-array-index-key
key={i}
className={classNames(
c.match(/[0-9]/) && 'text-info',

Some files were not shown because too many files have changed in this diff Show More