Skip to content

chore: post-Jules-triage followups#338

Open
zknpr wants to merge 2 commits into
mainfrom
followups/post-jules-triage
Open

chore: post-Jules-triage followups#338
zknpr wants to merge 2 commits into
mainfrom
followups/post-jules-triage

Conversation

@zknpr
Copy link
Copy Markdown
Owner

@zknpr zknpr commented May 20, 2026

Summary

Three coverage/typing followups noted while triaging the Jules + dependabot PR backlog.

WasmDatabaseEngine: tighten internal sql.js types
The internal WasmPreparedStatement / WasmDatabaseInstance interfaces used unknown[] for bind/run params, forcing a params as unknown[] cast at the iterateStatements site. Switched to CellValue[] everywhere internally, dropping the cast. This is the fix #312 should have made (#312 chose unknown[] which would now be even further from the merged SqlValue[] declarations in #306).

Export WorkerPort
#326 (connectWorkerPort tests) imported WorkerPort which wasn't exported from src/core/rpc.ts — tsx tolerated it, but tsc --noEmit flagged TS2459. Adding export keyword; no behavior change.

Test type fixes downstream of #305 and #330
#305 tightened MethodImplementations to (...args: unknown[]) => unknown (from any[]); #330 tightened WebviewMessageHandler's hostBridge param to the real HostBridge type. Both correctly tightened production code but the existing tests passed widened/partial mocks that no longer satisfy the stricter types. Cast at the test call sites to make tsc --noEmit clean again without weakening the production signatures.

registerEditorProvider test (closes #292 gap)
Switched the two remaining bare import.meta.env.VSCODE_BROWSER_EXT reads in editorController.ts to optional chaining (consistent with threadPool.ts and cryptoShim.ts which already do this), so the module can be required from tsx without throwing. Added tests/unit/editorController.test.ts covering:

  • readOnly=trueDatabaseViewerProvider (regardless of verified)
  • verified=falseDatabaseViewerProvider
  • verified=true + readOnly=falseDatabaseEditorProvider
  • retainContextWhenHidden=false in webview options
  • function returns a disposable

This closes the coverage gap from #292 (which was closed without iterating).

Test plan

  • npm test → 269 pass, 0 fail (was 264; +5 from new file)
  • npx tsc --noEmit on src/ → 0 errors (baseline had 1 pre-existing in hostBridge.ts that the ⚡ [Performance] Eliminate concurrent IPC map-promise-all in hostBridge cell batch updates #323 merge resolved as a side effect)
  • Eyeball that nothing meaningful changed in the production registerEditorProvider semantics — optional-chain replacement is a no-op when import.meta.env is the defined object, and graceful when it's undefined (test path)

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes

    • Fixed potential runtime errors in editor initialization by handling missing environment configuration.
  • Tests

    • Added comprehensive unit tests for editor provider registration functionality.
  • Refactor

    • Strengthened internal type contracts for database operations and improved API exports for better type safety.

Review Change Stack

Tighten internal sql.js types in WasmDatabaseEngine to CellValue[],
removing the `params as unknown[]` cast at the iterateStatements bind
site (gap noted while closing #312).

Export WorkerPort interface so #326's connectWorkerPort tests typecheck
under `tsc --noEmit`, and apply matching variance/structural casts to
rpc.test.ts and webviewMessageHandler.test.ts so the tightened types
from #305 (`unknown[]`) and #330 (`HostBridge`) don't introduce new tsc
errors.

Switch the two remaining bare `import.meta.env.VSCODE_BROWSER_EXT`
reads in editorController.ts to optional chaining, matching the pattern
already used in threadPool.ts and cryptoShim.ts. This unblocks testing
the read-only vs read-write registration branch.

Add tests/unit/editorController.test.ts covering registerEditorProvider:
- readOnly=true picks DatabaseViewerProvider regardless of verified
- verified=false picks DatabaseViewerProvider
- verified=true + readOnly=false picks DatabaseEditorProvider
- retainContextWhenHidden=false is set
- returns a disposable

This closes the coverage gap from #292 that I closed without iterating.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@vercel
Copy link
Copy Markdown
Contributor

vercel Bot commented May 20, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
sq-lite-explorer Ready Ready Preview, Comment May 20, 2026 3:45pm

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 20, 2026

Warning

Rate limit exceeded

@zknpr has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 33 minutes and 43 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: 43d320bf-8907-442e-90e8-2cb2cf81783f

📥 Commits

Reviewing files that changed from the base of the PR and between e0f06a2 and 2b0a1b7.

📒 Files selected for processing (1)
  • tests/unit/editorController.test.ts
📝 Walkthrough

Walkthrough

This PR tightens type safety in the WASM database engine by replacing unknown[] and any[] with CellValue[] types, exports the WorkerPort interface, adds optional-chaining guards for import.meta.env in the editor controller, introduces a comprehensive test suite for provider registration, and updates existing tests with explicit type casts.

Changes

Type Safety and Testing Improvements

Layer / File(s) Summary
WASM Database Engine Type Contracts
src/core/engine/wasm/WasmDatabaseEngine.ts
WasmPreparedStatement methods and WasmDatabaseInstance.exec now declare parameters and row values using CellValue[] instead of unknown[]. Parameter binding in executeQuery and row restoration in undoColumnDrop use the updated types consistently.
Worker Port Public Interface
src/core/rpc.ts
WorkerPort interface is exported from the module, making it part of the public RPC contract.
Editor Controller Environment Guards
src/editorController.ts
Webview dataset initialization and provider selection logic now use optional chaining to safely access import.meta.env, preventing errors when the environment object is undefined.
Editor Controller Provider Registration Tests
tests/unit/editorController.test.ts
Comprehensive test suite validates provider selection (read-only vs. read-write, verified state), webview options (retainContextWhenHidden value), and disposable behavior. Tests pre-configure VS Code environment and mock worker factory for reproducible evaluation.
Test Type Safety Updates
tests/unit/rpc.test.ts, tests/unit/webviewMessageHandler.test.ts
RPC test uses Record<string, (...args: unknown[]) => unknown> for generic method dispatch; webview message handler tests explicitly cast mock objects to HostBridge type.

Sequence Diagram(s)

No sequence diagram generated; these changes are primarily type contract refinements, export additions, defensive guards, and test coverage rather than control-flow modifications.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Poem

🐰 Types now flow like carrots clean,
Unknown banished from the scene!
Guards protect from env's gray mist,
Tests affirm what can't be missed,
Safety grows with every line. 🌱✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Title check ❓ Inconclusive The title 'chore: post-Jules-triage followups' is vague and generic, using non-descriptive language that does not convey meaningful information about the changeset. Consider a more specific title that highlights the primary change, such as 'chore: tighten sql.js types and export WorkerPort' or similar.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed The PR successfully addresses all coding objectives from linked issues #312 and #292: tightens sql.js types in WasmDatabaseEngine to use CellValue[], exports WorkerPort, adds editorController test coverage, and applies optional chaining for safe module loading.
Out of Scope Changes check ✅ Passed All changes are directly aligned with the linked issues: type improvements, WorkerPort export, test additions, and test/type fixes for downstream impacts of earlier tightenings.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch followups/post-jules-triage

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request improves type safety in the WASM database engine by replacing unknown[] with CellValue[] and adds optional chaining to import.meta.env accesses to prevent crashes in environments where it is undefined. It also introduces a new unit test suite for the editorController and exports the WorkerPort interface. Feedback was provided regarding a change in rpc.test.ts where using unknown[] and type casting reduced type safety; a suggestion was made to restore the more specific function signature.

Comment thread tests/unit/rpc.test.ts
Comment on lines +14 to 16
const methods: Record<string, (...args: unknown[]) => unknown> = {
add: (...args: unknown[]) => (args[0] as number) + (args[1] as number)
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

This change reduces type safety by using unknown[] and type casting. The original, more specific function signature (a: number, b: number) => a + b is preferable as it's more readable and safer, and it is assignable to the required (...args: unknown[]) => unknown type.

I suggest restoring the safer function implementation while keeping the explicit type annotation:

Suggested change
const methods: Record<string, (...args: unknown[]) => unknown> = {
add: (...args: unknown[]) => (args[0] as number) + (args[1] as number)
};
const methods: Record<string, (...args: unknown[]) => unknown> = {
add: (a: number, b: number) => a + b
};

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/core/engine/wasm/WasmDatabaseEngine.ts`:
- Around line 34-46: The CellValue type used by the WasmPreparedStatement and
WasmDatabaseInstance interfaces is missing boolean support; update the CellValue
type definition to include boolean so binding boolean values is allowed (affects
usages in WasmPreparedStatement methods bind, run, get and WasmDatabaseInstance
methods exec and prepare), i.e. add boolean to the existing union for CellValue
so TypeScript reflects sql.js's accepted parameter types.

In `@tests/unit/editorController.test.ts`:
- Around line 10-14: The test currently assigns to readonly VS Code API fields
directly (ExtensionKind, env.remoteName, extensions) which is fragile; replace
those direct assignments by using Object.defineProperty on the mock object
(e.g., define ExtensionKind, define env with remoteName, and define
extensions.getExtension) so properties are set as non-writable/configurable as
needed; update the mocked symbols referenced in this file (ExtensionKind,
mockVscode.env.remoteName, and mockVscode.extensions.getExtension) to be defined
via Object.defineProperty to mirror VS Code readonly behavior.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ee31b1c2-9b39-40d5-bb66-6382caf26f46

📥 Commits

Reviewing files that changed from the base of the PR and between 364f1fd and e0f06a2.

📒 Files selected for processing (6)
  • src/core/engine/wasm/WasmDatabaseEngine.ts
  • src/core/rpc.ts
  • src/editorController.ts
  • tests/unit/editorController.test.ts
  • tests/unit/rpc.test.ts
  • tests/unit/webviewMessageHandler.test.ts
📜 Review details
🧰 Additional context used
📓 Path-based instructions (4)
tests/unit/*.test.ts

📄 CodeRabbit inference engine (CLAUDE.md)

tests/unit/*.test.ts: Use Object.defineProperty(obj, prop, { value, writable: true, configurable: true }) for setting readonly VS Code API fields like vscode.env.uiKind in unit tests
Import tests/unit/vscode_mock_setup.ts at the beginning of unit test files to ensure VS Code mocks are initialized before running tests

Files:

  • tests/unit/rpc.test.ts
  • tests/unit/webviewMessageHandler.test.ts
  • tests/unit/editorController.test.ts
src/**/*.ts

📄 CodeRabbit inference engine (CLAUDE.md)

src/**/*.ts: Use prepared statements with ? placeholders for all query parameter values to prevent SQL injection
Always use escapeIdentifier() function for table and column names in SQL queries to prevent identifier-based SQL injection
Use validateSqlType() for all user-provided SQL types in DDL statements to prevent type-based SQL injection
Validate PRAGMA string values with the regex /^[a-zA-Z0-9_-]+$/ whitelist and check numeric PRAGMA values with Number.isFinite()
Use escapeLikePattern() for user input in LIKE queries with the ESCAPE '\\' clause to prevent LIKE wildcard injection
Use zero-copy transfer for large binary data (ArrayBuffers) in RPC communication by wrapping with the Transfer wrapper
Use SAVEPOINT/RELEASE/ROLLBACK TO instead of BEGIN TRANSACTION in updateCellBatch to safely handle nested transactions
Use the safeRollback(context) helper when handling transaction errors to log failures instead of throwing, preventing secondary rollback errors
Check for SQLite json_patch() availability at engine construction time and use it in UPDATE statements when available, falling back to JS-side applyMergePatch() when unavailable
Use getNodeFs() from sqlite-db.ts to safely require the Node.js fs module, which returns undefined in browser environments
Check import.meta.env.VSCODE_BROWSER_EXT to conditionally handle environment-specific code paths for browser vs Node.js platforms
Use the Core RPC protocol defined in src/core/rpc.ts for all Worker communication and when the Extension invokes Webview methods
Use buildMethodProxy() from src/core/rpc.ts to create proxy objects that automatically serialize RPC calls to workers or the webview
Record database modifications in ModificationTracker via recordModification() before committing changes to track undo/redo history
Write all executed SQL (both read and write operations) to the 'SQLite Explorer' output channel via GlobalOutputChannel?.appendLine() for debugging...

Files:

  • src/core/rpc.ts
  • src/editorController.ts
  • src/core/engine/wasm/WasmDatabaseEngine.ts
{src/**/*.ts,core/ui/modules/*.js}

📄 CodeRabbit inference engine (CLAUDE.md)

Serialize Uint8Array using the marker format { __type: 'Uint8Array', base64: '...' } with exactly 2 keys to prevent collisions with user data

Files:

  • src/core/rpc.ts
  • src/editorController.ts
  • src/core/engine/wasm/WasmDatabaseEngine.ts
src/editorController.ts

📄 CodeRabbit inference engine (CLAUDE.md)

src/editorController.ts: Use retainContextWhenHidden: false for webview configuration to destroy webviews when hidden and preserve state via vscodeApi.setState()/getState()
Use nonce-based Content Security Policy for scripts (no 'unsafe-inline') and for <style> tags in the webview
Implement CustomEditorProvider with openCustomDocument() to create DatabaseDocument, resolveCustomEditor() to create webview and RPC, and save()/dispose() lifecycle methods

Files:

  • src/editorController.ts
🔇 Additional comments (7)
src/editorController.ts (1)

263-264: LGTM!

Also applies to: 381-393

tests/unit/editorController.test.ts (1)

18-27: ⚡ Quick win

and

src/core/engine/wasm/WasmDatabaseEngine.ts (2)

125-125: LGTM!


304-304: LGTM!

src/core/rpc.ts (1)

348-351: LGTM!

tests/unit/rpc.test.ts (1)

14-16: LGTM!

tests/unit/webviewMessageHandler.test.ts (1)

16-16: LGTM!

Also applies to: 54-54, 80-80

Comment on lines 34 to +46
interface WasmPreparedStatement {
run(params?: unknown[]): void;
bind(params?: unknown[]): boolean;
get(params?: unknown[]): CellValue[] | undefined;
run(params?: CellValue[]): void;
bind(params?: CellValue[]): boolean;
get(params?: CellValue[]): CellValue[] | undefined;
step(): boolean;
reset(): void;
free(): boolean;
getColumnNames(): string[];
}

export interface WasmDatabaseInstance {
exec(sql: string, params?: unknown[]): Array<{ columns: string[]; values: unknown[][] }>;
prepare(sql: string, params?: unknown[]): WasmPreparedStatement;
exec(sql: string, params?: CellValue[]): Array<{ columns: string[]; values: CellValue[][] }>;
prepare(sql: string, params?: CellValue[]): WasmPreparedStatement;
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
# Check CellValue type definition to understand the constraint
rg -A 10 "type CellValue" --type=ts

# Search for sql.js usage patterns to see what types are actually passed
rg -C 3 "\.bind\(|\.run\(|\.exec\(" src/core/engine/wasm/ --type=ts

Repository: zknpr/SQLite-Explorer

Length of output: 4829


🌐 Web query:

What parameter types does sql.js bind() method accept for prepared statement parameters?

💡 Result:

The bind method in sql.js accepts two primary parameter types to bind values to a prepared statement [1][2]. Depending on the type of parameters defined in your SQL statement, you should provide either an array or an object [1][2]: 1. Array: Use an array when binding values to anonymous (positional) parameters (e.g.,?,?NNN) [1][2]. The order of values in the array corresponds to the order of parameters in the SQL statement [2]. 2. Object: Use an object when binding values to named parameters (e.g.,:VVV, @VVV, $VVV) [1][2]. The keys of the object must match the parameter names defined in the SQL string [2]. Note that the prefixes (:, @, $) must be included in the object keys [1][2]. Mapping of JavaScript types to SQLite types: The library automatically handles the mapping of JavaScript data types to their corresponding SQLite types as follows [1][3]: JavaScript Type | SQLite Type --- | --- number | REAL, INTEGER boolean | INTEGER string | TEXT Array, Uint8Array | BLOB null | NULL The bind method resets the statement before applying new values [1][2]. If you pass null, the method does nothing and returns true [1][3].

Citations:


Add boolean to the CellValue type definition to match sql.js parameter support.

The interface declarations constrain sql.js parameters to CellValue[] (string | number | null | Uint8Array), but sql.js's official documentation shows the bind() method accepts boolean values, which it maps to SQLite INTEGER. The CellValue type should include boolean to accurately reflect the library's capabilities and prevent type safety gaps when boolean data is used with prepared statements.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/core/engine/wasm/WasmDatabaseEngine.ts` around lines 34 - 46, The
CellValue type used by the WasmPreparedStatement and WasmDatabaseInstance
interfaces is missing boolean support; update the CellValue type definition to
include boolean so binding boolean values is allowed (affects usages in
WasmPreparedStatement methods bind, run, get and WasmDatabaseInstance methods
exec and prepare), i.e. add boolean to the existing union for CellValue so
TypeScript reflects sql.js's accepted parameter types.

Comment on lines +10 to +14
(mockVscode as any).ExtensionKind = { Workspace: 2, UI: 1 };
mockVscode.env.remoteName = 'remote';
(mockVscode as any).extensions = {
getExtension: () => ({ extensionKind: 2 })
};
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

# Check if the file exists and read its content
if [ -f "tests/unit/editorController.test.ts" ]; then
  echo "=== File exists ==="
  wc -l tests/unit/editorController.test.ts
  echo ""
  echo "=== First 30 lines (including imports and lines 10-14) ==="
  head -n 30 tests/unit/editorController.test.ts
else
  echo "File not found"
fi

Repository: zknpr/SQLite-Explorer

Length of output: 1441


🏁 Script executed:

# Also check for vscode_mock_setup import
rg -n "vscode_mock_setup" tests/unit/editorController.test.ts | head -5

Repository: zknpr/SQLite-Explorer

Length of output: 97


🏁 Script executed:

# Search for any other uses of ExtensionKind, env.remoteName, or extensions in the test file
rg -n "(ExtensionKind|remoteName|extensions)" tests/unit/editorController.test.ts

Repository: zknpr/SQLite-Explorer

Length of output: 289


Use Object.defineProperty for mocked VS Code readonly fields.

Direct assignment to VS Code API fields like ExtensionKind, env.remoteName, and extensions should use Object.defineProperty instead for better test robustness and consistency with readonly property expectations.

Suggested patch
-(mockVscode as any).ExtensionKind = { Workspace: 2, UI: 1 };
-mockVscode.env.remoteName = 'remote';
-(mockVscode as any).extensions = {
-    getExtension: () => ({ extensionKind: 2 })
-};
+Object.defineProperty(mockVscode as object, 'ExtensionKind', {
+    value: { Workspace: 2, UI: 1 },
+    writable: true,
+    configurable: true,
+});
+Object.defineProperty(mockVscode.env as object, 'remoteName', {
+    value: 'remote',
+    writable: true,
+    configurable: true,
+});
+Object.defineProperty(mockVscode as object, 'extensions', {
+    value: { getExtension: () => ({ extensionKind: 2 }) },
+    writable: true,
+    configurable: true,
+});
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
(mockVscode as any).ExtensionKind = { Workspace: 2, UI: 1 };
mockVscode.env.remoteName = 'remote';
(mockVscode as any).extensions = {
getExtension: () => ({ extensionKind: 2 })
};
Object.defineProperty(mockVscode as object, 'ExtensionKind', {
value: { Workspace: 2, UI: 1 },
writable: true,
configurable: true,
});
Object.defineProperty(mockVscode.env as object, 'remoteName', {
value: 'remote',
writable: true,
configurable: true,
});
Object.defineProperty(mockVscode as object, 'extensions', {
value: { getExtension: () => ({ extensionKind: 2 }) },
writable: true,
configurable: true,
});
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/unit/editorController.test.ts` around lines 10 - 14, The test currently
assigns to readonly VS Code API fields directly (ExtensionKind, env.remoteName,
extensions) which is fragile; replace those direct assignments by using
Object.defineProperty on the mock object (e.g., define ExtensionKind, define env
with remoteName, and define extensions.getExtension) so properties are set as
non-writable/configurable as needed; update the mocked symbols referenced in
this file (ExtensionKind, mockVscode.env.remoteName, and
mockVscode.extensions.getExtension) to be defined via Object.defineProperty to
mirror VS Code readonly behavior.

Apply review feedback from PR #338: line 39 read `mockVscode.window.registerCustomEditorProvider` without the `as any` cast that line 40 has — the mock window object doesn't declare this property, so it introduced a fresh TS2339, regressing the tsc-clean invariant that this PR was meant to restore. Add the matching cast.

Also drop `before, after` from the import list since the test only uses `beforeEach`/`afterEach`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant