feat(init): validate config at entry — close #15, #18 - #31

Merged
AndresL230 merged 5 commits into
mainfrom
feat/init-config-validation
May 13, 2026
Merged

feat(init): validate config at entry — close #15, #18#31
AndresL230 merged 5 commits into
mainfrom
feat/init-config-validation

Conversation

@AndresL230

@AndresL230AndresL230 commented May 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Behavior change

Previously-broken cloud configs (silent 404s or 401s forever) now throw at init(). No real telemetry is lost — these users were never shipping data. Consider a 0.2.0 bump and a "Breaking" callout if you want to signal the new throwing contract explicitly.

Test plan

  • 13 unit tests for validateConfig (tests/validate-config.test.ts)
  • 7 integration tests in tests/init.test.ts pinning that throws gate the interceptor install (regression contract: isInstalled() === false after throw)
  • Full suite: 212/212 unit + 7/7 dist bundle tests pass
  • npm run lint clean
  • npm run build clean (ESM + CJS + DTS)
  • Manual sanity: node -e "require('./dist/cjs/index.cjs').init({apiKey:'bad'})" throws with the expected message

Closes#15
Closes#18

Summary by CodeRabbit

  • New Features

    • SDK now performs synchronous configuration validation at initialization, requiring cloud-mode configurations to have a properly-formatted API key and project ID, while local mode requires no validation.
  • Documentation

    • Updated README with validation behavior details for both cloud and local modes.
  • Tests

    • Added comprehensive test coverage for configuration validation scenarios.

Review Change Stack

@coderabbitai

coderabbitaiBot commented May 13, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 22a52825-32c1-44ca-8fc7-c4335a1f7b78

📥 Commits

Reviewing files that changed from the base of the PR and between 49f0da5 and 7f37c88.

📒 Files selected for processing (5)
  • README.md
  • src/core/validate-config.ts
  • src/init.ts
  • tests/init.test.ts
  • tests/validate-config.test.ts

📝 Walkthrough

Walkthrough

This PR adds synchronous pre-flight validation to the ReCost Node SDK's init() function. When cloud mode is enabled (via apiKey), the SDK now rejects invalid configurations immediately: apiKey must start with "rc-" and projectId must be non-empty. Local mode requires no validation. Invalid configs throw before any SDK installation occurs.

Changes

Configuration validation for cloud mode

Layer / File(s)Summary
Validation rules, unit tests, and documentation
src/core/validate-config.ts, tests/validate-config.test.ts, README.md
validateConfig() enforces apiKey format ("rc-" prefix) and requires non-empty projectId in cloud mode. Errors include dashboard URL and redacted key previews. Unit tests verify all acceptance/rejection cases, error-message safety, and local-mode exemption. README documents validation behavior for users.
Init flow integration and end-to-end tests
src/init.ts, tests/init.test.ts
init() imports and invokes validateConfig() after the enabled gate, failing fast before interceptor installation. Existing resilience tests updated to use valid cloud-mode config. New test suite verifies invalid configs throw before isInstalled() returns true, and that a failed init() does not leave a stale module-level handle.

Sequence Diagram

sequenceDiagram
participant Caller
participant init
participant validateConfig
participant Transport
Caller->>init: init(config)
init->>init: check enabled gate
alt enabled is false
init-->>Caller: return disabled handle
else enabled is true
init->>validateConfig: validateConfig(config)
alt invalid config
validateConfig-->>Caller: throw Error
else valid config
validateConfig-->>init: return
init->>Transport: install interceptor
init->>init: start flush timer
init-->>Caller: return handle
end
end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 The rabbits hop through configs true,
Validation guards what users do—
No empty keys, no missing projectId sight,
Cloud mode now fails fast, before the flight! 🚀

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title 'feat(init): validate config at entry — close #15, #18' accurately summarizes the main change: adding configuration validation at SDK initialization entry point.
Linked Issues check✅ PassedThe PR fully implements requirements from #15 and #18: validates projectId presence in cloud mode, rejects malformed apiKey values, redacts secrets in errors, maintains local-mode validation-free behavior, and includes comprehensive unit and integration tests.
Out of Scope Changes check✅ PassedAll changes are tightly scoped to configuration validation at init: new validateConfig module, init integration, comprehensive tests, and README documentation of validation behavior.
Docstring Coverage✅ PassedDocstring 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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/init-config-validation

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.

@AndresL230
AndresL230 merged commit 32dbbe5 into mainMay 13, 2026
1 check passed
@AndresL230
AndresL230 deleted the feat/init-config-validation branch May 21, 2026 04:15
Sign up for freeto 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.

Mode detection is silent — invalid API key auto-enters cloud mode and fails Node SDK cloud mode accepts empty projectId, produces 404 URLs

1 participant

@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

feat(init): validate config at entry — close #15, #18 - #31

Merged
AndresL230 merged 5 commits into
mainfrom
feat/init-config-validation
May 13, 2026
Merged

feat(init): validate config at entry — close #15, #18#31
AndresL230 merged 5 commits into
mainfrom
feat/init-config-validation

Conversation

@AndresL230

@AndresL230AndresL230 commented May 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Behavior change

Previously-broken cloud configs (silent 404s or 401s forever) now throw at init(). No real telemetry is lost — these users were never shipping data. Consider a 0.2.0 bump and a "Breaking" callout if you want to signal the new throwing contract explicitly.

Test plan

  • 13 unit tests for validateConfig (tests/validate-config.test.ts)
  • 7 integration tests in tests/init.test.ts pinning that throws gate the interceptor install (regression contract: isInstalled() === false after throw)
  • Full suite: 212/212 unit + 7/7 dist bundle tests pass
  • npm run lint clean
  • npm run build clean (ESM + CJS + DTS)
  • Manual sanity: node -e "require('./dist/cjs/index.cjs').init({apiKey:'bad'})" throws with the expected message

Closes#15
Closes#18

Summary by CodeRabbit

  • New Features

    • SDK now performs synchronous configuration validation at initialization, requiring cloud-mode configurations to have a properly-formatted API key and project ID, while local mode requires no validation.
  • Documentation

    • Updated README with validation behavior details for both cloud and local modes.
  • Tests

    • Added comprehensive test coverage for configuration validation scenarios.

Review Change Stack

@coderabbitai

coderabbitaiBot commented May 13, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 22a52825-32c1-44ca-8fc7-c4335a1f7b78

📥 Commits

Reviewing files that changed from the base of the PR and between 49f0da5 and 7f37c88.

📒 Files selected for processing (5)
  • README.md
  • src/core/validate-config.ts
  • src/init.ts
  • tests/init.test.ts
  • tests/validate-config.test.ts

📝 Walkthrough

Walkthrough

This PR adds synchronous pre-flight validation to the ReCost Node SDK's init() function. When cloud mode is enabled (via apiKey), the SDK now rejects invalid configurations immediately: apiKey must start with "rc-" and projectId must be non-empty. Local mode requires no validation. Invalid configs throw before any SDK installation occurs.

Changes

Configuration validation for cloud mode

Layer / File(s)Summary
Validation rules, unit tests, and documentation
src/core/validate-config.ts, tests/validate-config.test.ts, README.md
validateConfig() enforces apiKey format ("rc-" prefix) and requires non-empty projectId in cloud mode. Errors include dashboard URL and redacted key previews. Unit tests verify all acceptance/rejection cases, error-message safety, and local-mode exemption. README documents validation behavior for users.
Init flow integration and end-to-end tests
src/init.ts, tests/init.test.ts
init() imports and invokes validateConfig() after the enabled gate, failing fast before interceptor installation. Existing resilience tests updated to use valid cloud-mode config. New test suite verifies invalid configs throw before isInstalled() returns true, and that a failed init() does not leave a stale module-level handle.

Sequence Diagram

sequenceDiagram
participant Caller
participant init
participant validateConfig
participant Transport
Caller->>init: init(config)
init->>init: check enabled gate
alt enabled is false
init-->>Caller: return disabled handle
else enabled is true
init->>validateConfig: validateConfig(config)
alt invalid config
validateConfig-->>Caller: throw Error
else valid config
validateConfig-->>init: return
init->>Transport: install interceptor
init->>init: start flush timer
init-->>Caller: return handle
end
end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 The rabbits hop through configs true,
Validation guards what users do—
No empty keys, no missing projectId sight,
Cloud mode now fails fast, before the flight! 🚀

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title 'feat(init): validate config at entry — close #15, #18' accurately summarizes the main change: adding configuration validation at SDK initialization entry point.
Linked Issues check✅ PassedThe PR fully implements requirements from #15 and #18: validates projectId presence in cloud mode, rejects malformed apiKey values, redacts secrets in errors, maintains local-mode validation-free behavior, and includes comprehensive unit and integration tests.
Out of Scope Changes check✅ PassedAll changes are tightly scoped to configuration validation at init: new validateConfig module, init integration, comprehensive tests, and README documentation of validation behavior.
Docstring Coverage✅ PassedDocstring 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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/init-config-validation

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.

@AndresL230
AndresL230 merged commit 32dbbe5 into mainMay 13, 2026
1 check passed
@AndresL230
AndresL230 deleted the feat/init-config-validation branch May 21, 2026 04:15
Sign up for freeto 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.

Mode detection is silent — invalid API key auto-enters cloud mode and fails Node SDK cloud mode accepts empty projectId, produces 404 URLs

1 participant

@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(init): validate config at entry — close #15, #18 - #31

Merged
AndresL230 merged 5 commits into
mainfrom
feat/init-config-validation
May 13, 2026
Merged

feat(init): validate config at entry — close #15, #18#31
AndresL230 merged 5 commits into
mainfrom
feat/init-config-validation

Conversation

@AndresL230

@AndresL230AndresL230 commented May 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Behavior change

Previously-broken cloud configs (silent 404s or 401s forever) now throw at init(). No real telemetry is lost — these users were never shipping data. Consider a 0.2.0 bump and a "Breaking" callout if you want to signal the new throwing contract explicitly.

Test plan

  • 13 unit tests for validateConfig (tests/validate-config.test.ts)
  • 7 integration tests in tests/init.test.ts pinning that throws gate the interceptor install (regression contract: isInstalled() === false after throw)
  • Full suite: 212/212 unit + 7/7 dist bundle tests pass
  • npm run lint clean
  • npm run build clean (ESM + CJS + DTS)
  • Manual sanity: node -e "require('./dist/cjs/index.cjs').init({apiKey:'bad'})" throws with the expected message

Closes#15
Closes#18

Summary by CodeRabbit

  • New Features

    • SDK now performs synchronous configuration validation at initialization, requiring cloud-mode configurations to have a properly-formatted API key and project ID, while local mode requires no validation.
  • Documentation

    • Updated README with validation behavior details for both cloud and local modes.
  • Tests

    • Added comprehensive test coverage for configuration validation scenarios.

Review Change Stack

@coderabbitai

coderabbitaiBot commented May 13, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 22a52825-32c1-44ca-8fc7-c4335a1f7b78

📥 Commits

Reviewing files that changed from the base of the PR and between 49f0da5 and 7f37c88.

📒 Files selected for processing (5)
  • README.md
  • src/core/validate-config.ts
  • src/init.ts
  • tests/init.test.ts
  • tests/validate-config.test.ts

📝 Walkthrough

Walkthrough

This PR adds synchronous pre-flight validation to the ReCost Node SDK's init() function. When cloud mode is enabled (via apiKey), the SDK now rejects invalid configurations immediately: apiKey must start with "rc-" and projectId must be non-empty. Local mode requires no validation. Invalid configs throw before any SDK installation occurs.

Changes

Configuration validation for cloud mode

Layer / File(s)Summary
Validation rules, unit tests, and documentation
src/core/validate-config.ts, tests/validate-config.test.ts, README.md
validateConfig() enforces apiKey format ("rc-" prefix) and requires non-empty projectId in cloud mode. Errors include dashboard URL and redacted key previews. Unit tests verify all acceptance/rejection cases, error-message safety, and local-mode exemption. README documents validation behavior for users.
Init flow integration and end-to-end tests
src/init.ts, tests/init.test.ts
init() imports and invokes validateConfig() after the enabled gate, failing fast before interceptor installation. Existing resilience tests updated to use valid cloud-mode config. New test suite verifies invalid configs throw before isInstalled() returns true, and that a failed init() does not leave a stale module-level handle.

Sequence Diagram

sequenceDiagram
participant Caller
participant init
participant validateConfig
participant Transport
Caller->>init: init(config)
init->>init: check enabled gate
alt enabled is false
init-->>Caller: return disabled handle
else enabled is true
init->>validateConfig: validateConfig(config)
alt invalid config
validateConfig-->>Caller: throw Error
else valid config
validateConfig-->>init: return
init->>Transport: install interceptor
init->>init: start flush timer
init-->>Caller: return handle
end
end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 The rabbits hop through configs true,
Validation guards what users do—
No empty keys, no missing projectId sight,
Cloud mode now fails fast, before the flight! 🚀

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title 'feat(init): validate config at entry — close #15, #18' accurately summarizes the main change: adding configuration validation at SDK initialization entry point.
Linked Issues check✅ PassedThe PR fully implements requirements from #15 and #18: validates projectId presence in cloud mode, rejects malformed apiKey values, redacts secrets in errors, maintains local-mode validation-free behavior, and includes comprehensive unit and integration tests.
Out of Scope Changes check✅ PassedAll changes are tightly scoped to configuration validation at init: new validateConfig module, init integration, comprehensive tests, and README documentation of validation behavior.
Docstring Coverage✅ PassedDocstring 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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/init-config-validation

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.

@AndresL230
AndresL230 merged commit 32dbbe5 into mainMay 13, 2026
1 check passed
@AndresL230
AndresL230 deleted the feat/init-config-validation branch May 21, 2026 04:15
Sign up for freeto 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.

Mode detection is silent — invalid API key auto-enters cloud mode and fails Node SDK cloud mode accepts empty projectId, produces 404 URLs

1 participant

@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(init): validate config at entry — close #15, #18 - #31

Merged
AndresL230 merged 5 commits into
mainfrom
feat/init-config-validation
May 13, 2026
Merged

feat(init): validate config at entry — close #15, #18#31
AndresL230 merged 5 commits into
mainfrom
feat/init-config-validation

Conversation

@AndresL230

@AndresL230AndresL230 commented May 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Behavior change

Previously-broken cloud configs (silent 404s or 401s forever) now throw at init(). No real telemetry is lost — these users were never shipping data. Consider a 0.2.0 bump and a "Breaking" callout if you want to signal the new throwing contract explicitly.

Test plan

  • 13 unit tests for validateConfig (tests/validate-config.test.ts)
  • 7 integration tests in tests/init.test.ts pinning that throws gate the interceptor install (regression contract: isInstalled() === false after throw)
  • Full suite: 212/212 unit + 7/7 dist bundle tests pass
  • npm run lint clean
  • npm run build clean (ESM + CJS + DTS)
  • Manual sanity: node -e "require('./dist/cjs/index.cjs').init({apiKey:'bad'})" throws with the expected message

Closes#15
Closes#18

Summary by CodeRabbit

  • New Features

    • SDK now performs synchronous configuration validation at initialization, requiring cloud-mode configurations to have a properly-formatted API key and project ID, while local mode requires no validation.
  • Documentation

    • Updated README with validation behavior details for both cloud and local modes.
  • Tests

    • Added comprehensive test coverage for configuration validation scenarios.

Review Change Stack

@coderabbitai

coderabbitaiBot commented May 13, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 22a52825-32c1-44ca-8fc7-c4335a1f7b78

📥 Commits

Reviewing files that changed from the base of the PR and between 49f0da5 and 7f37c88.

📒 Files selected for processing (5)
  • README.md
  • src/core/validate-config.ts
  • src/init.ts
  • tests/init.test.ts
  • tests/validate-config.test.ts

📝 Walkthrough

Walkthrough

This PR adds synchronous pre-flight validation to the ReCost Node SDK's init() function. When cloud mode is enabled (via apiKey), the SDK now rejects invalid configurations immediately: apiKey must start with "rc-" and projectId must be non-empty. Local mode requires no validation. Invalid configs throw before any SDK installation occurs.

Changes

Configuration validation for cloud mode

Layer / File(s)Summary
Validation rules, unit tests, and documentation
src/core/validate-config.ts, tests/validate-config.test.ts, README.md
validateConfig() enforces apiKey format ("rc-" prefix) and requires non-empty projectId in cloud mode. Errors include dashboard URL and redacted key previews. Unit tests verify all acceptance/rejection cases, error-message safety, and local-mode exemption. README documents validation behavior for users.
Init flow integration and end-to-end tests
src/init.ts, tests/init.test.ts
init() imports and invokes validateConfig() after the enabled gate, failing fast before interceptor installation. Existing resilience tests updated to use valid cloud-mode config. New test suite verifies invalid configs throw before isInstalled() returns true, and that a failed init() does not leave a stale module-level handle.

Sequence Diagram

sequenceDiagram
participant Caller
participant init
participant validateConfig
participant Transport
Caller->>init: init(config)
init->>init: check enabled gate
alt enabled is false
init-->>Caller: return disabled handle
else enabled is true
init->>validateConfig: validateConfig(config)
alt invalid config
validateConfig-->>Caller: throw Error
else valid config
validateConfig-->>init: return
init->>Transport: install interceptor
init->>init: start flush timer
init-->>Caller: return handle
end
end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 The rabbits hop through configs true,
Validation guards what users do—
No empty keys, no missing projectId sight,
Cloud mode now fails fast, before the flight! 🚀

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title 'feat(init): validate config at entry — close #15, #18' accurately summarizes the main change: adding configuration validation at SDK initialization entry point.
Linked Issues check✅ PassedThe PR fully implements requirements from #15 and #18: validates projectId presence in cloud mode, rejects malformed apiKey values, redacts secrets in errors, maintains local-mode validation-free behavior, and includes comprehensive unit and integration tests.
Out of Scope Changes check✅ PassedAll changes are tightly scoped to configuration validation at init: new validateConfig module, init integration, comprehensive tests, and README documentation of validation behavior.
Docstring Coverage✅ PassedDocstring 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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/init-config-validation

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.

@AndresL230
AndresL230 merged commit 32dbbe5 into mainMay 13, 2026
1 check passed
@AndresL230
AndresL230 deleted the feat/init-config-validation branch May 21, 2026 04:15
Sign up for freeto 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.

Mode detection is silent — invalid API key auto-enters cloud mode and fails Node SDK cloud mode accepts empty projectId, produces 404 URLs

1 participant

@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

feat(init): validate config at entry — close #15, #18 - #31

Merged
AndresL230 merged 5 commits into
mainfrom
feat/init-config-validation
May 13, 2026
Merged

feat(init): validate config at entry — close #15, #18#31
AndresL230 merged 5 commits into
mainfrom
feat/init-config-validation

Conversation

@AndresL230

@AndresL230AndresL230 commented May 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Behavior change

Previously-broken cloud configs (silent 404s or 401s forever) now throw at init(). No real telemetry is lost — these users were never shipping data. Consider a 0.2.0 bump and a "Breaking" callout if you want to signal the new throwing contract explicitly.

Test plan

  • 13 unit tests for validateConfig (tests/validate-config.test.ts)
  • 7 integration tests in tests/init.test.ts pinning that throws gate the interceptor install (regression contract: isInstalled() === false after throw)
  • Full suite: 212/212 unit + 7/7 dist bundle tests pass
  • npm run lint clean
  • npm run build clean (ESM + CJS + DTS)
  • Manual sanity: node -e "require('./dist/cjs/index.cjs').init({apiKey:'bad'})" throws with the expected message

Closes#15
Closes#18

Summary by CodeRabbit

  • New Features

    • SDK now performs synchronous configuration validation at initialization, requiring cloud-mode configurations to have a properly-formatted API key and project ID, while local mode requires no validation.
  • Documentation

    • Updated README with validation behavior details for both cloud and local modes.
  • Tests

    • Added comprehensive test coverage for configuration validation scenarios.

Review Change Stack

@coderabbitai

coderabbitaiBot commented May 13, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 22a52825-32c1-44ca-8fc7-c4335a1f7b78

📥 Commits

Reviewing files that changed from the base of the PR and between 49f0da5 and 7f37c88.

📒 Files selected for processing (5)
  • README.md
  • src/core/validate-config.ts
  • src/init.ts
  • tests/init.test.ts
  • tests/validate-config.test.ts

📝 Walkthrough

Walkthrough

This PR adds synchronous pre-flight validation to the ReCost Node SDK's init() function. When cloud mode is enabled (via apiKey), the SDK now rejects invalid configurations immediately: apiKey must start with "rc-" and projectId must be non-empty. Local mode requires no validation. Invalid configs throw before any SDK installation occurs.

Changes

Configuration validation for cloud mode

Layer / File(s)Summary
Validation rules, unit tests, and documentation
src/core/validate-config.ts, tests/validate-config.test.ts, README.md
validateConfig() enforces apiKey format ("rc-" prefix) and requires non-empty projectId in cloud mode. Errors include dashboard URL and redacted key previews. Unit tests verify all acceptance/rejection cases, error-message safety, and local-mode exemption. README documents validation behavior for users.
Init flow integration and end-to-end tests
src/init.ts, tests/init.test.ts
init() imports and invokes validateConfig() after the enabled gate, failing fast before interceptor installation. Existing resilience tests updated to use valid cloud-mode config. New test suite verifies invalid configs throw before isInstalled() returns true, and that a failed init() does not leave a stale module-level handle.

Sequence Diagram

sequenceDiagram
participant Caller
participant init
participant validateConfig
participant Transport
Caller->>init: init(config)
init->>init: check enabled gate
alt enabled is false
init-->>Caller: return disabled handle
else enabled is true
init->>validateConfig: validateConfig(config)
alt invalid config
validateConfig-->>Caller: throw Error
else valid config
validateConfig-->>init: return
init->>Transport: install interceptor
init->>init: start flush timer
init-->>Caller: return handle
end
end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 The rabbits hop through configs true,
Validation guards what users do—
No empty keys, no missing projectId sight,
Cloud mode now fails fast, before the flight! 🚀

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title 'feat(init): validate config at entry — close #15, #18' accurately summarizes the main change: adding configuration validation at SDK initialization entry point.
Linked Issues check✅ PassedThe PR fully implements requirements from #15 and #18: validates projectId presence in cloud mode, rejects malformed apiKey values, redacts secrets in errors, maintains local-mode validation-free behavior, and includes comprehensive unit and integration tests.
Out of Scope Changes check✅ PassedAll changes are tightly scoped to configuration validation at init: new validateConfig module, init integration, comprehensive tests, and README documentation of validation behavior.
Docstring Coverage✅ PassedDocstring 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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/init-config-validation

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.

@AndresL230
AndresL230 merged commit 32dbbe5 into mainMay 13, 2026
1 check passed
@AndresL230
AndresL230 deleted the feat/init-config-validation branch May 21, 2026 04:15
Sign up for freeto 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.

Mode detection is silent — invalid API key auto-enters cloud mode and fails Node SDK cloud mode accepts empty projectId, produces 404 URLs

1 participant

@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(init): validate config at entry — close #15, #18 - #31

Merged
AndresL230 merged 5 commits into
mainfrom
feat/init-config-validation
May 13, 2026
Merged

feat(init): validate config at entry — close #15, #18#31
AndresL230 merged 5 commits into
mainfrom
feat/init-config-validation

Conversation

@AndresL230

@AndresL230AndresL230 commented May 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Behavior change

Previously-broken cloud configs (silent 404s or 401s forever) now throw at init(). No real telemetry is lost — these users were never shipping data. Consider a 0.2.0 bump and a "Breaking" callout if you want to signal the new throwing contract explicitly.

Test plan

  • 13 unit tests for validateConfig (tests/validate-config.test.ts)
  • 7 integration tests in tests/init.test.ts pinning that throws gate the interceptor install (regression contract: isInstalled() === false after throw)
  • Full suite: 212/212 unit + 7/7 dist bundle tests pass
  • npm run lint clean
  • npm run build clean (ESM + CJS + DTS)
  • Manual sanity: node -e "require('./dist/cjs/index.cjs').init({apiKey:'bad'})" throws with the expected message

Closes#15
Closes#18

Summary by CodeRabbit

  • New Features

    • SDK now performs synchronous configuration validation at initialization, requiring cloud-mode configurations to have a properly-formatted API key and project ID, while local mode requires no validation.
  • Documentation

    • Updated README with validation behavior details for both cloud and local modes.
  • Tests

    • Added comprehensive test coverage for configuration validation scenarios.

Review Change Stack

@coderabbitai

coderabbitaiBot commented May 13, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 22a52825-32c1-44ca-8fc7-c4335a1f7b78

📥 Commits

Reviewing files that changed from the base of the PR and between 49f0da5 and 7f37c88.

📒 Files selected for processing (5)
  • README.md
  • src/core/validate-config.ts
  • src/init.ts
  • tests/init.test.ts
  • tests/validate-config.test.ts

📝 Walkthrough

Walkthrough

This PR adds synchronous pre-flight validation to the ReCost Node SDK's init() function. When cloud mode is enabled (via apiKey), the SDK now rejects invalid configurations immediately: apiKey must start with "rc-" and projectId must be non-empty. Local mode requires no validation. Invalid configs throw before any SDK installation occurs.

Changes

Configuration validation for cloud mode

Layer / File(s)Summary
Validation rules, unit tests, and documentation
src/core/validate-config.ts, tests/validate-config.test.ts, README.md
validateConfig() enforces apiKey format ("rc-" prefix) and requires non-empty projectId in cloud mode. Errors include dashboard URL and redacted key previews. Unit tests verify all acceptance/rejection cases, error-message safety, and local-mode exemption. README documents validation behavior for users.
Init flow integration and end-to-end tests
src/init.ts, tests/init.test.ts
init() imports and invokes validateConfig() after the enabled gate, failing fast before interceptor installation. Existing resilience tests updated to use valid cloud-mode config. New test suite verifies invalid configs throw before isInstalled() returns true, and that a failed init() does not leave a stale module-level handle.

Sequence Diagram

sequenceDiagram
participant Caller
participant init
participant validateConfig
participant Transport
Caller->>init: init(config)
init->>init: check enabled gate
alt enabled is false
init-->>Caller: return disabled handle
else enabled is true
init->>validateConfig: validateConfig(config)
alt invalid config
validateConfig-->>Caller: throw Error
else valid config
validateConfig-->>init: return
init->>Transport: install interceptor
init->>init: start flush timer
init-->>Caller: return handle
end
end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 The rabbits hop through configs true,
Validation guards what users do—
No empty keys, no missing projectId sight,
Cloud mode now fails fast, before the flight! 🚀

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title 'feat(init): validate config at entry — close #15, #18' accurately summarizes the main change: adding configuration validation at SDK initialization entry point.
Linked Issues check✅ PassedThe PR fully implements requirements from #15 and #18: validates projectId presence in cloud mode, rejects malformed apiKey values, redacts secrets in errors, maintains local-mode validation-free behavior, and includes comprehensive unit and integration tests.
Out of Scope Changes check✅ PassedAll changes are tightly scoped to configuration validation at init: new validateConfig module, init integration, comprehensive tests, and README documentation of validation behavior.
Docstring Coverage✅ PassedDocstring 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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/init-config-validation

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.

@AndresL230
AndresL230 merged commit 32dbbe5 into mainMay 13, 2026
1 check passed
@AndresL230
AndresL230 deleted the feat/init-config-validation branch May 21, 2026 04:15
Sign up for freeto 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.

Mode detection is silent — invalid API key auto-enters cloud mode and fails Node SDK cloud mode accepts empty projectId, produces 404 URLs

1 participant

@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

feat(init): validate config at entry — close #15, #18 - #31

Merged
AndresL230 merged 5 commits into
mainfrom
feat/init-config-validation
May 13, 2026
Merged

feat(init): validate config at entry — close #15, #18#31
AndresL230 merged 5 commits into
mainfrom
feat/init-config-validation

Conversation

@AndresL230

@AndresL230AndresL230 commented May 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Behavior change

Previously-broken cloud configs (silent 404s or 401s forever) now throw at init(). No real telemetry is lost — these users were never shipping data. Consider a 0.2.0 bump and a "Breaking" callout if you want to signal the new throwing contract explicitly.

Test plan

  • 13 unit tests for validateConfig (tests/validate-config.test.ts)
  • 7 integration tests in tests/init.test.ts pinning that throws gate the interceptor install (regression contract: isInstalled() === false after throw)
  • Full suite: 212/212 unit + 7/7 dist bundle tests pass
  • npm run lint clean
  • npm run build clean (ESM + CJS + DTS)
  • Manual sanity: node -e "require('./dist/cjs/index.cjs').init({apiKey:'bad'})" throws with the expected message

Closes#15
Closes#18

Summary by CodeRabbit

  • New Features

    • SDK now performs synchronous configuration validation at initialization, requiring cloud-mode configurations to have a properly-formatted API key and project ID, while local mode requires no validation.
  • Documentation

    • Updated README with validation behavior details for both cloud and local modes.
  • Tests

    • Added comprehensive test coverage for configuration validation scenarios.

Review Change Stack

@coderabbitai

coderabbitaiBot commented May 13, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 22a52825-32c1-44ca-8fc7-c4335a1f7b78

📥 Commits

Reviewing files that changed from the base of the PR and between 49f0da5 and 7f37c88.

📒 Files selected for processing (5)
  • README.md
  • src/core/validate-config.ts
  • src/init.ts
  • tests/init.test.ts
  • tests/validate-config.test.ts

📝 Walkthrough

Walkthrough

This PR adds synchronous pre-flight validation to the ReCost Node SDK's init() function. When cloud mode is enabled (via apiKey), the SDK now rejects invalid configurations immediately: apiKey must start with "rc-" and projectId must be non-empty. Local mode requires no validation. Invalid configs throw before any SDK installation occurs.

Changes

Configuration validation for cloud mode

Layer / File(s)Summary
Validation rules, unit tests, and documentation
src/core/validate-config.ts, tests/validate-config.test.ts, README.md
validateConfig() enforces apiKey format ("rc-" prefix) and requires non-empty projectId in cloud mode. Errors include dashboard URL and redacted key previews. Unit tests verify all acceptance/rejection cases, error-message safety, and local-mode exemption. README documents validation behavior for users.
Init flow integration and end-to-end tests
src/init.ts, tests/init.test.ts
init() imports and invokes validateConfig() after the enabled gate, failing fast before interceptor installation. Existing resilience tests updated to use valid cloud-mode config. New test suite verifies invalid configs throw before isInstalled() returns true, and that a failed init() does not leave a stale module-level handle.

Sequence Diagram

sequenceDiagram
participant Caller
participant init
participant validateConfig
participant Transport
Caller->>init: init(config)
init->>init: check enabled gate
alt enabled is false
init-->>Caller: return disabled handle
else enabled is true
init->>validateConfig: validateConfig(config)
alt invalid config
validateConfig-->>Caller: throw Error
else valid config
validateConfig-->>init: return
init->>Transport: install interceptor
init->>init: start flush timer
init-->>Caller: return handle
end
end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 The rabbits hop through configs true,
Validation guards what users do—
No empty keys, no missing projectId sight,
Cloud mode now fails fast, before the flight! 🚀

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title 'feat(init): validate config at entry — close #15, #18' accurately summarizes the main change: adding configuration validation at SDK initialization entry point.
Linked Issues check✅ PassedThe PR fully implements requirements from #15 and #18: validates projectId presence in cloud mode, rejects malformed apiKey values, redacts secrets in errors, maintains local-mode validation-free behavior, and includes comprehensive unit and integration tests.
Out of Scope Changes check✅ PassedAll changes are tightly scoped to configuration validation at init: new validateConfig module, init integration, comprehensive tests, and README documentation of validation behavior.
Docstring Coverage✅ PassedDocstring 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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/init-config-validation

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.

@AndresL230
AndresL230 merged commit 32dbbe5 into mainMay 13, 2026
1 check passed
@AndresL230
AndresL230 deleted the feat/init-config-validation branch May 21, 2026 04:15
Sign up for freeto 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.

Mode detection is silent — invalid API key auto-enters cloud mode and fails Node SDK cloud mode accepts empty projectId, produces 404 URLs

1 participant

@AndresL230
, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

feat(init): validate config at entry — close #15, #18 - #31

Merged
AndresL230 merged 5 commits into
mainfrom
feat/init-config-validation
May 13, 2026
Merged

feat(init): validate config at entry — close #15, #18#31
AndresL230 merged 5 commits into
mainfrom
feat/init-config-validation

Conversation

@AndresL230

@AndresL230AndresL230 commented May 13, 2026

Copy link
Copy Markdown
Contributor

Summary

Behavior change

Previously-broken cloud configs (silent 404s or 401s forever) now throw at init(). No real telemetry is lost — these users were never shipping data. Consider a 0.2.0 bump and a "Breaking" callout if you want to signal the new throwing contract explicitly.

Test plan

  • 13 unit tests for validateConfig (tests/validate-config.test.ts)
  • 7 integration tests in tests/init.test.ts pinning that throws gate the interceptor install (regression contract: isInstalled() === false after throw)
  • Full suite: 212/212 unit + 7/7 dist bundle tests pass
  • npm run lint clean
  • npm run build clean (ESM + CJS + DTS)
  • Manual sanity: node -e "require('./dist/cjs/index.cjs').init({apiKey:'bad'})" throws with the expected message

Closes#15
Closes#18

Summary by CodeRabbit

  • New Features

    • SDK now performs synchronous configuration validation at initialization, requiring cloud-mode configurations to have a properly-formatted API key and project ID, while local mode requires no validation.
  • Documentation

    • Updated README with validation behavior details for both cloud and local modes.
  • Tests

    • Added comprehensive test coverage for configuration validation scenarios.

Review Change Stack

@coderabbitai

coderabbitaiBot commented May 13, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 22a52825-32c1-44ca-8fc7-c4335a1f7b78

📥 Commits

Reviewing files that changed from the base of the PR and between 49f0da5 and 7f37c88.

📒 Files selected for processing (5)
  • README.md
  • src/core/validate-config.ts
  • src/init.ts
  • tests/init.test.ts
  • tests/validate-config.test.ts

📝 Walkthrough

Walkthrough

This PR adds synchronous pre-flight validation to the ReCost Node SDK's init() function. When cloud mode is enabled (via apiKey), the SDK now rejects invalid configurations immediately: apiKey must start with "rc-" and projectId must be non-empty. Local mode requires no validation. Invalid configs throw before any SDK installation occurs.

Changes

Configuration validation for cloud mode

Layer / File(s)Summary
Validation rules, unit tests, and documentation
src/core/validate-config.ts, tests/validate-config.test.ts, README.md
validateConfig() enforces apiKey format ("rc-" prefix) and requires non-empty projectId in cloud mode. Errors include dashboard URL and redacted key previews. Unit tests verify all acceptance/rejection cases, error-message safety, and local-mode exemption. README documents validation behavior for users.
Init flow integration and end-to-end tests
src/init.ts, tests/init.test.ts
init() imports and invokes validateConfig() after the enabled gate, failing fast before interceptor installation. Existing resilience tests updated to use valid cloud-mode config. New test suite verifies invalid configs throw before isInstalled() returns true, and that a failed init() does not leave a stale module-level handle.

Sequence Diagram

sequenceDiagram
participant Caller
participant init
participant validateConfig
participant Transport
Caller->>init: init(config)
init->>init: check enabled gate
alt enabled is false
init-->>Caller: return disabled handle
else enabled is true
init->>validateConfig: validateConfig(config)
alt invalid config
validateConfig-->>Caller: throw Error
else valid config
validateConfig-->>init: return
init->>Transport: install interceptor
init->>init: start flush timer
init-->>Caller: return handle
end
end
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Poem

🐰 The rabbits hop through configs true,
Validation guards what users do—
No empty keys, no missing projectId sight,
Cloud mode now fails fast, before the flight! 🚀

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check nameStatusExplanation
Description Check✅ PassedCheck skipped - CodeRabbit’s high-level summary is enabled.
Title check✅ PassedThe title 'feat(init): validate config at entry — close #15, #18' accurately summarizes the main change: adding configuration validation at SDK initialization entry point.
Linked Issues check✅ PassedThe PR fully implements requirements from #15 and #18: validates projectId presence in cloud mode, rejects malformed apiKey values, redacts secrets in errors, maintains local-mode validation-free behavior, and includes comprehensive unit and integration tests.
Out of Scope Changes check✅ PassedAll changes are tightly scoped to configuration validation at init: new validateConfig module, init integration, comprehensive tests, and README documentation of validation behavior.
Docstring Coverage✅ PassedDocstring 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 docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/init-config-validation

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.

@AndresL230
AndresL230 merged commit 32dbbe5 into mainMay 13, 2026
1 check passed
@AndresL230
AndresL230 deleted the feat/init-config-validation branch May 21, 2026 04:15
Sign up for freeto 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.

Mode detection is silent — invalid API key auto-enters cloud mode and fails Node SDK cloud mode accepts empty projectId, produces 404 URLs

1 participant

@AndresL230