Skip to content

Commit

Permalink
Merging ae10b5f into trunk-temp/pr-897/38b1e38b-1822-4f95-8a9f-55d13a…
Browse files Browse the repository at this point in the history
…46bac3
  • Loading branch information
trunk-io[bot] authored Jun 10, 2024
2 parents a42fbd3 + ae10b5f commit 08cb984
Show file tree
Hide file tree
Showing 30 changed files with 992 additions and 237 deletions.
1 change: 1 addition & 0 deletions .github/.release-please-manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
"arcjet-sveltekit": "1.0.0-alpha.13",
"decorate": "1.0.0-alpha.13",
"duration": "1.0.0-alpha.13",
"env": "1.0.0-alpha.13",
"eslint-config": "1.0.0-alpha.13",
"headers": "1.0.0-alpha.13",
"ip": "1.0.0-alpha.13",
Expand Down
4 changes: 4 additions & 0 deletions .github/release-please-config.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,10 @@
"component": "@arcjet/duration",
"skip-github-release": true
},
"env": {
"component": "@arcjet/env",
"skip-github-release": true
},
"eslint-config": {
"component": "@arcjet/eslint-config",
"skip-github-release": true
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,7 @@ find a specific one through the categories and descriptions below.
- [`@arcjet/runtime`](./runtime/README.md): Runtime detection.
- [`@arcjet/sprintf`](./sprintf/README.md): Platform-independent replacement for
`util.format`.
- [`@arcjet/env`](./env/README.md): Environment detection for Arcjet variables.

### Internal development

Expand Down
47 changes: 32 additions & 15 deletions arcjet-bun/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,21 @@ import core, {
ExtraProps,
RemoteClient,
RemoteClientOptions,
defaultBaseUrl,
createRemoteClient,
Arcjet,
} from "arcjet";
import findIP from "@arcjet/ip";
import ArcjetHeaders from "@arcjet/headers";
import type { Server } from "bun";
import { env } from "bun";
import {
baseUrl,
isDevelopment,
isProduction,
logLevel,
platform,
} from "@arcjet/env";
import { Logger } from "@arcjet/logger";

// Re-export all named exports from the generic SDK
export * from "arcjet";
Expand Down Expand Up @@ -59,25 +66,35 @@ type PlainObject = {
};

export function createBunRemoteClient(
options?: RemoteClientOptions,
options?: Partial<RemoteClientOptions>,
): RemoteClient {
// The base URL for the Arcjet API. Will default to the standard production
// API unless environment variable `ARCJET_BASE_URL` is set.
const baseUrl = options?.baseUrl ?? defaultBaseUrl();
const url = options?.baseUrl ?? baseUrl(env);

// The timeout for the Arcjet API in milliseconds. This is set to a low value
// in production so calls fail open.
const timeout = options?.timeout ?? (isProduction(env) ? 500 : 1000);

// Transport is the HTTP client that the client uses to make requests.
const transport =
options?.transport ??
createConnectTransport({
baseUrl,
baseUrl: url,
httpVersion: "1.1",
});

// TODO(#223): Do we want to allow overrides to either of these? If not, we should probably define a separate type for `options`
// TODO(#223): Create separate options type to exclude these
const sdkStack = "BUN";
const sdkVersion = "__ARCJET_SDK_VERSION__";

return createRemoteClient({ ...options, transport, sdkStack, sdkVersion });
return createRemoteClient({
transport,
baseUrl: url,
timeout,
sdkStack,
sdkVersion,
});
}

/**
Expand Down Expand Up @@ -131,12 +148,6 @@ export interface ArcjetBun<Props extends PlainObject> {
) => Response | Promise<Response>;
}

function detectPlatform() {
if (typeof env["FLY_APP_NAME"] === "string" && env["FLY_APP_NAME"] !== "") {
return "fly-io" as const;
}
}

// This is provided with an `ipCache` where it attempts to lookup the IP. This
// is primarily a workaround to the API design in Bun that requires access to
// the `Server` to lookup an IP.
Expand All @@ -156,12 +167,12 @@ function toArcjetRequest<Props extends PlainObject>(
ip: ipCache.get(request),
},
headers,
{ platform: detectPlatform() },
{ platform: platform(env) },
);
if (ip === "") {
// If the `ip` is empty but we're in development mode, we default the IP
// so the request doesn't fail.
if (env.NODE_ENV === "development" || env.ARCJET_ENV === "development") {
if (isDevelopment(env)) {
// TODO: Log that the fingerprint is being overridden once the adapter
// constructs the logger
ip = "127.0.0.1";
Expand Down Expand Up @@ -246,7 +257,13 @@ export default function arcjet<const Rules extends (Primitive | Product)[]>(
): ArcjetBun<Simplify<ExtraProps<Rules>>> {
const client = options.client ?? createBunRemoteClient();

const aj = core({ ...options, client });
const log = options.log
? options.log
: new Logger({
level: logLevel(env),
});

const aj = core({ ...options, client, log });

return withClient(aj);
}
2 changes: 2 additions & 0 deletions arcjet-bun/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@
"test": "NODE_OPTIONS=--experimental-vm-modules jest --passWithNoTests"
},
"dependencies": {
"@arcjet/env": "1.0.0-alpha.13",
"@arcjet/headers": "1.0.0-alpha.13",
"@arcjet/ip": "1.0.0-alpha.13",
"@arcjet/logger": "1.0.0-alpha.13",
"@connectrpc/connect-node": "1.4.0",
"arcjet": "1.0.0-alpha.13"
},
Expand Down
53 changes: 32 additions & 21 deletions arcjet-next/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,19 @@ import arcjet, {
ExtraProps,
RemoteClient,
RemoteClientOptions,
defaultBaseUrl,
createRemoteClient,
Arcjet,
} from "arcjet";
import findIP from "@arcjet/ip";
import ArcjetHeaders from "@arcjet/headers";
import {
baseUrl,
isDevelopment,
isProduction,
logLevel,
platform,
} from "@arcjet/env";
import { Logger } from "@arcjet/logger";

// Re-export all named exports from the generic SDK
export * from "arcjet";
Expand Down Expand Up @@ -64,19 +71,23 @@ type PlainObject = {
};

export function createNextRemoteClient(
options?: RemoteClientOptions,
options?: Partial<RemoteClientOptions>,
): RemoteClient {
// The base URL for the Arcjet API. Will default to the standard production
// API unless environment variable `ARCJET_BASE_URL` is set.
const baseUrl = options?.baseUrl ?? defaultBaseUrl();
const url = options?.baseUrl ?? baseUrl(process.env);

// The timeout for the Arcjet API in milliseconds. This is set to a low value
// in production so calls fail open.
const timeout = options?.timeout ?? (isProduction(process.env) ? 500 : 1000);

// Transport is the HTTP client that the client uses to make requests.
// The Connect Node client doesn't work on edge runtimes: https://github.com/bufbuild/connect-es/pull/589
// so set the transport using connect-web. The interceptor is required for it work in the edge runtime.
const transport =
options?.transport ??
createConnectTransport({
baseUrl,
baseUrl: url,
interceptors: [
/**
* Ensures redirects are followed to properly support the Next.js/Vercel Edge
Expand All @@ -92,11 +103,17 @@ export function createNextRemoteClient(
fetch,
});

// TODO(#223): Do we want to allow overrides to either of these? If not, we should probably define a separate type for `options`
// TODO(#223): Create separate options type to exclude these
const sdkStack = "NEXTJS";
const sdkVersion = "__ARCJET_SDK_VERSION__";

return createRemoteClient({ ...options, transport, sdkStack, sdkVersion });
return createRemoteClient({
transport,
baseUrl: url,
timeout,
sdkStack,
sdkVersion,
});
}

// Interface of fields that the Arcjet Next.js SDK expects on `Request` objects.
Expand Down Expand Up @@ -193,30 +210,18 @@ export interface ArcjetNext<Props extends PlainObject> {
): ArcjetNext<Simplify<Props & ExtraProps<Rule>>>;
}

function detectPlatform() {
if (
typeof process.env["FLY_APP_NAME"] === "string" &&
process.env["FLY_APP_NAME"] !== ""
) {
return "fly-io" as const;
}
}

function toArcjetRequest<Props extends PlainObject>(
request: ArcjetNextRequest,
props: Props,
): ArcjetRequest<Props> {
// We construct an ArcjetHeaders to normalize over Headers
const headers = new ArcjetHeaders(request.headers);

let ip = findIP(request, headers, { platform: detectPlatform() });
let ip = findIP(request, headers, { platform: platform(process.env) });
if (ip === "") {
// If the `ip` is empty but we're in development mode, we default the IP
// so the request doesn't fail.
if (
process.env["NODE_ENV"] === "development" ||
process.env["ARCJET_ENV"] === "development"
) {
if (isDevelopment(process.env)) {
// TODO: Log that the fingerprint is being overridden once the adapter
// constructs the logger
ip = "127.0.0.1";
Expand Down Expand Up @@ -334,7 +339,13 @@ export default function arcjetNext<const Rules extends (Primitive | Product)[]>(
): ArcjetNext<Simplify<ExtraProps<Rules>>> {
const client = options.client ?? createNextRemoteClient();

const aj = arcjet({ ...options, client });
const log = options.log
? options.log
: new Logger({
level: logLevel(process.env),
});

const aj = arcjet({ ...options, client, log });

return withClient(aj);
}
Expand Down
2 changes: 2 additions & 0 deletions arcjet-next/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@
"test": "NODE_OPTIONS=--experimental-vm-modules jest --passWithNoTests"
},
"dependencies": {
"@arcjet/env": "1.0.0-alpha.13",
"@arcjet/headers": "1.0.0-alpha.13",
"@arcjet/ip": "1.0.0-alpha.13",
"@arcjet/logger": "1.0.0-alpha.13",
"@connectrpc/connect-web": "1.4.0",
"arcjet": "1.0.0-alpha.13"
},
Expand Down
53 changes: 32 additions & 21 deletions arcjet-node/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,19 @@ import core, {
ExtraProps,
RemoteClient,
RemoteClientOptions,
defaultBaseUrl,
createRemoteClient,
Arcjet,
} from "arcjet";
import findIP from "@arcjet/ip";
import ArcjetHeaders from "@arcjet/headers";
import {
baseUrl,
isDevelopment,
isProduction,
logLevel,
platform,
} from "@arcjet/env";
import { Logger } from "@arcjet/logger";

// Re-export all named exports from the generic SDK
export * from "arcjet";
Expand Down Expand Up @@ -56,25 +63,35 @@ type PlainObject = {
};

export function createNodeRemoteClient(
options?: RemoteClientOptions,
options?: Partial<RemoteClientOptions>,
): RemoteClient {
// The base URL for the Arcjet API. Will default to the standard production
// API unless environment variable `ARCJET_BASE_URL` is set.
const baseUrl = options?.baseUrl ?? defaultBaseUrl();
const url = options?.baseUrl ?? baseUrl(process.env);

// The timeout for the Arcjet API in milliseconds. This is set to a low value
// in production so calls fail open.
const timeout = options?.timeout ?? (isProduction(process.env) ? 500 : 1000);

// Transport is the HTTP client that the client uses to make requests.
const transport =
options?.transport ??
createConnectTransport({
baseUrl,
baseUrl: url,
httpVersion: "2",
});

// TODO(#223): Do we want to allow overrides to either of these? If not, we should probably define a separate type for `options`
// TODO(#223): Create separate options type to exclude these
const sdkStack = "NODEJS";
const sdkVersion = "__ARCJET_SDK_VERSION__";

return createRemoteClient({ ...options, transport, sdkStack, sdkVersion });
return createRemoteClient({
transport,
baseUrl: url,
timeout,
sdkStack,
sdkVersion,
});
}

// Interface of fields that the Arcjet Node.js SDK expects on `IncomingMessage`
Expand Down Expand Up @@ -133,15 +150,6 @@ export interface ArcjetNode<Props extends PlainObject> {
): ArcjetNode<Simplify<Props & ExtraProps<Rule>>>;
}

function detectPlatform() {
if (
typeof process.env["FLY_APP_NAME"] === "string" &&
process.env["FLY_APP_NAME"] !== ""
) {
return "fly-io" as const;
}
}

function toArcjetRequest<Props extends PlainObject>(
request: ArcjetNodeRequest,
props: Props,
Expand All @@ -152,14 +160,11 @@ function toArcjetRequest<Props extends PlainObject>(
// We construct an ArcjetHeaders to normalize over Headers
const headers = new ArcjetHeaders(request.headers);

let ip = findIP(request, headers, { platform: detectPlatform() });
let ip = findIP(request, headers, { platform: platform(process.env) });
if (ip === "") {
// If the `ip` is empty but we're in development mode, we default the IP
// so the request doesn't fail.
if (
process.env["NODE_ENV"] === "development" ||
process.env["ARCJET_ENV"] === "development"
) {
if (isDevelopment(process.env)) {
// TODO: Log that the fingerprint is being overridden once the adapter
// constructs the logger
ip = "127.0.0.1";
Expand Down Expand Up @@ -246,7 +251,13 @@ export default function arcjet<const Rules extends (Primitive | Product)[]>(
): ArcjetNode<Simplify<ExtraProps<Rules>>> {
const client = options.client ?? createNodeRemoteClient();

const aj = core({ ...options, client });
const log = options.log
? options.log
: new Logger({
level: logLevel(process.env),
});

const aj = core({ ...options, client, log });

return withClient(aj);
}
2 changes: 2 additions & 0 deletions arcjet-node/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@
"test": "NODE_OPTIONS=--experimental-vm-modules jest --passWithNoTests"
},
"dependencies": {
"@arcjet/env": "1.0.0-alpha.13",
"@arcjet/headers": "1.0.0-alpha.13",
"@arcjet/ip": "1.0.0-alpha.13",
"@arcjet/logger": "1.0.0-alpha.13",
"@connectrpc/connect-node": "1.4.0",
"arcjet": "1.0.0-alpha.13"
},
Expand Down
Loading

0 comments on commit 08cb984

Please sign in to comment.