Skip to content

feat: added support for proxy#3

Merged
SiebeBaree merged 1 commit into
mainfrom
t3code/37716b57
Apr 21, 2026
Merged

feat: added support for proxy#3
SiebeBaree merged 1 commit into
mainfrom
t3code/37716b57

Conversation

@SiebeBaree
Copy link
Copy Markdown
Member

@SiebeBaree SiebeBaree commented Apr 21, 2026

Summary by CodeRabbit

Release Notes

  • New Features

    • Proxy support enabling server-side placeholder substitution for upstream API calls without exposing secrets.
    • Proxy-only configuration mode to restrict client to proxy methods only.
    • New error types: ProxyError and ProxyValidationError.
  • Documentation

    • Updated with proxy configuration options, usage patterns, and expanded error taxonomy.
  • Tests

    • Added comprehensive test coverage for proxy functionality.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 21, 2026

Walkthrough

This pull request adds comprehensive proxy support to the Enkryptify client. It introduces a new EnkryptifyProxy class (src/proxy.ts) that handles server-side placeholder substitution for calling upstream APIs with variables like %VARIABLE_NAME% instead of secret values. The implementation includes two request methods: fetch (fetch-compatible API) and request (typed JSON payload API with optional per-call overrides). New error types (ProxyError, ProxyValidationError) are added for proxy-specific failures. The existing Enkryptify class is extended with a proxy getter and guards to enforce proxy-only mode where direct methods throw errors. Type definitions are expanded with proxy-specific interfaces and JSON value types, and comprehensive test coverage validates proxy behavior, token exchange, and lifecycle safety.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~30 minutes

Possibly related PRs

  • SDK v0.1 #1 — Main PR that this extends; introduces the foundational Enkryptify class, errors, and types that are now augmented with the proxy subsystem and proxy-only guards.
🚥 Pre-merge checks | ✅ 4 | ❌ 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 (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'feat: added support for proxy' accurately describes the main change: introducing proxy functionality to the Enkryptify client, including proxy endpoints, configuration, error handling, and comprehensive tests.
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.

✏️ 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 t3code/37716b57

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

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: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@src/enkryptify.ts`:
- Around line 113-125: The code uses a brittle fallback proxy URL
(DEFAULT_PROXY_URL / `https://proxy-poc-black.vercel.app`) when neither
`config.proxy?.url` nor `process.env.ENKRYPTIFY_PROXY_URL` is set, which can
silently route traffic to a preview deployment; update the initialization in
`proxyUrl`/`EnkryptifyProxy` use to either require an explicit proxy URL (fail
fast with a clear error when `config.proxy?.url` and `ENKRYPTIFY_PROXY_URL` are
both missing) or replace `DEFAULT_PROXY_URL` with an official stable domain, and
ensure any error message references `proxyUrl`/`config.proxy` so consumers know
to set `ENKRYPTIFY_PROXY_URL` instead of relying on the preview host.

In `@src/proxy.ts`:
- Around line 181-204: The `#send` method currently returns fetch Response
verbatim, so callers never observe the advertised
ProxyError/ProxyValidationError types; change `#send` to detect proxy-originated
errors (e.g., check for a proxy-specific response header such as X-Proxy-Error
or the proxy JSON shape {error:{code,message}} on non-2xx responses), parse the
body, and convert those into the exported ProxyError or ProxyValidationError
types before throwing, while letting transport (fetch) exceptions continue to
bubble and leaving non-proxy upstream responses untouched; update the detection
logic inside the `#send` implementation (the method that calls fetch against
this.#proxyUrl and currently returns response) to parse response.json() when the
discriminator is present, construct and throw the correct
ProxyError/ProxyValidationError, and keep other responses returned verbatim (or
update docs/types if you prefer to remove typed proxy errors).
- Around line 81-94: The fetch path currently allows an empty URL to be
serialized and sent; add a local validation in the same scope where url is
computed (the client.proxy.fetch implementation that uses const url = typeof
input === "string" ? input : String(input)) to reject empty strings—e.g., if url
=== "" or url.trim() === "" then throw an EnkryptifyError with a clear message
(matching request() behavior) before calling
normalizeMethod/normalizeHeaders/parseFetchBody or this.#send; reference the
existing EnkryptifyError type and keep the check near the url computation to
avoid a remote round trip.
🪄 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: d988cca9-af43-42a8-9e3e-722a21713527

📥 Commits

Reviewing files that changed from the base of the PR and between f0e161b and 802a041.

📒 Files selected for processing (7)
  • README.md
  • src/enkryptify.ts
  • src/errors.ts
  • src/index.ts
  • src/proxy.ts
  • src/types.ts
  • tests/proxy.test.ts

Comment thread src/enkryptify.ts
Comment on lines +113 to +125
const proxyUrl = config.proxy?.url ?? process.env.ENKRYPTIFY_PROXY_URL ?? DEFAULT_PROXY_URL;
this.#proxyOnly = config.proxy?.proxyOnly ?? false;
this.#proxy = new EnkryptifyProxy({
proxyUrl,
auth,
tokenExchange: this.#tokenExchange,
workspace: this.#workspace,
project: this.#project,
environment: this.#environment,
usePersonalValues: this.#usePersonalValues,
logger: this.#logger,
isDestroyed: () => this.#destroyed,
});
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

Avoid a preview deployment as the implicit proxy backend.

The fallback chain ends at https://proxy-poc-black.vercel.app, so any consumer who forgets to set proxy.url / ENKRYPTIFY_PROXY_URL is silently pinned to a non-canonical service. That's a brittle production default and can turn a config mistake into routing proxy auth to the wrong host. Prefer an official stable domain here, or fail fast when no explicit proxy URL is configured.

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

In `@src/enkryptify.ts` around lines 113 - 125, The code uses a brittle fallback
proxy URL (DEFAULT_PROXY_URL / `https://proxy-poc-black.vercel.app`) when
neither `config.proxy?.url` nor `process.env.ENKRYPTIFY_PROXY_URL` is set, which
can silently route traffic to a preview deployment; update the initialization in
`proxyUrl`/`EnkryptifyProxy` use to either require an explicit proxy URL (fail
fast with a clear error when `config.proxy?.url` and `ENKRYPTIFY_PROXY_URL` are
both missing) or replace `DEFAULT_PROXY_URL` with an official stable domain, and
ensure any error message references `proxyUrl`/`config.proxy` so consumers know
to set `ENKRYPTIFY_PROXY_URL` instead of relying on the preview host.

Comment thread src/proxy.ts
Comment on lines +81 to +94
const url = typeof input === "string" ? input : String(input);

const method = normalizeMethod(init?.method);
const headers = normalizeHeaders(init?.headers);
const body = parseFetchBody(init?.body);

if ((method === "GET" || method === "HEAD") && body !== undefined) {
throw new EnkryptifyError(
`${method} requests cannot include a body. Remove the body or change the method.\n` +
"Docs: https://docs.enkryptify.com/sdk/proxy",
);
}

return this.#send(
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

Validate empty URLs in client.proxy.fetch() as well.

request() rejects url: "", but fetch("") currently serializes an empty target URL and lets the proxy fail remotely. That makes the two entry points inconsistent and turns a local argument error into a network round trip.

Suggested fix
-        const url = typeof input === "string" ? input : String(input);
+        const url = typeof input === "string" ? input : String(input);
+        if (!url) {
+            throw new EnkryptifyError("Proxy request requires a non-empty `url`.");
+        }
📝 Committable suggestion

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

Suggested change
const url = typeof input === "string" ? input : String(input);
const method = normalizeMethod(init?.method);
const headers = normalizeHeaders(init?.headers);
const body = parseFetchBody(init?.body);
if ((method === "GET" || method === "HEAD") && body !== undefined) {
throw new EnkryptifyError(
`${method} requests cannot include a body. Remove the body or change the method.\n` +
"Docs: https://docs.enkryptify.com/sdk/proxy",
);
}
return this.#send(
const url = typeof input === "string" ? input : String(input);
if (!url) {
throw new EnkryptifyError("Proxy request requires a non-empty `url`.");
}
const method = normalizeMethod(init?.method);
const headers = normalizeHeaders(init?.headers);
const body = parseFetchBody(init?.body);
if ((method === "GET" || method === "HEAD") && body !== undefined) {
throw new EnkryptifyError(
`${method} requests cannot include a body. Remove the body or change the method.\n` +
"Docs: https://docs.enkryptify.com/sdk/proxy",
);
}
return this.#send(
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@src/proxy.ts` around lines 81 - 94, The fetch path currently allows an empty
URL to be serialized and sent; add a local validation in the same scope where
url is computed (the client.proxy.fetch implementation that uses const url =
typeof input === "string" ? input : String(input)) to reject empty strings—e.g.,
if url === "" or url.trim() === "" then throw an EnkryptifyError with a clear
message (matching request() behavior) before calling
normalizeMethod/normalizeHeaders/parseFetchBody or this.#send; reference the
existing EnkryptifyError type and keep the check near the url computation to
avoid a remote round trip.

Comment thread src/proxy.ts
Comment on lines +181 to +204
const response = await fetch(this.#proxyUrl, {
method: "POST",
headers: {
Authorization: `Bearer ${token}`,
"Content-Type": "application/json",
},
body: JSON.stringify(wireBody),
signal,
});

this.#logger.debug(`Proxy responded with HTTP ${response.status} in ${Date.now() - start}ms`);

// Return the Response verbatim — whatever status, body, and headers it carries.
//
// The Proxy forwards upstream responses unchanged (2xx or not), so mapping status
// codes to typed errors here is fundamentally unsafe: an upstream 401 from the
// caller's target API (e.g. OpenWeatherMap rejecting its own API key) is
// indistinguishable on the wire from a proxy 401 (e.g. Enkryptify token expired),
// and translating both into AuthenticationError produced wrong, misleading errors.
//
// Callers handle non-2xx like native fetch: check `response.ok` / `response.status`
// and read the body. Proxy-layer errors are delivered as `{error: {code, message}}`
// JSON bodies that callers can parse for specifics.
return response;
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

The new proxy error types are unreachable from this implementation.

#send() returns every HTTP response verbatim, and transport failures still bubble out as raw fetch errors. That means the new public ProxyError / ProxyValidationError contract can never actually be observed by callers, while src/index.ts, src/types.ts, and the README now advertise those types. Either add a reliable proxy-origin discriminator and map only those failures, or drop the typed proxy-error contract from this PR.

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

In `@src/proxy.ts` around lines 181 - 204, The `#send` method currently returns
fetch Response verbatim, so callers never observe the advertised
ProxyError/ProxyValidationError types; change `#send` to detect proxy-originated
errors (e.g., check for a proxy-specific response header such as X-Proxy-Error
or the proxy JSON shape {error:{code,message}} on non-2xx responses), parse the
body, and convert those into the exported ProxyError or ProxyValidationError
types before throwing, while letting transport (fetch) exceptions continue to
bubble and leaving non-proxy upstream responses untouched; update the detection
logic inside the `#send` implementation (the method that calls fetch against
this.#proxyUrl and currently returns response) to parse response.json() when the
discriminator is present, construct and throw the correct
ProxyError/ProxyValidationError, and keep other responses returned verbatim (or
update docs/types if you prefer to remove typed proxy errors).

@SiebeBaree SiebeBaree merged commit e05bb47 into main Apr 21, 2026
6 checks passed
@coderabbitai coderabbitai Bot mentioned this pull request Apr 21, 2026
@SiebeBaree SiebeBaree deleted the t3code/37716b57 branch April 29, 2026 05:49
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