og-pilot-js 0.1.0
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/LICENSE +21 -0
- package/README.md +92 -0
- package/dist/index.cjs +305 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +68 -0
- package/dist/index.d.ts +68 -0
- package/dist/index.js +268 -0
- package/dist/index.js.map +1 -0
- package/package.json +37 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Sunergos IT LLC
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
# OG Pilot JS
|
|
2
|
+
|
|
3
|
+
A small JavaScript/TypeScript client for generating OG Pilot Open Graph images via signed JWTs.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install og-pilot-js
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Configuration
|
|
12
|
+
|
|
13
|
+
The default client reads from `OG_PILOT_API_KEY` and `OG_PILOT_DOMAIN`.
|
|
14
|
+
You can override them at runtime:
|
|
15
|
+
|
|
16
|
+
```ts
|
|
17
|
+
import { configure } from "og-pilot-js";
|
|
18
|
+
|
|
19
|
+
configure((config) => {
|
|
20
|
+
config.apiKey = process.env.OG_PILOT_API_KEY;
|
|
21
|
+
config.domain = process.env.OG_PILOT_DOMAIN;
|
|
22
|
+
// Optional overrides:
|
|
23
|
+
// config.openTimeoutMs = 5000;
|
|
24
|
+
// config.readTimeoutMs = 10000;
|
|
25
|
+
});
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Usage
|
|
29
|
+
|
|
30
|
+
Generate an image URL (follows the redirect returned by OG Pilot):
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { createImage } from "og-pilot-js";
|
|
34
|
+
|
|
35
|
+
const imageUrl = await createImage({
|
|
36
|
+
template: "blog_post",
|
|
37
|
+
title: "How to Build Amazing OG Images",
|
|
38
|
+
description: "A complete guide to social media previews",
|
|
39
|
+
bg_color: "#1a1a1a",
|
|
40
|
+
text_color: "#ffffff",
|
|
41
|
+
author_name: "Jane Smith",
|
|
42
|
+
publish_date: "2024-01-15"
|
|
43
|
+
}, {
|
|
44
|
+
iat: Date.now() // optional; refresh cache daily
|
|
45
|
+
});
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
If you omit `iat`, OG Pilot will cache the image indefinitely. Provide an `iat`
|
|
49
|
+
to refresh the cache daily. You can pass a `Date`, epoch seconds, or epoch
|
|
50
|
+
milliseconds (`Date.now()` is auto-converted).
|
|
51
|
+
|
|
52
|
+
Fetch JSON metadata instead:
|
|
53
|
+
|
|
54
|
+
```ts
|
|
55
|
+
import { createImage } from "og-pilot-js";
|
|
56
|
+
|
|
57
|
+
const data = await createImage(
|
|
58
|
+
{
|
|
59
|
+
template: "page",
|
|
60
|
+
title: "Hello OG Pilot"
|
|
61
|
+
},
|
|
62
|
+
{ json: true }
|
|
63
|
+
);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
## Framework notes
|
|
67
|
+
|
|
68
|
+
This library is meant for server-side usage. Keep your API key private and do not
|
|
69
|
+
call it from client-side/browser code. In Next.js or Nuxt, call it from API routes
|
|
70
|
+
or server handlers.
|
|
71
|
+
|
|
72
|
+
## Advanced usage
|
|
73
|
+
|
|
74
|
+
Create a dedicated client with custom configuration:
|
|
75
|
+
|
|
76
|
+
```ts
|
|
77
|
+
import { createClient } from "og-pilot-js";
|
|
78
|
+
|
|
79
|
+
const ogPilot = createClient({
|
|
80
|
+
apiKey: process.env.OG_PILOT_API_KEY,
|
|
81
|
+
domain: process.env.OG_PILOT_DOMAIN
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
const url = await ogPilot.createImage({ title: "Hello" });
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Development
|
|
88
|
+
|
|
89
|
+
```bash
|
|
90
|
+
npm run build
|
|
91
|
+
npm run typecheck
|
|
92
|
+
```
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,305 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
Client: () => Client,
|
|
24
|
+
Configuration: () => Configuration,
|
|
25
|
+
ConfigurationError: () => ConfigurationError,
|
|
26
|
+
OgPilotError: () => OgPilotError,
|
|
27
|
+
RequestError: () => RequestError,
|
|
28
|
+
client: () => client,
|
|
29
|
+
configure: () => configure,
|
|
30
|
+
createClient: () => createClient,
|
|
31
|
+
createImage: () => createImage,
|
|
32
|
+
default: () => index_default,
|
|
33
|
+
getConfig: () => getConfig,
|
|
34
|
+
resetConfig: () => resetConfig
|
|
35
|
+
});
|
|
36
|
+
module.exports = __toCommonJS(index_exports);
|
|
37
|
+
|
|
38
|
+
// src/config.ts
|
|
39
|
+
var DEFAULT_BASE_URL = "https://ogpilot.com";
|
|
40
|
+
function readEnv(key) {
|
|
41
|
+
if (typeof process !== "undefined" && process.env) {
|
|
42
|
+
return process.env[key];
|
|
43
|
+
}
|
|
44
|
+
return void 0;
|
|
45
|
+
}
|
|
46
|
+
var Configuration = class {
|
|
47
|
+
constructor(options = {}) {
|
|
48
|
+
this.apiKey = options.apiKey ?? readEnv("OG_PILOT_API_KEY");
|
|
49
|
+
this.domain = options.domain ?? readEnv("OG_PILOT_DOMAIN");
|
|
50
|
+
this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
|
|
51
|
+
this.openTimeoutMs = options.openTimeoutMs ?? 5e3;
|
|
52
|
+
this.readTimeoutMs = options.readTimeoutMs ?? 1e4;
|
|
53
|
+
this.fetch = options.fetch;
|
|
54
|
+
}
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
// src/errors.ts
|
|
58
|
+
var OgPilotError = class extends Error {
|
|
59
|
+
constructor(message) {
|
|
60
|
+
super(message);
|
|
61
|
+
this.name = "OgPilotError";
|
|
62
|
+
}
|
|
63
|
+
};
|
|
64
|
+
var ConfigurationError = class extends OgPilotError {
|
|
65
|
+
constructor(message) {
|
|
66
|
+
super(message);
|
|
67
|
+
this.name = "ConfigurationError";
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
var RequestError = class extends OgPilotError {
|
|
71
|
+
constructor(message, status) {
|
|
72
|
+
super(message);
|
|
73
|
+
this.name = "RequestError";
|
|
74
|
+
this.status = status;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
// src/jwt.ts
|
|
79
|
+
var encoder = new TextEncoder();
|
|
80
|
+
function toBase64(bytes) {
|
|
81
|
+
if (typeof Buffer !== "undefined") {
|
|
82
|
+
return Buffer.from(bytes).toString("base64");
|
|
83
|
+
}
|
|
84
|
+
let binary = "";
|
|
85
|
+
for (let i = 0; i < bytes.length; i += 1) {
|
|
86
|
+
binary += String.fromCharCode(bytes[i]);
|
|
87
|
+
}
|
|
88
|
+
if (typeof btoa === "undefined") {
|
|
89
|
+
throw new Error("btoa is not available in this environment");
|
|
90
|
+
}
|
|
91
|
+
return btoa(binary);
|
|
92
|
+
}
|
|
93
|
+
function base64UrlEncodeBytes(bytes) {
|
|
94
|
+
return toBase64(bytes).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
95
|
+
}
|
|
96
|
+
function base64UrlEncodeString(value) {
|
|
97
|
+
return base64UrlEncodeBytes(encoder.encode(value));
|
|
98
|
+
}
|
|
99
|
+
function getSubtleCrypto() {
|
|
100
|
+
if (typeof globalThis !== "undefined" && globalThis.crypto && globalThis.crypto.subtle) {
|
|
101
|
+
return globalThis.crypto.subtle;
|
|
102
|
+
}
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
async function hmacSha256(data, secret) {
|
|
106
|
+
const subtle = getSubtleCrypto();
|
|
107
|
+
if (!subtle) {
|
|
108
|
+
throw new Error("Web Crypto API is not available; requires a Node 18+ or Edge runtime.");
|
|
109
|
+
}
|
|
110
|
+
const key = await subtle.importKey(
|
|
111
|
+
"raw",
|
|
112
|
+
encoder.encode(secret),
|
|
113
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
114
|
+
false,
|
|
115
|
+
["sign"]
|
|
116
|
+
);
|
|
117
|
+
const signature = await subtle.sign("HMAC", key, encoder.encode(data));
|
|
118
|
+
return new Uint8Array(signature);
|
|
119
|
+
}
|
|
120
|
+
async function signJwt(payload, secret) {
|
|
121
|
+
const header = { alg: "HS256", typ: "JWT" };
|
|
122
|
+
const encodedHeader = base64UrlEncodeString(JSON.stringify(header));
|
|
123
|
+
const encodedPayload = base64UrlEncodeString(JSON.stringify(payload));
|
|
124
|
+
const signingInput = `${encodedHeader}.${encodedPayload}`;
|
|
125
|
+
const signature = await hmacSha256(signingInput, secret);
|
|
126
|
+
return `${signingInput}.${base64UrlEncodeBytes(signature)}`;
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
// src/client.ts
|
|
130
|
+
var ENDPOINT_PATH = "/api/v1/images";
|
|
131
|
+
var Client = class {
|
|
132
|
+
constructor(config = {}) {
|
|
133
|
+
this.config = config instanceof Configuration ? config : new Configuration(config);
|
|
134
|
+
}
|
|
135
|
+
async createImage(params = {}, options = {}) {
|
|
136
|
+
const { json = false, iat, headers = {} } = options;
|
|
137
|
+
const url = await this.buildUrl(params ?? {}, iat);
|
|
138
|
+
const response = await this.request(url, json, headers);
|
|
139
|
+
if (json) {
|
|
140
|
+
const body = await response.text();
|
|
141
|
+
return JSON.parse(body);
|
|
142
|
+
}
|
|
143
|
+
return response.headers.get("location") ?? response.url ?? url.toString();
|
|
144
|
+
}
|
|
145
|
+
async request(url, json, headers) {
|
|
146
|
+
const fetchImpl = this.config.fetch ?? (typeof fetch !== "undefined" ? fetch : void 0);
|
|
147
|
+
if (!fetchImpl) {
|
|
148
|
+
throw new ConfigurationError(
|
|
149
|
+
"Fetch API is not available; provide a fetch implementation in the configuration."
|
|
150
|
+
);
|
|
151
|
+
}
|
|
152
|
+
const requestHeaders = new Headers();
|
|
153
|
+
if (json) {
|
|
154
|
+
requestHeaders.set("Accept", "application/json");
|
|
155
|
+
}
|
|
156
|
+
Object.entries(headers).forEach(([key, value]) => {
|
|
157
|
+
requestHeaders.set(key, value);
|
|
158
|
+
});
|
|
159
|
+
const timeoutMs = this.totalTimeoutMs();
|
|
160
|
+
const controller = new AbortController();
|
|
161
|
+
let timeoutId;
|
|
162
|
+
if (timeoutMs && timeoutMs > 0) {
|
|
163
|
+
timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
164
|
+
}
|
|
165
|
+
try {
|
|
166
|
+
const response = await fetchImpl(url.toString(), {
|
|
167
|
+
method: "GET",
|
|
168
|
+
headers: requestHeaders,
|
|
169
|
+
redirect: "manual",
|
|
170
|
+
signal: controller.signal
|
|
171
|
+
});
|
|
172
|
+
if (response.status >= 400) {
|
|
173
|
+
const body = await response.text().catch(() => "");
|
|
174
|
+
throw new RequestError(
|
|
175
|
+
`OG Pilot request failed with status ${response.status}: ${body}`,
|
|
176
|
+
response.status
|
|
177
|
+
);
|
|
178
|
+
}
|
|
179
|
+
return response;
|
|
180
|
+
} catch (error) {
|
|
181
|
+
if (error instanceof RequestError) {
|
|
182
|
+
throw error;
|
|
183
|
+
}
|
|
184
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
185
|
+
throw new RequestError(`OG Pilot request timed out: ${error.message}`);
|
|
186
|
+
}
|
|
187
|
+
if (error instanceof Error) {
|
|
188
|
+
throw new RequestError(`OG Pilot request failed: ${error.message}`);
|
|
189
|
+
}
|
|
190
|
+
throw new RequestError("OG Pilot request failed.");
|
|
191
|
+
} finally {
|
|
192
|
+
if (timeoutId) {
|
|
193
|
+
clearTimeout(timeoutId);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
async buildUrl(params, iat) {
|
|
198
|
+
const payload = this.buildPayload(params, iat);
|
|
199
|
+
const token = await signJwt(payload, this.apiKey());
|
|
200
|
+
const url = new URL(ENDPOINT_PATH, this.config.baseUrl);
|
|
201
|
+
url.searchParams.set("token", token);
|
|
202
|
+
return url;
|
|
203
|
+
}
|
|
204
|
+
buildPayload(params, iat) {
|
|
205
|
+
const payload = { ...params };
|
|
206
|
+
if (iat !== void 0 && iat !== null) {
|
|
207
|
+
payload.iat = normalizeIat(iat);
|
|
208
|
+
}
|
|
209
|
+
if (payload.iss === void 0 || payload.iss === null) {
|
|
210
|
+
payload.iss = this.domain();
|
|
211
|
+
}
|
|
212
|
+
if (payload.sub === void 0 || payload.sub === null) {
|
|
213
|
+
payload.sub = this.apiKeyPrefix();
|
|
214
|
+
}
|
|
215
|
+
this.validatePayload(payload);
|
|
216
|
+
return payload;
|
|
217
|
+
}
|
|
218
|
+
validatePayload(payload) {
|
|
219
|
+
if (payload.iss === void 0 || payload.iss === null || String(payload.iss).length === 0) {
|
|
220
|
+
throw new ConfigurationError("OG Pilot domain is missing");
|
|
221
|
+
}
|
|
222
|
+
if (payload.sub === void 0 || payload.sub === null || String(payload.sub).length === 0) {
|
|
223
|
+
throw new ConfigurationError("OG Pilot API key prefix is missing");
|
|
224
|
+
}
|
|
225
|
+
if (payload.title === void 0 || payload.title === null || String(payload.title).length === 0) {
|
|
226
|
+
throw new Error("OG Pilot title is required");
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
apiKey() {
|
|
230
|
+
if (this.config.apiKey !== void 0 && this.config.apiKey !== null) {
|
|
231
|
+
return this.config.apiKey;
|
|
232
|
+
}
|
|
233
|
+
throw new ConfigurationError("OG Pilot API key is missing");
|
|
234
|
+
}
|
|
235
|
+
domain() {
|
|
236
|
+
if (this.config.domain !== void 0 && this.config.domain !== null) {
|
|
237
|
+
return this.config.domain;
|
|
238
|
+
}
|
|
239
|
+
throw new ConfigurationError("OG Pilot domain is missing");
|
|
240
|
+
}
|
|
241
|
+
apiKeyPrefix() {
|
|
242
|
+
return this.apiKey().slice(0, 8);
|
|
243
|
+
}
|
|
244
|
+
totalTimeoutMs() {
|
|
245
|
+
const openTimeoutMs = this.config.openTimeoutMs;
|
|
246
|
+
const readTimeoutMs = this.config.readTimeoutMs;
|
|
247
|
+
if (openTimeoutMs === void 0 && readTimeoutMs === void 0) {
|
|
248
|
+
return void 0;
|
|
249
|
+
}
|
|
250
|
+
const open = typeof openTimeoutMs === "number" ? openTimeoutMs : 0;
|
|
251
|
+
const read = typeof readTimeoutMs === "number" ? readTimeoutMs : 0;
|
|
252
|
+
return open + read;
|
|
253
|
+
}
|
|
254
|
+
};
|
|
255
|
+
function normalizeIat(iat) {
|
|
256
|
+
if (iat instanceof Date) {
|
|
257
|
+
return Math.floor(iat.getTime() / 1e3);
|
|
258
|
+
}
|
|
259
|
+
if (iat > 1e11) {
|
|
260
|
+
return Math.floor(iat / 1e3);
|
|
261
|
+
}
|
|
262
|
+
return Math.floor(iat);
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// src/index.ts
|
|
266
|
+
var defaultConfig = new Configuration();
|
|
267
|
+
var configure = (updater) => {
|
|
268
|
+
updater(defaultConfig);
|
|
269
|
+
return defaultConfig;
|
|
270
|
+
};
|
|
271
|
+
var resetConfig = () => {
|
|
272
|
+
defaultConfig = new Configuration();
|
|
273
|
+
};
|
|
274
|
+
var getConfig = () => defaultConfig;
|
|
275
|
+
var client = () => new Client(defaultConfig);
|
|
276
|
+
var createImage = (params = {}, options = {}) => client().createImage(params, options);
|
|
277
|
+
var createClient = (options = {}) => new Client(options);
|
|
278
|
+
var OgPilot = {
|
|
279
|
+
configure,
|
|
280
|
+
resetConfig,
|
|
281
|
+
getConfig,
|
|
282
|
+
client,
|
|
283
|
+
createClient,
|
|
284
|
+
createImage,
|
|
285
|
+
Configuration,
|
|
286
|
+
ConfigurationError,
|
|
287
|
+
OgPilotError,
|
|
288
|
+
RequestError
|
|
289
|
+
};
|
|
290
|
+
var index_default = OgPilot;
|
|
291
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
292
|
+
0 && (module.exports = {
|
|
293
|
+
Client,
|
|
294
|
+
Configuration,
|
|
295
|
+
ConfigurationError,
|
|
296
|
+
OgPilotError,
|
|
297
|
+
RequestError,
|
|
298
|
+
client,
|
|
299
|
+
configure,
|
|
300
|
+
createClient,
|
|
301
|
+
createImage,
|
|
302
|
+
getConfig,
|
|
303
|
+
resetConfig
|
|
304
|
+
});
|
|
305
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/config.ts","../src/errors.ts","../src/jwt.ts","../src/client.ts"],"sourcesContent":["import { Client } from \"./client\";\nimport { Configuration, OgPilotConfigOptions } from \"./config\";\nimport { ConfigurationError, OgPilotError, RequestError } from \"./errors\";\n\nlet defaultConfig = new Configuration();\n\nexport const configure = (updater: (config: Configuration) => void): 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 => new Client(options);\n\nconst OgPilot = {\n configure,\n resetConfig,\n getConfig,\n client,\n createClient,\n createImage,\n Configuration,\n ConfigurationError,\n OgPilotError,\n RequestError\n};\n\nexport default OgPilot;\nexport { Client, Configuration, OgPilotConfigOptions, ConfigurationError, OgPilotError, RequestError };\nexport type { CreateImageOptions } from \"./client\";\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","import { Configuration, OgPilotConfigOptions } from \"./config\";\nimport { ConfigurationError, RequestError } from \"./errors\";\nimport { signJwt } from \"./jwt\";\n\nexport interface CreateImageOptions {\n json?: boolean;\n iat?: number | Date;\n headers?: Record<string, string>;\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 = 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 { json = false, iat, headers = {} } = options;\n const url = await this.buildUrl(params ?? {}, 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 private async request(url: URL, json: boolean, headers: Record<string, string>): Promise<Response> {\n const fetchImpl = 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(params: Record<string, unknown>, iat?: number | Date): 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(params: Record<string, unknown>, iat?: number | Date): 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 (payload.iss === undefined || payload.iss === null || String(payload.iss).length === 0) {\n throw new ConfigurationError(\"OG Pilot domain is missing\");\n }\n\n if (payload.sub === undefined || payload.sub === null || String(payload.sub).length === 0) {\n throw new ConfigurationError(\"OG Pilot API key prefix is missing\");\n }\n\n if (payload.title === undefined || payload.title === null || String(payload.title).length === 0) {\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
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
interface OgPilotConfigOptions {
|
|
2
|
+
apiKey?: string;
|
|
3
|
+
domain?: string;
|
|
4
|
+
baseUrl?: string;
|
|
5
|
+
openTimeoutMs?: number;
|
|
6
|
+
readTimeoutMs?: number;
|
|
7
|
+
fetch?: typeof fetch;
|
|
8
|
+
}
|
|
9
|
+
declare class Configuration {
|
|
10
|
+
apiKey?: string;
|
|
11
|
+
domain?: string;
|
|
12
|
+
baseUrl: string;
|
|
13
|
+
openTimeoutMs?: number;
|
|
14
|
+
readTimeoutMs?: number;
|
|
15
|
+
fetch?: typeof fetch;
|
|
16
|
+
constructor(options?: OgPilotConfigOptions);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface CreateImageOptions {
|
|
20
|
+
json?: boolean;
|
|
21
|
+
iat?: number | Date;
|
|
22
|
+
headers?: Record<string, string>;
|
|
23
|
+
}
|
|
24
|
+
declare class Client {
|
|
25
|
+
private config;
|
|
26
|
+
constructor(config?: Configuration | OgPilotConfigOptions);
|
|
27
|
+
createImage(params?: Record<string, unknown>, options?: CreateImageOptions): Promise<unknown>;
|
|
28
|
+
private request;
|
|
29
|
+
private buildUrl;
|
|
30
|
+
private buildPayload;
|
|
31
|
+
private validatePayload;
|
|
32
|
+
private apiKey;
|
|
33
|
+
private domain;
|
|
34
|
+
private apiKeyPrefix;
|
|
35
|
+
private totalTimeoutMs;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
declare class OgPilotError extends Error {
|
|
39
|
+
constructor(message: string);
|
|
40
|
+
}
|
|
41
|
+
declare class ConfigurationError extends OgPilotError {
|
|
42
|
+
constructor(message: string);
|
|
43
|
+
}
|
|
44
|
+
declare class RequestError extends OgPilotError {
|
|
45
|
+
status?: number;
|
|
46
|
+
constructor(message: string, status?: number);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
declare const configure: (updater: (config: Configuration) => void) => Configuration;
|
|
50
|
+
declare const resetConfig: () => void;
|
|
51
|
+
declare const getConfig: () => Configuration;
|
|
52
|
+
declare const client: () => Client;
|
|
53
|
+
declare const createImage: (params?: Record<string, unknown>, options?: Parameters<Client["createImage"]>[1]) => ReturnType<Client["createImage"]>;
|
|
54
|
+
declare const createClient: (options?: OgPilotConfigOptions) => Client;
|
|
55
|
+
declare const OgPilot: {
|
|
56
|
+
configure: (updater: (config: Configuration) => void) => Configuration;
|
|
57
|
+
resetConfig: () => void;
|
|
58
|
+
getConfig: () => Configuration;
|
|
59
|
+
client: () => Client;
|
|
60
|
+
createClient: (options?: OgPilotConfigOptions) => Client;
|
|
61
|
+
createImage: (params?: Record<string, unknown>, options?: Parameters<Client["createImage"]>[1]) => ReturnType<Client["createImage"]>;
|
|
62
|
+
Configuration: typeof Configuration;
|
|
63
|
+
ConfigurationError: typeof ConfigurationError;
|
|
64
|
+
OgPilotError: typeof OgPilotError;
|
|
65
|
+
RequestError: typeof RequestError;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export { Client, Configuration, ConfigurationError, type CreateImageOptions, type OgPilotConfigOptions, OgPilotError, RequestError, client, configure, createClient, createImage, OgPilot as default, getConfig, resetConfig };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
interface OgPilotConfigOptions {
|
|
2
|
+
apiKey?: string;
|
|
3
|
+
domain?: string;
|
|
4
|
+
baseUrl?: string;
|
|
5
|
+
openTimeoutMs?: number;
|
|
6
|
+
readTimeoutMs?: number;
|
|
7
|
+
fetch?: typeof fetch;
|
|
8
|
+
}
|
|
9
|
+
declare class Configuration {
|
|
10
|
+
apiKey?: string;
|
|
11
|
+
domain?: string;
|
|
12
|
+
baseUrl: string;
|
|
13
|
+
openTimeoutMs?: number;
|
|
14
|
+
readTimeoutMs?: number;
|
|
15
|
+
fetch?: typeof fetch;
|
|
16
|
+
constructor(options?: OgPilotConfigOptions);
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
interface CreateImageOptions {
|
|
20
|
+
json?: boolean;
|
|
21
|
+
iat?: number | Date;
|
|
22
|
+
headers?: Record<string, string>;
|
|
23
|
+
}
|
|
24
|
+
declare class Client {
|
|
25
|
+
private config;
|
|
26
|
+
constructor(config?: Configuration | OgPilotConfigOptions);
|
|
27
|
+
createImage(params?: Record<string, unknown>, options?: CreateImageOptions): Promise<unknown>;
|
|
28
|
+
private request;
|
|
29
|
+
private buildUrl;
|
|
30
|
+
private buildPayload;
|
|
31
|
+
private validatePayload;
|
|
32
|
+
private apiKey;
|
|
33
|
+
private domain;
|
|
34
|
+
private apiKeyPrefix;
|
|
35
|
+
private totalTimeoutMs;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
declare class OgPilotError extends Error {
|
|
39
|
+
constructor(message: string);
|
|
40
|
+
}
|
|
41
|
+
declare class ConfigurationError extends OgPilotError {
|
|
42
|
+
constructor(message: string);
|
|
43
|
+
}
|
|
44
|
+
declare class RequestError extends OgPilotError {
|
|
45
|
+
status?: number;
|
|
46
|
+
constructor(message: string, status?: number);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
declare const configure: (updater: (config: Configuration) => void) => Configuration;
|
|
50
|
+
declare const resetConfig: () => void;
|
|
51
|
+
declare const getConfig: () => Configuration;
|
|
52
|
+
declare const client: () => Client;
|
|
53
|
+
declare const createImage: (params?: Record<string, unknown>, options?: Parameters<Client["createImage"]>[1]) => ReturnType<Client["createImage"]>;
|
|
54
|
+
declare const createClient: (options?: OgPilotConfigOptions) => Client;
|
|
55
|
+
declare const OgPilot: {
|
|
56
|
+
configure: (updater: (config: Configuration) => void) => Configuration;
|
|
57
|
+
resetConfig: () => void;
|
|
58
|
+
getConfig: () => Configuration;
|
|
59
|
+
client: () => Client;
|
|
60
|
+
createClient: (options?: OgPilotConfigOptions) => Client;
|
|
61
|
+
createImage: (params?: Record<string, unknown>, options?: Parameters<Client["createImage"]>[1]) => ReturnType<Client["createImage"]>;
|
|
62
|
+
Configuration: typeof Configuration;
|
|
63
|
+
ConfigurationError: typeof ConfigurationError;
|
|
64
|
+
OgPilotError: typeof OgPilotError;
|
|
65
|
+
RequestError: typeof RequestError;
|
|
66
|
+
};
|
|
67
|
+
|
|
68
|
+
export { Client, Configuration, ConfigurationError, type CreateImageOptions, type OgPilotConfigOptions, OgPilotError, RequestError, client, configure, createClient, createImage, OgPilot as default, getConfig, resetConfig };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,268 @@
|
|
|
1
|
+
// src/config.ts
|
|
2
|
+
var DEFAULT_BASE_URL = "https://ogpilot.com";
|
|
3
|
+
function readEnv(key) {
|
|
4
|
+
if (typeof process !== "undefined" && process.env) {
|
|
5
|
+
return process.env[key];
|
|
6
|
+
}
|
|
7
|
+
return void 0;
|
|
8
|
+
}
|
|
9
|
+
var Configuration = class {
|
|
10
|
+
constructor(options = {}) {
|
|
11
|
+
this.apiKey = options.apiKey ?? readEnv("OG_PILOT_API_KEY");
|
|
12
|
+
this.domain = options.domain ?? readEnv("OG_PILOT_DOMAIN");
|
|
13
|
+
this.baseUrl = options.baseUrl ?? DEFAULT_BASE_URL;
|
|
14
|
+
this.openTimeoutMs = options.openTimeoutMs ?? 5e3;
|
|
15
|
+
this.readTimeoutMs = options.readTimeoutMs ?? 1e4;
|
|
16
|
+
this.fetch = options.fetch;
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
// src/errors.ts
|
|
21
|
+
var OgPilotError = class extends Error {
|
|
22
|
+
constructor(message) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.name = "OgPilotError";
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
var ConfigurationError = class extends OgPilotError {
|
|
28
|
+
constructor(message) {
|
|
29
|
+
super(message);
|
|
30
|
+
this.name = "ConfigurationError";
|
|
31
|
+
}
|
|
32
|
+
};
|
|
33
|
+
var RequestError = class extends OgPilotError {
|
|
34
|
+
constructor(message, status) {
|
|
35
|
+
super(message);
|
|
36
|
+
this.name = "RequestError";
|
|
37
|
+
this.status = status;
|
|
38
|
+
}
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
// src/jwt.ts
|
|
42
|
+
var encoder = new TextEncoder();
|
|
43
|
+
function toBase64(bytes) {
|
|
44
|
+
if (typeof Buffer !== "undefined") {
|
|
45
|
+
return Buffer.from(bytes).toString("base64");
|
|
46
|
+
}
|
|
47
|
+
let binary = "";
|
|
48
|
+
for (let i = 0; i < bytes.length; i += 1) {
|
|
49
|
+
binary += String.fromCharCode(bytes[i]);
|
|
50
|
+
}
|
|
51
|
+
if (typeof btoa === "undefined") {
|
|
52
|
+
throw new Error("btoa is not available in this environment");
|
|
53
|
+
}
|
|
54
|
+
return btoa(binary);
|
|
55
|
+
}
|
|
56
|
+
function base64UrlEncodeBytes(bytes) {
|
|
57
|
+
return toBase64(bytes).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/g, "");
|
|
58
|
+
}
|
|
59
|
+
function base64UrlEncodeString(value) {
|
|
60
|
+
return base64UrlEncodeBytes(encoder.encode(value));
|
|
61
|
+
}
|
|
62
|
+
function getSubtleCrypto() {
|
|
63
|
+
if (typeof globalThis !== "undefined" && globalThis.crypto && globalThis.crypto.subtle) {
|
|
64
|
+
return globalThis.crypto.subtle;
|
|
65
|
+
}
|
|
66
|
+
return null;
|
|
67
|
+
}
|
|
68
|
+
async function hmacSha256(data, secret) {
|
|
69
|
+
const subtle = getSubtleCrypto();
|
|
70
|
+
if (!subtle) {
|
|
71
|
+
throw new Error("Web Crypto API is not available; requires a Node 18+ or Edge runtime.");
|
|
72
|
+
}
|
|
73
|
+
const key = await subtle.importKey(
|
|
74
|
+
"raw",
|
|
75
|
+
encoder.encode(secret),
|
|
76
|
+
{ name: "HMAC", hash: "SHA-256" },
|
|
77
|
+
false,
|
|
78
|
+
["sign"]
|
|
79
|
+
);
|
|
80
|
+
const signature = await subtle.sign("HMAC", key, encoder.encode(data));
|
|
81
|
+
return new Uint8Array(signature);
|
|
82
|
+
}
|
|
83
|
+
async function signJwt(payload, secret) {
|
|
84
|
+
const header = { alg: "HS256", typ: "JWT" };
|
|
85
|
+
const encodedHeader = base64UrlEncodeString(JSON.stringify(header));
|
|
86
|
+
const encodedPayload = base64UrlEncodeString(JSON.stringify(payload));
|
|
87
|
+
const signingInput = `${encodedHeader}.${encodedPayload}`;
|
|
88
|
+
const signature = await hmacSha256(signingInput, secret);
|
|
89
|
+
return `${signingInput}.${base64UrlEncodeBytes(signature)}`;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// src/client.ts
|
|
93
|
+
var ENDPOINT_PATH = "/api/v1/images";
|
|
94
|
+
var Client = class {
|
|
95
|
+
constructor(config = {}) {
|
|
96
|
+
this.config = config instanceof Configuration ? config : new Configuration(config);
|
|
97
|
+
}
|
|
98
|
+
async createImage(params = {}, options = {}) {
|
|
99
|
+
const { json = false, iat, headers = {} } = options;
|
|
100
|
+
const url = await this.buildUrl(params ?? {}, iat);
|
|
101
|
+
const response = await this.request(url, json, headers);
|
|
102
|
+
if (json) {
|
|
103
|
+
const body = await response.text();
|
|
104
|
+
return JSON.parse(body);
|
|
105
|
+
}
|
|
106
|
+
return response.headers.get("location") ?? response.url ?? url.toString();
|
|
107
|
+
}
|
|
108
|
+
async request(url, json, headers) {
|
|
109
|
+
const fetchImpl = this.config.fetch ?? (typeof fetch !== "undefined" ? fetch : void 0);
|
|
110
|
+
if (!fetchImpl) {
|
|
111
|
+
throw new ConfigurationError(
|
|
112
|
+
"Fetch API is not available; provide a fetch implementation in the configuration."
|
|
113
|
+
);
|
|
114
|
+
}
|
|
115
|
+
const requestHeaders = new Headers();
|
|
116
|
+
if (json) {
|
|
117
|
+
requestHeaders.set("Accept", "application/json");
|
|
118
|
+
}
|
|
119
|
+
Object.entries(headers).forEach(([key, value]) => {
|
|
120
|
+
requestHeaders.set(key, value);
|
|
121
|
+
});
|
|
122
|
+
const timeoutMs = this.totalTimeoutMs();
|
|
123
|
+
const controller = new AbortController();
|
|
124
|
+
let timeoutId;
|
|
125
|
+
if (timeoutMs && timeoutMs > 0) {
|
|
126
|
+
timeoutId = setTimeout(() => controller.abort(), timeoutMs);
|
|
127
|
+
}
|
|
128
|
+
try {
|
|
129
|
+
const response = await fetchImpl(url.toString(), {
|
|
130
|
+
method: "GET",
|
|
131
|
+
headers: requestHeaders,
|
|
132
|
+
redirect: "manual",
|
|
133
|
+
signal: controller.signal
|
|
134
|
+
});
|
|
135
|
+
if (response.status >= 400) {
|
|
136
|
+
const body = await response.text().catch(() => "");
|
|
137
|
+
throw new RequestError(
|
|
138
|
+
`OG Pilot request failed with status ${response.status}: ${body}`,
|
|
139
|
+
response.status
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
return response;
|
|
143
|
+
} catch (error) {
|
|
144
|
+
if (error instanceof RequestError) {
|
|
145
|
+
throw error;
|
|
146
|
+
}
|
|
147
|
+
if (error instanceof Error && error.name === "AbortError") {
|
|
148
|
+
throw new RequestError(`OG Pilot request timed out: ${error.message}`);
|
|
149
|
+
}
|
|
150
|
+
if (error instanceof Error) {
|
|
151
|
+
throw new RequestError(`OG Pilot request failed: ${error.message}`);
|
|
152
|
+
}
|
|
153
|
+
throw new RequestError("OG Pilot request failed.");
|
|
154
|
+
} finally {
|
|
155
|
+
if (timeoutId) {
|
|
156
|
+
clearTimeout(timeoutId);
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
async buildUrl(params, iat) {
|
|
161
|
+
const payload = this.buildPayload(params, iat);
|
|
162
|
+
const token = await signJwt(payload, this.apiKey());
|
|
163
|
+
const url = new URL(ENDPOINT_PATH, this.config.baseUrl);
|
|
164
|
+
url.searchParams.set("token", token);
|
|
165
|
+
return url;
|
|
166
|
+
}
|
|
167
|
+
buildPayload(params, iat) {
|
|
168
|
+
const payload = { ...params };
|
|
169
|
+
if (iat !== void 0 && iat !== null) {
|
|
170
|
+
payload.iat = normalizeIat(iat);
|
|
171
|
+
}
|
|
172
|
+
if (payload.iss === void 0 || payload.iss === null) {
|
|
173
|
+
payload.iss = this.domain();
|
|
174
|
+
}
|
|
175
|
+
if (payload.sub === void 0 || payload.sub === null) {
|
|
176
|
+
payload.sub = this.apiKeyPrefix();
|
|
177
|
+
}
|
|
178
|
+
this.validatePayload(payload);
|
|
179
|
+
return payload;
|
|
180
|
+
}
|
|
181
|
+
validatePayload(payload) {
|
|
182
|
+
if (payload.iss === void 0 || payload.iss === null || String(payload.iss).length === 0) {
|
|
183
|
+
throw new ConfigurationError("OG Pilot domain is missing");
|
|
184
|
+
}
|
|
185
|
+
if (payload.sub === void 0 || payload.sub === null || String(payload.sub).length === 0) {
|
|
186
|
+
throw new ConfigurationError("OG Pilot API key prefix is missing");
|
|
187
|
+
}
|
|
188
|
+
if (payload.title === void 0 || payload.title === null || String(payload.title).length === 0) {
|
|
189
|
+
throw new Error("OG Pilot title is required");
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
apiKey() {
|
|
193
|
+
if (this.config.apiKey !== void 0 && this.config.apiKey !== null) {
|
|
194
|
+
return this.config.apiKey;
|
|
195
|
+
}
|
|
196
|
+
throw new ConfigurationError("OG Pilot API key is missing");
|
|
197
|
+
}
|
|
198
|
+
domain() {
|
|
199
|
+
if (this.config.domain !== void 0 && this.config.domain !== null) {
|
|
200
|
+
return this.config.domain;
|
|
201
|
+
}
|
|
202
|
+
throw new ConfigurationError("OG Pilot domain is missing");
|
|
203
|
+
}
|
|
204
|
+
apiKeyPrefix() {
|
|
205
|
+
return this.apiKey().slice(0, 8);
|
|
206
|
+
}
|
|
207
|
+
totalTimeoutMs() {
|
|
208
|
+
const openTimeoutMs = this.config.openTimeoutMs;
|
|
209
|
+
const readTimeoutMs = this.config.readTimeoutMs;
|
|
210
|
+
if (openTimeoutMs === void 0 && readTimeoutMs === void 0) {
|
|
211
|
+
return void 0;
|
|
212
|
+
}
|
|
213
|
+
const open = typeof openTimeoutMs === "number" ? openTimeoutMs : 0;
|
|
214
|
+
const read = typeof readTimeoutMs === "number" ? readTimeoutMs : 0;
|
|
215
|
+
return open + read;
|
|
216
|
+
}
|
|
217
|
+
};
|
|
218
|
+
function normalizeIat(iat) {
|
|
219
|
+
if (iat instanceof Date) {
|
|
220
|
+
return Math.floor(iat.getTime() / 1e3);
|
|
221
|
+
}
|
|
222
|
+
if (iat > 1e11) {
|
|
223
|
+
return Math.floor(iat / 1e3);
|
|
224
|
+
}
|
|
225
|
+
return Math.floor(iat);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// src/index.ts
|
|
229
|
+
var defaultConfig = new Configuration();
|
|
230
|
+
var configure = (updater) => {
|
|
231
|
+
updater(defaultConfig);
|
|
232
|
+
return defaultConfig;
|
|
233
|
+
};
|
|
234
|
+
var resetConfig = () => {
|
|
235
|
+
defaultConfig = new Configuration();
|
|
236
|
+
};
|
|
237
|
+
var getConfig = () => defaultConfig;
|
|
238
|
+
var client = () => new Client(defaultConfig);
|
|
239
|
+
var createImage = (params = {}, options = {}) => client().createImage(params, options);
|
|
240
|
+
var createClient = (options = {}) => new Client(options);
|
|
241
|
+
var OgPilot = {
|
|
242
|
+
configure,
|
|
243
|
+
resetConfig,
|
|
244
|
+
getConfig,
|
|
245
|
+
client,
|
|
246
|
+
createClient,
|
|
247
|
+
createImage,
|
|
248
|
+
Configuration,
|
|
249
|
+
ConfigurationError,
|
|
250
|
+
OgPilotError,
|
|
251
|
+
RequestError
|
|
252
|
+
};
|
|
253
|
+
var index_default = OgPilot;
|
|
254
|
+
export {
|
|
255
|
+
Client,
|
|
256
|
+
Configuration,
|
|
257
|
+
ConfigurationError,
|
|
258
|
+
OgPilotError,
|
|
259
|
+
RequestError,
|
|
260
|
+
client,
|
|
261
|
+
configure,
|
|
262
|
+
createClient,
|
|
263
|
+
createImage,
|
|
264
|
+
index_default as default,
|
|
265
|
+
getConfig,
|
|
266
|
+
resetConfig
|
|
267
|
+
};
|
|
268
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/config.ts","../src/errors.ts","../src/jwt.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","import { Configuration, OgPilotConfigOptions } from \"./config\";\nimport { ConfigurationError, RequestError } from \"./errors\";\nimport { signJwt } from \"./jwt\";\n\nexport interface CreateImageOptions {\n json?: boolean;\n iat?: number | Date;\n headers?: Record<string, string>;\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 = 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 { json = false, iat, headers = {} } = options;\n const url = await this.buildUrl(params ?? {}, 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 private async request(url: URL, json: boolean, headers: Record<string, string>): Promise<Response> {\n const fetchImpl = 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(params: Record<string, unknown>, iat?: number | Date): 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(params: Record<string, unknown>, iat?: number | Date): 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 (payload.iss === undefined || payload.iss === null || String(payload.iss).length === 0) {\n throw new ConfigurationError(\"OG Pilot domain is missing\");\n }\n\n if (payload.sub === undefined || payload.sub === null || String(payload.sub).length === 0) {\n throw new ConfigurationError(\"OG Pilot API key prefix is missing\");\n }\n\n if (payload.title === undefined || payload.title === null || String(payload.title).length === 0) {\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\";\n\nlet defaultConfig = new Configuration();\n\nexport const configure = (updater: (config: Configuration) => void): 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 => new Client(options);\n\nconst OgPilot = {\n configure,\n resetConfig,\n getConfig,\n client,\n createClient,\n createImage,\n Configuration,\n ConfigurationError,\n OgPilotError,\n RequestError\n};\n\nexport default OgPilot;\nexport { Client, Configuration, OgPilotConfigOptions, ConfigurationError, OgPilotError, RequestError };\nexport type { CreateImageOptions } from \"./client\";\n"],"mappings":"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","names":[]}
|
package/package.json
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "og-pilot-js",
|
|
3
|
+
"version": "0.1.0",
|
|
4
|
+
"description": "JavaScript/TypeScript client for the OG Pilot Open Graph image generator.",
|
|
5
|
+
"license": "MIT",
|
|
6
|
+
"author": "Sunergos IT LLC",
|
|
7
|
+
"homepage": "https://ogpilot.com",
|
|
8
|
+
"type": "module",
|
|
9
|
+
"main": "./dist/index.cjs",
|
|
10
|
+
"module": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.js",
|
|
16
|
+
"require": "./dist/index.cjs"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"files": [
|
|
20
|
+
"dist",
|
|
21
|
+
"README.md",
|
|
22
|
+
"LICENSE"
|
|
23
|
+
],
|
|
24
|
+
"sideEffects": false,
|
|
25
|
+
"engines": {
|
|
26
|
+
"node": ">=18"
|
|
27
|
+
},
|
|
28
|
+
"scripts": {
|
|
29
|
+
"build": "tsup",
|
|
30
|
+
"typecheck": "tsc --noEmit"
|
|
31
|
+
},
|
|
32
|
+
"devDependencies": {
|
|
33
|
+
"@types/node": "^25.1.0",
|
|
34
|
+
"tsup": "^8.0.0",
|
|
35
|
+
"typescript": "^5.5.0"
|
|
36
|
+
}
|
|
37
|
+
}
|