@getsupertab/supertab-connect-sdk 0.1.0-beta.33 → 0.1.0-beta.35
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 +122 -154
- package/dist/index.cjs +1 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +121 -41
- package/dist/index.d.ts +121 -41
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/package.json +4 -2
package/README.md
CHANGED
|
@@ -12,31 +12,23 @@ yarn add @getsupertab/supertab-connect-sdk
|
|
|
12
12
|
|
|
13
13
|
## Basic Usage
|
|
14
14
|
|
|
15
|
-
###
|
|
15
|
+
### Cloudflare Workers
|
|
16
16
|
|
|
17
|
-
```
|
|
18
|
-
import { SupertabConnect } from "@getsupertab/supertab-connect-sdk";
|
|
19
|
-
|
|
20
|
-
// Initialize the SDK
|
|
21
|
-
const supertabConnect = new SupertabConnect({
|
|
22
|
-
apiKey: "stc_live_your_api_key",
|
|
23
|
-
merchantSystemUrn: "your_merchant_system_urn",
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
// Verify a license token
|
|
27
|
-
const verification = await supertabConnect.verifyLicenseToken(
|
|
28
|
-
licenseToken,
|
|
29
|
-
"https://example.com/article"
|
|
30
|
-
);
|
|
17
|
+
```ts
|
|
18
|
+
import { SupertabConnect, Env, ExecutionContext } from "@getsupertab/supertab-connect-sdk";
|
|
31
19
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
20
|
+
export default {
|
|
21
|
+
async fetch(
|
|
22
|
+
request: Request,
|
|
23
|
+
env: Env,
|
|
24
|
+
ctx: ExecutionContext
|
|
25
|
+
): Promise<Response> {
|
|
26
|
+
return SupertabConnect.cloudflareHandleRequests(request, env, ctx);
|
|
27
|
+
},
|
|
28
|
+
};
|
|
37
29
|
```
|
|
38
30
|
|
|
39
|
-
### Fastly Compute
|
|
31
|
+
### Fastly Compute
|
|
40
32
|
|
|
41
33
|
```js
|
|
42
34
|
/// <reference types="@fastly/js-compute" />
|
|
@@ -44,54 +36,41 @@ import { SecretStore } from "fastly:secret-store";
|
|
|
44
36
|
import { SupertabConnect } from "@getsupertab/supertab-connect-sdk";
|
|
45
37
|
|
|
46
38
|
const configDict = new SecretStore("demo");
|
|
47
|
-
const
|
|
48
|
-
|
|
49
|
-
merchantSystemUrn: configDict.get("MERCHANT_SYSTEM_URN"),
|
|
50
|
-
};
|
|
39
|
+
const merchantSystemUrn = configDict.get("MERCHANT_SYSTEM_URN");
|
|
40
|
+
const merchantApiKey = configDict.get("MERCHANT_API_KEY");
|
|
51
41
|
|
|
52
|
-
// The entry point for the request handler.
|
|
53
42
|
addEventListener("fetch", (event) =>
|
|
54
43
|
event.respondWith(
|
|
55
44
|
SupertabConnect.fastlyHandleRequests(
|
|
56
45
|
event.request,
|
|
57
|
-
|
|
58
|
-
|
|
46
|
+
merchantSystemUrn,
|
|
47
|
+
merchantApiKey,
|
|
48
|
+
"origin-backend"
|
|
59
49
|
)
|
|
60
50
|
)
|
|
61
51
|
);
|
|
62
52
|
```
|
|
63
53
|
|
|
64
|
-
###
|
|
54
|
+
### AWS CloudFront Lambda@Edge
|
|
65
55
|
|
|
66
56
|
```ts
|
|
67
|
-
import {
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
57
|
+
import {
|
|
58
|
+
SupertabConnect,
|
|
59
|
+
CloudFrontRequestEvent,
|
|
60
|
+
CloudFrontRequestResult,
|
|
61
|
+
} from "@getsupertab/supertab-connect-sdk";
|
|
62
|
+
|
|
63
|
+
export async function handler(
|
|
64
|
+
event: CloudFrontRequestEvent
|
|
65
|
+
): Promise<CloudFrontRequestResult> {
|
|
66
|
+
return SupertabConnect.cloudfrontHandleRequests(event, {
|
|
67
|
+
apiKey: "stc_live_your_api_key",
|
|
68
|
+
merchantSystemUrn: "your_merchant_system_urn",
|
|
69
|
+
});
|
|
70
|
+
}
|
|
78
71
|
```
|
|
79
72
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
The SDK is configured using the `SupertabConnectConfig` object
|
|
83
|
-
|
|
84
|
-
| Parameter | Type | Required | Default | Description |
|
|
85
|
-
| ------------------- | ------ | -------- | ------- | ------------------------------- |
|
|
86
|
-
| `apiKey` | string | Yes | - | Your Supertab merchant API key |
|
|
87
|
-
| `merchantSystemUrn` | string | Yes | - | Your merchant system identifier |
|
|
88
|
-
|
|
89
|
-
## Public API Reference
|
|
90
|
-
|
|
91
|
-
### `constructor(config: SupertabConnectConfig, reset: boolean = false)`
|
|
92
|
-
|
|
93
|
-
Creates a new instance of the SupertabConnect SDK.
|
|
94
|
-
If the SDK was already initialized and the config parameters are different, it will throw an error unless `reset` is set to true.
|
|
73
|
+
### Manual Setup
|
|
95
74
|
|
|
96
75
|
```ts
|
|
97
76
|
import { SupertabConnect } from "@getsupertab/supertab-connect-sdk";
|
|
@@ -100,148 +79,137 @@ const supertabConnect = new SupertabConnect({
|
|
|
100
79
|
apiKey: "stc_live_your_api_key",
|
|
101
80
|
merchantSystemUrn: "your_merchant_system_urn",
|
|
102
81
|
});
|
|
103
|
-
```
|
|
104
82
|
|
|
105
|
-
|
|
83
|
+
// Verify a license token and record an analytics event
|
|
84
|
+
const result = await supertabConnect.verifyAndRecord({
|
|
85
|
+
token: licenseToken,
|
|
86
|
+
resourceUrl: "https://example.com/article",
|
|
87
|
+
userAgent: request.headers.get("User-Agent") ?? undefined,
|
|
88
|
+
ctx, // pass your platform's execution context for non-blocking event recording
|
|
89
|
+
});
|
|
106
90
|
|
|
107
|
-
|
|
108
|
-
|
|
91
|
+
if (result.valid) {
|
|
92
|
+
// Allow access
|
|
93
|
+
} else {
|
|
94
|
+
console.log("Denied:", result.error);
|
|
95
|
+
}
|
|
96
|
+
```
|
|
109
97
|
|
|
110
|
-
|
|
98
|
+
## Configuration Options
|
|
111
99
|
|
|
112
|
-
|
|
100
|
+
The SDK is configured using the `SupertabConnectConfig` object:
|
|
113
101
|
|
|
114
|
-
|
|
102
|
+
| Parameter | Type | Required | Default | Description |
|
|
103
|
+
| ------------------- | ------------------ | -------- | -------- | ------------------------------------------------------------------ |
|
|
104
|
+
| `apiKey` | `string` | Yes | - | Your Supertab merchant API key |
|
|
105
|
+
| `merchantSystemUrn` | `string` | Yes | - | Your merchant system identifier |
|
|
106
|
+
| `enforcement` | `EnforcementMode` | No | `SOFT` | Enforcement mode: `DISABLED`, `SOFT`, or `STRICT` |
|
|
107
|
+
| `botDetector` | `BotDetector` | No | - | Custom bot detection function `(request, ctx?) => boolean` |
|
|
108
|
+
| `debug` | `boolean` | No | `false` | Enable debug logging |
|
|
115
109
|
|
|
116
|
-
|
|
110
|
+
## Public API Reference
|
|
117
111
|
|
|
118
|
-
|
|
119
|
-
- `merchantSystemUrn` (string): Your merchant system identifier (recommended to be stored in a Fastly SecretStore)
|
|
120
|
-
- `merchantApiKey` (string): Your Supertab merchant API key (recommended to be stored in a Fastly SecretStore)
|
|
121
|
-
- `enableRSL` (boolean, optional): Enable RSL license.xml hosting (default: false)
|
|
112
|
+
### `constructor(config: SupertabConnectConfig, reset?: boolean)`
|
|
122
113
|
|
|
123
|
-
|
|
114
|
+
Creates a new SupertabConnect instance (singleton). Returns the existing instance if one already exists with the same config. Throws if an instance with different config exists unless `reset` is `true`.
|
|
124
115
|
|
|
125
|
-
|
|
126
|
-
- If the requester is not a bot to be blocked, or if the license token is present and valid, returns 200 OK
|
|
127
|
-
- If license token is invalid or missing, returns 401 Unauthorized
|
|
116
|
+
### `resetInstance(): void`
|
|
128
117
|
|
|
129
|
-
|
|
118
|
+
Clear the singleton instance, allowing a new one to be created with different config.
|
|
130
119
|
|
|
131
|
-
|
|
120
|
+
### `verify(options): Promise<RSLVerificationResult>` (static)
|
|
132
121
|
|
|
133
|
-
|
|
122
|
+
Pure token verification — verifies a license token without recording any events.
|
|
134
123
|
|
|
135
|
-
**Parameters:**
|
|
124
|
+
**Parameters (options object):**
|
|
136
125
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
126
|
+
| Parameter | Type | Required | Description |
|
|
127
|
+
| ------------- | --------- | -------- | ------------------------------------------------ |
|
|
128
|
+
| `token` | `string` | Yes | The license token to verify |
|
|
129
|
+
| `resourceUrl` | `string` | Yes | The URL of the resource being accessed |
|
|
130
|
+
| `baseUrl` | `string` | No | Override for the Supertab Connect API base URL |
|
|
131
|
+
| `debug` | `boolean` | No | Enable debug logging |
|
|
140
132
|
|
|
141
|
-
**Returns:**
|
|
133
|
+
**Returns:** `{ valid: boolean; error?: string }`
|
|
142
134
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
135
|
+
```ts
|
|
136
|
+
const result = await SupertabConnect.verify({
|
|
137
|
+
token: licenseToken,
|
|
138
|
+
resourceUrl: "https://example.com/article",
|
|
139
|
+
});
|
|
140
|
+
```
|
|
146
141
|
|
|
147
|
-
### `
|
|
142
|
+
### `verifyAndRecord(options): Promise<RSLVerificationResult>`
|
|
148
143
|
|
|
149
|
-
|
|
150
|
-
Any of out-of-the-box bot detector methods can be used or a custom one can be supplied provided it follows the specified signature.
|
|
144
|
+
Verifies a license token and records an analytics event. Uses the instance's `apiKey` and `merchantSystemUrn` for event recording.
|
|
151
145
|
|
|
152
|
-
**Parameters:**
|
|
146
|
+
**Parameters (options object):**
|
|
153
147
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
148
|
+
| Parameter | Type | Required | Description |
|
|
149
|
+
| ------------- | ------------------ | -------- | ---------------------------------------------------------------- |
|
|
150
|
+
| `token` | `string` | Yes | The license token to verify |
|
|
151
|
+
| `resourceUrl` | `string` | Yes | The URL of the resource being accessed |
|
|
152
|
+
| `userAgent` | `string` | No | User agent string for event recording |
|
|
153
|
+
| `debug` | `boolean` | No | Enable debug logging |
|
|
154
|
+
| `ctx` | `ExecutionContext` | No | Execution context for non-blocking event recording |
|
|
157
155
|
|
|
158
|
-
**Returns:**
|
|
156
|
+
**Returns:** `{ valid: boolean; error?: string }`
|
|
159
157
|
|
|
160
|
-
|
|
161
|
-
- If the requester is not a bot to be blocked, or if the license token is present and valid, returns 200 OK
|
|
162
|
-
- If license token is invalid or missing, returns 401 Unauthorized
|
|
158
|
+
### `handleRequest(request, ctx?): Promise<HandlerResult>`
|
|
163
159
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
Verifies license tokens issued by the Supertab platform. Internally, it fetches the platform JWKs hosted by Supertab Connect and verifies the ES256 signature.
|
|
160
|
+
Handles an incoming request end-to-end: extracts the license token from the `Authorization` header, verifies it, records an analytics event, and applies bot detection and enforcement mode when no token is present.
|
|
167
161
|
|
|
168
162
|
**Parameters:**
|
|
169
163
|
|
|
170
|
-
- `
|
|
171
|
-
- `
|
|
164
|
+
- `request` (`Request`): The incoming HTTP request
|
|
165
|
+
- `ctx` (`ExecutionContext`, optional): Execution context for non-blocking event recording
|
|
172
166
|
|
|
173
|
-
**Returns:**
|
|
167
|
+
**Returns:** `HandlerResult` — either `{ action: "allow" }` or `{ action: "block", status, body, headers }`.
|
|
174
168
|
|
|
175
|
-
|
|
176
|
-
- `valid`: boolean indicating if token is valid
|
|
177
|
-
- `reason`: string reason for failure (if invalid)
|
|
178
|
-
- `licenseId`: the license ID (if valid)
|
|
179
|
-
- `payload`: decoded token payload (if valid)
|
|
169
|
+
### `cloudflareHandleRequests(request, env, ctx): Promise<Response>` (static)
|
|
180
170
|
|
|
181
|
-
|
|
171
|
+
Convenience handler for Cloudflare Workers. Reads config from Worker environment bindings (`MERCHANT_API_KEY`, `MERCHANT_SYSTEM_URN`).
|
|
182
172
|
|
|
183
|
-
|
|
184
|
-
const licenseToken = "eyJhbGciOiJFUzI1..."; // Token from Authorization header
|
|
185
|
-
const verification = await supertabConnect.verifyLicenseToken(
|
|
186
|
-
licenseToken,
|
|
187
|
-
"https://example.com/article"
|
|
188
|
-
);
|
|
173
|
+
**Parameters:**
|
|
189
174
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
} else {
|
|
194
|
-
// Block access
|
|
195
|
-
console.log("License verification failed:", verification.reason);
|
|
196
|
-
}
|
|
197
|
-
```
|
|
175
|
+
- `request` (`Request`): The incoming Worker request
|
|
176
|
+
- `env` (`Env`): Worker environment bindings
|
|
177
|
+
- `ctx` (`ExecutionContext`): Worker execution context
|
|
198
178
|
|
|
199
|
-
### `
|
|
179
|
+
### `fastlyHandleRequests(request, merchantSystemUrn, merchantApiKey, originBackend, options?): Promise<Response>` (static)
|
|
200
180
|
|
|
201
|
-
|
|
181
|
+
Convenience handler for Fastly Compute.
|
|
202
182
|
|
|
203
183
|
**Parameters:**
|
|
204
184
|
|
|
205
|
-
- `
|
|
206
|
-
- `
|
|
207
|
-
- `
|
|
185
|
+
- `request` (`Request`): The incoming Fastly request
|
|
186
|
+
- `merchantSystemUrn` (`string`): Your merchant system identifier
|
|
187
|
+
- `merchantApiKey` (`string`): Your Supertab merchant API key
|
|
188
|
+
- `originBackend` (`string`): The Fastly backend name to forward allowed requests to
|
|
189
|
+
- `options.enableRSL` (`boolean`, optional): Serve `license.xml` at `/license.xml` for RSL-compliant clients (default: `false`)
|
|
190
|
+
- `options.botDetector` (`BotDetector`, optional): Custom bot detection function
|
|
191
|
+
- `options.enforcement` (`EnforcementMode`, optional): Enforcement mode
|
|
208
192
|
|
|
209
|
-
|
|
193
|
+
### `cloudfrontHandleRequests(event, options): Promise<CloudFrontRequestResult>` (static)
|
|
210
194
|
|
|
211
|
-
|
|
212
|
-
// Record a page view with additional properties
|
|
213
|
-
await supertabConnect.recordEvent("page_viewed", {
|
|
214
|
-
page_url: request.url,
|
|
215
|
-
user_agent: request.headers.get("User-Agent"),
|
|
216
|
-
referrer: request.headers.get("Referer"),
|
|
217
|
-
article_id: "12345",
|
|
218
|
-
});
|
|
219
|
-
```
|
|
220
|
-
|
|
221
|
-
### `checkIfBotRequest(request: Request): boolean`
|
|
222
|
-
|
|
223
|
-
A simple check based on the information passed in request's Headers to decide whether it comes from a crawler/bot/AI agent or not.
|
|
195
|
+
Convenience handler for AWS CloudFront Lambda@Edge viewer-request functions.
|
|
224
196
|
|
|
225
197
|
**Parameters:**
|
|
226
198
|
|
|
227
|
-
- `
|
|
228
|
-
|
|
229
|
-
**Returns:**
|
|
199
|
+
- `event` (`CloudFrontRequestEvent`): The CloudFront viewer-request event
|
|
200
|
+
- `options` (`CloudfrontHandlerOptions`): Configuration object with `apiKey`, `merchantSystemUrn`, and optional `botDetector`/`enforcement`
|
|
230
201
|
|
|
231
|
-
|
|
202
|
+
### `obtainLicenseToken(options): Promise<string>` (static)
|
|
232
203
|
|
|
233
|
-
|
|
204
|
+
Request a license token from the Supertab Connect token endpoint using OAuth2 client credentials.
|
|
234
205
|
|
|
235
|
-
|
|
206
|
+
**Parameters (options object):**
|
|
236
207
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
- `licenseXml` (string): XML license document associated with the resource url attempting to access
|
|
208
|
+
| Parameter | Type | Required | Description |
|
|
209
|
+
| -------------- | --------- | -------- | ----------------------------------------------- |
|
|
210
|
+
| `clientId` | `string` | Yes | OAuth client identifier |
|
|
211
|
+
| `clientSecret` | `string` | Yes | OAuth client secret for client_credentials flow |
|
|
212
|
+
| `resourceUrl` | `string` | Yes | Resource URL to obtain a license for |
|
|
213
|
+
| `debug` | `boolean` | No | Enable debug logging |
|
|
244
214
|
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
- `Promise<string>`: The issued license access token
|
|
215
|
+
```
|
package/dist/index.cjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
"use strict";var H=Object.create;var R=Object.defineProperty;var W=Object.getOwnPropertyDescriptor;var M=Object.getOwnPropertyNames;var V=Object.getPrototypeOf,j=Object.prototype.hasOwnProperty;var X=(n,e)=>{for(var r in e)R(n,r,{get:e[r],enumerable:!0})},P=(n,e,r,t)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of M(e))!j.call(n,s)&&s!==r&&R(n,s,{get:()=>e[s],enumerable:!(t=W(e,s))||t.enumerable});return n};var G=(n,e,r)=>(r=n!=null?H(V(n)):{},P(e||!n||!n.__esModule?R(r,"default",{value:n,enumerable:!0}):r,n)),z=n=>P(R({},"__esModule",{value:!0}),n);var oe={};X(oe,{EnforcementMode:()=>L,HandlerAction:()=>y,SupertabConnect:()=>U,defaultBotDetector:()=>K});module.exports=z(oe);var L=(t=>(t.DISABLED="disabled",t.SOFT="soft",t.STRICT="strict",t))(L||{});var g="stc-backend",y=(r=>(r.ALLOW="allow",r.BLOCK="block",r))(y||{});var E=null;function v(){return E||(E=import("jose")),E}async function Y(n,e,r){try{let t=await fetch(n,e);if(!t.ok){let o=await t.text().catch(()=>""),i=`Failed to obtain license token: ${t.status} ${t.statusText}${o?` - ${o}`:""}`;throw new Error(i)}let s;try{s=await t.json()}catch(o){throw r&&console.error("Failed to parse license token response as JSON:",o),new Error("Failed to parse license token response as JSON")}if(!s?.access_token)throw new Error("License token response missing access_token");return s.access_token}catch(t){throw r&&console.error("Error generating license token:",t),t}}async function Q(n,e){let t=`${new URL(n).origin}/license.xml`,s=await fetch(t);if(!s.ok)throw e&&console.error(`Failed to fetch license.xml from ${t}: ${s.status}`),new Error(`Failed to fetch license.xml from ${t}: ${s.status}`);let o=await s.text();return e&&console.debug("Fetched license.xml from",t),o}function Z(n,e){let r=[],t=/<content\s([^>]*)>([\s\S]*?)<\/content>/gi,s=/url\s*=\s*"([^"]*)"/i,o=/server\s*=\s*"([^"]*)"/i,i=/<license[^>]*>[\s\S]*?<\/license>/i,a=0,c;for(;(c=t.exec(n))!==null;){a++;let l=c[1],d=c[2],f=l.match(s),h=l.match(o),m=d.match(i);if(f&&h&&m)r.push({urlPattern:f[1],server:h[1],licenseXml:m[0]});else if(e){let w=[!f&&"url",!h&&"server",!m&&"<license>"].filter(Boolean).join(", ");console.debug(`Skipping <content> element #${a}: missing ${w}`)}}return e&&console.debug(`Found ${a} <content> element(s), ${r.length} valid`),r}function ee(n,e,r){let t=new URL(e),s=t.host,o=t.pathname;r&&console.debug(`Matching resource URL: ${e} (host=${s}, path=${o})`);let i=null,a=-1;for(let c of n){let l;try{l=new URL(c.urlPattern)}catch{r&&console.debug(`Skipping block with invalid URL pattern: ${c.urlPattern}`);continue}if(l.host!==s){r&&console.debug(`Skipping block: host mismatch (pattern=${l.host}, resource=${s})`);continue}let d=l.pathname;if(d===o)return r&&console.debug(`Exact match found: ${c.urlPattern}`),c;if(d.endsWith("/*")){let f=d.slice(0,-1);if(o.startsWith(f)){let h=f.length;h>a&&(a=h,i=c)}}}return r&&console.debug(i?`Wildcard match found: ${i.urlPattern} (specificity=${a})`:`No matching content block found for ${e}`),i}async function C({clientId:n,clientSecret:e,resourceUrl:r,debug:t}){let s=await Q(r,t);t&&console.debug(`Fetched license.xml (${s.length} chars)`);let o=Z(s,t);if(o.length===0)throw t&&console.error("No valid <content> elements with <license> found in license.xml"),new Error("No valid <content> elements with <license> found in license.xml");let i=ee(o,r,t);if(!i){if(t){let d=o.map(f=>f.urlPattern).join(", ");console.error(`No <content> element matches resource URL: ${r}. Available patterns: ${d}`)}throw new Error(`No <content> element in license.xml matches resource URL: ${r}`)}t&&(console.debug("Matched content block for resource URL:",r),console.debug("Using license XML:",i.licenseXml));let a=i.server+"/token";t&&console.debug(`Requesting license token from ${a}`);let c=new URLSearchParams({grant_type:"client_credentials",license:i.licenseXml,resource:i.urlPattern}),l={method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json",Authorization:"Basic "+btoa(`${n}:${e}`)},body:c.toString()};return Y(a,l,t)}var A=new Map;function te(){let n={method:"GET"};return globalThis?.fastly&&(n={...n,backend:g}),n}async function ne({cacheKey:n,url:e,debug:r,failureMessage:t,logLabel:s}){if(!A.has(n))try{let o=await fetch(e,te());if(!o.ok)throw new Error(`${t}: ${o.status}`);let i=await o.json();A.set(n,i)}catch(o){throw r&&console.error(s,o),o}return A.get(n)}async function D(n,e){let r=`${n}/.well-known/jwks.json/platform`;return e&&console.debug(`Fetching platform JWKS from URL: ${r}`),ne({cacheKey:"platform_jwks",url:r,debug:e,failureMessage:"Failed to fetch platform JWKS",logLabel:"Error fetching platform JWKS:"})}var k=n=>n.trim().replace(/\/+$/,"");async function S({licenseToken:n,requestUrl:e,supertabBaseUrl:r,debug:t}){let{decodeProtectedHeader:s,decodeJwt:o,jwtVerify:i}=await v();if(!n)return{valid:!1,reason:"missing_license_token"};let a;try{a=s(n)}catch(p){return t&&console.error("Invalid license JWT header:",p),{valid:!1,reason:"invalid_license_header"}}if(a.alg!=="ES256")return t&&console.error("Unsupported license JWT alg:",a.alg),{valid:!1,reason:"invalid_license_algorithm"};let c;try{c=o(n)}catch(p){return t&&console.error("Invalid license JWT payload:",p),{valid:!1,reason:"invalid_license_payload"}}let l=c.license_id,d=c.iss,f=d?k(d):void 0,h=k(r);if(!f||!f.startsWith(h))return t&&console.error("License JWT issuer is missing or malformed:",d),{valid:!1,reason:"invalid_license_issuer",licenseId:l};let m=Array.isArray(c.aud)?c.aud.filter(p=>typeof p=="string"):typeof c.aud=="string"?[c.aud]:[],w=k(e);if(!m.some(p=>{let b=k(p);return b?w.startsWith(b):!1}))return t&&console.error("License JWT audience does not match request URL:",c.aud),{valid:!1,reason:"invalid_license_audience",licenseId:l};let _;try{_=await D(r,t)}catch(p){return t&&console.error("Failed to fetch platform JWKS:",p),{valid:!1,reason:"server_error",licenseId:l}}try{let b=await i(n,async I=>{let x=_.keys.find(q=>q.kid===I.kid);if(!x)throw new Error(`No matching platform key found: ${I.kid}`);return x},{issuer:d,algorithms:[a.alg],clockTolerance:"1m"});return{valid:!0,licenseId:l,payload:b.payload}}catch(p){return t&&console.error("License JWT verification failed:",p),p instanceof Error&&p.message?.includes("exp")?{valid:!1,reason:"license_token_expired",licenseId:l}:{valid:!1,reason:"license_signature_verification_failed",licenseId:l}}}function B({requestUrl:n}){let e=new URL(n);return`${e.protocol}//${e.host}/license.xml`}function N(n){let e=B({requestUrl:n});return{action:"allow",headers:{Link:`<${e}>; rel="license"; type="application/rsl+xml"`,"X-RSL-Status":"token_required","X-RSL-Reason":"missing"}}}function T({reason:n,requestUrl:e,supertabBaseUrl:r}){let t,s,o;switch(n){case"missing_license_token":o=401,t="invalid_request",s="Authorization header missing or malformed";break;case"invalid_license_algorithm":o=401,t="invalid_request",s="Unsupported token algorithm";break;case"license_token_expired":o=401,t="invalid_token",s="The license token has expired";break;case"license_signature_verification_failed":o=401,t="invalid_token",s="The license token signature is invalid";break;case"invalid_license_header":o=401,t="invalid_token",s="The license token header is malformed";break;case"invalid_license_payload":o=401,t="invalid_token",s="The license token payload is malformed";break;case"invalid_license_issuer":o=401,t="invalid_token",s="The license token issuer is not recognized";break;case"invalid_license_audience":o=403,t="insufficient_scope",s="The license does not grant access to this resource";break;case"server_error":o=503,t="server_error",s="The server encountered an error validating the license";break;default:o=401,t="invalid_token",s="License token missing, expired, revoked, or malformed"}let i=B({requestUrl:e});return{action:"block",status:o,body:`Access to this resource requires a valid license token. Error: ${t} - ${s}`,headers:{"Content-Type":"text/plain; charset=UTF-8","WWW-Authenticate":`License error="${t}", error_description="${s}"`,Link:`<${i}>; rel="license"; type="application/rsl+xml"`}}}function se(){let n={method:"GET"};return globalThis?.fastly&&(n={...n,backend:g}),n}async function $(n,e){let r=`${n}/merchants/systems/${e}/license.xml`,t=await fetch(r,se());if(!t.ok)return new Response("License not found",{status:404});let s=await t.text();return new Response(s,{status:200,headers:new Headers({"Content-Type":"application/xml"})})}async function O(n){let e=await S({licenseToken:n.token,requestUrl:n.url,supertabBaseUrl:n.supertabBaseUrl,debug:n.debug});if(n.recordEvent){let r=e.valid?"license_used":e.reason,t={page_url:n.url,user_agent:n.userAgent,verification_status:e.valid?"valid":"invalid",verification_reason:e.valid?"success":e.reason},s=n.recordEvent(r,t,e.licenseId);n.ctx?.waitUntil&&n.ctx.waitUntil(s)}return e.valid?{action:"allow"}:T({reason:e.reason,requestUrl:n.url,supertabBaseUrl:n.supertabBaseUrl})}async function F(n,e,r){let t=await n.handleRequest(e,r);if(t.action==="block")return new Response(t.body,{status:t.status,headers:new Headers(t.headers)});let s=await fetch(e);if(t.headers){let o=new Response(s.body,s);for(let[i,a]of Object.entries(t.headers))o.headers.set(i,a);return o}return s}async function J(n,e,r,t){if(t&&new URL(e.url).pathname==="/license.xml")return await $(t.baseUrl,t.merchantSystemUrn);let s=await n.handleRequest(e);if(s.action==="block")return new Response(s.body,{status:s.status,headers:new Headers(s.headers)});let o=await fetch(e,{backend:r});if(s.headers){let i=new Response(o.body,o);for(let[a,c]of Object.entries(s.headers))i.headers.set(a,c);return i}return o}function K(n){let e=n.headers.get("User-Agent")||"",r=n.headers.get("accept")||"",t=n.headers.get("sec-ch-ua"),s=n.headers.get("accept-language"),o=n.cf?.botManagement?.score,i=["chatgpt-user","perplexitybot","gptbot","anthropic-ai","ccbot","claude-web","claudebot","cohere-ai","youbot","diffbot","oai-searchbot","meta-externalagent","timpibot","amazonbot","bytespider","perplexity-user","googlebot","bot","curl","wget"],a=e.toLowerCase(),c=i.some(m=>a.includes(m)),l=e.toLowerCase().includes("headless")||e.toLowerCase().includes("puppeteer")||!t,d=!e.toLowerCase().includes("headless")&&!e.toLowerCase().includes("puppeteer")&&!t,f=!r||!s,h=typeof o=="number"&&o<30;return(a.includes("safari")||a.includes("mozilla"))&&l&&d?!1:c||l||f||h}var u=class u{constructor(e,r=!1){if(!r&&u._instance){if(!(e.apiKey===u._instance.apiKey&&e.merchantSystemUrn===u._instance.merchantSystemUrn))throw new Error("Cannot create a new instance with different configuration. Use resetInstance to clear the existing instance.");return u._instance}if(r&&u._instance&&u.resetInstance(),!e.apiKey||!e.merchantSystemUrn)throw new Error("Missing required configuration: apiKey and merchantSystemUrn are required");this.apiKey=e.apiKey,this.merchantSystemUrn=e.merchantSystemUrn,this.enforcement=e.enforcement??"soft",this.botDetector=e.botDetector,this.debug=e.debug??!1,u._instance=this}static resetInstance(){u._instance=null}static setBaseUrl(e){u.baseUrl=e}static getBaseUrl(){return u.baseUrl}async verifyLicenseToken(e,r){return S({licenseToken:e,requestUrl:r,supertabBaseUrl:u.baseUrl,debug:this.debug})}async recordEvent(e,r={},t){let s={event_name:e,merchant_system_urn:this.merchantSystemUrn?this.merchantSystemUrn:"",license_id:t,properties:r};try{let o={method:"POST",headers:{Authorization:`Bearer ${this.apiKey}`,"Content-Type":"application/json"},body:JSON.stringify(s)};globalThis?.fastly&&(o={...o,backend:g});let i=await fetch(`${u.baseUrl}/events`,o);i.ok||console.log(`Failed to record event: ${i.status}`)}catch(o){console.log("Error recording event:",o)}}async handleRequest(e,r){let t=e.headers.get("Authorization")||"",s=t.startsWith("License ")?t.slice(8):null,o=e.url,i=e.headers.get("User-Agent")||"unknown";if(s)return this.enforcement==="disabled"?{action:"allow"}:O({token:s,url:o,userAgent:i,supertabBaseUrl:u.baseUrl,debug:this.debug,recordEvent:this.recordEvent.bind(this),ctx:r});if(!(this.botDetector?.(e,r)??!1))return{action:"allow"};switch(this.enforcement){case"strict":return T({reason:"missing_license_token",requestUrl:o,supertabBaseUrl:u.baseUrl});case"soft":return N(o);default:return{action:"allow"}}}static async obtainLicenseToken(e,r,t,s=!1){return C({clientId:e,clientSecret:r,resourceUrl:t,debug:s})}static async cloudflareHandleRequests(e,r,t){let s=new u({apiKey:r.MERCHANT_API_KEY,merchantSystemUrn:r.MERCHANT_SYSTEM_URN});return F(s,e,t)}static async fastlyHandleRequests(e,r,t,s,o){let{enableRSL:i=!1,botDetector:a,enforcement:c}=o??{},l=new u({apiKey:t,merchantSystemUrn:r,botDetector:a,enforcement:c});return J(l,e,s,i?{baseUrl:u.baseUrl,merchantSystemUrn:r}:void 0)}};u.baseUrl="https://api-connect.supertab.co",u._instance=null;var U=u;0&&(module.exports={EnforcementMode,HandlerAction,SupertabConnect,defaultBotDetector});
|
|
1
|
+
"use strict";var W=Object.create;var b=Object.defineProperty;var j=Object.getOwnPropertyDescriptor;var G=Object.getOwnPropertyNames;var X=Object.getPrototypeOf,z=Object.prototype.hasOwnProperty;var Y=(t,e)=>{for(var r in e)b(t,r,{get:e[r],enumerable:!0})},P=(t,e,r,n)=>{if(e&&typeof e=="object"||typeof e=="function")for(let s of G(e))!z.call(t,s)&&s!==r&&b(t,s,{get:()=>e[s],enumerable:!(n=j(e,s))||n.enumerable});return t};var Q=(t,e,r)=>(r=t!=null?W(X(t)):{},P(e||!t||!t.__esModule?b(r,"default",{value:t,enumerable:!0}):r,t)),Z=t=>P(b({},"__esModule",{value:!0}),t);var ue={};Y(ue,{EnforcementMode:()=>I,HandlerAction:()=>R,SupertabConnect:()=>T,defaultBotDetector:()=>J});module.exports=Z(ue);var I=(n=>(n.DISABLED="disabled",n.SOFT="soft",n.STRICT="strict",n))(I||{});var y="stc-backend",R=(r=>(r.ALLOW="allow",r.BLOCK="block",r))(R||{});var w=null;function S(){return w||(w=import("jose")),w}async function ee(t,e,r){try{let n=await fetch(t,e);if(!n.ok){let o=await n.text().catch(()=>""),a=`Failed to obtain license token: ${n.status} ${n.statusText}${o?` - ${o}`:""}`;throw new Error(a)}let s;try{s=await n.json()}catch(o){throw r&&console.error("Failed to parse license token response as JSON:",o),new Error("Failed to parse license token response as JSON")}if(!s?.access_token)throw new Error("License token response missing access_token");return s.access_token}catch(n){throw r&&console.error("Error generating license token:",n),n}}async function te(t,e){let n=`${new URL(t).origin}/license.xml`,s=await fetch(n);if(!s.ok)throw e&&console.error(`Failed to fetch license.xml from ${n}: ${s.status}`),new Error(`Failed to fetch license.xml from ${n}: ${s.status}`);let o=await s.text();return e&&console.debug("Fetched license.xml from",n),o}function re(t,e){let r=[],n=/<content\s([^>]*)>([\s\S]*?)<\/content>/gi,s=/url\s*=\s*"([^"]*)"/i,o=/server\s*=\s*"([^"]*)"/i,a=/<license[^>]*>[\s\S]*?<\/license>/i,c=0,i;for(;(i=n.exec(t))!==null;){c++;let l=i[1],d=i[2],p=l.match(s),m=l.match(o),g=d.match(a);if(p&&m&&g)r.push({urlPattern:p[1],server:m[1],licenseXml:g[0]});else if(e){let A=[!p&&"url",!m&&"server",!g&&"<license>"].filter(Boolean).join(", ");console.debug(`Skipping <content> element #${c}: missing ${A}`)}}return e&&console.debug(`Found ${c} <content> element(s), ${r.length} valid`),r}function ne(t,e,r){let n=new URL(e),s=n.host,o=n.pathname;r&&console.debug(`Matching resource URL: ${e} (host=${s}, path=${o})`);let a=null,c=-1;for(let i of t){let l;try{l=new URL(i.urlPattern)}catch{r&&console.debug(`Skipping block with invalid URL pattern: ${i.urlPattern}`);continue}if(l.host!==s){r&&console.debug(`Skipping block: host mismatch (pattern=${l.host}, resource=${s})`);continue}let d=l.pathname;if(d===o)return r&&console.debug(`Exact match found: ${i.urlPattern}`),i;if(d.endsWith("/*")){let p=d.slice(0,-1);if(o.startsWith(p)){let m=p.length;m>c&&(c=m,a=i)}}}return r&&console.debug(a?`Wildcard match found: ${a.urlPattern} (specificity=${c})`:`No matching content block found for ${e}`),a}async function N({clientId:t,clientSecret:e,resourceUrl:r,debug:n}){let s=await te(r,n);n&&console.debug(`Fetched license.xml (${s.length} chars)`);let o=re(s,n);if(o.length===0)throw n&&console.error("No valid <content> elements with <license> found in license.xml"),new Error("No valid <content> elements with <license> found in license.xml");let a=ne(o,r,n);if(!a){if(n){let d=o.map(p=>p.urlPattern).join(", ");console.error(`No <content> element matches resource URL: ${r}. Available patterns: ${d}`)}throw new Error(`No <content> element in license.xml matches resource URL: ${r}`)}n&&(console.debug("Matched content block for resource URL:",r),console.debug("Using license XML:",a.licenseXml));let c=a.server+"/token";n&&console.debug(`Requesting license token from ${c}`);let i=new URLSearchParams({grant_type:"client_credentials",license:a.licenseXml,resource:a.urlPattern}),l={method:"POST",headers:{"Content-Type":"application/x-www-form-urlencoded",Accept:"application/json",Authorization:"Basic "+btoa(`${t}:${e}`)},body:i.toString()};return ee(c,l,n)}var k=new Map;function se(){let t={method:"GET"};return globalThis?.fastly&&(t={...t,backend:y}),t}async function oe({cacheKey:t,url:e,debug:r,failureMessage:n,logLabel:s}){if(!k.has(t))try{let o=await fetch(e,se());if(!o.ok)throw new Error(`${n}: ${o.status}`);let a=await o.json();k.set(t,a)}catch(o){throw r&&console.error(s,o),o}return k.get(t)}async function q(t,e){let r=`${t}/.well-known/jwks.json/platform`;return e&&console.debug(`Fetching platform JWKS from URL: ${r}`),oe({cacheKey:"platform_jwks",url:r,debug:e,failureMessage:"Failed to fetch platform JWKS",logLabel:"Error fetching platform JWKS:"})}async function F({apiKey:t,merchantSystemUrn:e,baseUrl:r,eventName:n,properties:s,licenseId:o,debug:a=!1}){let c={event_name:n,merchant_system_urn:e,license_id:o,properties:s};try{let i={method:"POST",headers:{Authorization:`Bearer ${t}`,"Content-Type":"application/json"},body:JSON.stringify(c)};globalThis?.fastly&&(i={...i,backend:y});let l=await fetch(`${r}/events`,i);!l.ok&&a&&console.error(`Failed to record event: ${l.status}`)}catch(i){a&&console.error("Error recording event:",i)}}var L=t=>t.trim().replace(/\/+$/,"");function h(t){switch(t){case"missing_license_token":return"Authorization header missing or malformed";case"invalid_license_algorithm":return"Unsupported token algorithm";case"license_token_expired":return"The license token has expired";case"license_signature_verification_failed":return"The license token signature is invalid";case"invalid_license_header":return"The license token header is malformed";case"invalid_license_payload":return"The license token payload is malformed";case"invalid_license_issuer":return"The license token issuer is not recognized";case"invalid_license_audience":return"The license does not grant access to this resource";case"server_error":return"The server encountered an error validating the license";default:return"License token missing, expired, revoked, or malformed"}}async function x({licenseToken:t,requestUrl:e,supertabBaseUrl:r,debug:n}){let{decodeProtectedHeader:s,decodeJwt:o,jwtVerify:a}=await S();if(!t)return{valid:!1,reason:"missing_license_token",error:h("missing_license_token")};let c;try{c=s(t)}catch(f){return n&&console.error("Invalid license JWT header:",f),{valid:!1,reason:"invalid_license_header",error:h("invalid_license_header")}}if(c.alg!=="ES256")return n&&console.error("Unsupported license JWT alg:",c.alg),{valid:!1,reason:"invalid_license_algorithm",error:h("invalid_license_algorithm")};let i;try{i=o(t)}catch(f){return n&&console.error("Invalid license JWT payload:",f),{valid:!1,reason:"invalid_license_payload",error:h("invalid_license_payload")}}let l=i.license_id,d=i.iss,p=d?L(d):void 0,m=L(r);if(!p||!p.startsWith(m))return n&&console.error("License JWT issuer is missing or malformed:",d),{valid:!1,reason:"invalid_license_issuer",error:h("invalid_license_issuer"),licenseId:l};let g=Array.isArray(i.aud)?i.aud.filter(f=>typeof f=="string"):typeof i.aud=="string"?[i.aud]:[],A=L(e);if(!g.some(f=>{let E=L(f);return E?A.startsWith(E):!1}))return n&&console.error("License JWT audience does not match request URL:",i.aud),{valid:!1,reason:"invalid_license_audience",error:h("invalid_license_audience"),licenseId:l};let C;try{C=await q(r,n)}catch(f){return n&&console.error("Failed to fetch platform JWKS:",f),{valid:!1,reason:"server_error",error:h("server_error"),licenseId:l}}try{let E=await a(t,async _=>{let D=C.keys.find(M=>M.kid===_.kid);if(!D)throw new Error(`No matching platform key found: ${_.kid}`);return D},{issuer:d,algorithms:[c.alg],clockTolerance:"1m"});return{valid:!0,licenseId:l,payload:E.payload}}catch(f){return n&&console.error("License JWT verification failed:",f),f instanceof Error&&f.message?.includes("exp")?{valid:!1,reason:"license_token_expired",error:h("license_token_expired"),licenseId:l}:{valid:!1,reason:"license_signature_verification_failed",error:h("license_signature_verification_failed"),licenseId:l}}}function O({requestUrl:t}){let e=new URL(t);return`${e.protocol}//${e.host}/license.xml`}function $(t){let e=O({requestUrl:t});return{action:"allow",headers:{Link:`<${e}>; rel="license"; type="application/rsl+xml"`,"X-RSL-Status":"token_required","X-RSL-Reason":"missing"}}}function ae(t){switch(t){case"missing_license_token":case"invalid_license_algorithm":return{rslError:"invalid_request",status:401};case"license_token_expired":case"license_signature_verification_failed":case"invalid_license_header":case"invalid_license_payload":case"invalid_license_issuer":return{rslError:"invalid_token",status:401};case"invalid_license_audience":return{rslError:"insufficient_scope",status:403};case"server_error":return{rslError:"server_error",status:503};default:return{rslError:"invalid_token",status:401}}}function ce(t){return t.replace(/[\r\n]/g,"").replace(/\\/g,"\\\\").replace(/"/g,'\\"')}function U({reason:t,error:e,requestUrl:r}){let{rslError:n,status:s}=ae(t),o=ce(e),a=O({requestUrl:r});return{action:"block",status:s,body:`Access to this resource requires a valid license token. Error: ${n} - ${e}`,headers:{"Content-Type":"text/plain; charset=UTF-8","WWW-Authenticate":`License error="${n}", error_description="${o}"`,Link:`<${a}>; rel="license"; type="application/rsl+xml"`}}}function le(){let t={method:"GET"};return globalThis?.fastly&&(t={...t,backend:y}),t}async function B(t,e){let r=`${t}/merchants/systems/${e}/license.xml`,n=await fetch(r,le());if(!n.ok)return new Response("License not found",{status:404});let s=await n.text();return new Response(s,{status:200,headers:new Headers({"Content-Type":"application/xml"})})}async function v(t){let e=await x({licenseToken:t.token,requestUrl:t.url,supertabBaseUrl:t.supertabBaseUrl,debug:t.debug}),r=F({apiKey:t.apiKey,merchantSystemUrn:t.merchantSystemUrn,baseUrl:t.supertabBaseUrl,eventName:e.valid?"license_used":e.reason,properties:{page_url:t.url,user_agent:t.userAgent,verification_status:e.valid?"valid":"invalid",verification_reason:e.valid?"success":e.reason},licenseId:e.licenseId,debug:t.debug});return t.ctx?.waitUntil&&t.ctx.waitUntil(r),e}async function H(t,e,r){let n=await t.handleRequest(e,r);if(n.action==="block")return new Response(n.body,{status:n.status,headers:new Headers(n.headers)});let s=await fetch(e);if(n.headers){let o=new Response(s.body,s);for(let[a,c]of Object.entries(n.headers))o.headers.set(a,c);return o}return s}async function K(t,e,r,n){if(n&&new URL(e.url).pathname==="/license.xml")return await B(n.baseUrl,n.merchantSystemUrn);let s=await t.handleRequest(e);if(s.action==="block")return new Response(s.body,{status:s.status,headers:new Headers(s.headers)});let o=await fetch(e,{backend:r});if(s.headers){let a=new Response(o.body,o);for(let[c,i]of Object.entries(s.headers))a.headers.set(c,i);return a}return o}async function V(t,e){let r=e.Records[0].cf.request,n=`https://${r.headers.host[0].value}${r.uri}${r.querystring?"?"+r.querystring:""}`,s=new Headers;Object.entries(r.headers).forEach(([c,i])=>{i.forEach(({value:l})=>s.append(c,l))});let o=new Request(n,{method:r.method,headers:s}),a=await t.handleRequest(o);if(a.action==="block"){let c={};return Object.entries(a.headers).forEach(([i,l])=>{c[i.toLowerCase()]=[{key:i,value:l}]}),{status:a.status.toString(),statusDescription:a.status===401?"Unauthorized":"Payment Required",headers:c,body:a.body}}return r}function J(t){let e=t.headers.get("User-Agent")||"",r=t.headers.get("accept")||"",n=t.headers.get("sec-ch-ua"),s=t.headers.get("accept-language"),o=t.cf?.botManagement?.score,a=["chatgpt-user","perplexitybot","gptbot","anthropic-ai","ccbot","claude-web","claudebot","cohere-ai","youbot","diffbot","oai-searchbot","meta-externalagent","timpibot","amazonbot","bytespider","perplexity-user","googlebot","bot","curl","wget"],c=e.toLowerCase(),i=a.some(g=>c.includes(g)),l=c.includes("headless")||c.includes("puppeteer")||!n,d=!c.includes("headless")&&!c.includes("puppeteer")&&!n,p=!r||!s,m=typeof o=="number"&&o<30;return(c.includes("safari")||c.includes("mozilla"))&&l&&d?!1:i||l||p||m}var u=class u{constructor(e,r=!1){if(!r&&u._instance){if(!(e.apiKey===u._instance.apiKey&&e.merchantSystemUrn===u._instance.merchantSystemUrn))throw new Error("Cannot create a new instance with different configuration. Use resetInstance to clear the existing instance.");return u._instance}if(r&&u._instance&&u.resetInstance(),!e.apiKey||!e.merchantSystemUrn)throw new Error("Missing required configuration: apiKey and merchantSystemUrn are required");this.apiKey=e.apiKey,this.merchantSystemUrn=e.merchantSystemUrn,this.enforcement=e.enforcement??"soft",this.botDetector=e.botDetector,this.debug=e.debug??!1,u._instance=this}static resetInstance(){u._instance=null}static setBaseUrl(e){u.baseUrl=e}static getBaseUrl(){return u.baseUrl}static async verify(e){let r=e.baseUrl??u.baseUrl,n=await x({licenseToken:e.token,requestUrl:e.resourceUrl,supertabBaseUrl:r,debug:e.debug??!1});return n.valid?{valid:!0}:{valid:!1,error:n.error}}async verifyAndRecord(e){let r=await v({token:e.token,url:e.resourceUrl,userAgent:e.userAgent??"unknown",supertabBaseUrl:u.baseUrl,debug:e.debug??this.debug,apiKey:this.apiKey,merchantSystemUrn:this.merchantSystemUrn,ctx:e.ctx});return r.valid?{valid:!0}:{valid:!1,error:r.error}}async handleRequest(e,r){let n=e.headers.get("Authorization")||"",s=n.startsWith("License ")?n.slice(8):null,o=e.url,a=e.headers.get("User-Agent")||"unknown";if(s){if(this.enforcement==="disabled")return{action:"allow"};let i=await v({token:s,url:o,userAgent:a,supertabBaseUrl:u.baseUrl,debug:this.debug,apiKey:this.apiKey,merchantSystemUrn:this.merchantSystemUrn,ctx:r});return i.valid?{action:"allow"}:U({reason:i.reason,error:i.error,requestUrl:o})}if(!(this.botDetector?.(e,r)??!1))return{action:"allow"};switch(this.enforcement){case"strict":return U({reason:"missing_license_token",error:"Authorization header missing or malformed",requestUrl:o});case"soft":return $(o);default:return{action:"allow"}}}static async obtainLicenseToken(e){return N({clientId:e.clientId,clientSecret:e.clientSecret,resourceUrl:e.resourceUrl,debug:e.debug})}static async cloudflareHandleRequests(e,r,n){let s=new u({apiKey:r.MERCHANT_API_KEY,merchantSystemUrn:r.MERCHANT_SYSTEM_URN});return H(s,e,n)}static async fastlyHandleRequests(e,r,n,s,o){let{enableRSL:a=!1,botDetector:c,enforcement:i}=o??{},l=new u({apiKey:n,merchantSystemUrn:r,botDetector:c,enforcement:i});return K(l,e,s,a?{baseUrl:u.baseUrl,merchantSystemUrn:r}:void 0)}static async cloudfrontHandleRequests(e,r){let n=new u({apiKey:r.apiKey,merchantSystemUrn:r.merchantSystemUrn,botDetector:r.botDetector,enforcement:r.enforcement});return V(n,e)}};u.baseUrl="https://api-connect.supertab.co",u._instance=null;var T=u;0&&(module.exports={EnforcementMode,HandlerAction,SupertabConnect,defaultBotDetector});
|
|
2
2
|
//# sourceMappingURL=index.cjs.map
|