Skip to content

refactor(tracker): simplify config value parsing#519

Merged
izadoesdev merged 1 commit into
stagingfrom
codex/desloppify-tracker-config
Jun 30, 2026
Merged

refactor(tracker): simplify config value parsing#519
izadoesdev merged 1 commit into
stagingfrom
codex/desloppify-tracker-config

Conversation

@izadoesdev

@izadoesdev izadoesdev commented Jun 30, 2026

Copy link
Copy Markdown
Member

Summary

  • remove forced any writes from tracker config parsing
  • share scalar coercion for script data-* attributes and script URL query params
  • keep config precedence unchanged: global config, then script data attributes, then script URL params

Verification

  • bunx ultracite check packages/tracker/src/core/utils.ts
  • cd packages/tracker && bun run check-types
  • cd packages/tracker && bun run test
  • bun run check-types
  • bun run lint
  • bun run test

AI disclosure

  • Prepared with AI assistance and human-reviewed before merge.

Summary by cubic

Simplifies tracker config parsing by centralizing value coercion and removing unsafe any writes. Shared parsers handle booleans, numbers, and JSON for both data-* attributes and script URL params, preserving empty strings in URL params and treating empty data-* values as true, with precedence unchanged.

  • Refactors
    • Added parseConfigValue and parseJsonAttribute for consistent coercion.
    • Removed intermediate any maps; tightened config typing.
    • Added unit test covering precedence and empty-string semantics.

Written for commit 31e9067. Summary will update on new commits.

Review in cubic

@vercel

vercel Bot commented Jun 30, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
databuddy-status Ready Ready Preview, Comment Jun 30, 2026 5:48pm
2 Skipped Deployments
Project Deployment Actions Updated (UTC)
dashboard Skipped Skipped Jun 30, 2026 5:48pm
documentation Skipped Skipped Jun 30, 2026 5:48pm

@coderabbitai

coderabbitai Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: a190d3c1-199f-4035-a746-cb75b937c785

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch codex/desloppify-tracker-config

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.

@greptile-apps

greptile-apps Bot commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This PR refactors getTrackerConfig in packages/tracker/src/core/utils.ts by extracting two small helper functions — parseConfigValue and parseJsonAttribute — to share scalar coercion logic between data-* attribute parsing and script URL query-param parsing, removing all as any casts in the process.

  • parseConfigValue now coerces empty-string values ("") to true, which is the existing behaviour for data attributes but is a new behaviour for URL query params (e.g. ?key= would previously be kept as the string "", and now becomes true).
  • The local config variable type changes from let config: TrackerOptions (with intermediate dataAttributes: Record<string, any>) to const config: TrackerOptions & Record<string, unknown>, eliminating the intermediate spread and the as any casts.

Confidence Score: 4/5

Safe to merge; the refactor is a straightforward extraction of two helpers with no logic changes for the common paths. The only behavioural difference is how empty URL query-param values are handled, which is a rare edge case.

The parseConfigValue helper now coerces "" to true for URL query params, whereas before those would remain as the empty string. This is a new code path that wasn't exercised by the previous logic, and there are no unit tests covering getTrackerConfig's URL-param branch. Everything else — the as any removal, the type intersection, the parseJsonAttribute extraction — is a clean, equivalent refactor.

packages/tracker/src/core/utils.ts — specifically the URL-param parsing loop that now calls parseConfigValue with the empty-string → true coercion.

Important Files Changed

Filename Overview
packages/tracker/src/core/utils.ts Refactored config parsing to extract parseConfigValue and parseJsonAttribute helpers, eliminating as any casts. Introduces a subtle edge-case behaviour change: empty URL query-param values now coerce to true instead of remaining as "".

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[getTrackerConfig] --> B{window defined?}
    B -- No --> C[return clientId: '']
    B -- Yes --> D[Spread globalConfig into config]
    D --> E{script element found?}
    E -- No --> J[return config]
    E -- Yes --> F[Iterate data-* attributes]
    F --> G{key === skipPatterns\nor maskPatterns?}
    G -- Yes --> H[parseJsonAttribute\nJSON.parse or fallback to array]
    G -- No --> I[parseConfigValue\ntrue / false / number / string]
    H --> F
    I --> F
    F --> K[Parse script src URL params]
    K --> L[parseConfigValue for each param]
    L --> J
Loading
%%{init: {'theme': 'base', 'themeVariables': {"darkMode": true, "background": "#0d1117", "primaryColor": "#21262d", "primaryTextColor": "#e6edf3", "primaryBorderColor": "#8b949e", "lineColor": "#8b949e", "textColor": "#e6edf3", "edgeLabelBackground": "#161b22", "actorBkg": "#21262d", "actorBorder": "#8b949e", "actorTextColor": "#e6edf3", "actorLineColor": "#8b949e", "signalColor": "#8b949e", "signalTextColor": "#e6edf3", "noteBkgColor": "#373320", "noteBorderColor": "#d4a72c", "noteTextColor": "#f0e6c0", "labelBoxBkgColor": "#21262d", "labelBoxBorderColor": "#8b949e", "labelTextColor": "#e6edf3", "loopTextColor": "#e6edf3", "activationBkgColor": "#30363d", "activationBorderColor": "#8b949e"}}}%%
flowchart TD
    A[getTrackerConfig] --> B{window defined?}
    B -- No --> C[return clientId: '']
    B -- Yes --> D[Spread globalConfig into config]
    D --> E{script element found?}
    E -- No --> J[return config]
    E -- Yes --> F[Iterate data-* attributes]
    F --> G{key === skipPatterns\nor maskPatterns?}
    G -- Yes --> H[parseJsonAttribute\nJSON.parse or fallback to array]
    G -- No --> I[parseConfigValue\ntrue / false / number / string]
    H --> F
    I --> F
    F --> K[Parse script src URL params]
    K --> L[parseConfigValue for each param]
    L --> J
Loading

Reviews (1): Last reviewed commit: "refactor(tracker): simplify config value..." | Re-trigger Greptile

Comment thread packages/tracker/src/core/utils.ts Outdated
Comment on lines +24 to +27
function parseConfigValue(value: string): boolean | number | string {
if (value === "true" || value === "") {
return true;
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

P2 The empty-string branch in parseConfigValue is applied to URL query-param values for the first time in this PR. In the old code, a ?key= param (empty value) would fall through to the final else branch and be kept as the string "". Now it returns true. If any consumer ever passes an empty param value expecting a string "", they'll silently get a boolean true instead. Consider guarding the empty-string → true coercion behind a flag, or at least documenting the intentional alignment.

Suggested change
function parseConfigValue(value: string): boolean | number | string {
if (value === "true" || value === "") {
return true;
}
function parseConfigValue(
value: string,
treatEmptyAsTrue = false,
): boolean | number | string {
if (value === "true" || (treatEmptyAsTrue && value === "")) {
return true;
}

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

1 issue found across 1 file

Confidence score: 3/5

  • In packages/tracker/src/core/utils.ts, URL-param coercion now treats empty values as true, so cases like clientId= can become a boolean and break tracker initialization at runtime; merging as-is risks a user-facing regression for integrations that pass empty query params — preserve empty-string values while keeping boolean-attribute behavior, and add a regression test for clientId= before merging.
Architecture diagram
sequenceDiagram
    participant Init as Script Initializer
    participant GetConfig as getTrackerConfig()
    participant Global as window.databuddyConfig
    participant Script as <script> element
    participant URL as script.src URL
    participant ParseValue as parseConfigValue()
    participant ParseJSON as parseJsonAttribute()
    participant Config as config object

    Note over Init,Config: Config parsing with new shared coercion

    Init->>GetConfig: getTrackerConfig()
    GetConfig->>Global: read global config
    Global-->>GetConfig: globalConfig record
    GetConfig->>Config: config = { clientId: "", ...globalConfig }
    
    alt Script element exists
        GetConfig->>Script: iterate attributes
        loop For each attribute
            alt name starts with "data-"
                Script->>GetConfig: attr.name, attr.value
                GetConfig->>GetConfig: extract key (camelCase)
                alt key is "skipPatterns" or "maskPatterns"
                    GetConfig->>ParseJSON: parseJsonAttribute(value)
                    ParseJSON->>ParseJSON: try JSON.parse
                    alt success
                        ParseJSON-->>GetConfig: parsed array
                    else fail
                        ParseJSON-->>GetConfig: []
                    end
                    GetConfig->>Config: config[key] = result
                else scalar attribute
                    GetConfig->>ParseValue: parseConfigValue(value)
                    alt value === "true" or ""
                        ParseValue-->>GetConfig: true
                    else value === "false"
                        ParseValue-->>GetConfig: false
                    else /^\d+$/.test(value)
                        ParseValue-->>GetConfig: Number(value)
                    else
                        ParseValue-->>GetConfig: value as string
                    end
                    GetConfig->>Config: config[key] = result
                end
            end
        end
    end

    alt Script has valid src URL
        GetConfig->>URL: new URL(script.src)
        URL->>URL: extract search params
        loop For each search param
            URL->>GetConfig: key, value
            GetConfig->>ParseValue: parseConfigValue(value)
            ParseValue-->>GetConfig: coerced value
            GetConfig->>Config: config[key] = coerced value
        end
    end

    GetConfig-->>Init: merged TrackerOptions config
    Note over Init,Config: Precedence: global < data-* < URL params
Loading

Shadow auto-approve: would not auto-approve because issues were found.

Re-trigger cubic

Comment thread packages/tracker/src/core/utils.ts
@izadoesdev
izadoesdev force-pushed the codex/desloppify-tracker-config branch from c04fe29 to 31e9067 Compare June 30, 2026 17:47
@vercel
vercel Bot temporarily deployed to Preview – documentation June 30, 2026 17:47 Inactive
@vercel
vercel Bot temporarily deployed to Preview – dashboard June 30, 2026 17:47 Inactive
@izadoesdev

Copy link
Copy Markdown
Member Author

Subagent review caught one behavior regression before merge: empty URL query params were being coerced like empty data-* attributes. Fixed in 31e90672d by keeping empty-string-as-true only for data attributes and adding packages/tracker/tests/unit/utils.test.ts to lock URL param precedence/empty values.

@unkey-deploy

unkey-deploy Bot commented Jun 30, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Unkey Deploy

Name Status Preview Inspect Updated (UTC)
api (preview) Ready Visit Preview Inspect Jun 30, 2026 5:48pm

@izadoesdev
izadoesdev merged commit 146d575 into staging Jun 30, 2026
17 checks passed
@izadoesdev
izadoesdev deleted the codex/desloppify-tracker-config branch June 30, 2026 17:50
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