@drawbridge/drawbridge-utils 0.0.41 → 0.0.43
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/dist/ai.cjs +4 -4
- package/dist/ai.js +127 -8
- package/dist/axios.cjs +1 -1
- package/dist/axios.js +1 -1
- package/dist/cdn.cjs +1 -1
- package/dist/cdn.js +1 -1
- package/dist/circuit.cjs +1 -1
- package/dist/circuit.js +50 -3
- package/dist/encrypt.cjs +3 -3
- package/dist/encrypt.js +38 -5
- package/dist/fetch.cjs +1 -1
- package/dist/fetch.js +1 -1
- package/dist/http.cjs +1 -1
- package/dist/http.js +1 -1
- package/dist/nanoid.cjs +1 -1
- package/dist/nanoid.js +1 -1
- package/dist/oauth/index.cjs +196 -0
- package/dist/oauth/index.d.cts +231 -0
- package/dist/oauth/index.d.ts +231 -0
- package/dist/oauth/index.js +151 -0
- package/dist/oauth/server.cjs +377 -0
- package/dist/oauth/server.d.cts +387 -0
- package/dist/oauth/server.d.ts +387 -0
- package/dist/oauth/server.js +341 -0
- package/dist/orders.cjs +1 -1
- package/dist/orders.js +1 -1
- package/dist/redirect.cjs +1 -1
- package/dist/redirect.js +1 -1
- package/dist/shopify.cjs +5 -5
- package/dist/shopify.js +46 -11
- package/dist/slugify.cjs +1 -1
- package/dist/slugify.js +1 -1
- package/dist/token.cjs +1 -1
- package/dist/token.js +21 -5
- package/dist/transactions.cjs +1 -1
- package/dist/transactions.js +108 -4
- package/dist/upload.cjs +1 -1
- package/dist/upload.js +1 -1
- package/package.json +20 -4
- package/dist/chunk-2DRAIKGZ.js +0 -38
- package/dist/chunk-6HH36OK6.js +0 -54
- package/dist/chunk-JT2PAZAZ.js +0 -113
- package/dist/chunk-OS2AHUWX.js +0 -27
- package/dist/oauth.cjs +0 -94
- package/dist/oauth.d.cts +0 -129
- package/dist/oauth.d.ts +0 -129
- package/dist/oauth.js +0 -70
package/dist/ai.cjs
CHANGED
|
@@ -16,7 +16,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
16
|
};
|
|
17
17
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
18
|
|
|
19
|
-
// ai.js
|
|
19
|
+
// lib/ai.js
|
|
20
20
|
var ai_exports = {};
|
|
21
21
|
__export(ai_exports, {
|
|
22
22
|
MARKUP: () => MARKUP,
|
|
@@ -31,7 +31,7 @@ __export(ai_exports, {
|
|
|
31
31
|
module.exports = __toCommonJS(ai_exports);
|
|
32
32
|
var import_genai = require("@google/genai");
|
|
33
33
|
|
|
34
|
-
// circuit.js
|
|
34
|
+
// lib/circuit.js
|
|
35
35
|
var CLOSED = "CLOSED";
|
|
36
36
|
var OPEN = "OPEN";
|
|
37
37
|
var HALF_OPEN = "HALF_OPEN";
|
|
@@ -82,7 +82,7 @@ var circuit = ({
|
|
|
82
82
|
};
|
|
83
83
|
};
|
|
84
84
|
|
|
85
|
-
// transactions.js
|
|
85
|
+
// lib/transactions.js
|
|
86
86
|
var import_drawbridge_telemetry = require("@drawbridge/drawbridge-telemetry");
|
|
87
87
|
var insertTransaction = async ({
|
|
88
88
|
db,
|
|
@@ -155,7 +155,7 @@ var debit = async ({
|
|
|
155
155
|
});
|
|
156
156
|
};
|
|
157
157
|
|
|
158
|
-
// ai.js
|
|
158
|
+
// lib/ai.js
|
|
159
159
|
var google_client = new import_genai.GoogleGenAI({
|
|
160
160
|
apiKey: process.env.GOOGLE_API_KEY
|
|
161
161
|
});
|
package/dist/ai.js
CHANGED
|
@@ -1,12 +1,131 @@
|
|
|
1
|
-
|
|
2
|
-
debit
|
|
3
|
-
} from "./chunk-JT2PAZAZ.js";
|
|
4
|
-
import {
|
|
5
|
-
circuit
|
|
6
|
-
} from "./chunk-6HH36OK6.js";
|
|
7
|
-
|
|
8
|
-
// ai.js
|
|
1
|
+
// lib/ai.js
|
|
9
2
|
import { GoogleGenAI } from "@google/genai";
|
|
3
|
+
|
|
4
|
+
// lib/circuit.js
|
|
5
|
+
var CLOSED = "CLOSED";
|
|
6
|
+
var OPEN = "OPEN";
|
|
7
|
+
var HALF_OPEN = "HALF_OPEN";
|
|
8
|
+
var circuit = ({
|
|
9
|
+
name,
|
|
10
|
+
threshold = 5,
|
|
11
|
+
timeout = 3e4
|
|
12
|
+
}) => {
|
|
13
|
+
let state = CLOSED;
|
|
14
|
+
let failures = 0;
|
|
15
|
+
let openedAt = null;
|
|
16
|
+
const trip = () => {
|
|
17
|
+
state = OPEN;
|
|
18
|
+
openedAt = Date.now();
|
|
19
|
+
console.error(`Circuit breaker OPEN: ${name}`);
|
|
20
|
+
};
|
|
21
|
+
const reset = () => {
|
|
22
|
+
state = CLOSED;
|
|
23
|
+
failures = 0;
|
|
24
|
+
openedAt = null;
|
|
25
|
+
console.log(`Circuit breaker CLOSED: ${name}`);
|
|
26
|
+
};
|
|
27
|
+
return async (fn) => {
|
|
28
|
+
if (state === OPEN) {
|
|
29
|
+
if (Date.now() - openedAt >= timeout) {
|
|
30
|
+
state = HALF_OPEN;
|
|
31
|
+
} else {
|
|
32
|
+
const error = new Error(`${name} is temporarily unavailable`);
|
|
33
|
+
error.status = 503;
|
|
34
|
+
throw error;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
try {
|
|
38
|
+
const result = await fn();
|
|
39
|
+
if (state === HALF_OPEN) {
|
|
40
|
+
reset();
|
|
41
|
+
} else {
|
|
42
|
+
failures = 0;
|
|
43
|
+
}
|
|
44
|
+
return result;
|
|
45
|
+
} catch (error) {
|
|
46
|
+
failures++;
|
|
47
|
+
if (state === HALF_OPEN || failures >= threshold) {
|
|
48
|
+
trip();
|
|
49
|
+
}
|
|
50
|
+
throw error;
|
|
51
|
+
}
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
// lib/transactions.js
|
|
56
|
+
import { currentTraceId } from "@drawbridge/drawbridge-telemetry";
|
|
57
|
+
var insertTransaction = async ({
|
|
58
|
+
db,
|
|
59
|
+
user,
|
|
60
|
+
type,
|
|
61
|
+
category,
|
|
62
|
+
source,
|
|
63
|
+
amount,
|
|
64
|
+
_id,
|
|
65
|
+
stripeInvoiceId,
|
|
66
|
+
stripeEventId,
|
|
67
|
+
session,
|
|
68
|
+
...rest
|
|
69
|
+
}) => {
|
|
70
|
+
var _a;
|
|
71
|
+
const beforeRaw = (_a = user == null ? void 0 : user.balance) == null ? void 0 : _a[type];
|
|
72
|
+
const balance = typeof beforeRaw === "number" ? { before: beforeRaw, after: beforeRaw + amount } : void 0;
|
|
73
|
+
const trace = currentTraceId();
|
|
74
|
+
await db.create({
|
|
75
|
+
authenticated: user,
|
|
76
|
+
collection: "transaction",
|
|
77
|
+
data: {
|
|
78
|
+
..._id && { _id },
|
|
79
|
+
user: user == null ? void 0 : user.id,
|
|
80
|
+
type,
|
|
81
|
+
category,
|
|
82
|
+
source,
|
|
83
|
+
amount,
|
|
84
|
+
...balance && { balance },
|
|
85
|
+
...trace && { trace },
|
|
86
|
+
...rest,
|
|
87
|
+
...stripeInvoiceId && { stripeInvoiceId },
|
|
88
|
+
...stripeEventId && { stripeEventId }
|
|
89
|
+
},
|
|
90
|
+
...session && { options: { session } }
|
|
91
|
+
});
|
|
92
|
+
};
|
|
93
|
+
var debit = async ({
|
|
94
|
+
db,
|
|
95
|
+
user,
|
|
96
|
+
amount,
|
|
97
|
+
type,
|
|
98
|
+
category,
|
|
99
|
+
source,
|
|
100
|
+
stripeInvoiceId,
|
|
101
|
+
stripeEventId,
|
|
102
|
+
session,
|
|
103
|
+
...rest
|
|
104
|
+
}) => {
|
|
105
|
+
if (!Number.isInteger(amount) || amount <= 0) {
|
|
106
|
+
throw new Error(`debit() requires a positive integer amount, got ${amount}`);
|
|
107
|
+
}
|
|
108
|
+
if (!type) {
|
|
109
|
+
throw new Error('debit() requires a type (e.g., "ai")');
|
|
110
|
+
}
|
|
111
|
+
if (!source) {
|
|
112
|
+
throw new Error('debit() requires a source ("system" | "admin" | "user")');
|
|
113
|
+
}
|
|
114
|
+
await insertTransaction({
|
|
115
|
+
db,
|
|
116
|
+
user,
|
|
117
|
+
type,
|
|
118
|
+
category,
|
|
119
|
+
source,
|
|
120
|
+
amount: -amount,
|
|
121
|
+
stripeInvoiceId,
|
|
122
|
+
stripeEventId,
|
|
123
|
+
session,
|
|
124
|
+
...rest
|
|
125
|
+
});
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
// lib/ai.js
|
|
10
129
|
var google_client = new GoogleGenAI({
|
|
11
130
|
apiKey: process.env.GOOGLE_API_KEY
|
|
12
131
|
});
|
package/dist/axios.cjs
CHANGED
|
@@ -26,7 +26,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
));
|
|
27
27
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
28
|
|
|
29
|
-
// axios.js
|
|
29
|
+
// lib/axios.js
|
|
30
30
|
var axios_exports = {};
|
|
31
31
|
__export(axios_exports, {
|
|
32
32
|
axios: () => axios,
|
package/dist/axios.js
CHANGED
package/dist/cdn.cjs
CHANGED
|
@@ -16,7 +16,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
16
|
};
|
|
17
17
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
18
|
|
|
19
|
-
// cdn.js
|
|
19
|
+
// lib/cdn.js
|
|
20
20
|
var cdn_exports = {};
|
|
21
21
|
__export(cdn_exports, {
|
|
22
22
|
cdnShopify: () => cdnShopify,
|
package/dist/cdn.js
CHANGED
package/dist/circuit.cjs
CHANGED
|
@@ -16,7 +16,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
16
|
};
|
|
17
17
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
18
|
|
|
19
|
-
// circuit.js
|
|
19
|
+
// lib/circuit.js
|
|
20
20
|
var circuit_exports = {};
|
|
21
21
|
__export(circuit_exports, {
|
|
22
22
|
circuit: () => circuit
|
package/dist/circuit.js
CHANGED
|
@@ -1,6 +1,53 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
// lib/circuit.js
|
|
2
|
+
var CLOSED = "CLOSED";
|
|
3
|
+
var OPEN = "OPEN";
|
|
4
|
+
var HALF_OPEN = "HALF_OPEN";
|
|
5
|
+
var circuit = ({
|
|
6
|
+
name,
|
|
7
|
+
threshold = 5,
|
|
8
|
+
timeout = 3e4
|
|
9
|
+
}) => {
|
|
10
|
+
let state = CLOSED;
|
|
11
|
+
let failures = 0;
|
|
12
|
+
let openedAt = null;
|
|
13
|
+
const trip = () => {
|
|
14
|
+
state = OPEN;
|
|
15
|
+
openedAt = Date.now();
|
|
16
|
+
console.error(`Circuit breaker OPEN: ${name}`);
|
|
17
|
+
};
|
|
18
|
+
const reset = () => {
|
|
19
|
+
state = CLOSED;
|
|
20
|
+
failures = 0;
|
|
21
|
+
openedAt = null;
|
|
22
|
+
console.log(`Circuit breaker CLOSED: ${name}`);
|
|
23
|
+
};
|
|
24
|
+
return async (fn) => {
|
|
25
|
+
if (state === OPEN) {
|
|
26
|
+
if (Date.now() - openedAt >= timeout) {
|
|
27
|
+
state = HALF_OPEN;
|
|
28
|
+
} else {
|
|
29
|
+
const error = new Error(`${name} is temporarily unavailable`);
|
|
30
|
+
error.status = 503;
|
|
31
|
+
throw error;
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
try {
|
|
35
|
+
const result = await fn();
|
|
36
|
+
if (state === HALF_OPEN) {
|
|
37
|
+
reset();
|
|
38
|
+
} else {
|
|
39
|
+
failures = 0;
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
} catch (error) {
|
|
43
|
+
failures++;
|
|
44
|
+
if (state === HALF_OPEN || failures >= threshold) {
|
|
45
|
+
trip();
|
|
46
|
+
}
|
|
47
|
+
throw error;
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
};
|
|
4
51
|
export {
|
|
5
52
|
circuit
|
|
6
53
|
};
|
package/dist/encrypt.cjs
CHANGED
|
@@ -26,7 +26,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
));
|
|
27
27
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
28
|
|
|
29
|
-
// encrypt.js
|
|
29
|
+
// lib/encrypt.js
|
|
30
30
|
var encrypt_exports = {};
|
|
31
31
|
__export(encrypt_exports, {
|
|
32
32
|
decrypt: () => decrypt,
|
|
@@ -35,14 +35,14 @@ __export(encrypt_exports, {
|
|
|
35
35
|
module.exports = __toCommonJS(encrypt_exports);
|
|
36
36
|
var import_crypto2 = __toESM(require("crypto"), 1);
|
|
37
37
|
|
|
38
|
-
// token.js
|
|
38
|
+
// lib/token.js
|
|
39
39
|
var import_crypto = __toESM(require("crypto"), 1);
|
|
40
40
|
var generate = (bytes = 32, encoding = "base64url") => {
|
|
41
41
|
const buf = import_crypto.default.randomBytes(bytes);
|
|
42
42
|
return encoding ? buf.toString(encoding) : buf;
|
|
43
43
|
};
|
|
44
44
|
|
|
45
|
-
// encrypt.js
|
|
45
|
+
// lib/encrypt.js
|
|
46
46
|
var ALGORITHM = "aes-256-gcm";
|
|
47
47
|
var getKey = () => Buffer.from(process.env.ENCRYPT_CONNECTION_SECRET, "hex");
|
|
48
48
|
var encrypt = (value) => {
|
package/dist/encrypt.js
CHANGED
|
@@ -1,8 +1,41 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
import "
|
|
1
|
+
// lib/encrypt.js
|
|
2
|
+
import crypto2 from "crypto";
|
|
3
|
+
|
|
4
|
+
// lib/token.js
|
|
5
|
+
import crypto from "crypto";
|
|
6
|
+
var generate = (bytes = 32, encoding = "base64url") => {
|
|
7
|
+
const buf = crypto.randomBytes(bytes);
|
|
8
|
+
return encoding ? buf.toString(encoding) : buf;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
// lib/encrypt.js
|
|
12
|
+
var ALGORITHM = "aes-256-gcm";
|
|
13
|
+
var getKey = () => Buffer.from(process.env.ENCRYPT_CONNECTION_SECRET, "hex");
|
|
14
|
+
var encrypt = (value) => {
|
|
15
|
+
const iv = generate(12, null);
|
|
16
|
+
const cipher = crypto2.createCipheriv(ALGORITHM, getKey(), iv);
|
|
17
|
+
const data = Buffer.concat([
|
|
18
|
+
cipher.update(JSON.stringify(value), "utf8"),
|
|
19
|
+
cipher.final()
|
|
20
|
+
]);
|
|
21
|
+
const tag = cipher.getAuthTag();
|
|
22
|
+
return [iv, tag, data].map((b) => b.toString("hex")).join(":");
|
|
23
|
+
};
|
|
24
|
+
var decrypt = (value) => {
|
|
25
|
+
if (typeof value !== "string") return value;
|
|
26
|
+
const [ivHex, tagHex, dataHex] = value.split(":");
|
|
27
|
+
const decipher = crypto2.createDecipheriv(
|
|
28
|
+
ALGORITHM,
|
|
29
|
+
getKey(),
|
|
30
|
+
Buffer.from(ivHex, "hex")
|
|
31
|
+
);
|
|
32
|
+
decipher.setAuthTag(Buffer.from(tagHex, "hex"));
|
|
33
|
+
const result = Buffer.concat([
|
|
34
|
+
decipher.update(Buffer.from(dataHex, "hex")),
|
|
35
|
+
decipher.final()
|
|
36
|
+
]);
|
|
37
|
+
return JSON.parse(result.toString("utf8"));
|
|
38
|
+
};
|
|
6
39
|
export {
|
|
7
40
|
decrypt,
|
|
8
41
|
encrypt
|
package/dist/fetch.cjs
CHANGED
|
@@ -26,7 +26,7 @@ var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__ge
|
|
|
26
26
|
));
|
|
27
27
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
28
|
|
|
29
|
-
// fetch.js
|
|
29
|
+
// lib/fetch.js
|
|
30
30
|
var fetch_exports = {};
|
|
31
31
|
__export(fetch_exports, {
|
|
32
32
|
queryString: () => queryString,
|
package/dist/fetch.js
CHANGED
package/dist/http.cjs
CHANGED
|
@@ -16,7 +16,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
16
|
};
|
|
17
17
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
18
|
|
|
19
|
-
// http.js
|
|
19
|
+
// lib/http.js
|
|
20
20
|
var http_exports = {};
|
|
21
21
|
__export(http_exports, {
|
|
22
22
|
request: () => request
|
package/dist/http.js
CHANGED
package/dist/nanoid.cjs
CHANGED
|
@@ -16,7 +16,7 @@ var __copyProps = (to, from, except, desc) => {
|
|
|
16
16
|
};
|
|
17
17
|
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
18
18
|
|
|
19
|
-
// nanoid.js
|
|
19
|
+
// lib/nanoid.js
|
|
20
20
|
var nanoid_exports = {};
|
|
21
21
|
__export(nanoid_exports, {
|
|
22
22
|
nanoid: () => nanoid,
|
package/dist/nanoid.js
CHANGED
|
@@ -0,0 +1,196 @@
|
|
|
1
|
+
var __create = Object.create;
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __getProtoOf = Object.getPrototypeOf;
|
|
6
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
7
|
+
var __export = (target, all) => {
|
|
8
|
+
for (var name in all)
|
|
9
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
10
|
+
};
|
|
11
|
+
var __copyProps = (to, from, except, desc) => {
|
|
12
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
13
|
+
for (let key of __getOwnPropNames(from))
|
|
14
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
15
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
16
|
+
}
|
|
17
|
+
return to;
|
|
18
|
+
};
|
|
19
|
+
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
|
|
20
|
+
// If the importer is in node compatibility mode or this is not an ESM
|
|
21
|
+
// file that has been converted to a CommonJS file using a Babel-
|
|
22
|
+
// compatible transform (i.e. "__esModule" has not been set), then set
|
|
23
|
+
// "default" to the CommonJS "module.exports" for node compatibility.
|
|
24
|
+
isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
|
|
25
|
+
mod
|
|
26
|
+
));
|
|
27
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
28
|
+
|
|
29
|
+
// lib/oauth/index.js
|
|
30
|
+
var oauth_exports = {};
|
|
31
|
+
__export(oauth_exports, {
|
|
32
|
+
compare: () => compare,
|
|
33
|
+
createOAuthClient: () => createOAuthClient,
|
|
34
|
+
developer: () => developer,
|
|
35
|
+
generateToken: () => generateToken,
|
|
36
|
+
hashToken: () => hashToken,
|
|
37
|
+
intersect: () => intersect,
|
|
38
|
+
isDeveloperAllowed: () => isDeveloperAllowed,
|
|
39
|
+
parse: () => parse,
|
|
40
|
+
scopes: () => scopes,
|
|
41
|
+
validate: () => validate
|
|
42
|
+
});
|
|
43
|
+
module.exports = __toCommonJS(oauth_exports);
|
|
44
|
+
|
|
45
|
+
// lib/token.js
|
|
46
|
+
var import_crypto = __toESM(require("crypto"), 1);
|
|
47
|
+
var generate = (bytes = 32, encoding = "base64url") => {
|
|
48
|
+
const buf = import_crypto.default.randomBytes(bytes);
|
|
49
|
+
return encoding ? buf.toString(encoding) : buf;
|
|
50
|
+
};
|
|
51
|
+
var hash = (value, key) => {
|
|
52
|
+
if (!value) return null;
|
|
53
|
+
if (key) {
|
|
54
|
+
return import_crypto.default.createHmac("sha256", key).update(String(value)).digest("base64url");
|
|
55
|
+
}
|
|
56
|
+
return import_crypto.default.createHash("sha256").update(String(value)).digest("base64url");
|
|
57
|
+
};
|
|
58
|
+
var compare = (a, b) => {
|
|
59
|
+
if (typeof a !== "string" || typeof b !== "string") return false;
|
|
60
|
+
if (a.length !== b.length) return false;
|
|
61
|
+
return import_crypto.default.timingSafeEqual(
|
|
62
|
+
Buffer.from(a),
|
|
63
|
+
Buffer.from(b)
|
|
64
|
+
);
|
|
65
|
+
};
|
|
66
|
+
|
|
67
|
+
// lib/oauth/index.js
|
|
68
|
+
var scopes = [
|
|
69
|
+
"profile:read",
|
|
70
|
+
"profile:write",
|
|
71
|
+
"organization:read",
|
|
72
|
+
"organization:write",
|
|
73
|
+
"campaigns:read",
|
|
74
|
+
"campaigns:write",
|
|
75
|
+
"contacts:read",
|
|
76
|
+
"contacts:write",
|
|
77
|
+
"workflows:read",
|
|
78
|
+
"workflows:write",
|
|
79
|
+
"connections:read",
|
|
80
|
+
"connections:write",
|
|
81
|
+
"billing:read",
|
|
82
|
+
"billing:write",
|
|
83
|
+
"admin"
|
|
84
|
+
];
|
|
85
|
+
var developer = [
|
|
86
|
+
"profile:read",
|
|
87
|
+
"organization:read",
|
|
88
|
+
"campaigns:read",
|
|
89
|
+
"campaigns:write",
|
|
90
|
+
"contacts:read",
|
|
91
|
+
"contacts:write",
|
|
92
|
+
"workflows:read",
|
|
93
|
+
"workflows:write",
|
|
94
|
+
"connections:read",
|
|
95
|
+
"connections:write"
|
|
96
|
+
];
|
|
97
|
+
var parse = (raw) => {
|
|
98
|
+
if (!raw) return [];
|
|
99
|
+
if (Array.isArray(raw)) return raw;
|
|
100
|
+
return String(raw).split(/\s+/).filter(Boolean);
|
|
101
|
+
};
|
|
102
|
+
var validate = (scopes2) => {
|
|
103
|
+
const parsed = parse(scopes2);
|
|
104
|
+
const invalid = parsed.filter((scope) => !scopes2.includes(scope));
|
|
105
|
+
return {
|
|
106
|
+
invalid,
|
|
107
|
+
valid: invalid.length === 0
|
|
108
|
+
};
|
|
109
|
+
};
|
|
110
|
+
var intersect = (requested, allowed) => {
|
|
111
|
+
const r = parse(requested);
|
|
112
|
+
const a = parse(allowed);
|
|
113
|
+
return r.filter((scope) => a.includes(scope));
|
|
114
|
+
};
|
|
115
|
+
var isDeveloperAllowed = (scope) => developer.includes(scope);
|
|
116
|
+
var hashToken = (raw) => hash(raw, process.env.OAUTH_TOKEN_HMAC_KEY);
|
|
117
|
+
var generateToken = () => generate(32, "base64url");
|
|
118
|
+
var REFRESH_LEAD_SECONDS = 60;
|
|
119
|
+
var createOAuthClient = ({
|
|
120
|
+
clientId,
|
|
121
|
+
clientSecret,
|
|
122
|
+
scopes: scopes2 = [],
|
|
123
|
+
tokenUri
|
|
124
|
+
}) => {
|
|
125
|
+
if (!clientId) throw new Error("createOAuthClient: clientId required");
|
|
126
|
+
if (!clientSecret) throw new Error("createOAuthClient: clientSecret required");
|
|
127
|
+
if (!tokenUri) throw new Error("createOAuthClient: tokenUri required");
|
|
128
|
+
let cached = null;
|
|
129
|
+
let pending = null;
|
|
130
|
+
const isFresh = () => {
|
|
131
|
+
if (!cached) return false;
|
|
132
|
+
const now = Math.floor(Date.now() / 1e3);
|
|
133
|
+
return cached.expiresAt - REFRESH_LEAD_SECONDS > now;
|
|
134
|
+
};
|
|
135
|
+
const fetchToken = async () => {
|
|
136
|
+
const params = new URLSearchParams();
|
|
137
|
+
params.set("grant_type", "client_credentials");
|
|
138
|
+
if (scopes2.length > 0) {
|
|
139
|
+
params.set("scope", scopes2.join(" "));
|
|
140
|
+
}
|
|
141
|
+
const basic = Buffer.from(clientId + ":" + clientSecret).toString("base64");
|
|
142
|
+
const response = await fetch(
|
|
143
|
+
tokenUri,
|
|
144
|
+
{
|
|
145
|
+
body: params.toString(),
|
|
146
|
+
headers: {
|
|
147
|
+
"authorization": "Basic " + basic,
|
|
148
|
+
"content-type": "application/x-www-form-urlencoded"
|
|
149
|
+
},
|
|
150
|
+
method: "POST"
|
|
151
|
+
}
|
|
152
|
+
);
|
|
153
|
+
if (!response.ok) {
|
|
154
|
+
const text = await response.text();
|
|
155
|
+
throw new Error("createOAuthClient: token fetch failed (" + response.status + "): " + text);
|
|
156
|
+
}
|
|
157
|
+
const body = await response.json();
|
|
158
|
+
cached = {
|
|
159
|
+
accessToken: body.access_token,
|
|
160
|
+
expiresAt: Math.floor(Date.now() / 1e3) + Number(body.expires_in || 3600),
|
|
161
|
+
scope: body.scope
|
|
162
|
+
};
|
|
163
|
+
return cached.accessToken;
|
|
164
|
+
};
|
|
165
|
+
const refresh = () => {
|
|
166
|
+
if (pending) return pending;
|
|
167
|
+
pending = fetchToken().finally(() => {
|
|
168
|
+
pending = null;
|
|
169
|
+
});
|
|
170
|
+
return pending;
|
|
171
|
+
};
|
|
172
|
+
return {
|
|
173
|
+
token: async () => {
|
|
174
|
+
if (isFresh()) return cached.accessToken;
|
|
175
|
+
return refresh();
|
|
176
|
+
},
|
|
177
|
+
// Force a refresh on the next call. Use this when a request returns 401
|
|
178
|
+
// before the cached token's expiry — the server may have revoked it.
|
|
179
|
+
invalidate: () => {
|
|
180
|
+
cached = null;
|
|
181
|
+
}
|
|
182
|
+
};
|
|
183
|
+
};
|
|
184
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
185
|
+
0 && (module.exports = {
|
|
186
|
+
compare,
|
|
187
|
+
createOAuthClient,
|
|
188
|
+
developer,
|
|
189
|
+
generateToken,
|
|
190
|
+
hashToken,
|
|
191
|
+
intersect,
|
|
192
|
+
isDeveloperAllowed,
|
|
193
|
+
parse,
|
|
194
|
+
scopes,
|
|
195
|
+
validate
|
|
196
|
+
});
|