og-pilot-js 0.2.0 → 0.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +109 -18
- package/dist/index.cjs +103 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +65 -1
- package/dist/index.d.ts +65 -1
- package/dist/index.js +99 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -88,38 +88,129 @@ The client automatically injects a `path` parameter on every request:
|
|
|
88
88
|
| `default: true` | Forces the `path` parameter to `/`, regardless of the current request (unless `path` is provided explicitly) |
|
|
89
89
|
| `path: "/..."` | Uses the provided path verbatim (normalized to start with `/`), overriding auto-resolution |
|
|
90
90
|
|
|
91
|
-
###
|
|
91
|
+
### Framework Integration
|
|
92
92
|
|
|
93
|
-
|
|
93
|
+
#### Next.js (App Router)
|
|
94
94
|
|
|
95
|
-
|
|
95
|
+
In Next.js, the recommended approach is to use `generateMetadata` and build the
|
|
96
|
+
path directly from `params` and `searchParams` (no middleware needed):
|
|
96
97
|
|
|
97
98
|
```ts
|
|
98
|
-
|
|
99
|
+
// app/products/[id]/page.tsx
|
|
100
|
+
import type { Metadata } from "next";
|
|
101
|
+
import { buildPathFromNextProps, createImage } from "og-pilot-js";
|
|
102
|
+
|
|
103
|
+
export async function generateMetadata(props): Promise<Metadata> {
|
|
104
|
+
const path = await buildPathFromNextProps("/products/[id]", props);
|
|
105
|
+
const imageUrl = await createImage(
|
|
106
|
+
{
|
|
107
|
+
template: "product",
|
|
108
|
+
title: "Product page",
|
|
109
|
+
},
|
|
110
|
+
{ path }
|
|
111
|
+
);
|
|
112
|
+
|
|
113
|
+
return {
|
|
114
|
+
openGraph: {
|
|
115
|
+
images: [imageUrl],
|
|
116
|
+
},
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
```
|
|
99
120
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
}
|
|
121
|
+
For catch-all routes:
|
|
122
|
+
|
|
123
|
+
```ts
|
|
124
|
+
// app/blog/[...slug]/page.tsx
|
|
125
|
+
import { buildPathFromNextProps } from "og-pilot-js";
|
|
126
|
+
|
|
127
|
+
export async function generateMetadata(props) {
|
|
128
|
+
const path = await buildPathFromNextProps("/blog/[...slug]", props);
|
|
129
|
+
// => /blog/2024/launch?ref=twitter
|
|
130
|
+
}
|
|
105
131
|
```
|
|
106
132
|
|
|
107
|
-
|
|
133
|
+
#### Express
|
|
108
134
|
|
|
109
135
|
```ts
|
|
110
|
-
import
|
|
111
|
-
import {
|
|
112
|
-
|
|
136
|
+
import express from "express";
|
|
137
|
+
import { createExpressMiddleware } from "og-pilot-js";
|
|
138
|
+
|
|
139
|
+
const app = express();
|
|
140
|
+
app.use(createExpressMiddleware());
|
|
141
|
+
|
|
142
|
+
// Now path is automatically captured in all routes
|
|
143
|
+
app.get("/blog/:slug", async (req, res) => {
|
|
144
|
+
const imageUrl = await createImage({
|
|
145
|
+
template: "blog_post",
|
|
146
|
+
title: "My Blog Post",
|
|
147
|
+
});
|
|
148
|
+
// path is automatically set to /blog/:slug
|
|
149
|
+
});
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
#### Nuxt (useSeoMeta)
|
|
113
153
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
154
|
+
Nuxt recommends `useSeoMeta` for SEO tags. You can generate the OG image URL
|
|
155
|
+
server-side and pass it directly:
|
|
156
|
+
|
|
157
|
+
```vue
|
|
158
|
+
<!-- app/pages/products/[id].vue -->
|
|
159
|
+
<script setup lang="ts">
|
|
160
|
+
import { createImage } from "og-pilot-js";
|
|
161
|
+
|
|
162
|
+
const route = useRoute();
|
|
163
|
+
|
|
164
|
+
if (import.meta.server) {
|
|
165
|
+
const imageUrl = await createImage(
|
|
166
|
+
{
|
|
167
|
+
template: "product",
|
|
168
|
+
title: "Product page",
|
|
169
|
+
},
|
|
170
|
+
{ path: route.fullPath }
|
|
171
|
+
);
|
|
172
|
+
|
|
173
|
+
useSeoMeta({
|
|
174
|
+
title: "Product page",
|
|
175
|
+
ogTitle: "Product page",
|
|
176
|
+
ogImage: imageUrl,
|
|
177
|
+
twitterCard: "summary_large_image",
|
|
117
178
|
});
|
|
118
|
-
return NextResponse.next();
|
|
119
179
|
}
|
|
180
|
+
</script>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
If you need reactive metadata, pass a computed getter:
|
|
184
|
+
|
|
185
|
+
```vue
|
|
186
|
+
<script setup lang="ts">
|
|
187
|
+
const title = ref("My title");
|
|
188
|
+
|
|
189
|
+
useSeoMeta({
|
|
190
|
+
title,
|
|
191
|
+
ogTitle: () => title.value,
|
|
192
|
+
});
|
|
193
|
+
</script>
|
|
120
194
|
```
|
|
121
195
|
|
|
122
|
-
|
|
196
|
+
#### Other Frameworks
|
|
197
|
+
|
|
198
|
+
For SvelteKit, Remix, or other frameworks, use `withRequestContext` in your server middleware:
|
|
199
|
+
|
|
200
|
+
```ts
|
|
201
|
+
// SvelteKit hooks (src/hooks.server.ts)
|
|
202
|
+
import { setCurrentRequest } from "og-pilot-js";
|
|
203
|
+
import type { Handle } from "@sveltejs/kit";
|
|
204
|
+
|
|
205
|
+
export const handle: Handle = async ({ event, resolve }) => {
|
|
206
|
+
setCurrentRequest({ url: event.url.pathname + event.url.search });
|
|
207
|
+
return resolve(event);
|
|
208
|
+
};
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
#### Using withRequestContext (async-safe)
|
|
212
|
+
|
|
213
|
+
For fine-grained control or when middleware isn't suitable:
|
|
123
214
|
|
|
124
215
|
```ts
|
|
125
216
|
import { withRequestContext, createImage } from "og-pilot-js";
|
package/dist/index.cjs
CHANGED
|
@@ -25,13 +25,17 @@ __export(index_exports, {
|
|
|
25
25
|
ConfigurationError: () => ConfigurationError,
|
|
26
26
|
OgPilotError: () => OgPilotError,
|
|
27
27
|
RequestError: () => RequestError,
|
|
28
|
+
buildPathFromNextParams: () => buildPathFromNextParams,
|
|
29
|
+
buildPathFromNextProps: () => buildPathFromNextProps,
|
|
28
30
|
clearCurrentRequest: () => clearCurrentRequest,
|
|
29
31
|
client: () => client,
|
|
30
32
|
configure: () => configure,
|
|
31
33
|
createClient: () => createClient,
|
|
34
|
+
createExpressMiddleware: () => createExpressMiddleware,
|
|
32
35
|
createImage: () => createImage,
|
|
33
36
|
default: () => index_default,
|
|
34
37
|
getConfig: () => getConfig,
|
|
38
|
+
getPathFromExpressRequest: () => getPathFromExpressRequest,
|
|
35
39
|
resetConfig: () => resetConfig,
|
|
36
40
|
setCurrentRequest: () => setCurrentRequest,
|
|
37
41
|
withRequestContext: () => withRequestContext
|
|
@@ -184,6 +188,75 @@ function getCurrentPath() {
|
|
|
184
188
|
}
|
|
185
189
|
return getPathFromEnv();
|
|
186
190
|
}
|
|
191
|
+
async function buildPathFromNextProps(routePattern, props) {
|
|
192
|
+
const params = await props.params;
|
|
193
|
+
const searchParams = props.searchParams ? await props.searchParams : void 0;
|
|
194
|
+
return buildPathFromNextParams(routePattern, params, searchParams);
|
|
195
|
+
}
|
|
196
|
+
function buildPathFromNextParams(routePattern, params, searchParams) {
|
|
197
|
+
const segments = routePattern.split("/").filter((segment) => segment.length > 0);
|
|
198
|
+
const builtSegments = [];
|
|
199
|
+
for (const segment of segments) {
|
|
200
|
+
const catchAllMatch = segment.match(/^\[\.\.\.(.+)\]$/);
|
|
201
|
+
const optionalCatchAllMatch = segment.match(/^\[\[\.\.\.(.+)\]\]$/);
|
|
202
|
+
const paramMatch = segment.match(/^\[(.+)\]$/);
|
|
203
|
+
if (optionalCatchAllMatch) {
|
|
204
|
+
const key = optionalCatchAllMatch[1];
|
|
205
|
+
const value = params[key];
|
|
206
|
+
if (value === void 0) {
|
|
207
|
+
continue;
|
|
208
|
+
}
|
|
209
|
+
if (Array.isArray(value)) {
|
|
210
|
+
builtSegments.push(...value);
|
|
211
|
+
} else {
|
|
212
|
+
builtSegments.push(value);
|
|
213
|
+
}
|
|
214
|
+
continue;
|
|
215
|
+
}
|
|
216
|
+
if (catchAllMatch) {
|
|
217
|
+
const key = catchAllMatch[1];
|
|
218
|
+
const value = params[key];
|
|
219
|
+
if (value === void 0) {
|
|
220
|
+
continue;
|
|
221
|
+
}
|
|
222
|
+
if (Array.isArray(value)) {
|
|
223
|
+
builtSegments.push(...value);
|
|
224
|
+
} else {
|
|
225
|
+
builtSegments.push(value);
|
|
226
|
+
}
|
|
227
|
+
continue;
|
|
228
|
+
}
|
|
229
|
+
if (paramMatch) {
|
|
230
|
+
const key = paramMatch[1];
|
|
231
|
+
const value = params[key];
|
|
232
|
+
if (value === void 0) {
|
|
233
|
+
continue;
|
|
234
|
+
}
|
|
235
|
+
if (Array.isArray(value)) {
|
|
236
|
+
builtSegments.push(value.join("/"));
|
|
237
|
+
} else {
|
|
238
|
+
builtSegments.push(value);
|
|
239
|
+
}
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
builtSegments.push(segment);
|
|
243
|
+
}
|
|
244
|
+
const path = `/${builtSegments.join("/")}`;
|
|
245
|
+
const query = serializeSearchParams(searchParams);
|
|
246
|
+
return query.length > 0 ? `${path}?${query}` : path;
|
|
247
|
+
}
|
|
248
|
+
function createExpressMiddleware() {
|
|
249
|
+
return (req, _res, next) => {
|
|
250
|
+
setCurrentRequest({
|
|
251
|
+
url: req.originalUrl || req.url,
|
|
252
|
+
path: req.originalUrl || req.url
|
|
253
|
+
});
|
|
254
|
+
next();
|
|
255
|
+
};
|
|
256
|
+
}
|
|
257
|
+
function getPathFromExpressRequest(req) {
|
|
258
|
+
return req.originalUrl || req.url || "/";
|
|
259
|
+
}
|
|
187
260
|
function extractPathFromUrl(url) {
|
|
188
261
|
if (url.startsWith("http://") || url.startsWith("https://")) {
|
|
189
262
|
try {
|
|
@@ -195,6 +268,28 @@ function extractPathFromUrl(url) {
|
|
|
195
268
|
}
|
|
196
269
|
return url;
|
|
197
270
|
}
|
|
271
|
+
function serializeSearchParams(searchParams) {
|
|
272
|
+
if (!searchParams) {
|
|
273
|
+
return "";
|
|
274
|
+
}
|
|
275
|
+
if (searchParams instanceof URLSearchParams) {
|
|
276
|
+
return searchParams.toString();
|
|
277
|
+
}
|
|
278
|
+
const params = new URLSearchParams();
|
|
279
|
+
for (const [key, value] of Object.entries(searchParams)) {
|
|
280
|
+
if (value === void 0) {
|
|
281
|
+
continue;
|
|
282
|
+
}
|
|
283
|
+
if (Array.isArray(value)) {
|
|
284
|
+
for (const entry of value) {
|
|
285
|
+
params.append(key, entry);
|
|
286
|
+
}
|
|
287
|
+
} else {
|
|
288
|
+
params.append(key, value);
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
return params.toString();
|
|
292
|
+
}
|
|
198
293
|
function getPathFromEnv() {
|
|
199
294
|
if (typeof process === "undefined" || !process.env) {
|
|
200
295
|
return void 0;
|
|
@@ -428,6 +523,10 @@ var OgPilot = {
|
|
|
428
523
|
setCurrentRequest,
|
|
429
524
|
clearCurrentRequest,
|
|
430
525
|
withRequestContext,
|
|
526
|
+
createExpressMiddleware,
|
|
527
|
+
getPathFromExpressRequest,
|
|
528
|
+
buildPathFromNextProps,
|
|
529
|
+
buildPathFromNextParams,
|
|
431
530
|
Configuration,
|
|
432
531
|
ConfigurationError,
|
|
433
532
|
OgPilotError,
|
|
@@ -441,12 +540,16 @@ var index_default = OgPilot;
|
|
|
441
540
|
ConfigurationError,
|
|
442
541
|
OgPilotError,
|
|
443
542
|
RequestError,
|
|
543
|
+
buildPathFromNextParams,
|
|
544
|
+
buildPathFromNextProps,
|
|
444
545
|
clearCurrentRequest,
|
|
445
546
|
client,
|
|
446
547
|
configure,
|
|
447
548
|
createClient,
|
|
549
|
+
createExpressMiddleware,
|
|
448
550
|
createImage,
|
|
449
551
|
getConfig,
|
|
552
|
+
getPathFromExpressRequest,
|
|
450
553
|
resetConfig,
|
|
451
554
|
setCurrentRequest,
|
|
452
555
|
withRequestContext
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/errors.ts","../src/jwt.ts","../src/request-context.ts","../src/client.ts"],"sourcesContent":["import { Client } from \"./client\";\nimport { Configuration, OgPilotConfigOptions } from \"./config\";\nimport { ConfigurationError, OgPilotError, RequestError } from \"./errors\";\nimport {\n clearCurrentRequest,\n setCurrentRequest,\n withRequestContext,\n} from \"./request-context\";\n\nlet defaultConfig = new Configuration();\n\nexport const configure = (\n updater: (config: Configuration) => void\n): Configuration => {\n updater(defaultConfig);\n return defaultConfig;\n};\n\nexport const resetConfig = (): void => {\n defaultConfig = new Configuration();\n};\n\nexport const getConfig = (): Configuration => defaultConfig;\n\nexport const client = (): Client => new Client(defaultConfig);\n\nexport const createImage = (\n params: Record<string, unknown> = {},\n options: Parameters<Client[\"createImage\"]>[1] = {}\n): ReturnType<Client[\"createImage\"]> => client().createImage(params, options);\n\nexport const createClient = (options: OgPilotConfigOptions = {}): Client =>\n new Client(options);\n\nconst OgPilot = {\n configure,\n resetConfig,\n getConfig,\n client,\n createClient,\n createImage,\n setCurrentRequest,\n clearCurrentRequest,\n withRequestContext,\n Configuration,\n ConfigurationError,\n OgPilotError,\n RequestError,\n};\n\nexport default OgPilot;\nexport type { CreateImageOptions } from \"./client\";\nexport {\n clearCurrentRequest,\n Client,\n Configuration,\n ConfigurationError,\n OgPilotConfigOptions,\n OgPilotError,\n RequestError,\n setCurrentRequest,\n withRequestContext,\n};\n","export interface OgPilotConfigOptions {\n apiKey?: string;\n domain?: string;\n baseUrl?: string;\n openTimeoutMs?: number;\n readTimeoutMs?: number;\n fetch?: typeof fetch;\n}\n\nconst DEFAULT_BASE_URL = \"https://ogpilot.com\";\n\nfunction readEnv(key: string): string | undefined {\n if (typeof process !== \"undefined\" && process.env) {\n return process.env[key];\n }\n\n return undefined;\n}\n\nexport class Configuration {\n apiKey?: string;\n domain?: string;\n baseUrl: string;\n openTimeoutMs?: number;\n readTimeoutMs?: number;\n fetch?: typeof fetch;\n\n constructor(options: OgPilotConfigOptions = {}) {\n this.apiKey = options.apiKey ?? readEnv(\"OG_PILOT_API_KEY\");\n this.domain = options.domain ?? readEnv(\"OG_PILOT_DOMAIN\");\n this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;\n this.openTimeoutMs = options.openTimeoutMs ?? 5000;\n this.readTimeoutMs = options.readTimeoutMs ?? 10000;\n this.fetch = options.fetch;\n }\n}\n","export class OgPilotError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"OgPilotError\";\n }\n}\n\nexport class ConfigurationError extends OgPilotError {\n constructor(message: string) {\n super(message);\n this.name = \"ConfigurationError\";\n }\n}\n\nexport class RequestError extends OgPilotError {\n status?: number;\n\n constructor(message: string, status?: number) {\n super(message);\n this.name = \"RequestError\";\n this.status = status;\n }\n}\n","const encoder = new TextEncoder();\n\nfunction toBase64(bytes: Uint8Array): string {\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(bytes).toString(\"base64\");\n }\n\n let binary = \"\";\n for (let i = 0; i < bytes.length; i += 1) {\n binary += String.fromCharCode(bytes[i]);\n }\n\n if (typeof btoa === \"undefined\") {\n throw new Error(\"btoa is not available in this environment\");\n }\n\n return btoa(binary);\n}\n\nfunction base64UrlEncodeBytes(bytes: Uint8Array): string {\n return toBase64(bytes).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/g, \"\");\n}\n\nfunction base64UrlEncodeString(value: string): string {\n return base64UrlEncodeBytes(encoder.encode(value));\n}\n\nfunction getSubtleCrypto(): SubtleCrypto | null {\n if (typeof globalThis !== \"undefined\" && globalThis.crypto && globalThis.crypto.subtle) {\n return globalThis.crypto.subtle;\n }\n\n return null;\n}\n\nasync function hmacSha256(data: string, secret: string): Promise<Uint8Array> {\n const subtle = getSubtleCrypto();\n\n if (!subtle) {\n throw new Error(\"Web Crypto API is not available; requires a Node 18+ or Edge runtime.\");\n }\n\n const key = await subtle.importKey(\n \"raw\",\n encoder.encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"]\n );\n\n const signature = await subtle.sign(\"HMAC\", key, encoder.encode(data));\n return new Uint8Array(signature);\n}\n\nexport async function signJwt(payload: Record<string, unknown>, secret: string): Promise<string> {\n const header = { alg: \"HS256\", typ: \"JWT\" };\n const encodedHeader = base64UrlEncodeString(JSON.stringify(header));\n const encodedPayload = base64UrlEncodeString(JSON.stringify(payload));\n const signingInput = `${encodedHeader}.${encodedPayload}`;\n const signature = await hmacSha256(signingInput, secret);\n\n return `${signingInput}.${base64UrlEncodeBytes(signature)}`;\n}\n","/**\n * Request context for automatic path resolution.\n *\n * In Node.js environments, this uses AsyncLocalStorage to store the current\n * request URL per async execution context. In edge runtimes or browsers,\n * it falls back to a simple variable (not request-scoped).\n */\n\ntype RequestInfo = {\n url?: string;\n path?: string;\n};\n\ninterface AsyncStorage {\n getStore: () => RequestInfo | undefined;\n run: <T>(store: RequestInfo, callback: () => T) => T;\n}\n\n// Try to use AsyncLocalStorage if available (Node.js 12.17+)\nlet asyncLocalStorage: AsyncStorage | null = null;\n\n// Fallback for environments without AsyncLocalStorage\nlet fallbackRequest: RequestInfo | undefined;\n\n// Create a fallback implementation\nfunction createFallbackStorage(): AsyncStorage {\n return {\n getStore: () => fallbackRequest,\n run: <T>(_store: RequestInfo, callback: () => T): T => {\n const prev = fallbackRequest;\n fallbackRequest = _store;\n try {\n return callback();\n } finally {\n fallbackRequest = prev;\n }\n },\n };\n}\n\n// Lazy initialization to avoid issues in environments where async_hooks isn't available\nfunction getAsyncLocalStorage(): AsyncStorage {\n if (asyncLocalStorage === null) {\n try {\n // Dynamic import to avoid bundler issues\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { AsyncLocalStorage } = require(\"async_hooks\");\n const storage = new AsyncLocalStorage();\n asyncLocalStorage = {\n getStore: () => storage.getStore() as RequestInfo | undefined,\n run: <T>(store: RequestInfo, callback: () => T): T =>\n storage.run(store, callback),\n };\n } catch {\n // AsyncLocalStorage not available, use fallback\n asyncLocalStorage = createFallbackStorage();\n }\n }\n return asyncLocalStorage!;\n}\n\n/**\n * Sets the current request context for automatic path resolution.\n * Call this in your middleware/handler before using OG Pilot.\n *\n * @example Express middleware\n * ```ts\n * app.use((req, res, next) => {\n * setCurrentRequest({ url: req.originalUrl });\n * next();\n * });\n * ```\n *\n * @example Next.js middleware\n * ```ts\n * export function middleware(request: NextRequest) {\n * setCurrentRequest({ url: request.nextUrl.pathname + request.nextUrl.search });\n * return NextResponse.next();\n * }\n * ```\n */\nexport function setCurrentRequest(request: RequestInfo): void {\n fallbackRequest = request;\n}\n\n/**\n * Clears the current request context.\n * Call this after the request is complete if using setCurrentRequest directly.\n */\nexport function clearCurrentRequest(): void {\n fallbackRequest = undefined;\n}\n\n/**\n * Runs a callback with the given request context.\n * The context is automatically cleared after the callback completes.\n * This is the preferred method for setting request context.\n *\n * @example Express middleware\n * ```ts\n * import { withRequestContext } from \"og-pilot-js\";\n *\n * app.use((req, res, next) => {\n * withRequestContext({ url: req.originalUrl }, () => {\n * next();\n * });\n * });\n * ```\n */\nexport function withRequestContext<T>(\n request: RequestInfo,\n callback: () => T\n): T {\n return getAsyncLocalStorage().run(request, callback);\n}\n\n/**\n * Gets the current request info from context.\n * @internal\n */\nexport function getCurrentRequest(): RequestInfo | undefined {\n // Try AsyncLocalStorage first, then fallback\n const store = getAsyncLocalStorage().getStore();\n return store ?? fallbackRequest;\n}\n\n/**\n * Gets the current request path from context or environment.\n * @internal\n */\nexport function getCurrentPath(): string | undefined {\n const request = getCurrentRequest();\n\n if (request?.path) {\n return request.path;\n }\n\n if (request?.url) {\n return extractPathFromUrl(request.url);\n }\n\n // Fallback to environment variables (similar to Ruby's env_fullpath)\n return getPathFromEnv();\n}\n\nfunction extractPathFromUrl(url: string): string {\n // Handle full URLs\n if (url.startsWith(\"http://\") || url.startsWith(\"https://\")) {\n try {\n const parsed = new URL(url);\n return parsed.pathname + parsed.search;\n } catch {\n return url;\n }\n }\n\n return url;\n}\n\nfunction getPathFromEnv(): string | undefined {\n if (typeof process === \"undefined\" || !process.env) {\n return undefined;\n }\n\n const env = process.env;\n\n // Check various environment variables (similar to Ruby implementation)\n const requestUri = env.REQUEST_URI;\n if (requestUri && requestUri.length > 0) {\n return requestUri;\n }\n\n const originalFullpath = env.ORIGINAL_FULLPATH;\n if (originalFullpath && originalFullpath.length > 0) {\n return originalFullpath;\n }\n\n const pathInfo = env.PATH_INFO;\n if (pathInfo && pathInfo.length > 0) {\n const queryString = env.QUERY_STRING ?? \"\";\n return queryString.length > 0 ? `${pathInfo}?${queryString}` : pathInfo;\n }\n\n const requestPath = env.REQUEST_PATH;\n if (requestPath && requestPath.length > 0) {\n return requestPath;\n }\n\n return undefined;\n}\n","import { Configuration, OgPilotConfigOptions } from \"./config\";\nimport { ConfigurationError, RequestError } from \"./errors\";\nimport { signJwt } from \"./jwt\";\nimport { getCurrentPath } from \"./request-context\";\n\nexport interface CreateImageOptions {\n json?: boolean;\n iat?: number | Date;\n headers?: Record<string, string>;\n /**\n * When true, forces the path to \"/\" regardless of the current request.\n * Useful for generating default/fallback OG images.\n */\n default?: boolean;\n}\n\nconst ENDPOINT_PATH = \"/api/v1/images\";\n\nexport class Client {\n private config: Configuration;\n\n constructor(config: Configuration | OgPilotConfigOptions = {}) {\n this.config =\n config instanceof Configuration ? config : new Configuration(config);\n }\n\n async createImage(\n params: Record<string, unknown> = {},\n options: CreateImageOptions = {}\n ): Promise<unknown> {\n const {\n json = false,\n iat,\n headers = {},\n default: useDefault = false,\n } = options;\n\n // Always include a path; manual overrides win, otherwise resolve from the current request.\n const resolvedParams = { ...params };\n const manualPath = resolvedParams.path;\n delete resolvedParams.path;\n resolvedParams.path = this.resolvePath(manualPath, useDefault);\n\n const url = await this.buildUrl(resolvedParams, iat);\n const response = await this.request(url, json, headers);\n\n if (json) {\n const body = await response.text();\n return JSON.parse(body);\n }\n\n return response.headers.get(\"location\") ?? response.url ?? url.toString();\n }\n\n /**\n * Resolves the path parameter for the request.\n * Priority: manual path > current request path > \"/\"\n */\n private resolvePath(manualPath: unknown, useDefault: boolean): string {\n // Manual path always wins if provided\n if (manualPath !== undefined && manualPath !== null) {\n const pathStr = String(manualPath).trim();\n if (pathStr.length > 0) {\n return this.normalizePath(pathStr);\n }\n }\n\n // If default is true, return \"/\"\n if (useDefault) {\n return \"/\";\n }\n\n // Try to get path from current request context\n const currentPath = getCurrentPath();\n return this.normalizePath(currentPath);\n }\n\n /**\n * Normalizes a path to ensure it starts with \"/\" and handles full URLs.\n */\n private normalizePath(path: string | undefined | null): string {\n if (path === undefined || path === null) {\n return \"/\";\n }\n\n let cleaned = String(path).trim();\n if (cleaned.length === 0) {\n return \"/\";\n }\n\n // Extract path from full URLs\n if (cleaned.startsWith(\"http://\") || cleaned.startsWith(\"https://\")) {\n try {\n const url = new URL(cleaned);\n cleaned = url.pathname + url.search;\n } catch {\n // Keep as-is if URL parsing fails\n }\n }\n\n // Ensure path starts with \"/\"\n if (!cleaned.startsWith(\"/\")) {\n cleaned = \"/\" + cleaned;\n }\n\n return cleaned;\n }\n\n private async request(\n url: URL,\n json: boolean,\n headers: Record<string, string>\n ): Promise<Response> {\n const fetchImpl =\n this.config.fetch ?? (typeof fetch !== \"undefined\" ? fetch : undefined);\n\n if (!fetchImpl) {\n throw new ConfigurationError(\n \"Fetch API is not available; provide a fetch implementation in the configuration.\"\n );\n }\n\n const requestHeaders = new Headers();\n if (json) {\n requestHeaders.set(\"Accept\", \"application/json\");\n }\n\n Object.entries(headers).forEach(([key, value]) => {\n requestHeaders.set(key, value);\n });\n\n const timeoutMs = this.totalTimeoutMs();\n const controller = new AbortController();\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n if (timeoutMs && timeoutMs > 0) {\n timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n }\n\n try {\n const response = await fetchImpl(url.toString(), {\n method: \"GET\",\n headers: requestHeaders,\n redirect: \"manual\",\n signal: controller.signal,\n });\n\n if (response.status >= 400) {\n const body = await response.text().catch(() => \"\");\n throw new RequestError(\n `OG Pilot request failed with status ${response.status}: ${body}`,\n response.status\n );\n }\n\n return response;\n } catch (error) {\n if (error instanceof RequestError) {\n throw error;\n }\n\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new RequestError(`OG Pilot request timed out: ${error.message}`);\n }\n\n if (error instanceof Error) {\n throw new RequestError(`OG Pilot request failed: ${error.message}`);\n }\n\n throw new RequestError(\"OG Pilot request failed.\");\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n }\n\n private async buildUrl(\n params: Record<string, unknown>,\n iat?: number | Date\n ): Promise<URL> {\n const payload = this.buildPayload(params, iat);\n const token = await signJwt(payload, this.apiKey());\n const url = new URL(ENDPOINT_PATH, this.config.baseUrl);\n url.searchParams.set(\"token\", token);\n return url;\n }\n\n private buildPayload(\n params: Record<string, unknown>,\n iat?: number | Date\n ): Record<string, unknown> {\n const payload: Record<string, unknown> = { ...params };\n\n if (iat !== undefined && iat !== null) {\n payload.iat = normalizeIat(iat);\n }\n\n if (payload.iss === undefined || payload.iss === null) {\n payload.iss = this.domain();\n }\n\n if (payload.sub === undefined || payload.sub === null) {\n payload.sub = this.apiKeyPrefix();\n }\n\n this.validatePayload(payload);\n return payload;\n }\n\n private validatePayload(payload: Record<string, unknown>): void {\n if (\n payload.iss === undefined ||\n payload.iss === null ||\n String(payload.iss).length === 0\n ) {\n throw new ConfigurationError(\"OG Pilot domain is missing\");\n }\n\n if (\n payload.sub === undefined ||\n payload.sub === null ||\n String(payload.sub).length === 0\n ) {\n throw new ConfigurationError(\"OG Pilot API key prefix is missing\");\n }\n\n if (\n payload.title === undefined ||\n payload.title === null ||\n String(payload.title).length === 0\n ) {\n throw new Error(\"OG Pilot title is required\");\n }\n }\n\n private apiKey(): string {\n if (this.config.apiKey !== undefined && this.config.apiKey !== null) {\n return this.config.apiKey;\n }\n\n throw new ConfigurationError(\"OG Pilot API key is missing\");\n }\n\n private domain(): string {\n if (this.config.domain !== undefined && this.config.domain !== null) {\n return this.config.domain;\n }\n\n throw new ConfigurationError(\"OG Pilot domain is missing\");\n }\n\n private apiKeyPrefix(): string {\n return this.apiKey().slice(0, 8);\n }\n\n private totalTimeoutMs(): number | undefined {\n const openTimeoutMs = this.config.openTimeoutMs;\n const readTimeoutMs = this.config.readTimeoutMs;\n\n if (openTimeoutMs === undefined && readTimeoutMs === undefined) {\n return undefined;\n }\n\n const open = typeof openTimeoutMs === \"number\" ? openTimeoutMs : 0;\n const read = typeof readTimeoutMs === \"number\" ? readTimeoutMs : 0;\n return open + read;\n }\n}\n\nfunction normalizeIat(iat: number | Date): number {\n if (iat instanceof Date) {\n return Math.floor(iat.getTime() / 1000);\n }\n\n if (iat > 100000000000) {\n return Math.floor(iat / 1000);\n }\n\n return Math.floor(iat);\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/errors.ts","../src/jwt.ts","../src/request-context.ts","../src/client.ts"],"sourcesContent":["import { Client } from \"./client\";\nimport { Configuration, OgPilotConfigOptions } from \"./config\";\nimport { ConfigurationError, OgPilotError, RequestError } from \"./errors\";\nimport {\n buildPathFromNextParams,\n buildPathFromNextProps,\n clearCurrentRequest,\n createExpressMiddleware,\n getPathFromExpressRequest,\n setCurrentRequest,\n withRequestContext,\n} from \"./request-context\";\n\nlet defaultConfig = new Configuration();\n\nexport const configure = (\n updater: (config: Configuration) => void\n): Configuration => {\n updater(defaultConfig);\n return defaultConfig;\n};\n\nexport const resetConfig = (): void => {\n defaultConfig = new Configuration();\n};\n\nexport const getConfig = (): Configuration => defaultConfig;\n\nexport const client = (): Client => new Client(defaultConfig);\n\nexport const createImage = (\n params: Record<string, unknown> = {},\n options: Parameters<Client[\"createImage\"]>[1] = {}\n): ReturnType<Client[\"createImage\"]> => client().createImage(params, options);\n\nexport const createClient = (options: OgPilotConfigOptions = {}): Client =>\n new Client(options);\n\nconst OgPilot = {\n configure,\n resetConfig,\n getConfig,\n client,\n createClient,\n createImage,\n setCurrentRequest,\n clearCurrentRequest,\n withRequestContext,\n createExpressMiddleware,\n getPathFromExpressRequest,\n buildPathFromNextProps,\n buildPathFromNextParams,\n Configuration,\n ConfigurationError,\n OgPilotError,\n RequestError,\n};\n\nexport default OgPilot;\nexport type { CreateImageOptions } from \"./client\";\nexport type {\n NextMetadataProps,\n NextParams,\n NextSearchParams,\n} from \"./request-context\";\nexport {\n buildPathFromNextParams,\n buildPathFromNextProps,\n clearCurrentRequest,\n Client,\n Configuration,\n ConfigurationError,\n createExpressMiddleware,\n getPathFromExpressRequest,\n OgPilotConfigOptions,\n OgPilotError,\n RequestError,\n setCurrentRequest,\n withRequestContext,\n};\n","export interface OgPilotConfigOptions {\n apiKey?: string;\n domain?: string;\n baseUrl?: string;\n openTimeoutMs?: number;\n readTimeoutMs?: number;\n fetch?: typeof fetch;\n}\n\nconst DEFAULT_BASE_URL = \"https://ogpilot.com\";\n\nfunction readEnv(key: string): string | undefined {\n if (typeof process !== \"undefined\" && process.env) {\n return process.env[key];\n }\n\n return undefined;\n}\n\nexport class Configuration {\n apiKey?: string;\n domain?: string;\n baseUrl: string;\n openTimeoutMs?: number;\n readTimeoutMs?: number;\n fetch?: typeof fetch;\n\n constructor(options: OgPilotConfigOptions = {}) {\n this.apiKey = options.apiKey ?? readEnv(\"OG_PILOT_API_KEY\");\n this.domain = options.domain ?? readEnv(\"OG_PILOT_DOMAIN\");\n this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;\n this.openTimeoutMs = options.openTimeoutMs ?? 5000;\n this.readTimeoutMs = options.readTimeoutMs ?? 10000;\n this.fetch = options.fetch;\n }\n}\n","export class OgPilotError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"OgPilotError\";\n }\n}\n\nexport class ConfigurationError extends OgPilotError {\n constructor(message: string) {\n super(message);\n this.name = \"ConfigurationError\";\n }\n}\n\nexport class RequestError extends OgPilotError {\n status?: number;\n\n constructor(message: string, status?: number) {\n super(message);\n this.name = \"RequestError\";\n this.status = status;\n }\n}\n","const encoder = new TextEncoder();\n\nfunction toBase64(bytes: Uint8Array): string {\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(bytes).toString(\"base64\");\n }\n\n let binary = \"\";\n for (let i = 0; i < bytes.length; i += 1) {\n binary += String.fromCharCode(bytes[i]);\n }\n\n if (typeof btoa === \"undefined\") {\n throw new Error(\"btoa is not available in this environment\");\n }\n\n return btoa(binary);\n}\n\nfunction base64UrlEncodeBytes(bytes: Uint8Array): string {\n return toBase64(bytes).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/g, \"\");\n}\n\nfunction base64UrlEncodeString(value: string): string {\n return base64UrlEncodeBytes(encoder.encode(value));\n}\n\nfunction getSubtleCrypto(): SubtleCrypto | null {\n if (typeof globalThis !== \"undefined\" && globalThis.crypto && globalThis.crypto.subtle) {\n return globalThis.crypto.subtle;\n }\n\n return null;\n}\n\nasync function hmacSha256(data: string, secret: string): Promise<Uint8Array> {\n const subtle = getSubtleCrypto();\n\n if (!subtle) {\n throw new Error(\"Web Crypto API is not available; requires a Node 18+ or Edge runtime.\");\n }\n\n const key = await subtle.importKey(\n \"raw\",\n encoder.encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"]\n );\n\n const signature = await subtle.sign(\"HMAC\", key, encoder.encode(data));\n return new Uint8Array(signature);\n}\n\nexport async function signJwt(payload: Record<string, unknown>, secret: string): Promise<string> {\n const header = { alg: \"HS256\", typ: \"JWT\" };\n const encodedHeader = base64UrlEncodeString(JSON.stringify(header));\n const encodedPayload = base64UrlEncodeString(JSON.stringify(payload));\n const signingInput = `${encodedHeader}.${encodedPayload}`;\n const signature = await hmacSha256(signingInput, secret);\n\n return `${signingInput}.${base64UrlEncodeBytes(signature)}`;\n}\n","/**\n * Request context for automatic path resolution.\n *\n * In Node.js environments, this uses AsyncLocalStorage to store the current\n * request URL per async execution context. In edge runtimes or browsers,\n * it falls back to a simple variable (not request-scoped).\n */\n\ntype RequestInfo = {\n url?: string;\n path?: string;\n};\n\ninterface AsyncStorage {\n getStore: () => RequestInfo | undefined;\n run: <T>(store: RequestInfo, callback: () => T) => T;\n}\n\n// Try to use AsyncLocalStorage if available (Node.js 12.17+)\nlet asyncLocalStorage: AsyncStorage | null = null;\n\n// Fallback for environments without AsyncLocalStorage\nlet fallbackRequest: RequestInfo | undefined;\n\n// Create a fallback implementation\nfunction createFallbackStorage(): AsyncStorage {\n return {\n getStore: () => fallbackRequest,\n run: <T>(_store: RequestInfo, callback: () => T): T => {\n const prev = fallbackRequest;\n fallbackRequest = _store;\n try {\n return callback();\n } finally {\n fallbackRequest = prev;\n }\n },\n };\n}\n\n// Lazy initialization to avoid issues in environments where async_hooks isn't available\nfunction getAsyncLocalStorage(): AsyncStorage {\n if (asyncLocalStorage === null) {\n try {\n // Dynamic import to avoid bundler issues\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { AsyncLocalStorage } = require(\"async_hooks\");\n const storage = new AsyncLocalStorage();\n asyncLocalStorage = {\n getStore: () => storage.getStore() as RequestInfo | undefined,\n run: <T>(store: RequestInfo, callback: () => T): T =>\n storage.run(store, callback),\n };\n } catch {\n // AsyncLocalStorage not available, use fallback\n asyncLocalStorage = createFallbackStorage();\n }\n }\n return asyncLocalStorage!;\n}\n\n/**\n * Sets the current request context for automatic path resolution.\n * Call this in your middleware/handler before using OG Pilot.\n *\n * @example Express middleware\n * ```ts\n * app.use((req, res, next) => {\n * setCurrentRequest({ url: req.originalUrl });\n * next();\n * });\n * ```\n *\n * @example Next.js middleware\n * ```ts\n * export function middleware(request: NextRequest) {\n * setCurrentRequest({ url: request.nextUrl.pathname + request.nextUrl.search });\n * return NextResponse.next();\n * }\n * ```\n */\nexport function setCurrentRequest(request: RequestInfo): void {\n fallbackRequest = request;\n}\n\n/**\n * Clears the current request context.\n * Call this after the request is complete if using setCurrentRequest directly.\n */\nexport function clearCurrentRequest(): void {\n fallbackRequest = undefined;\n}\n\n/**\n * Runs a callback with the given request context.\n * The context is automatically cleared after the callback completes.\n * This is the preferred method for setting request context.\n *\n * @example Express middleware\n * ```ts\n * import { withRequestContext } from \"og-pilot-js\";\n *\n * app.use((req, res, next) => {\n * withRequestContext({ url: req.originalUrl }, () => {\n * next();\n * });\n * });\n * ```\n */\nexport function withRequestContext<T>(\n request: RequestInfo,\n callback: () => T\n): T {\n return getAsyncLocalStorage().run(request, callback);\n}\n\n/**\n * Gets the current request info from context.\n * @internal\n */\nexport function getCurrentRequest(): RequestInfo | undefined {\n // Try AsyncLocalStorage first, then fallback\n const store = getAsyncLocalStorage().getStore();\n return store ?? fallbackRequest;\n}\n\n/**\n * Gets the current request path from context or environment.\n * @internal\n */\nexport function getCurrentPath(): string | undefined {\n const request = getCurrentRequest();\n\n if (request?.path) {\n return request.path;\n }\n\n if (request?.url) {\n return extractPathFromUrl(request.url);\n }\n\n // Fallback to environment variables (similar to Ruby's env_fullpath)\n return getPathFromEnv();\n}\n\n// ============================================================================\n// Framework-specific helpers\n// ============================================================================\n\nexport type NextParamValue = string | string[] | undefined;\nexport type NextParams = Record<string, NextParamValue>;\nexport type NextSearchParams = Record<string, NextParamValue>;\nexport type NextMetadataProps = {\n params: NextParams | Promise<NextParams>;\n searchParams?: NextSearchParams | Promise<NextSearchParams>;\n};\n\n/**\n * Builds a URL path for Next.js App Router routes.\n *\n * Pass your route pattern (e.g. \"/products/[id]\") and Next.js params/searchParams.\n * This avoids middleware and fits naturally inside generateMetadata().\n *\n * @example app/products/[id]/page.tsx\n * ```ts\n * import { buildPathFromNextProps } from \"og-pilot-js\";\n *\n * export async function generateMetadata(props) {\n * const path = await buildPathFromNextProps(\"/products/[id]\", props);\n * // => \"/products/123?ref=twitter\"\n * }\n * ```\n */\nexport async function buildPathFromNextProps(\n routePattern: string,\n props: NextMetadataProps\n): Promise<string> {\n const params = await props.params;\n const searchParams = props.searchParams\n ? await props.searchParams\n : undefined;\n return buildPathFromNextParams(routePattern, params, searchParams);\n}\n\n/**\n * Builds a URL path for Next.js App Router routes from params/searchParams.\n *\n * @example\n * ```ts\n * const path = buildPathFromNextParams(\n * \"/blog/[...slug]\",\n * { slug: [\"2024\", \"launch\"] },\n * { ref: \"twitter\" }\n * );\n * // => \"/blog/2024/launch?ref=twitter\"\n * ```\n */\nexport function buildPathFromNextParams(\n routePattern: string,\n params: NextParams,\n searchParams?: NextSearchParams\n): string {\n const segments = routePattern\n .split(\"/\")\n .filter((segment) => segment.length > 0);\n const builtSegments: string[] = [];\n\n for (const segment of segments) {\n const catchAllMatch = segment.match(/^\\[\\.\\.\\.(.+)\\]$/);\n const optionalCatchAllMatch = segment.match(/^\\[\\[\\.\\.\\.(.+)\\]\\]$/);\n const paramMatch = segment.match(/^\\[(.+)\\]$/);\n\n if (optionalCatchAllMatch) {\n const key = optionalCatchAllMatch[1];\n const value = params[key];\n if (value === undefined) {\n continue;\n }\n if (Array.isArray(value)) {\n builtSegments.push(...value);\n } else {\n builtSegments.push(value);\n }\n continue;\n }\n\n if (catchAllMatch) {\n const key = catchAllMatch[1];\n const value = params[key];\n if (value === undefined) {\n continue;\n }\n if (Array.isArray(value)) {\n builtSegments.push(...value);\n } else {\n builtSegments.push(value);\n }\n continue;\n }\n\n if (paramMatch) {\n const key = paramMatch[1];\n const value = params[key];\n if (value === undefined) {\n continue;\n }\n if (Array.isArray(value)) {\n builtSegments.push(value.join(\"/\"));\n } else {\n builtSegments.push(value);\n }\n continue;\n }\n\n builtSegments.push(segment);\n }\n\n const path = `/${builtSegments.join(\"/\")}`;\n const query = serializeSearchParams(searchParams);\n return query.length > 0 ? `${path}?${query}` : path;\n}\n\n/**\n * Creates an Express/Connect middleware that automatically sets request context.\n *\n * @example Express\n * ```ts\n * import express from \"express\";\n * import { createExpressMiddleware } from \"og-pilot-js\";\n *\n * const app = express();\n * app.use(createExpressMiddleware());\n * ```\n */\nexport function createExpressMiddleware(): ExpressMiddleware {\n return (req, _res, next) => {\n setCurrentRequest({\n url: req.originalUrl || req.url,\n path: req.originalUrl || req.url,\n });\n next();\n };\n}\n\n/**\n * Helper to extract path from an Express/Node.js request object.\n */\nexport function getPathFromExpressRequest(req: ExpressRequest): string {\n return req.originalUrl || req.url || \"/\";\n}\n\n// Type definitions for framework compatibility\n// These are minimal to avoid requiring framework dependencies\n\ninterface ExpressRequest {\n originalUrl?: string;\n url?: string;\n}\n\ntype ExpressMiddleware = (\n req: ExpressRequest,\n res: unknown,\n next: () => void\n) => void;\n\nfunction extractPathFromUrl(url: string): string {\n // Handle full URLs\n if (url.startsWith(\"http://\") || url.startsWith(\"https://\")) {\n try {\n const parsed = new URL(url);\n return parsed.pathname + parsed.search;\n } catch {\n return url;\n }\n }\n\n return url;\n}\n\nfunction serializeSearchParams(\n searchParams?: NextSearchParams | URLSearchParams\n): string {\n if (!searchParams) {\n return \"\";\n }\n\n if (searchParams instanceof URLSearchParams) {\n return searchParams.toString();\n }\n\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(searchParams)) {\n if (value === undefined) {\n continue;\n }\n if (Array.isArray(value)) {\n for (const entry of value) {\n params.append(key, entry);\n }\n } else {\n params.append(key, value);\n }\n }\n\n return params.toString();\n}\n\nfunction getPathFromEnv(): string | undefined {\n if (typeof process === \"undefined\" || !process.env) {\n return undefined;\n }\n\n const env = process.env;\n\n // Check various environment variables (similar to Ruby implementation)\n const requestUri = env.REQUEST_URI;\n if (requestUri && requestUri.length > 0) {\n return requestUri;\n }\n\n const originalFullpath = env.ORIGINAL_FULLPATH;\n if (originalFullpath && originalFullpath.length > 0) {\n return originalFullpath;\n }\n\n const pathInfo = env.PATH_INFO;\n if (pathInfo && pathInfo.length > 0) {\n const queryString = env.QUERY_STRING ?? \"\";\n return queryString.length > 0 ? `${pathInfo}?${queryString}` : pathInfo;\n }\n\n const requestPath = env.REQUEST_PATH;\n if (requestPath && requestPath.length > 0) {\n return requestPath;\n }\n\n return undefined;\n}\n","import { Configuration, OgPilotConfigOptions } from \"./config\";\nimport { ConfigurationError, RequestError } from \"./errors\";\nimport { signJwt } from \"./jwt\";\nimport { getCurrentPath } from \"./request-context\";\n\nexport interface CreateImageOptions {\n json?: boolean;\n iat?: number | Date;\n headers?: Record<string, string>;\n /**\n * When true, forces the path to \"/\" regardless of the current request.\n * Useful for generating default/fallback OG images.\n */\n default?: boolean;\n}\n\nconst ENDPOINT_PATH = \"/api/v1/images\";\n\nexport class Client {\n private config: Configuration;\n\n constructor(config: Configuration | OgPilotConfigOptions = {}) {\n this.config =\n config instanceof Configuration ? config : new Configuration(config);\n }\n\n async createImage(\n params: Record<string, unknown> = {},\n options: CreateImageOptions = {}\n ): Promise<unknown> {\n const {\n json = false,\n iat,\n headers = {},\n default: useDefault = false,\n } = options;\n\n // Always include a path; manual overrides win, otherwise resolve from the current request.\n const resolvedParams = { ...params };\n const manualPath = resolvedParams.path;\n delete resolvedParams.path;\n resolvedParams.path = this.resolvePath(manualPath, useDefault);\n\n const url = await this.buildUrl(resolvedParams, iat);\n const response = await this.request(url, json, headers);\n\n if (json) {\n const body = await response.text();\n return JSON.parse(body);\n }\n\n return response.headers.get(\"location\") ?? response.url ?? url.toString();\n }\n\n /**\n * Resolves the path parameter for the request.\n * Priority: manual path > current request path > \"/\"\n */\n private resolvePath(manualPath: unknown, useDefault: boolean): string {\n // Manual path always wins if provided\n if (manualPath !== undefined && manualPath !== null) {\n const pathStr = String(manualPath).trim();\n if (pathStr.length > 0) {\n return this.normalizePath(pathStr);\n }\n }\n\n // If default is true, return \"/\"\n if (useDefault) {\n return \"/\";\n }\n\n // Try to get path from current request context\n const currentPath = getCurrentPath();\n return this.normalizePath(currentPath);\n }\n\n /**\n * Normalizes a path to ensure it starts with \"/\" and handles full URLs.\n */\n private normalizePath(path: string | undefined | null): string {\n if (path === undefined || path === null) {\n return \"/\";\n }\n\n let cleaned = String(path).trim();\n if (cleaned.length === 0) {\n return \"/\";\n }\n\n // Extract path from full URLs\n if (cleaned.startsWith(\"http://\") || cleaned.startsWith(\"https://\")) {\n try {\n const url = new URL(cleaned);\n cleaned = url.pathname + url.search;\n } catch {\n // Keep as-is if URL parsing fails\n }\n }\n\n // Ensure path starts with \"/\"\n if (!cleaned.startsWith(\"/\")) {\n cleaned = \"/\" + cleaned;\n }\n\n return cleaned;\n }\n\n private async request(\n url: URL,\n json: boolean,\n headers: Record<string, string>\n ): Promise<Response> {\n const fetchImpl =\n this.config.fetch ?? (typeof fetch !== \"undefined\" ? fetch : undefined);\n\n if (!fetchImpl) {\n throw new ConfigurationError(\n \"Fetch API is not available; provide a fetch implementation in the configuration.\"\n );\n }\n\n const requestHeaders = new Headers();\n if (json) {\n requestHeaders.set(\"Accept\", \"application/json\");\n }\n\n Object.entries(headers).forEach(([key, value]) => {\n requestHeaders.set(key, value);\n });\n\n const timeoutMs = this.totalTimeoutMs();\n const controller = new AbortController();\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n if (timeoutMs && timeoutMs > 0) {\n timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n }\n\n try {\n const response = await fetchImpl(url.toString(), {\n method: \"GET\",\n headers: requestHeaders,\n redirect: \"manual\",\n signal: controller.signal,\n });\n\n if (response.status >= 400) {\n const body = await response.text().catch(() => \"\");\n throw new RequestError(\n `OG Pilot request failed with status ${response.status}: ${body}`,\n response.status\n );\n }\n\n return response;\n } catch (error) {\n if (error instanceof RequestError) {\n throw error;\n }\n\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new RequestError(`OG Pilot request timed out: ${error.message}`);\n }\n\n if (error instanceof Error) {\n throw new RequestError(`OG Pilot request failed: ${error.message}`);\n }\n\n throw new RequestError(\"OG Pilot request failed.\");\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n }\n\n private async buildUrl(\n params: Record<string, unknown>,\n iat?: number | Date\n ): Promise<URL> {\n const payload = this.buildPayload(params, iat);\n const token = await signJwt(payload, this.apiKey());\n const url = new URL(ENDPOINT_PATH, this.config.baseUrl);\n url.searchParams.set(\"token\", token);\n return url;\n }\n\n private buildPayload(\n params: Record<string, unknown>,\n iat?: number | Date\n ): Record<string, unknown> {\n const payload: Record<string, unknown> = { ...params };\n\n if (iat !== undefined && iat !== null) {\n payload.iat = normalizeIat(iat);\n }\n\n if (payload.iss === undefined || payload.iss === null) {\n payload.iss = this.domain();\n }\n\n if (payload.sub === undefined || payload.sub === null) {\n payload.sub = this.apiKeyPrefix();\n }\n\n this.validatePayload(payload);\n return payload;\n }\n\n private validatePayload(payload: Record<string, unknown>): void {\n if (\n payload.iss === undefined ||\n payload.iss === null ||\n String(payload.iss).length === 0\n ) {\n throw new ConfigurationError(\"OG Pilot domain is missing\");\n }\n\n if (\n payload.sub === undefined ||\n payload.sub === null ||\n String(payload.sub).length === 0\n ) {\n throw new ConfigurationError(\"OG Pilot API key prefix is missing\");\n }\n\n if (\n payload.title === undefined ||\n payload.title === null ||\n String(payload.title).length === 0\n ) {\n throw new Error(\"OG Pilot title is required\");\n }\n }\n\n private apiKey(): string {\n if (this.config.apiKey !== undefined && this.config.apiKey !== null) {\n return this.config.apiKey;\n }\n\n throw new ConfigurationError(\"OG Pilot API key is missing\");\n }\n\n private domain(): string {\n if (this.config.domain !== undefined && this.config.domain !== null) {\n return this.config.domain;\n }\n\n throw new ConfigurationError(\"OG Pilot domain is missing\");\n }\n\n private apiKeyPrefix(): string {\n return this.apiKey().slice(0, 8);\n }\n\n private totalTimeoutMs(): number | undefined {\n const openTimeoutMs = this.config.openTimeoutMs;\n const readTimeoutMs = this.config.readTimeoutMs;\n\n if (openTimeoutMs === undefined && readTimeoutMs === undefined) {\n return undefined;\n }\n\n const open = typeof openTimeoutMs === \"number\" ? openTimeoutMs : 0;\n const read = typeof readTimeoutMs === \"number\" ? readTimeoutMs : 0;\n return open + read;\n }\n}\n\nfunction normalizeIat(iat: number | Date): number {\n if (iat instanceof Date) {\n return Math.floor(iat.getTime() / 1000);\n }\n\n if (iat > 100000000000) {\n return Math.floor(iat / 1000);\n }\n\n return Math.floor(iat);\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -114,6 +114,66 @@ declare function clearCurrentRequest(): void;
|
|
|
114
114
|
* ```
|
|
115
115
|
*/
|
|
116
116
|
declare function withRequestContext<T>(request: RequestInfo, callback: () => T): T;
|
|
117
|
+
type NextParamValue = string | string[] | undefined;
|
|
118
|
+
type NextParams = Record<string, NextParamValue>;
|
|
119
|
+
type NextSearchParams = Record<string, NextParamValue>;
|
|
120
|
+
type NextMetadataProps = {
|
|
121
|
+
params: NextParams | Promise<NextParams>;
|
|
122
|
+
searchParams?: NextSearchParams | Promise<NextSearchParams>;
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Builds a URL path for Next.js App Router routes.
|
|
126
|
+
*
|
|
127
|
+
* Pass your route pattern (e.g. "/products/[id]") and Next.js params/searchParams.
|
|
128
|
+
* This avoids middleware and fits naturally inside generateMetadata().
|
|
129
|
+
*
|
|
130
|
+
* @example app/products/[id]/page.tsx
|
|
131
|
+
* ```ts
|
|
132
|
+
* import { buildPathFromNextProps } from "og-pilot-js";
|
|
133
|
+
*
|
|
134
|
+
* export async function generateMetadata(props) {
|
|
135
|
+
* const path = await buildPathFromNextProps("/products/[id]", props);
|
|
136
|
+
* // => "/products/123?ref=twitter"
|
|
137
|
+
* }
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
declare function buildPathFromNextProps(routePattern: string, props: NextMetadataProps): Promise<string>;
|
|
141
|
+
/**
|
|
142
|
+
* Builds a URL path for Next.js App Router routes from params/searchParams.
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```ts
|
|
146
|
+
* const path = buildPathFromNextParams(
|
|
147
|
+
* "/blog/[...slug]",
|
|
148
|
+
* { slug: ["2024", "launch"] },
|
|
149
|
+
* { ref: "twitter" }
|
|
150
|
+
* );
|
|
151
|
+
* // => "/blog/2024/launch?ref=twitter"
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
declare function buildPathFromNextParams(routePattern: string, params: NextParams, searchParams?: NextSearchParams): string;
|
|
155
|
+
/**
|
|
156
|
+
* Creates an Express/Connect middleware that automatically sets request context.
|
|
157
|
+
*
|
|
158
|
+
* @example Express
|
|
159
|
+
* ```ts
|
|
160
|
+
* import express from "express";
|
|
161
|
+
* import { createExpressMiddleware } from "og-pilot-js";
|
|
162
|
+
*
|
|
163
|
+
* const app = express();
|
|
164
|
+
* app.use(createExpressMiddleware());
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
declare function createExpressMiddleware(): ExpressMiddleware;
|
|
168
|
+
/**
|
|
169
|
+
* Helper to extract path from an Express/Node.js request object.
|
|
170
|
+
*/
|
|
171
|
+
declare function getPathFromExpressRequest(req: ExpressRequest): string;
|
|
172
|
+
interface ExpressRequest {
|
|
173
|
+
originalUrl?: string;
|
|
174
|
+
url?: string;
|
|
175
|
+
}
|
|
176
|
+
type ExpressMiddleware = (req: ExpressRequest, res: unknown, next: () => void) => void;
|
|
117
177
|
|
|
118
178
|
declare const configure: (updater: (config: Configuration) => void) => Configuration;
|
|
119
179
|
declare const resetConfig: () => void;
|
|
@@ -131,10 +191,14 @@ declare const OgPilot: {
|
|
|
131
191
|
setCurrentRequest: typeof setCurrentRequest;
|
|
132
192
|
clearCurrentRequest: typeof clearCurrentRequest;
|
|
133
193
|
withRequestContext: typeof withRequestContext;
|
|
194
|
+
createExpressMiddleware: typeof createExpressMiddleware;
|
|
195
|
+
getPathFromExpressRequest: typeof getPathFromExpressRequest;
|
|
196
|
+
buildPathFromNextProps: typeof buildPathFromNextProps;
|
|
197
|
+
buildPathFromNextParams: typeof buildPathFromNextParams;
|
|
134
198
|
Configuration: typeof Configuration;
|
|
135
199
|
ConfigurationError: typeof ConfigurationError;
|
|
136
200
|
OgPilotError: typeof OgPilotError;
|
|
137
201
|
RequestError: typeof RequestError;
|
|
138
202
|
};
|
|
139
203
|
|
|
140
|
-
export { Client, Configuration, ConfigurationError, type CreateImageOptions, type OgPilotConfigOptions, OgPilotError, RequestError, clearCurrentRequest, client, configure, createClient, createImage, OgPilot as default, getConfig, resetConfig, setCurrentRequest, withRequestContext };
|
|
204
|
+
export { Client, Configuration, ConfigurationError, type CreateImageOptions, type NextMetadataProps, type NextParams, type NextSearchParams, type OgPilotConfigOptions, OgPilotError, RequestError, buildPathFromNextParams, buildPathFromNextProps, clearCurrentRequest, client, configure, createClient, createExpressMiddleware, createImage, OgPilot as default, getConfig, getPathFromExpressRequest, resetConfig, setCurrentRequest, withRequestContext };
|
package/dist/index.d.ts
CHANGED
|
@@ -114,6 +114,66 @@ declare function clearCurrentRequest(): void;
|
|
|
114
114
|
* ```
|
|
115
115
|
*/
|
|
116
116
|
declare function withRequestContext<T>(request: RequestInfo, callback: () => T): T;
|
|
117
|
+
type NextParamValue = string | string[] | undefined;
|
|
118
|
+
type NextParams = Record<string, NextParamValue>;
|
|
119
|
+
type NextSearchParams = Record<string, NextParamValue>;
|
|
120
|
+
type NextMetadataProps = {
|
|
121
|
+
params: NextParams | Promise<NextParams>;
|
|
122
|
+
searchParams?: NextSearchParams | Promise<NextSearchParams>;
|
|
123
|
+
};
|
|
124
|
+
/**
|
|
125
|
+
* Builds a URL path for Next.js App Router routes.
|
|
126
|
+
*
|
|
127
|
+
* Pass your route pattern (e.g. "/products/[id]") and Next.js params/searchParams.
|
|
128
|
+
* This avoids middleware and fits naturally inside generateMetadata().
|
|
129
|
+
*
|
|
130
|
+
* @example app/products/[id]/page.tsx
|
|
131
|
+
* ```ts
|
|
132
|
+
* import { buildPathFromNextProps } from "og-pilot-js";
|
|
133
|
+
*
|
|
134
|
+
* export async function generateMetadata(props) {
|
|
135
|
+
* const path = await buildPathFromNextProps("/products/[id]", props);
|
|
136
|
+
* // => "/products/123?ref=twitter"
|
|
137
|
+
* }
|
|
138
|
+
* ```
|
|
139
|
+
*/
|
|
140
|
+
declare function buildPathFromNextProps(routePattern: string, props: NextMetadataProps): Promise<string>;
|
|
141
|
+
/**
|
|
142
|
+
* Builds a URL path for Next.js App Router routes from params/searchParams.
|
|
143
|
+
*
|
|
144
|
+
* @example
|
|
145
|
+
* ```ts
|
|
146
|
+
* const path = buildPathFromNextParams(
|
|
147
|
+
* "/blog/[...slug]",
|
|
148
|
+
* { slug: ["2024", "launch"] },
|
|
149
|
+
* { ref: "twitter" }
|
|
150
|
+
* );
|
|
151
|
+
* // => "/blog/2024/launch?ref=twitter"
|
|
152
|
+
* ```
|
|
153
|
+
*/
|
|
154
|
+
declare function buildPathFromNextParams(routePattern: string, params: NextParams, searchParams?: NextSearchParams): string;
|
|
155
|
+
/**
|
|
156
|
+
* Creates an Express/Connect middleware that automatically sets request context.
|
|
157
|
+
*
|
|
158
|
+
* @example Express
|
|
159
|
+
* ```ts
|
|
160
|
+
* import express from "express";
|
|
161
|
+
* import { createExpressMiddleware } from "og-pilot-js";
|
|
162
|
+
*
|
|
163
|
+
* const app = express();
|
|
164
|
+
* app.use(createExpressMiddleware());
|
|
165
|
+
* ```
|
|
166
|
+
*/
|
|
167
|
+
declare function createExpressMiddleware(): ExpressMiddleware;
|
|
168
|
+
/**
|
|
169
|
+
* Helper to extract path from an Express/Node.js request object.
|
|
170
|
+
*/
|
|
171
|
+
declare function getPathFromExpressRequest(req: ExpressRequest): string;
|
|
172
|
+
interface ExpressRequest {
|
|
173
|
+
originalUrl?: string;
|
|
174
|
+
url?: string;
|
|
175
|
+
}
|
|
176
|
+
type ExpressMiddleware = (req: ExpressRequest, res: unknown, next: () => void) => void;
|
|
117
177
|
|
|
118
178
|
declare const configure: (updater: (config: Configuration) => void) => Configuration;
|
|
119
179
|
declare const resetConfig: () => void;
|
|
@@ -131,10 +191,14 @@ declare const OgPilot: {
|
|
|
131
191
|
setCurrentRequest: typeof setCurrentRequest;
|
|
132
192
|
clearCurrentRequest: typeof clearCurrentRequest;
|
|
133
193
|
withRequestContext: typeof withRequestContext;
|
|
194
|
+
createExpressMiddleware: typeof createExpressMiddleware;
|
|
195
|
+
getPathFromExpressRequest: typeof getPathFromExpressRequest;
|
|
196
|
+
buildPathFromNextProps: typeof buildPathFromNextProps;
|
|
197
|
+
buildPathFromNextParams: typeof buildPathFromNextParams;
|
|
134
198
|
Configuration: typeof Configuration;
|
|
135
199
|
ConfigurationError: typeof ConfigurationError;
|
|
136
200
|
OgPilotError: typeof OgPilotError;
|
|
137
201
|
RequestError: typeof RequestError;
|
|
138
202
|
};
|
|
139
203
|
|
|
140
|
-
export { Client, Configuration, ConfigurationError, type CreateImageOptions, type OgPilotConfigOptions, OgPilotError, RequestError, clearCurrentRequest, client, configure, createClient, createImage, OgPilot as default, getConfig, resetConfig, setCurrentRequest, withRequestContext };
|
|
204
|
+
export { Client, Configuration, ConfigurationError, type CreateImageOptions, type NextMetadataProps, type NextParams, type NextSearchParams, type OgPilotConfigOptions, OgPilotError, RequestError, buildPathFromNextParams, buildPathFromNextProps, clearCurrentRequest, client, configure, createClient, createExpressMiddleware, createImage, OgPilot as default, getConfig, getPathFromExpressRequest, resetConfig, setCurrentRequest, withRequestContext };
|
package/dist/index.js
CHANGED
|
@@ -151,6 +151,75 @@ function getCurrentPath() {
|
|
|
151
151
|
}
|
|
152
152
|
return getPathFromEnv();
|
|
153
153
|
}
|
|
154
|
+
async function buildPathFromNextProps(routePattern, props) {
|
|
155
|
+
const params = await props.params;
|
|
156
|
+
const searchParams = props.searchParams ? await props.searchParams : void 0;
|
|
157
|
+
return buildPathFromNextParams(routePattern, params, searchParams);
|
|
158
|
+
}
|
|
159
|
+
function buildPathFromNextParams(routePattern, params, searchParams) {
|
|
160
|
+
const segments = routePattern.split("/").filter((segment) => segment.length > 0);
|
|
161
|
+
const builtSegments = [];
|
|
162
|
+
for (const segment of segments) {
|
|
163
|
+
const catchAllMatch = segment.match(/^\[\.\.\.(.+)\]$/);
|
|
164
|
+
const optionalCatchAllMatch = segment.match(/^\[\[\.\.\.(.+)\]\]$/);
|
|
165
|
+
const paramMatch = segment.match(/^\[(.+)\]$/);
|
|
166
|
+
if (optionalCatchAllMatch) {
|
|
167
|
+
const key = optionalCatchAllMatch[1];
|
|
168
|
+
const value = params[key];
|
|
169
|
+
if (value === void 0) {
|
|
170
|
+
continue;
|
|
171
|
+
}
|
|
172
|
+
if (Array.isArray(value)) {
|
|
173
|
+
builtSegments.push(...value);
|
|
174
|
+
} else {
|
|
175
|
+
builtSegments.push(value);
|
|
176
|
+
}
|
|
177
|
+
continue;
|
|
178
|
+
}
|
|
179
|
+
if (catchAllMatch) {
|
|
180
|
+
const key = catchAllMatch[1];
|
|
181
|
+
const value = params[key];
|
|
182
|
+
if (value === void 0) {
|
|
183
|
+
continue;
|
|
184
|
+
}
|
|
185
|
+
if (Array.isArray(value)) {
|
|
186
|
+
builtSegments.push(...value);
|
|
187
|
+
} else {
|
|
188
|
+
builtSegments.push(value);
|
|
189
|
+
}
|
|
190
|
+
continue;
|
|
191
|
+
}
|
|
192
|
+
if (paramMatch) {
|
|
193
|
+
const key = paramMatch[1];
|
|
194
|
+
const value = params[key];
|
|
195
|
+
if (value === void 0) {
|
|
196
|
+
continue;
|
|
197
|
+
}
|
|
198
|
+
if (Array.isArray(value)) {
|
|
199
|
+
builtSegments.push(value.join("/"));
|
|
200
|
+
} else {
|
|
201
|
+
builtSegments.push(value);
|
|
202
|
+
}
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
builtSegments.push(segment);
|
|
206
|
+
}
|
|
207
|
+
const path = `/${builtSegments.join("/")}`;
|
|
208
|
+
const query = serializeSearchParams(searchParams);
|
|
209
|
+
return query.length > 0 ? `${path}?${query}` : path;
|
|
210
|
+
}
|
|
211
|
+
function createExpressMiddleware() {
|
|
212
|
+
return (req, _res, next) => {
|
|
213
|
+
setCurrentRequest({
|
|
214
|
+
url: req.originalUrl || req.url,
|
|
215
|
+
path: req.originalUrl || req.url
|
|
216
|
+
});
|
|
217
|
+
next();
|
|
218
|
+
};
|
|
219
|
+
}
|
|
220
|
+
function getPathFromExpressRequest(req) {
|
|
221
|
+
return req.originalUrl || req.url || "/";
|
|
222
|
+
}
|
|
154
223
|
function extractPathFromUrl(url) {
|
|
155
224
|
if (url.startsWith("http://") || url.startsWith("https://")) {
|
|
156
225
|
try {
|
|
@@ -162,6 +231,28 @@ function extractPathFromUrl(url) {
|
|
|
162
231
|
}
|
|
163
232
|
return url;
|
|
164
233
|
}
|
|
234
|
+
function serializeSearchParams(searchParams) {
|
|
235
|
+
if (!searchParams) {
|
|
236
|
+
return "";
|
|
237
|
+
}
|
|
238
|
+
if (searchParams instanceof URLSearchParams) {
|
|
239
|
+
return searchParams.toString();
|
|
240
|
+
}
|
|
241
|
+
const params = new URLSearchParams();
|
|
242
|
+
for (const [key, value] of Object.entries(searchParams)) {
|
|
243
|
+
if (value === void 0) {
|
|
244
|
+
continue;
|
|
245
|
+
}
|
|
246
|
+
if (Array.isArray(value)) {
|
|
247
|
+
for (const entry of value) {
|
|
248
|
+
params.append(key, entry);
|
|
249
|
+
}
|
|
250
|
+
} else {
|
|
251
|
+
params.append(key, value);
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
return params.toString();
|
|
255
|
+
}
|
|
165
256
|
function getPathFromEnv() {
|
|
166
257
|
if (typeof process === "undefined" || !process.env) {
|
|
167
258
|
return void 0;
|
|
@@ -395,6 +486,10 @@ var OgPilot = {
|
|
|
395
486
|
setCurrentRequest,
|
|
396
487
|
clearCurrentRequest,
|
|
397
488
|
withRequestContext,
|
|
489
|
+
createExpressMiddleware,
|
|
490
|
+
getPathFromExpressRequest,
|
|
491
|
+
buildPathFromNextProps,
|
|
492
|
+
buildPathFromNextParams,
|
|
398
493
|
Configuration,
|
|
399
494
|
ConfigurationError,
|
|
400
495
|
OgPilotError,
|
|
@@ -407,13 +502,17 @@ export {
|
|
|
407
502
|
ConfigurationError,
|
|
408
503
|
OgPilotError,
|
|
409
504
|
RequestError,
|
|
505
|
+
buildPathFromNextParams,
|
|
506
|
+
buildPathFromNextProps,
|
|
410
507
|
clearCurrentRequest,
|
|
411
508
|
client,
|
|
412
509
|
configure,
|
|
413
510
|
createClient,
|
|
511
|
+
createExpressMiddleware,
|
|
414
512
|
createImage,
|
|
415
513
|
index_default as default,
|
|
416
514
|
getConfig,
|
|
515
|
+
getPathFromExpressRequest,
|
|
417
516
|
resetConfig,
|
|
418
517
|
setCurrentRequest,
|
|
419
518
|
withRequestContext
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/config.ts","../src/errors.ts","../src/jwt.ts","../src/request-context.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["export interface OgPilotConfigOptions {\n apiKey?: string;\n domain?: string;\n baseUrl?: string;\n openTimeoutMs?: number;\n readTimeoutMs?: number;\n fetch?: typeof fetch;\n}\n\nconst DEFAULT_BASE_URL = \"https://ogpilot.com\";\n\nfunction readEnv(key: string): string | undefined {\n if (typeof process !== \"undefined\" && process.env) {\n return process.env[key];\n }\n\n return undefined;\n}\n\nexport class Configuration {\n apiKey?: string;\n domain?: string;\n baseUrl: string;\n openTimeoutMs?: number;\n readTimeoutMs?: number;\n fetch?: typeof fetch;\n\n constructor(options: OgPilotConfigOptions = {}) {\n this.apiKey = options.apiKey ?? readEnv(\"OG_PILOT_API_KEY\");\n this.domain = options.domain ?? readEnv(\"OG_PILOT_DOMAIN\");\n this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;\n this.openTimeoutMs = options.openTimeoutMs ?? 5000;\n this.readTimeoutMs = options.readTimeoutMs ?? 10000;\n this.fetch = options.fetch;\n }\n}\n","export class OgPilotError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"OgPilotError\";\n }\n}\n\nexport class ConfigurationError extends OgPilotError {\n constructor(message: string) {\n super(message);\n this.name = \"ConfigurationError\";\n }\n}\n\nexport class RequestError extends OgPilotError {\n status?: number;\n\n constructor(message: string, status?: number) {\n super(message);\n this.name = \"RequestError\";\n this.status = status;\n }\n}\n","const encoder = new TextEncoder();\n\nfunction toBase64(bytes: Uint8Array): string {\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(bytes).toString(\"base64\");\n }\n\n let binary = \"\";\n for (let i = 0; i < bytes.length; i += 1) {\n binary += String.fromCharCode(bytes[i]);\n }\n\n if (typeof btoa === \"undefined\") {\n throw new Error(\"btoa is not available in this environment\");\n }\n\n return btoa(binary);\n}\n\nfunction base64UrlEncodeBytes(bytes: Uint8Array): string {\n return toBase64(bytes).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/g, \"\");\n}\n\nfunction base64UrlEncodeString(value: string): string {\n return base64UrlEncodeBytes(encoder.encode(value));\n}\n\nfunction getSubtleCrypto(): SubtleCrypto | null {\n if (typeof globalThis !== \"undefined\" && globalThis.crypto && globalThis.crypto.subtle) {\n return globalThis.crypto.subtle;\n }\n\n return null;\n}\n\nasync function hmacSha256(data: string, secret: string): Promise<Uint8Array> {\n const subtle = getSubtleCrypto();\n\n if (!subtle) {\n throw new Error(\"Web Crypto API is not available; requires a Node 18+ or Edge runtime.\");\n }\n\n const key = await subtle.importKey(\n \"raw\",\n encoder.encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"]\n );\n\n const signature = await subtle.sign(\"HMAC\", key, encoder.encode(data));\n return new Uint8Array(signature);\n}\n\nexport async function signJwt(payload: Record<string, unknown>, secret: string): Promise<string> {\n const header = { alg: \"HS256\", typ: \"JWT\" };\n const encodedHeader = base64UrlEncodeString(JSON.stringify(header));\n const encodedPayload = base64UrlEncodeString(JSON.stringify(payload));\n const signingInput = `${encodedHeader}.${encodedPayload}`;\n const signature = await hmacSha256(signingInput, secret);\n\n return `${signingInput}.${base64UrlEncodeBytes(signature)}`;\n}\n","/**\n * Request context for automatic path resolution.\n *\n * In Node.js environments, this uses AsyncLocalStorage to store the current\n * request URL per async execution context. In edge runtimes or browsers,\n * it falls back to a simple variable (not request-scoped).\n */\n\ntype RequestInfo = {\n url?: string;\n path?: string;\n};\n\ninterface AsyncStorage {\n getStore: () => RequestInfo | undefined;\n run: <T>(store: RequestInfo, callback: () => T) => T;\n}\n\n// Try to use AsyncLocalStorage if available (Node.js 12.17+)\nlet asyncLocalStorage: AsyncStorage | null = null;\n\n// Fallback for environments without AsyncLocalStorage\nlet fallbackRequest: RequestInfo | undefined;\n\n// Create a fallback implementation\nfunction createFallbackStorage(): AsyncStorage {\n return {\n getStore: () => fallbackRequest,\n run: <T>(_store: RequestInfo, callback: () => T): T => {\n const prev = fallbackRequest;\n fallbackRequest = _store;\n try {\n return callback();\n } finally {\n fallbackRequest = prev;\n }\n },\n };\n}\n\n// Lazy initialization to avoid issues in environments where async_hooks isn't available\nfunction getAsyncLocalStorage(): AsyncStorage {\n if (asyncLocalStorage === null) {\n try {\n // Dynamic import to avoid bundler issues\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { AsyncLocalStorage } = require(\"async_hooks\");\n const storage = new AsyncLocalStorage();\n asyncLocalStorage = {\n getStore: () => storage.getStore() as RequestInfo | undefined,\n run: <T>(store: RequestInfo, callback: () => T): T =>\n storage.run(store, callback),\n };\n } catch {\n // AsyncLocalStorage not available, use fallback\n asyncLocalStorage = createFallbackStorage();\n }\n }\n return asyncLocalStorage!;\n}\n\n/**\n * Sets the current request context for automatic path resolution.\n * Call this in your middleware/handler before using OG Pilot.\n *\n * @example Express middleware\n * ```ts\n * app.use((req, res, next) => {\n * setCurrentRequest({ url: req.originalUrl });\n * next();\n * });\n * ```\n *\n * @example Next.js middleware\n * ```ts\n * export function middleware(request: NextRequest) {\n * setCurrentRequest({ url: request.nextUrl.pathname + request.nextUrl.search });\n * return NextResponse.next();\n * }\n * ```\n */\nexport function setCurrentRequest(request: RequestInfo): void {\n fallbackRequest = request;\n}\n\n/**\n * Clears the current request context.\n * Call this after the request is complete if using setCurrentRequest directly.\n */\nexport function clearCurrentRequest(): void {\n fallbackRequest = undefined;\n}\n\n/**\n * Runs a callback with the given request context.\n * The context is automatically cleared after the callback completes.\n * This is the preferred method for setting request context.\n *\n * @example Express middleware\n * ```ts\n * import { withRequestContext } from \"og-pilot-js\";\n *\n * app.use((req, res, next) => {\n * withRequestContext({ url: req.originalUrl }, () => {\n * next();\n * });\n * });\n * ```\n */\nexport function withRequestContext<T>(\n request: RequestInfo,\n callback: () => T\n): T {\n return getAsyncLocalStorage().run(request, callback);\n}\n\n/**\n * Gets the current request info from context.\n * @internal\n */\nexport function getCurrentRequest(): RequestInfo | undefined {\n // Try AsyncLocalStorage first, then fallback\n const store = getAsyncLocalStorage().getStore();\n return store ?? fallbackRequest;\n}\n\n/**\n * Gets the current request path from context or environment.\n * @internal\n */\nexport function getCurrentPath(): string | undefined {\n const request = getCurrentRequest();\n\n if (request?.path) {\n return request.path;\n }\n\n if (request?.url) {\n return extractPathFromUrl(request.url);\n }\n\n // Fallback to environment variables (similar to Ruby's env_fullpath)\n return getPathFromEnv();\n}\n\nfunction extractPathFromUrl(url: string): string {\n // Handle full URLs\n if (url.startsWith(\"http://\") || url.startsWith(\"https://\")) {\n try {\n const parsed = new URL(url);\n return parsed.pathname + parsed.search;\n } catch {\n return url;\n }\n }\n\n return url;\n}\n\nfunction getPathFromEnv(): string | undefined {\n if (typeof process === \"undefined\" || !process.env) {\n return undefined;\n }\n\n const env = process.env;\n\n // Check various environment variables (similar to Ruby implementation)\n const requestUri = env.REQUEST_URI;\n if (requestUri && requestUri.length > 0) {\n return requestUri;\n }\n\n const originalFullpath = env.ORIGINAL_FULLPATH;\n if (originalFullpath && originalFullpath.length > 0) {\n return originalFullpath;\n }\n\n const pathInfo = env.PATH_INFO;\n if (pathInfo && pathInfo.length > 0) {\n const queryString = env.QUERY_STRING ?? \"\";\n return queryString.length > 0 ? `${pathInfo}?${queryString}` : pathInfo;\n }\n\n const requestPath = env.REQUEST_PATH;\n if (requestPath && requestPath.length > 0) {\n return requestPath;\n }\n\n return undefined;\n}\n","import { Configuration, OgPilotConfigOptions } from \"./config\";\nimport { ConfigurationError, RequestError } from \"./errors\";\nimport { signJwt } from \"./jwt\";\nimport { getCurrentPath } from \"./request-context\";\n\nexport interface CreateImageOptions {\n json?: boolean;\n iat?: number | Date;\n headers?: Record<string, string>;\n /**\n * When true, forces the path to \"/\" regardless of the current request.\n * Useful for generating default/fallback OG images.\n */\n default?: boolean;\n}\n\nconst ENDPOINT_PATH = \"/api/v1/images\";\n\nexport class Client {\n private config: Configuration;\n\n constructor(config: Configuration | OgPilotConfigOptions = {}) {\n this.config =\n config instanceof Configuration ? config : new Configuration(config);\n }\n\n async createImage(\n params: Record<string, unknown> = {},\n options: CreateImageOptions = {}\n ): Promise<unknown> {\n const {\n json = false,\n iat,\n headers = {},\n default: useDefault = false,\n } = options;\n\n // Always include a path; manual overrides win, otherwise resolve from the current request.\n const resolvedParams = { ...params };\n const manualPath = resolvedParams.path;\n delete resolvedParams.path;\n resolvedParams.path = this.resolvePath(manualPath, useDefault);\n\n const url = await this.buildUrl(resolvedParams, iat);\n const response = await this.request(url, json, headers);\n\n if (json) {\n const body = await response.text();\n return JSON.parse(body);\n }\n\n return response.headers.get(\"location\") ?? response.url ?? url.toString();\n }\n\n /**\n * Resolves the path parameter for the request.\n * Priority: manual path > current request path > \"/\"\n */\n private resolvePath(manualPath: unknown, useDefault: boolean): string {\n // Manual path always wins if provided\n if (manualPath !== undefined && manualPath !== null) {\n const pathStr = String(manualPath).trim();\n if (pathStr.length > 0) {\n return this.normalizePath(pathStr);\n }\n }\n\n // If default is true, return \"/\"\n if (useDefault) {\n return \"/\";\n }\n\n // Try to get path from current request context\n const currentPath = getCurrentPath();\n return this.normalizePath(currentPath);\n }\n\n /**\n * Normalizes a path to ensure it starts with \"/\" and handles full URLs.\n */\n private normalizePath(path: string | undefined | null): string {\n if (path === undefined || path === null) {\n return \"/\";\n }\n\n let cleaned = String(path).trim();\n if (cleaned.length === 0) {\n return \"/\";\n }\n\n // Extract path from full URLs\n if (cleaned.startsWith(\"http://\") || cleaned.startsWith(\"https://\")) {\n try {\n const url = new URL(cleaned);\n cleaned = url.pathname + url.search;\n } catch {\n // Keep as-is if URL parsing fails\n }\n }\n\n // Ensure path starts with \"/\"\n if (!cleaned.startsWith(\"/\")) {\n cleaned = \"/\" + cleaned;\n }\n\n return cleaned;\n }\n\n private async request(\n url: URL,\n json: boolean,\n headers: Record<string, string>\n ): Promise<Response> {\n const fetchImpl =\n this.config.fetch ?? (typeof fetch !== \"undefined\" ? fetch : undefined);\n\n if (!fetchImpl) {\n throw new ConfigurationError(\n \"Fetch API is not available; provide a fetch implementation in the configuration.\"\n );\n }\n\n const requestHeaders = new Headers();\n if (json) {\n requestHeaders.set(\"Accept\", \"application/json\");\n }\n\n Object.entries(headers).forEach(([key, value]) => {\n requestHeaders.set(key, value);\n });\n\n const timeoutMs = this.totalTimeoutMs();\n const controller = new AbortController();\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n if (timeoutMs && timeoutMs > 0) {\n timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n }\n\n try {\n const response = await fetchImpl(url.toString(), {\n method: \"GET\",\n headers: requestHeaders,\n redirect: \"manual\",\n signal: controller.signal,\n });\n\n if (response.status >= 400) {\n const body = await response.text().catch(() => \"\");\n throw new RequestError(\n `OG Pilot request failed with status ${response.status}: ${body}`,\n response.status\n );\n }\n\n return response;\n } catch (error) {\n if (error instanceof RequestError) {\n throw error;\n }\n\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new RequestError(`OG Pilot request timed out: ${error.message}`);\n }\n\n if (error instanceof Error) {\n throw new RequestError(`OG Pilot request failed: ${error.message}`);\n }\n\n throw new RequestError(\"OG Pilot request failed.\");\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n }\n\n private async buildUrl(\n params: Record<string, unknown>,\n iat?: number | Date\n ): Promise<URL> {\n const payload = this.buildPayload(params, iat);\n const token = await signJwt(payload, this.apiKey());\n const url = new URL(ENDPOINT_PATH, this.config.baseUrl);\n url.searchParams.set(\"token\", token);\n return url;\n }\n\n private buildPayload(\n params: Record<string, unknown>,\n iat?: number | Date\n ): Record<string, unknown> {\n const payload: Record<string, unknown> = { ...params };\n\n if (iat !== undefined && iat !== null) {\n payload.iat = normalizeIat(iat);\n }\n\n if (payload.iss === undefined || payload.iss === null) {\n payload.iss = this.domain();\n }\n\n if (payload.sub === undefined || payload.sub === null) {\n payload.sub = this.apiKeyPrefix();\n }\n\n this.validatePayload(payload);\n return payload;\n }\n\n private validatePayload(payload: Record<string, unknown>): void {\n if (\n payload.iss === undefined ||\n payload.iss === null ||\n String(payload.iss).length === 0\n ) {\n throw new ConfigurationError(\"OG Pilot domain is missing\");\n }\n\n if (\n payload.sub === undefined ||\n payload.sub === null ||\n String(payload.sub).length === 0\n ) {\n throw new ConfigurationError(\"OG Pilot API key prefix is missing\");\n }\n\n if (\n payload.title === undefined ||\n payload.title === null ||\n String(payload.title).length === 0\n ) {\n throw new Error(\"OG Pilot title is required\");\n }\n }\n\n private apiKey(): string {\n if (this.config.apiKey !== undefined && this.config.apiKey !== null) {\n return this.config.apiKey;\n }\n\n throw new ConfigurationError(\"OG Pilot API key is missing\");\n }\n\n private domain(): string {\n if (this.config.domain !== undefined && this.config.domain !== null) {\n return this.config.domain;\n }\n\n throw new ConfigurationError(\"OG Pilot domain is missing\");\n }\n\n private apiKeyPrefix(): string {\n return this.apiKey().slice(0, 8);\n }\n\n private totalTimeoutMs(): number | undefined {\n const openTimeoutMs = this.config.openTimeoutMs;\n const readTimeoutMs = this.config.readTimeoutMs;\n\n if (openTimeoutMs === undefined && readTimeoutMs === undefined) {\n return undefined;\n }\n\n const open = typeof openTimeoutMs === \"number\" ? openTimeoutMs : 0;\n const read = typeof readTimeoutMs === \"number\" ? readTimeoutMs : 0;\n return open + read;\n }\n}\n\nfunction normalizeIat(iat: number | Date): number {\n if (iat instanceof Date) {\n return Math.floor(iat.getTime() / 1000);\n }\n\n if (iat > 100000000000) {\n return Math.floor(iat / 1000);\n }\n\n return Math.floor(iat);\n}\n","import { Client } from \"./client\";\nimport { Configuration, OgPilotConfigOptions } from \"./config\";\nimport { ConfigurationError, OgPilotError, RequestError } from \"./errors\";\nimport {\n clearCurrentRequest,\n setCurrentRequest,\n withRequestContext,\n} from \"./request-context\";\n\nlet defaultConfig = new Configuration();\n\nexport const configure = (\n updater: (config: Configuration) => void\n): Configuration => {\n updater(defaultConfig);\n return defaultConfig;\n};\n\nexport const resetConfig = (): void => {\n defaultConfig = new Configuration();\n};\n\nexport const getConfig = (): Configuration => defaultConfig;\n\nexport const client = (): Client => new Client(defaultConfig);\n\nexport const createImage = (\n params: Record<string, unknown> = {},\n options: Parameters<Client[\"createImage\"]>[1] = {}\n): ReturnType<Client[\"createImage\"]> => client().createImage(params, options);\n\nexport const createClient = (options: OgPilotConfigOptions = {}): Client =>\n new Client(options);\n\nconst OgPilot = {\n configure,\n resetConfig,\n getConfig,\n client,\n createClient,\n createImage,\n setCurrentRequest,\n clearCurrentRequest,\n withRequestContext,\n Configuration,\n ConfigurationError,\n OgPilotError,\n RequestError,\n};\n\nexport default OgPilot;\nexport type { CreateImageOptions } from \"./client\";\nexport {\n clearCurrentRequest,\n Client,\n Configuration,\n ConfigurationError,\n OgPilotConfigOptions,\n OgPilotError,\n RequestError,\n setCurrentRequest,\n withRequestContext,\n};\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/config.ts","../src/errors.ts","../src/jwt.ts","../src/request-context.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["export interface OgPilotConfigOptions {\n apiKey?: string;\n domain?: string;\n baseUrl?: string;\n openTimeoutMs?: number;\n readTimeoutMs?: number;\n fetch?: typeof fetch;\n}\n\nconst DEFAULT_BASE_URL = \"https://ogpilot.com\";\n\nfunction readEnv(key: string): string | undefined {\n if (typeof process !== \"undefined\" && process.env) {\n return process.env[key];\n }\n\n return undefined;\n}\n\nexport class Configuration {\n apiKey?: string;\n domain?: string;\n baseUrl: string;\n openTimeoutMs?: number;\n readTimeoutMs?: number;\n fetch?: typeof fetch;\n\n constructor(options: OgPilotConfigOptions = {}) {\n this.apiKey = options.apiKey ?? readEnv(\"OG_PILOT_API_KEY\");\n this.domain = options.domain ?? readEnv(\"OG_PILOT_DOMAIN\");\n this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;\n this.openTimeoutMs = options.openTimeoutMs ?? 5000;\n this.readTimeoutMs = options.readTimeoutMs ?? 10000;\n this.fetch = options.fetch;\n }\n}\n","export class OgPilotError extends Error {\n constructor(message: string) {\n super(message);\n this.name = \"OgPilotError\";\n }\n}\n\nexport class ConfigurationError extends OgPilotError {\n constructor(message: string) {\n super(message);\n this.name = \"ConfigurationError\";\n }\n}\n\nexport class RequestError extends OgPilotError {\n status?: number;\n\n constructor(message: string, status?: number) {\n super(message);\n this.name = \"RequestError\";\n this.status = status;\n }\n}\n","const encoder = new TextEncoder();\n\nfunction toBase64(bytes: Uint8Array): string {\n if (typeof Buffer !== \"undefined\") {\n return Buffer.from(bytes).toString(\"base64\");\n }\n\n let binary = \"\";\n for (let i = 0; i < bytes.length; i += 1) {\n binary += String.fromCharCode(bytes[i]);\n }\n\n if (typeof btoa === \"undefined\") {\n throw new Error(\"btoa is not available in this environment\");\n }\n\n return btoa(binary);\n}\n\nfunction base64UrlEncodeBytes(bytes: Uint8Array): string {\n return toBase64(bytes).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/g, \"\");\n}\n\nfunction base64UrlEncodeString(value: string): string {\n return base64UrlEncodeBytes(encoder.encode(value));\n}\n\nfunction getSubtleCrypto(): SubtleCrypto | null {\n if (typeof globalThis !== \"undefined\" && globalThis.crypto && globalThis.crypto.subtle) {\n return globalThis.crypto.subtle;\n }\n\n return null;\n}\n\nasync function hmacSha256(data: string, secret: string): Promise<Uint8Array> {\n const subtle = getSubtleCrypto();\n\n if (!subtle) {\n throw new Error(\"Web Crypto API is not available; requires a Node 18+ or Edge runtime.\");\n }\n\n const key = await subtle.importKey(\n \"raw\",\n encoder.encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"]\n );\n\n const signature = await subtle.sign(\"HMAC\", key, encoder.encode(data));\n return new Uint8Array(signature);\n}\n\nexport async function signJwt(payload: Record<string, unknown>, secret: string): Promise<string> {\n const header = { alg: \"HS256\", typ: \"JWT\" };\n const encodedHeader = base64UrlEncodeString(JSON.stringify(header));\n const encodedPayload = base64UrlEncodeString(JSON.stringify(payload));\n const signingInput = `${encodedHeader}.${encodedPayload}`;\n const signature = await hmacSha256(signingInput, secret);\n\n return `${signingInput}.${base64UrlEncodeBytes(signature)}`;\n}\n","/**\n * Request context for automatic path resolution.\n *\n * In Node.js environments, this uses AsyncLocalStorage to store the current\n * request URL per async execution context. In edge runtimes or browsers,\n * it falls back to a simple variable (not request-scoped).\n */\n\ntype RequestInfo = {\n url?: string;\n path?: string;\n};\n\ninterface AsyncStorage {\n getStore: () => RequestInfo | undefined;\n run: <T>(store: RequestInfo, callback: () => T) => T;\n}\n\n// Try to use AsyncLocalStorage if available (Node.js 12.17+)\nlet asyncLocalStorage: AsyncStorage | null = null;\n\n// Fallback for environments without AsyncLocalStorage\nlet fallbackRequest: RequestInfo | undefined;\n\n// Create a fallback implementation\nfunction createFallbackStorage(): AsyncStorage {\n return {\n getStore: () => fallbackRequest,\n run: <T>(_store: RequestInfo, callback: () => T): T => {\n const prev = fallbackRequest;\n fallbackRequest = _store;\n try {\n return callback();\n } finally {\n fallbackRequest = prev;\n }\n },\n };\n}\n\n// Lazy initialization to avoid issues in environments where async_hooks isn't available\nfunction getAsyncLocalStorage(): AsyncStorage {\n if (asyncLocalStorage === null) {\n try {\n // Dynamic import to avoid bundler issues\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const { AsyncLocalStorage } = require(\"async_hooks\");\n const storage = new AsyncLocalStorage();\n asyncLocalStorage = {\n getStore: () => storage.getStore() as RequestInfo | undefined,\n run: <T>(store: RequestInfo, callback: () => T): T =>\n storage.run(store, callback),\n };\n } catch {\n // AsyncLocalStorage not available, use fallback\n asyncLocalStorage = createFallbackStorage();\n }\n }\n return asyncLocalStorage!;\n}\n\n/**\n * Sets the current request context for automatic path resolution.\n * Call this in your middleware/handler before using OG Pilot.\n *\n * @example Express middleware\n * ```ts\n * app.use((req, res, next) => {\n * setCurrentRequest({ url: req.originalUrl });\n * next();\n * });\n * ```\n *\n * @example Next.js middleware\n * ```ts\n * export function middleware(request: NextRequest) {\n * setCurrentRequest({ url: request.nextUrl.pathname + request.nextUrl.search });\n * return NextResponse.next();\n * }\n * ```\n */\nexport function setCurrentRequest(request: RequestInfo): void {\n fallbackRequest = request;\n}\n\n/**\n * Clears the current request context.\n * Call this after the request is complete if using setCurrentRequest directly.\n */\nexport function clearCurrentRequest(): void {\n fallbackRequest = undefined;\n}\n\n/**\n * Runs a callback with the given request context.\n * The context is automatically cleared after the callback completes.\n * This is the preferred method for setting request context.\n *\n * @example Express middleware\n * ```ts\n * import { withRequestContext } from \"og-pilot-js\";\n *\n * app.use((req, res, next) => {\n * withRequestContext({ url: req.originalUrl }, () => {\n * next();\n * });\n * });\n * ```\n */\nexport function withRequestContext<T>(\n request: RequestInfo,\n callback: () => T\n): T {\n return getAsyncLocalStorage().run(request, callback);\n}\n\n/**\n * Gets the current request info from context.\n * @internal\n */\nexport function getCurrentRequest(): RequestInfo | undefined {\n // Try AsyncLocalStorage first, then fallback\n const store = getAsyncLocalStorage().getStore();\n return store ?? fallbackRequest;\n}\n\n/**\n * Gets the current request path from context or environment.\n * @internal\n */\nexport function getCurrentPath(): string | undefined {\n const request = getCurrentRequest();\n\n if (request?.path) {\n return request.path;\n }\n\n if (request?.url) {\n return extractPathFromUrl(request.url);\n }\n\n // Fallback to environment variables (similar to Ruby's env_fullpath)\n return getPathFromEnv();\n}\n\n// ============================================================================\n// Framework-specific helpers\n// ============================================================================\n\nexport type NextParamValue = string | string[] | undefined;\nexport type NextParams = Record<string, NextParamValue>;\nexport type NextSearchParams = Record<string, NextParamValue>;\nexport type NextMetadataProps = {\n params: NextParams | Promise<NextParams>;\n searchParams?: NextSearchParams | Promise<NextSearchParams>;\n};\n\n/**\n * Builds a URL path for Next.js App Router routes.\n *\n * Pass your route pattern (e.g. \"/products/[id]\") and Next.js params/searchParams.\n * This avoids middleware and fits naturally inside generateMetadata().\n *\n * @example app/products/[id]/page.tsx\n * ```ts\n * import { buildPathFromNextProps } from \"og-pilot-js\";\n *\n * export async function generateMetadata(props) {\n * const path = await buildPathFromNextProps(\"/products/[id]\", props);\n * // => \"/products/123?ref=twitter\"\n * }\n * ```\n */\nexport async function buildPathFromNextProps(\n routePattern: string,\n props: NextMetadataProps\n): Promise<string> {\n const params = await props.params;\n const searchParams = props.searchParams\n ? await props.searchParams\n : undefined;\n return buildPathFromNextParams(routePattern, params, searchParams);\n}\n\n/**\n * Builds a URL path for Next.js App Router routes from params/searchParams.\n *\n * @example\n * ```ts\n * const path = buildPathFromNextParams(\n * \"/blog/[...slug]\",\n * { slug: [\"2024\", \"launch\"] },\n * { ref: \"twitter\" }\n * );\n * // => \"/blog/2024/launch?ref=twitter\"\n * ```\n */\nexport function buildPathFromNextParams(\n routePattern: string,\n params: NextParams,\n searchParams?: NextSearchParams\n): string {\n const segments = routePattern\n .split(\"/\")\n .filter((segment) => segment.length > 0);\n const builtSegments: string[] = [];\n\n for (const segment of segments) {\n const catchAllMatch = segment.match(/^\\[\\.\\.\\.(.+)\\]$/);\n const optionalCatchAllMatch = segment.match(/^\\[\\[\\.\\.\\.(.+)\\]\\]$/);\n const paramMatch = segment.match(/^\\[(.+)\\]$/);\n\n if (optionalCatchAllMatch) {\n const key = optionalCatchAllMatch[1];\n const value = params[key];\n if (value === undefined) {\n continue;\n }\n if (Array.isArray(value)) {\n builtSegments.push(...value);\n } else {\n builtSegments.push(value);\n }\n continue;\n }\n\n if (catchAllMatch) {\n const key = catchAllMatch[1];\n const value = params[key];\n if (value === undefined) {\n continue;\n }\n if (Array.isArray(value)) {\n builtSegments.push(...value);\n } else {\n builtSegments.push(value);\n }\n continue;\n }\n\n if (paramMatch) {\n const key = paramMatch[1];\n const value = params[key];\n if (value === undefined) {\n continue;\n }\n if (Array.isArray(value)) {\n builtSegments.push(value.join(\"/\"));\n } else {\n builtSegments.push(value);\n }\n continue;\n }\n\n builtSegments.push(segment);\n }\n\n const path = `/${builtSegments.join(\"/\")}`;\n const query = serializeSearchParams(searchParams);\n return query.length > 0 ? `${path}?${query}` : path;\n}\n\n/**\n * Creates an Express/Connect middleware that automatically sets request context.\n *\n * @example Express\n * ```ts\n * import express from \"express\";\n * import { createExpressMiddleware } from \"og-pilot-js\";\n *\n * const app = express();\n * app.use(createExpressMiddleware());\n * ```\n */\nexport function createExpressMiddleware(): ExpressMiddleware {\n return (req, _res, next) => {\n setCurrentRequest({\n url: req.originalUrl || req.url,\n path: req.originalUrl || req.url,\n });\n next();\n };\n}\n\n/**\n * Helper to extract path from an Express/Node.js request object.\n */\nexport function getPathFromExpressRequest(req: ExpressRequest): string {\n return req.originalUrl || req.url || \"/\";\n}\n\n// Type definitions for framework compatibility\n// These are minimal to avoid requiring framework dependencies\n\ninterface ExpressRequest {\n originalUrl?: string;\n url?: string;\n}\n\ntype ExpressMiddleware = (\n req: ExpressRequest,\n res: unknown,\n next: () => void\n) => void;\n\nfunction extractPathFromUrl(url: string): string {\n // Handle full URLs\n if (url.startsWith(\"http://\") || url.startsWith(\"https://\")) {\n try {\n const parsed = new URL(url);\n return parsed.pathname + parsed.search;\n } catch {\n return url;\n }\n }\n\n return url;\n}\n\nfunction serializeSearchParams(\n searchParams?: NextSearchParams | URLSearchParams\n): string {\n if (!searchParams) {\n return \"\";\n }\n\n if (searchParams instanceof URLSearchParams) {\n return searchParams.toString();\n }\n\n const params = new URLSearchParams();\n for (const [key, value] of Object.entries(searchParams)) {\n if (value === undefined) {\n continue;\n }\n if (Array.isArray(value)) {\n for (const entry of value) {\n params.append(key, entry);\n }\n } else {\n params.append(key, value);\n }\n }\n\n return params.toString();\n}\n\nfunction getPathFromEnv(): string | undefined {\n if (typeof process === \"undefined\" || !process.env) {\n return undefined;\n }\n\n const env = process.env;\n\n // Check various environment variables (similar to Ruby implementation)\n const requestUri = env.REQUEST_URI;\n if (requestUri && requestUri.length > 0) {\n return requestUri;\n }\n\n const originalFullpath = env.ORIGINAL_FULLPATH;\n if (originalFullpath && originalFullpath.length > 0) {\n return originalFullpath;\n }\n\n const pathInfo = env.PATH_INFO;\n if (pathInfo && pathInfo.length > 0) {\n const queryString = env.QUERY_STRING ?? \"\";\n return queryString.length > 0 ? `${pathInfo}?${queryString}` : pathInfo;\n }\n\n const requestPath = env.REQUEST_PATH;\n if (requestPath && requestPath.length > 0) {\n return requestPath;\n }\n\n return undefined;\n}\n","import { Configuration, OgPilotConfigOptions } from \"./config\";\nimport { ConfigurationError, RequestError } from \"./errors\";\nimport { signJwt } from \"./jwt\";\nimport { getCurrentPath } from \"./request-context\";\n\nexport interface CreateImageOptions {\n json?: boolean;\n iat?: number | Date;\n headers?: Record<string, string>;\n /**\n * When true, forces the path to \"/\" regardless of the current request.\n * Useful for generating default/fallback OG images.\n */\n default?: boolean;\n}\n\nconst ENDPOINT_PATH = \"/api/v1/images\";\n\nexport class Client {\n private config: Configuration;\n\n constructor(config: Configuration | OgPilotConfigOptions = {}) {\n this.config =\n config instanceof Configuration ? config : new Configuration(config);\n }\n\n async createImage(\n params: Record<string, unknown> = {},\n options: CreateImageOptions = {}\n ): Promise<unknown> {\n const {\n json = false,\n iat,\n headers = {},\n default: useDefault = false,\n } = options;\n\n // Always include a path; manual overrides win, otherwise resolve from the current request.\n const resolvedParams = { ...params };\n const manualPath = resolvedParams.path;\n delete resolvedParams.path;\n resolvedParams.path = this.resolvePath(manualPath, useDefault);\n\n const url = await this.buildUrl(resolvedParams, iat);\n const response = await this.request(url, json, headers);\n\n if (json) {\n const body = await response.text();\n return JSON.parse(body);\n }\n\n return response.headers.get(\"location\") ?? response.url ?? url.toString();\n }\n\n /**\n * Resolves the path parameter for the request.\n * Priority: manual path > current request path > \"/\"\n */\n private resolvePath(manualPath: unknown, useDefault: boolean): string {\n // Manual path always wins if provided\n if (manualPath !== undefined && manualPath !== null) {\n const pathStr = String(manualPath).trim();\n if (pathStr.length > 0) {\n return this.normalizePath(pathStr);\n }\n }\n\n // If default is true, return \"/\"\n if (useDefault) {\n return \"/\";\n }\n\n // Try to get path from current request context\n const currentPath = getCurrentPath();\n return this.normalizePath(currentPath);\n }\n\n /**\n * Normalizes a path to ensure it starts with \"/\" and handles full URLs.\n */\n private normalizePath(path: string | undefined | null): string {\n if (path === undefined || path === null) {\n return \"/\";\n }\n\n let cleaned = String(path).trim();\n if (cleaned.length === 0) {\n return \"/\";\n }\n\n // Extract path from full URLs\n if (cleaned.startsWith(\"http://\") || cleaned.startsWith(\"https://\")) {\n try {\n const url = new URL(cleaned);\n cleaned = url.pathname + url.search;\n } catch {\n // Keep as-is if URL parsing fails\n }\n }\n\n // Ensure path starts with \"/\"\n if (!cleaned.startsWith(\"/\")) {\n cleaned = \"/\" + cleaned;\n }\n\n return cleaned;\n }\n\n private async request(\n url: URL,\n json: boolean,\n headers: Record<string, string>\n ): Promise<Response> {\n const fetchImpl =\n this.config.fetch ?? (typeof fetch !== \"undefined\" ? fetch : undefined);\n\n if (!fetchImpl) {\n throw new ConfigurationError(\n \"Fetch API is not available; provide a fetch implementation in the configuration.\"\n );\n }\n\n const requestHeaders = new Headers();\n if (json) {\n requestHeaders.set(\"Accept\", \"application/json\");\n }\n\n Object.entries(headers).forEach(([key, value]) => {\n requestHeaders.set(key, value);\n });\n\n const timeoutMs = this.totalTimeoutMs();\n const controller = new AbortController();\n let timeoutId: ReturnType<typeof setTimeout> | undefined;\n\n if (timeoutMs && timeoutMs > 0) {\n timeoutId = setTimeout(() => controller.abort(), timeoutMs);\n }\n\n try {\n const response = await fetchImpl(url.toString(), {\n method: \"GET\",\n headers: requestHeaders,\n redirect: \"manual\",\n signal: controller.signal,\n });\n\n if (response.status >= 400) {\n const body = await response.text().catch(() => \"\");\n throw new RequestError(\n `OG Pilot request failed with status ${response.status}: ${body}`,\n response.status\n );\n }\n\n return response;\n } catch (error) {\n if (error instanceof RequestError) {\n throw error;\n }\n\n if (error instanceof Error && error.name === \"AbortError\") {\n throw new RequestError(`OG Pilot request timed out: ${error.message}`);\n }\n\n if (error instanceof Error) {\n throw new RequestError(`OG Pilot request failed: ${error.message}`);\n }\n\n throw new RequestError(\"OG Pilot request failed.\");\n } finally {\n if (timeoutId) {\n clearTimeout(timeoutId);\n }\n }\n }\n\n private async buildUrl(\n params: Record<string, unknown>,\n iat?: number | Date\n ): Promise<URL> {\n const payload = this.buildPayload(params, iat);\n const token = await signJwt(payload, this.apiKey());\n const url = new URL(ENDPOINT_PATH, this.config.baseUrl);\n url.searchParams.set(\"token\", token);\n return url;\n }\n\n private buildPayload(\n params: Record<string, unknown>,\n iat?: number | Date\n ): Record<string, unknown> {\n const payload: Record<string, unknown> = { ...params };\n\n if (iat !== undefined && iat !== null) {\n payload.iat = normalizeIat(iat);\n }\n\n if (payload.iss === undefined || payload.iss === null) {\n payload.iss = this.domain();\n }\n\n if (payload.sub === undefined || payload.sub === null) {\n payload.sub = this.apiKeyPrefix();\n }\n\n this.validatePayload(payload);\n return payload;\n }\n\n private validatePayload(payload: Record<string, unknown>): void {\n if (\n payload.iss === undefined ||\n payload.iss === null ||\n String(payload.iss).length === 0\n ) {\n throw new ConfigurationError(\"OG Pilot domain is missing\");\n }\n\n if (\n payload.sub === undefined ||\n payload.sub === null ||\n String(payload.sub).length === 0\n ) {\n throw new ConfigurationError(\"OG Pilot API key prefix is missing\");\n }\n\n if (\n payload.title === undefined ||\n payload.title === null ||\n String(payload.title).length === 0\n ) {\n throw new Error(\"OG Pilot title is required\");\n }\n }\n\n private apiKey(): string {\n if (this.config.apiKey !== undefined && this.config.apiKey !== null) {\n return this.config.apiKey;\n }\n\n throw new ConfigurationError(\"OG Pilot API key is missing\");\n }\n\n private domain(): string {\n if (this.config.domain !== undefined && this.config.domain !== null) {\n return this.config.domain;\n }\n\n throw new ConfigurationError(\"OG Pilot domain is missing\");\n }\n\n private apiKeyPrefix(): string {\n return this.apiKey().slice(0, 8);\n }\n\n private totalTimeoutMs(): number | undefined {\n const openTimeoutMs = this.config.openTimeoutMs;\n const readTimeoutMs = this.config.readTimeoutMs;\n\n if (openTimeoutMs === undefined && readTimeoutMs === undefined) {\n return undefined;\n }\n\n const open = typeof openTimeoutMs === \"number\" ? openTimeoutMs : 0;\n const read = typeof readTimeoutMs === \"number\" ? readTimeoutMs : 0;\n return open + read;\n }\n}\n\nfunction normalizeIat(iat: number | Date): number {\n if (iat instanceof Date) {\n return Math.floor(iat.getTime() / 1000);\n }\n\n if (iat > 100000000000) {\n return Math.floor(iat / 1000);\n }\n\n return Math.floor(iat);\n}\n","import { Client } from \"./client\";\nimport { Configuration, OgPilotConfigOptions } from \"./config\";\nimport { ConfigurationError, OgPilotError, RequestError } from \"./errors\";\nimport {\n buildPathFromNextParams,\n buildPathFromNextProps,\n clearCurrentRequest,\n createExpressMiddleware,\n getPathFromExpressRequest,\n setCurrentRequest,\n withRequestContext,\n} from \"./request-context\";\n\nlet defaultConfig = new Configuration();\n\nexport const configure = (\n updater: (config: Configuration) => void\n): Configuration => {\n updater(defaultConfig);\n return defaultConfig;\n};\n\nexport const resetConfig = (): void => {\n defaultConfig = new Configuration();\n};\n\nexport const getConfig = (): Configuration => defaultConfig;\n\nexport const client = (): Client => new Client(defaultConfig);\n\nexport const createImage = (\n params: Record<string, unknown> = {},\n options: Parameters<Client[\"createImage\"]>[1] = {}\n): ReturnType<Client[\"createImage\"]> => client().createImage(params, options);\n\nexport const createClient = (options: OgPilotConfigOptions = {}): Client =>\n new Client(options);\n\nconst OgPilot = {\n configure,\n resetConfig,\n getConfig,\n client,\n createClient,\n createImage,\n setCurrentRequest,\n clearCurrentRequest,\n withRequestContext,\n createExpressMiddleware,\n getPathFromExpressRequest,\n buildPathFromNextProps,\n buildPathFromNextParams,\n Configuration,\n ConfigurationError,\n OgPilotError,\n RequestError,\n};\n\nexport default OgPilot;\nexport type { CreateImageOptions } from \"./client\";\nexport type {\n NextMetadataProps,\n NextParams,\n NextSearchParams,\n} from \"./request-context\";\nexport {\n buildPathFromNextParams,\n buildPathFromNextProps,\n clearCurrentRequest,\n Client,\n Configuration,\n ConfigurationError,\n createExpressMiddleware,\n getPathFromExpressRequest,\n OgPilotConfigOptions,\n OgPilotError,\n RequestError,\n setCurrentRequest,\n withRequestContext,\n};\n"],"mappings":"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","names":[]}
|