Cover BOM wrapper and internal BOM baseURL handling
Co-authored-by: Eric Allam <eric@trigger.dev>
This commit is contained in:
@@ -10,6 +10,6 @@ Add a new `@trigger.dev/ai` package with:
|
||||
- reconnect-aware stream handling on top of Trigger.dev Realtime Streams v2
|
||||
- strict `baseURL` normalization/validation (trimming, path-safe slash handling, absolute `http(s)` URLs only, no query/hash/credentials)
|
||||
- rejection of internal whitespace characters in normalized `baseURL` values
|
||||
- rejection of internal invisible separator characters (e.g. zero-width spaces) in normalized `baseURL` values
|
||||
- rejection of internal invisible separator characters (e.g. zero-width/BOM characters) in normalized `baseURL` values
|
||||
- deterministic baseURL validation error ordering for multi-issue inputs (internal whitespace → protocol → query/hash → credentials)
|
||||
- explicit default `baseURL` behavior (`https://api.trigger.dev`) and case-insensitive `HTTP(S)` protocol acceptance
|
||||
|
||||
@@ -668,6 +668,7 @@ Examples:
|
||||
- ✅ ` https://api.trigger.dev/custom-prefix/// ` (trimmed + normalized)
|
||||
- ✅ `https://api.trigger.dev/custom%20prefix` (percent-encoded whitespace)
|
||||
- ✅ `https://api.trigger.dev/custom%3Fprefix%23segment` (percent-encoded `?` / `#`)
|
||||
- ✅ `\uFEFFhttps://api.trigger.dev/custom-prefix/\uFEFF` (BOM wrapper trimmed)
|
||||
- ❌ `https://api.trigger.dev?foo=bar`
|
||||
- ❌ `https://api.trigger.dev#fragment`
|
||||
- ❌ `https://user:pass@api.trigger.dev`
|
||||
@@ -677,6 +678,7 @@ Examples:
|
||||
- ❌ `https://api.trigger.dev/\tinternal`
|
||||
- ❌ `https://api.trigger.dev/\rinternal`
|
||||
- ❌ `https://api.trigger.dev/\u200Binternal`
|
||||
- ❌ `https://api.trigger.dev/\uFEFFinternal`
|
||||
|
||||
Validation errors use these exact messages:
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
- Added explicit validation that `baseURL` uses `http` or `https`.
|
||||
- Added explicit validation that `baseURL` excludes query parameters and hash fragments.
|
||||
- Added explicit validation that `baseURL` excludes username/password credentials.
|
||||
- Added explicit validation that `baseURL` excludes internal whitespace/invisible separator characters.
|
||||
- Added explicit validation that `baseURL` excludes internal whitespace/invisible separator characters (including zero-width/BOM characters).
|
||||
- Documented that `HTTP://` and `HTTPS://` are accepted (case-insensitive protocol matching).
|
||||
- Added deterministic validation ordering for multi-issue baseURL values
|
||||
(internal whitespace → protocol → query/hash → credentials).
|
||||
|
||||
@@ -175,6 +175,7 @@ Examples:
|
||||
- ✅ ` https://api.trigger.dev/custom-prefix/// ` (trimmed + normalized)
|
||||
- ✅ `https://api.trigger.dev/custom%20prefix` (percent-encoded whitespace)
|
||||
- ✅ `https://api.trigger.dev/custom%3Fprefix%23segment` (percent-encoded `?` / `#`)
|
||||
- ✅ `\uFEFFhttps://api.trigger.dev/custom-prefix/\uFEFF` (BOM wrapper trimmed)
|
||||
- ❌ `https://api.trigger.dev?foo=bar` (query string)
|
||||
- ❌ `https://api.trigger.dev#fragment` (hash fragment)
|
||||
- ❌ `https://user:pass@api.trigger.dev` (credentials)
|
||||
@@ -184,6 +185,7 @@ Examples:
|
||||
- ❌ `https://api.trigger.dev/\tinternal` (internal tab characters)
|
||||
- ❌ `https://api.trigger.dev/\rinternal` (internal carriage-return characters)
|
||||
- ❌ `https://api.trigger.dev/\u200Binternal` (internal zero-width-space characters)
|
||||
- ❌ `https://api.trigger.dev/\uFEFFinternal` (internal BOM characters)
|
||||
|
||||
Validation errors use these exact messages:
|
||||
|
||||
|
||||
@@ -764,6 +764,17 @@ describe("TriggerChatTransport", function () {
|
||||
}).toThrowError("baseURL must not contain internal whitespace characters");
|
||||
});
|
||||
|
||||
it("throws when baseURL contains internal BOM characters", function () {
|
||||
expect(function () {
|
||||
new TriggerChatTransport({
|
||||
task: "chat-task",
|
||||
accessToken: "pk_trigger",
|
||||
baseURL: "https://api.trigger.dev/\uFEFFinternal",
|
||||
stream: "chat-stream",
|
||||
});
|
||||
}).toThrowError("baseURL must not contain internal whitespace characters");
|
||||
});
|
||||
|
||||
it("throws when baseURL is a relative path", function () {
|
||||
expect(function () {
|
||||
new TriggerChatTransport({
|
||||
@@ -1006,6 +1017,17 @@ describe("TriggerChatTransport", function () {
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it("accepts BOM-wrapped baseURL values", function () {
|
||||
expect(function () {
|
||||
new TriggerChatTransport({
|
||||
task: "chat-task",
|
||||
accessToken: "pk_trigger",
|
||||
baseURL: "\uFEFFhttps://api.trigger.dev/custom-prefix/\uFEFF",
|
||||
stream: "chat-stream",
|
||||
});
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it("accepts percent-encoded whitespace in baseURL paths", function () {
|
||||
expect(function () {
|
||||
new TriggerChatTransport({
|
||||
@@ -3393,6 +3415,17 @@ describe("TriggerChatTransport", function () {
|
||||
}).toThrowError("baseURL must not contain internal whitespace characters");
|
||||
});
|
||||
|
||||
it("throws from factory when baseURL contains internal BOM characters", function () {
|
||||
expect(function () {
|
||||
createTriggerChatTransport({
|
||||
task: "chat-task",
|
||||
accessToken: "pk_trigger",
|
||||
baseURL: "https://api.trigger.dev/\uFEFFinternal",
|
||||
stream: "chat-stream",
|
||||
});
|
||||
}).toThrowError("baseURL must not contain internal whitespace characters");
|
||||
});
|
||||
|
||||
it("throws from factory when baseURL protocol is not http or https", function () {
|
||||
expect(function () {
|
||||
createTriggerChatTransport({
|
||||
@@ -3624,6 +3657,17 @@ describe("TriggerChatTransport", function () {
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it("accepts BOM-wrapped baseURL values from factory", function () {
|
||||
expect(function () {
|
||||
createTriggerChatTransport({
|
||||
task: "chat-task",
|
||||
accessToken: "pk_trigger",
|
||||
baseURL: "\uFEFFhttps://api.trigger.dev/custom-prefix/\uFEFF",
|
||||
stream: "chat-stream",
|
||||
});
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it("accepts percent-encoded whitespace in baseURL paths from factory", function () {
|
||||
expect(function () {
|
||||
createTriggerChatTransport({
|
||||
|
||||
Reference in New Issue
Block a user