Skip to content

feat: add encoding parameter to binary widget#1737

Merged
gugu merged 1 commit into
mainfrom
feature/binary-widget-encoding-param
Apr 25, 2026
Merged

feat: add encoding parameter to binary widget#1737
gugu merged 1 commit into
mainfrom
feature/binary-widget-encoding-param

Conversation

@gugu
Copy link
Copy Markdown
Contributor

@gugu gugu commented Apr 24, 2026

Support hex (default), base64, and ascii encodings for binary widget display, record view, edit input, and filter. Adds backend validation for the encoding param on create/update and covers each encoding with frontend and AVA tests. Filter continues to emit hex on the wire to preserve the backend comparator contract.

Summary by CodeRabbit

Release Notes

  • New Features

    • Added Binary widget type with configurable encoding support (hex, base64, or ascii).
    • Binary fields now display and accept data in the specified encoding format.
  • Bug Fixes

    • Enhanced validation for binary widget parameters with clearer error messaging for unsupported encodings.

Support hex (default), base64, and ascii encodings for binary widget
display, record view, edit input, and filter. Adds backend validation
for the encoding param on create/update and covers each encoding with
frontend and AVA tests. Filter continues to emit hex on the wire to
preserve the backend comparator contract.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings April 24, 2026 20:46
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 24, 2026

📝 Walkthrough

Walkthrough

This PR adds configurable binary encoding support across the application, enabling Binary widgets to handle hex, base64, and ASCII-encoded data. Backend changes add validation for encoding parameters, while frontend components are refactored to support dynamic encoding selection and conversion throughout display, editing, and filtering workflows.

Changes

Cohort / File(s) Summary
Backend Binary Widget Support
backend/src/enums/widget-type.enum.ts, backend/src/entities/widget/utils/validate-create-widgets-ds.ts
Added Binary enum value and validation logic for widget_params.encoding field, rejecting unsupported encodings (hex, base64, ascii allowed).
Backend E2E Tests
backend/test/ava-tests/saas-tests/table-widgets-e2e.test.ts
Three new test cases for POST /widget/:slug covering Binary widget creation with supported/unsupported/omitted encoding values.
Frontend Binary Display Components
frontend/src/app/components/ui-components/record-view-fields/binary/..., frontend/src/app/components/ui-components/table-display-fields/binary/...
Updated display logic to derive and render encoding-aware output via computed encoding, encodedValue, and copyTooltip properties.
Frontend Binary Edit Component
frontend/src/app/components/ui-components/record-edit-fields/binary/...
Replaced hex-only editing with configurable-encoding input handling; switched internal state from hexData to rawInput, added encoding-aware initialization and change detection.
Frontend Binary Filter Component
frontend/src/app/components/ui-components/filter-fields/binary/...
Refactored to support hex, base64, and ascii inputs via conditional template rendering; replaced hexValue-based model with rawInput and encoding-aware parsing.
Frontend Binary Utility Library
frontend/src/app/lib/binary.ts, frontend/src/app/lib/binary.spec.ts
Introduced BinaryEncoding type and utilities for multi-format conversion: bytesToBase64/base64StringToBytes, bytesToAscii, bytesToEncoded/encodedToBytes, and isBinaryEncoding validation.
Frontend Base64 Validator
frontend/src/app/validators/base64.validator.ts
Simplified validator to perform structural checks only (length divisibility and character/padding regex) without attempting decode.
Frontend Widget Dashboard
frontend/src/app/components/dashboard/db-table-view/db-table-widgets/db-table-widgets.component.ts
Updated Binary widget default widget_params template with explicit JSON5 configuration example.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~35 minutes

Possibly related PRs

Suggested reviewers

  • lyubov-voloshko
  • Artuomka

Poem

🐰 A Binary hare bounds through hex and base64,
Converting bytes in every encoding's door,
From ASCII art to base64's embrace,
Each widget finds its proper encoding place! 🎉

🚥 Pre-merge checks | ✅ 5 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The pull request title accurately and concisely summarizes the primary change: adding an encoding parameter to the binary widget across backend validation and frontend UI components.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Security Check ✅ Passed Binary widget encoding support implements robust security with strict literal union type restrictions and comprehensive input validation aligned with OWASP standards.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feature/binary-widget-encoding-param

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
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Adds an encoding widget parameter to the Binary widget so binary values can be displayed/edited as hex (default), base64, or ascii, while keeping filter values emitted to the backend in hex.

Changes:

  • Introduces binary encoding helpers (encode/decode + type guard) and expands unit tests for hex/base64/ascii behavior.
  • Updates Binary display, record-view, record-edit, and filter components to respect widget_params.encoding and update copy/tooltips accordingly.
  • Adds backend validation and AVA e2e coverage for accepting/rejecting Binary widget encoding values.

Reviewed changes

Copilot reviewed 19 out of 19 changed files in this pull request and generated 3 comments.

Show a summary per file
File Description
frontend/src/app/validators/base64.validator.ts Updates base64 validator logic to regex/length-based validation.
frontend/src/app/lib/binary.ts Adds encoding types/constants and base64/ascii encode/decode helpers.
frontend/src/app/lib/binary.spec.ts Adds tests for base64/ascii + encoded round-trips and type guard.
frontend/src/app/components/ui-components/table-display-fields/binary/binary.component.ts Displays/copies binary values using configured encoding.
frontend/src/app/components/ui-components/table-display-fields/binary/binary.component.html Copies encoded value and uses encoding-aware tooltip.
frontend/src/app/components/ui-components/table-display-fields/binary/binary.component.spec.ts Tests encoding behavior for table display field.
frontend/src/app/components/ui-components/record-view-fields/binary/binary.component.ts Record-view display/copy uses configured encoding and truncation logic.
frontend/src/app/components/ui-components/record-view-fields/binary/binary.component.html Copies encoded value and uses encoding-aware tooltip; tooltip shows full encoded when truncated.
frontend/src/app/components/ui-components/record-view-fields/binary/binary.component.spec.ts Tests encoding behavior for record view field.
frontend/src/app/components/ui-components/record-edit-fields/binary/binary.component.ts Edit input seeded/parsed according to encoding; emits Buffer-JSON when valid.
frontend/src/app/components/ui-components/record-edit-fields/binary/binary.component.html Switches validators/placeholder/label based on encoding.
frontend/src/app/components/ui-components/record-edit-fields/binary/binary.component.spec.ts Tests edit seeding and encode/decode paths per encoding.
frontend/src/app/components/ui-components/filter-fields/binary/binary.component.ts Accepts typed input in selected encoding but emits hex to backend.
frontend/src/app/components/ui-components/filter-fields/binary/binary.component.html Switches validators/placeholder/label based on encoding.
frontend/src/app/components/ui-components/filter-fields/binary/binary.component.spec.ts Tests filter input seeding and hex-on-wire behavior per encoding.
frontend/src/app/components/dashboard/db-table-view/db-table-widgets/db-table-widgets.component.ts Updates default Binary widget params docs to include encoding.
backend/test/ava-tests/saas-tests/table-widgets-e2e.test.ts Adds e2e coverage for Binary widget encoding acceptance/rejection.
backend/src/enums/widget-type.enum.ts Adds Binary to WidgetTypeEnum.
backend/src/entities/widget/utils/validate-create-widgets-ds.ts Validates Binary widget encoding param values.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +112 to +120
if (widget_type && widget_type === WidgetTypeEnum.Binary) {
const rawParams = widgetDS.widget_params;
if (rawParams) {
const widget_params: Record<string, any> =
typeof rawParams === 'string' ? JSON5.parse(rawParams) : (rawParams as Record<string, any>);
if (widget_params.encoding !== undefined && !['hex', 'base64', 'ascii'].includes(widget_params.encoding)) {
errors.push(Messages.WIDGET_PARAMETER_UNSUPPORTED('encoding', WidgetTypeEnum.Binary));
}
}
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

widget_params is JSON5-parsed here without any error handling. If a client sends an invalid JSON5 string for widget_params, JSON5.parse will throw and the endpoint will return a 500 instead of a validation error. Consider wrapping the parse in a try/catch and pushing a validation message when parsing fails (consistent with other validation errors returned from this function).

Copilot uses AI. Check for mistakes.
Comment on lines +63 to +80
onInputChange(value: string): void {
this.rawInput = value;
this.onFieldChange.emit(this.currentHex());
this.onComparatorChange.emit(this.filterMode);
}

private currentHex(): string {
if (!this.rawInput) {
this.isInvalidInput = false;
return '';
}
const bytes = encodedToBytes(this.rawInput, this.encoding());
if (bytes === null) {
this.isInvalidInput = true;
return '';
}
this.isInvalidInput = false;
return bytesToHex(bytes);
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

When rawInput is invalid for the selected encoding, currentHex() returns an empty string and onInputChange() still emits that to the parent. This can unintentionally apply a filter for empty binary data (with comparator still set to eq/contains/startswith) rather than preserving the previous value or preventing filter updates until the input is valid. Consider emitting the last valid hex (or the raw input) and/or gating onFieldChange.emit when bytes === null so invalid input doesn’t translate into a real backend filter value.

Copilot uses AI. Check for mistakes.
Comment on lines +3 to +8
export type BinaryEncoding = 'hex' | 'base64' | 'ascii';

export const BINARY_ENCODINGS = ['hex', 'base64', 'ascii'] as const;

export function isBinaryEncoding(value: unknown): value is BinaryEncoding {
return value === 'hex' || value === 'base64' || value === 'ascii';
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

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

BINARY_ENCODINGS and isBinaryEncoding() duplicate the same list of allowed values. This can drift over time if a new encoding is added. Consider deriving the type guard from BINARY_ENCODINGS (e.g., via includes) so there’s a single source of truth.

Suggested change
export type BinaryEncoding = 'hex' | 'base64' | 'ascii';
export const BINARY_ENCODINGS = ['hex', 'base64', 'ascii'] as const;
export function isBinaryEncoding(value: unknown): value is BinaryEncoding {
return value === 'hex' || value === 'base64' || value === 'ascii';
export const BINARY_ENCODINGS = ['hex', 'base64', 'ascii'] as const;
export type BinaryEncoding = (typeof BINARY_ENCODINGS)[number];
export function isBinaryEncoding(value: unknown): value is BinaryEncoding {
return typeof value === 'string' && BINARY_ENCODINGS.includes(value as BinaryEncoding);

Copilot uses AI. Check for mistakes.
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

🧹 Nitpick comments (6)
backend/test/ava-tests/saas-tests/table-widgets-e2e.test.ts (1)

1705-1810: Consider parameterizing over all three accepted encodings.

The accept-path currently only tests base64. Since the validator explicitly whitelists hex, base64, and ascii, parameterizing this test over the three valid values would guard against an accidental regression of the allowed list (e.g. ['hex','base64']) that would still pass today.

♻️ Sketch
for (const encoding of ['hex', 'base64', 'ascii'] as const) {
    test.serial(`${currentTest} should accept encoding=${encoding}`, async (t) => {
        // ... same body, parameterize widget_params and the params.encoding assertion
    });
}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/test/ava-tests/saas-tests/table-widgets-e2e.test.ts` around lines
1705 - 1810, The tests only assert that WidgetTypeEnum.Binary accepts 'base64'
but the validator allows 'hex', 'base64', and 'ascii'; update the tests around
the Binary widget cases (the test block names using currentTest and the
CreateOrUpdateTableWidgetsDto payloads) to parameterize over the three encodings
and assert each is accepted: iterate encodings = ['hex','base64','ascii'] and
for each create the payload with widget_params JSON.stringify({encoding}) when
posting to POST `/widget/${connectionId}?tableName=${tableNameForWidgets}`,
expect 201 and verify params.encoding via JSON5.parse(ro[0].widget_params)
equals the current encoding; keep the existing invalid-encoding and
absent-encoding tests as-is.
backend/src/entities/widget/utils/validate-create-widgets-ds.ts (1)

112-121: Extract the allowed encodings and consider flagging unknown keys.

Two minor improvements for this new Binary branch:

  1. The allowed encoding list ['hex', 'base64', 'ascii'] is hardcoded here and duplicated on the frontend (see BinaryEncoding usage in frontend/src/app/lib/binary.ts). Consider lifting this to a single exported constant (e.g. in backend/src/helpers/constants/constants.ts alongside FOREIGN_KEY_FIELDS, and mirrored on the frontend) so the backend validator and frontend type cannot drift.
  2. Unlike the Foreign_key branch (which flags any key not in FOREIGN_KEY_FIELDS), this branch only validates encoding. A typo like { encodng: 'hex' } would pass silently and be stored. Since encoding is the only currently-supported param, it would be cheap to reject unknown keys for Binary the same way.
♻️ Suggested refactor
 		if (widget_type && widget_type === WidgetTypeEnum.Binary) {
 			const rawParams = widgetDS.widget_params;
 			if (rawParams) {
 				const widget_params: Record<string, any> =
 					typeof rawParams === 'string' ? JSON5.parse(rawParams) : (rawParams as Record<string, any>);
-				if (widget_params.encoding !== undefined && !['hex', 'base64', 'ascii'].includes(widget_params.encoding)) {
-					errors.push(Messages.WIDGET_PARAMETER_UNSUPPORTED('encoding', WidgetTypeEnum.Binary));
+				const SUPPORTED_BINARY_ENCODINGS = ['hex', 'base64', 'ascii'];
+				for (const key of Object.keys(widget_params)) {
+					if (key !== 'encoding') {
+						errors.push(Messages.WIDGET_PARAMETER_UNSUPPORTED(key, WidgetTypeEnum.Binary));
+					}
+				}
+				if (widget_params.encoding !== undefined && !SUPPORTED_BINARY_ENCODINGS.includes(widget_params.encoding)) {
+					errors.push(Messages.WIDGET_PARAMETER_UNSUPPORTED('encoding', WidgetTypeEnum.Binary));
 				}
 			}
 		}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@backend/src/entities/widget/utils/validate-create-widgets-ds.ts` around lines
112 - 121, The Binary branch currently hardcodes allowed encodings and only
checks the "encoding" key so typos slip through; extract the encoding list into
a shared backend constant (e.g. add BINARY_ENCODINGS = ['hex','base64','ascii']
in the existing constants file) and use that in the validator where
WidgetTypeEnum.Binary is handled (look for widgetDS.widget_params and the
current ['hex','base64','ascii'] check), then additionally reject unknown keys
by comparing Object.keys(widget_params) against the single allowed set
(['encoding']) and push Messages.WIDGET_PARAMETER_UNSUPPORTED for any unexpected
param names (mirror the approach used for FOREIGN_KEY_FIELDS validation); keep
the frontend in sync by importing the same enum/constant there.
frontend/src/app/components/ui-components/record-view-fields/binary/binary.component.ts (1)

19-24: DRY suggestion: extract shared encoding derivation helper.

The same encoding, encodedValue, and copyTooltip computed pattern is duplicated verbatim in table-display-fields/binary/binary.component.ts (lines 19-24) and a near-identical derivation lives in the record-edit and filter binary components. Consider extracting a small helper in frontend/src/app/lib/binary.ts (e.g. resolveEncoding(widgetParams: { encoding?: unknown } | undefined): BinaryEncoding) to avoid four copies drifting apart over time.

♻️ Proposed helper
// frontend/src/app/lib/binary.ts
+export function resolveEncoding(widgetParams: { encoding?: unknown } | null | undefined): BinaryEncoding {
+  const raw = widgetParams?.encoding;
+  return isBinaryEncoding(raw) ? raw : 'hex';
+}
-import { bytesToEncoded, isBinaryEncoding, parseBinaryValue } from 'src/app/lib/binary';
+import { bytesToEncoded, parseBinaryValue, resolveEncoding } from 'src/app/lib/binary';
 ...
-  public readonly encoding = computed(() => {
-    const raw = this.widgetStructure()?.widget_params?.encoding;
-    return isBinaryEncoding(raw) ? raw : 'hex';
-  });
+  public readonly encoding = computed(() => resolveEncoding(this.widgetStructure()?.widget_params));
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/src/app/components/ui-components/record-view-fields/binary/binary.component.ts`
around lines 19 - 24, The encoding derivation logic is duplicated across
multiple binary components; extract a helper resolveEncoding(widgetParams) in
frontend/src/app/lib/binary.ts and use it in this component to compute encoding,
encodedValue and copyTooltip. Replace the computed encoding block (which reads
widgetStructure()?.widget_params?.encoding and calls isBinaryEncoding) with a
call to resolveEncoding(widgetStructure()?.widget_params), keep encodedValue
using bytesToEncoded(this.bytes(), this.encoding()) and copyTooltip using `Copy
${this.encoding()}`; ensure the helper returns the default 'hex' and exports a
BinaryEncoding type so table-display-fields/binary/binary.component.ts,
record-edit and filter binary components can import and use the same
resolveEncoding to remove duplication.
frontend/src/app/components/ui-components/record-edit-fields/binary/binary.component.ts (1)

31-34: Access modifier for signal doesn't match guideline.

encoding is implicitly public. Templates can still read protected members in Angular, so protected readonly satisfies both template binding and the style rule.

♻️ Proposed change
-	public readonly encoding = computed(() => {
+	protected readonly encoding = computed(() => {
 		const raw = this.widgetStructure()?.widget_params?.encoding;
 		return isBinaryEncoding(raw) ? raw : 'hex';
 	});

As per coding guidelines: "Signals for component state must be declared as protected or private readonly and initialized with signal() or computed()".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/src/app/components/ui-components/record-edit-fields/binary/binary.component.ts`
around lines 31 - 34, Change the access modifier on the computed signal named
encoding to match project guidelines: make the property protected readonly
instead of public (i.e., use "protected readonly encoding = computed(...)" in
the component where encoding is defined), leaving the implementation using
widgetStructure() and isBinaryEncoding unchanged so template bindings still
work.
frontend/src/app/components/ui-components/filter-fields/binary/binary.component.ts (2)

69-81: Private currentHex() mutates validity state as a side effect.

currentHex() reads like a pure getter but flips isInvalidInput. This couples validation to the serialization path and makes the flow harder to reason about (e.g. onFilterModeChange re-validates rawInput every time the comparator changes).

Consider splitting parsing and validation, e.g. computing bytes once per input change and deriving both isInvalidInput and the emitted hex from that single result.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/src/app/components/ui-components/filter-fields/binary/binary.component.ts`
around lines 69 - 81, currentHex() currently mutates isInvalidInput as a side
effect; make it a pure getter by removing any writes to isInvalidInput and
returning hex only (use encodedToBytes(this.rawInput, this.encoding()) and
bytesToHex when valid). Add a single place that parses the input (e.g. a new
private parsedBytes property or parseRawInput() called from
input/encoding/filter-mode change handlers such as onFilterModeChange) that
computes bytes once, sets isInvalidInput based on whether encodedToBytes
returned null, and stores the bytes for reuse; then have currentHex() read that
stored bytes and return '' if null. Ensure you update callers to call the new
parser on input/setting changes rather than relying on currentHex() to perform
validation.

34-37: Encoding signal should be protected readonly.

Same guideline issue as in record-edit-fields/binary/binary.component.ts: state signals must not be public. Prefer protected readonly so the template still binds.

♻️ Proposed change
-	public readonly encoding = computed(() => {
+	protected readonly encoding = computed(() => {
 		const raw = this.widgetStructure()?.widget_params?.encoding;
 		return isBinaryEncoding(raw) ? raw : 'hex';
 	});

As per coding guidelines: "Signals for component state must be declared as protected or private readonly and initialized with signal() or computed()".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/src/app/components/ui-components/filter-fields/binary/binary.component.ts`
around lines 34 - 37, The encoding computed signal in BinaryComponent is
declared public but must be protected readonly per component state signal
guidelines; update the declaration of the encoding computed (the computed(() =>
{ const raw = this.widgetStructure()?.widget_params?.encoding; return
isBinaryEncoding(raw) ? raw : 'hex'; })) to use protected readonly so templates
still bind but the signal is not public.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@frontend/src/app/components/ui-components/record-edit-fields/binary/binary.component.html`:
- Around line 26-32: The ascii branch currently lacks validation and mat-error
UI, so add an asciiValidator to the ASCII textarea and show a mat-error like the
hex/base64 branches: hook the validator into the template for the textarea bound
to [(ngModel)]="rawInput" and (ngModelChange)="onInputChange()", and add a
corresponding <mat-error> message that displays when asciiValidator fails;
implement asciiValidator (used by the component class handling
onInputChange/stringToBytes) to reject any code point > 0x7F and to detect
surrogate pairs/invalid UTF-16 sequences so users are warned when non-ASCII
characters are entered.

In `@frontend/src/app/lib/binary.ts`:
- Around line 75-89: bytesToAscii currently replaces non-printable bytes with
'.' which causes silent data loss on edits; change bytesToAscii to emit a
reversible representation for non-printable bytes (e.g. '\xNN' hex escapes)
instead of '.' so the original byte values can be round-tripped, and update
encodedToBytes(..., 'ascii') to parse those escapes back into the original
bytes; also simplify isPrintableAscii by removing the redundant "byte !== 0x7f"
check (keep the same printable-range logic). Ensure the unique symbols touched
are bytesToAscii, isPrintableAscii and encodedToBytes so you can locate and
coordinate the encode/decode changes across the binary encoding helpers and the
record-edit flow.

---

Nitpick comments:
In `@backend/src/entities/widget/utils/validate-create-widgets-ds.ts`:
- Around line 112-121: The Binary branch currently hardcodes allowed encodings
and only checks the "encoding" key so typos slip through; extract the encoding
list into a shared backend constant (e.g. add BINARY_ENCODINGS =
['hex','base64','ascii'] in the existing constants file) and use that in the
validator where WidgetTypeEnum.Binary is handled (look for
widgetDS.widget_params and the current ['hex','base64','ascii'] check), then
additionally reject unknown keys by comparing Object.keys(widget_params) against
the single allowed set (['encoding']) and push
Messages.WIDGET_PARAMETER_UNSUPPORTED for any unexpected param names (mirror the
approach used for FOREIGN_KEY_FIELDS validation); keep the frontend in sync by
importing the same enum/constant there.

In `@backend/test/ava-tests/saas-tests/table-widgets-e2e.test.ts`:
- Around line 1705-1810: The tests only assert that WidgetTypeEnum.Binary
accepts 'base64' but the validator allows 'hex', 'base64', and 'ascii'; update
the tests around the Binary widget cases (the test block names using currentTest
and the CreateOrUpdateTableWidgetsDto payloads) to parameterize over the three
encodings and assert each is accepted: iterate encodings =
['hex','base64','ascii'] and for each create the payload with widget_params
JSON.stringify({encoding}) when posting to POST
`/widget/${connectionId}?tableName=${tableNameForWidgets}`, expect 201 and
verify params.encoding via JSON5.parse(ro[0].widget_params) equals the current
encoding; keep the existing invalid-encoding and absent-encoding tests as-is.

In
`@frontend/src/app/components/ui-components/filter-fields/binary/binary.component.ts`:
- Around line 69-81: currentHex() currently mutates isInvalidInput as a side
effect; make it a pure getter by removing any writes to isInvalidInput and
returning hex only (use encodedToBytes(this.rawInput, this.encoding()) and
bytesToHex when valid). Add a single place that parses the input (e.g. a new
private parsedBytes property or parseRawInput() called from
input/encoding/filter-mode change handlers such as onFilterModeChange) that
computes bytes once, sets isInvalidInput based on whether encodedToBytes
returned null, and stores the bytes for reuse; then have currentHex() read that
stored bytes and return '' if null. Ensure you update callers to call the new
parser on input/setting changes rather than relying on currentHex() to perform
validation.
- Around line 34-37: The encoding computed signal in BinaryComponent is declared
public but must be protected readonly per component state signal guidelines;
update the declaration of the encoding computed (the computed(() => { const raw
= this.widgetStructure()?.widget_params?.encoding; return isBinaryEncoding(raw)
? raw : 'hex'; })) to use protected readonly so templates still bind but the
signal is not public.

In
`@frontend/src/app/components/ui-components/record-edit-fields/binary/binary.component.ts`:
- Around line 31-34: Change the access modifier on the computed signal named
encoding to match project guidelines: make the property protected readonly
instead of public (i.e., use "protected readonly encoding = computed(...)" in
the component where encoding is defined), leaving the implementation using
widgetStructure() and isBinaryEncoding unchanged so template bindings still
work.

In
`@frontend/src/app/components/ui-components/record-view-fields/binary/binary.component.ts`:
- Around line 19-24: The encoding derivation logic is duplicated across multiple
binary components; extract a helper resolveEncoding(widgetParams) in
frontend/src/app/lib/binary.ts and use it in this component to compute encoding,
encodedValue and copyTooltip. Replace the computed encoding block (which reads
widgetStructure()?.widget_params?.encoding and calls isBinaryEncoding) with a
call to resolveEncoding(widgetStructure()?.widget_params), keep encodedValue
using bytesToEncoded(this.bytes(), this.encoding()) and copyTooltip using `Copy
${this.encoding()}`; ensure the helper returns the default 'hex' and exports a
BinaryEncoding type so table-display-fields/binary/binary.component.ts,
record-edit and filter binary components can import and use the same
resolveEncoding to remove duplication.
🪄 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: CHILL

Plan: Pro

Run ID: b5f30d31-e854-4fe5-999f-f71ac477d0c3

📥 Commits

Reviewing files that changed from the base of the PR and between 8ec9628 and 48f0642.

📒 Files selected for processing (19)
  • backend/src/entities/widget/utils/validate-create-widgets-ds.ts
  • backend/src/enums/widget-type.enum.ts
  • backend/test/ava-tests/saas-tests/table-widgets-e2e.test.ts
  • frontend/src/app/components/dashboard/db-table-view/db-table-widgets/db-table-widgets.component.ts
  • frontend/src/app/components/ui-components/filter-fields/binary/binary.component.html
  • frontend/src/app/components/ui-components/filter-fields/binary/binary.component.spec.ts
  • frontend/src/app/components/ui-components/filter-fields/binary/binary.component.ts
  • frontend/src/app/components/ui-components/record-edit-fields/binary/binary.component.html
  • frontend/src/app/components/ui-components/record-edit-fields/binary/binary.component.spec.ts
  • frontend/src/app/components/ui-components/record-edit-fields/binary/binary.component.ts
  • frontend/src/app/components/ui-components/record-view-fields/binary/binary.component.html
  • frontend/src/app/components/ui-components/record-view-fields/binary/binary.component.spec.ts
  • frontend/src/app/components/ui-components/record-view-fields/binary/binary.component.ts
  • frontend/src/app/components/ui-components/table-display-fields/binary/binary.component.html
  • frontend/src/app/components/ui-components/table-display-fields/binary/binary.component.spec.ts
  • frontend/src/app/components/ui-components/table-display-fields/binary/binary.component.ts
  • frontend/src/app/lib/binary.spec.ts
  • frontend/src/app/lib/binary.ts
  • frontend/src/app/validators/base64.validator.ts

Comment on lines +26 to +32
@case ('ascii') {
<textarea matInput resizeToFitContent rows="8"
name="{{label()}}-{{key()}}-ascii-content"
[required]="required()" [disabled]="disabled()" [readonly]="readonly()"
[(ngModel)]="rawInput" (ngModelChange)="onInputChange()"
></textarea>
}
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

ASCII case silently accepts non-ASCII characters.

Unlike the hex and base64 branches, the ascii textarea has no validator and no mat-error. If the user types or pastes a character outside 0x00–0x7F (accented letters, emoji, CJK…), stringToBytes will still produce a byte per charCodeAt(i) — with bits silently truncated for surrogate pairs and no warning for code points > 127. Consider attaching an asciiValidator and surfacing a message symmetric to the other two cases.

🛡️ Sketch
         `@case` ('ascii') {
-            <textarea matInput resizeToFitContent rows="8"
+            <textarea matInput resizeToFitContent rows="8" asciiValidator
                 name="{{label()}}-{{key()}}-ascii-content"
+                `#binaryContent`="ngModel"
                 [required]="required()" [disabled]="disabled()" [readonly]="readonly()"
                 [(ngModel)]="rawInput" (ngModelChange)="onInputChange()"
             ></textarea>
+            `@if` (binaryContent.errors?.isInvalidAscii) {
+                <mat-error>Only 7-bit ASCII characters are allowed.</mat-error>
+            }
         }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@frontend/src/app/components/ui-components/record-edit-fields/binary/binary.component.html`
around lines 26 - 32, The ascii branch currently lacks validation and mat-error
UI, so add an asciiValidator to the ASCII textarea and show a mat-error like the
hex/base64 branches: hook the validator into the template for the textarea bound
to [(ngModel)]="rawInput" and (ngModelChange)="onInputChange()", and add a
corresponding <mat-error> message that displays when asciiValidator fails;
implement asciiValidator (used by the component class handling
onInputChange/stringToBytes) to reject any code point > 0x7F and to detect
surrogate pairs/invalid UTF-16 sequences so users are warned when non-ASCII
characters are entered.

Comment on lines +75 to +89
// Replacement character for non-printable ASCII bytes in display/encode.
const ASCII_REPLACEMENT = '.';

function isPrintableAscii(byte: number): boolean {
if (byte === 0x09 || byte === 0x0a || byte === 0x0d) return true;
return byte >= 0x20 && byte !== 0x7f && byte <= 0x7e;
}

export function bytesToAscii(bytes: number[]): string {
let out = '';
for (const b of bytes) {
out += isPrintableAscii(b) ? String.fromCharCode(b) : ASCII_REPLACEMENT;
}
return out;
}
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 | 🟠 Major

ASCII encoding is lossy and round-trips as data corruption in the record-edit path.

bytesToAscii replaces any non-printable byte with . (0x2e). In record-edit-fields/binary/binary.component.ts, ngOnInit seeds rawInput via bytesToEncoded(parseBinaryValue(this.value()), 'ascii'), and onInputChange round-trips the current rawInput through encodedToBytes(..., 'ascii')stringToBytes. So any pre-existing non-printable byte is shown as . and, on the next edit + save, is written back as a literal 0x2e. The original bytes are silently lost.

Concretely, bytes like 0x00, 0x7f, 0xff that existed in the DB become 0x2e as soon as the user modifies any part of the field.

Options:

  • Disable editing when encoding === 'ascii' and the parsed bytes contain any non-printable byte, or render ascii as read-only for the record-edit component.
  • Make encodedToBytes(str, 'ascii') reject/round-trip-check so a rawInput containing placeholder .s that don't match the originally-decoded bytes isn't silently accepted.
  • Document ASCII as display-only (and remove it from encodedToBytes/record-edit use).

Also minor: in isPrintableAscii, byte !== 0x7f is redundant because byte <= 0x7e already excludes 0x7f.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@frontend/src/app/lib/binary.ts` around lines 75 - 89, bytesToAscii currently
replaces non-printable bytes with '.' which causes silent data loss on edits;
change bytesToAscii to emit a reversible representation for non-printable bytes
(e.g. '\xNN' hex escapes) instead of '.' so the original byte values can be
round-tripped, and update encodedToBytes(..., 'ascii') to parse those escapes
back into the original bytes; also simplify isPrintableAscii by removing the
redundant "byte !== 0x7f" check (keep the same printable-range logic). Ensure
the unique symbols touched are bytesToAscii, isPrintableAscii and encodedToBytes
so you can locate and coordinate the encode/decode changes across the binary
encoding helpers and the record-edit flow.

@gugu gugu merged commit eeb1622 into main Apr 25, 2026
22 of 23 checks passed
@gugu gugu deleted the feature/binary-widget-encoding-param branch April 25, 2026 11:44
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.

2 participants