@foldset/express 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.
@@ -0,0 +1,18 @@
1
+ import type { Request } from "express";
2
+ import type { RequestAdapter } from "@foldset/core";
3
+ export declare class ExpressAdapter implements RequestAdapter {
4
+ private req;
5
+ constructor(req: Request);
6
+ getIpAddress(): string | null;
7
+ getHeader(name: string): string | undefined;
8
+ getMethod(): string;
9
+ getPath(): string;
10
+ getUrl(): string;
11
+ getHost(): string;
12
+ getAcceptHeader(): string;
13
+ getUserAgent(): string;
14
+ getQueryParams(): Record<string, string | string[]>;
15
+ getQueryParam(name: string): string | string[] | undefined;
16
+ getBody(): Promise<unknown>;
17
+ }
18
+ //# sourceMappingURL=adapter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"adapter.d.ts","sourceRoot":"","sources":["../src/adapter.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AACvC,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAEpD,qBAAa,cAAe,YAAW,cAAc;IACvC,OAAO,CAAC,GAAG;gBAAH,GAAG,EAAE,OAAO;IAEhC,YAAY,IAAI,MAAM,GAAG,IAAI;IAM7B,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS;IAI3C,SAAS,IAAI,MAAM;IAInB,OAAO,IAAI,MAAM;IAIjB,MAAM,IAAI,MAAM;IAIhB,OAAO,IAAI,MAAM;IAIjB,eAAe,IAAI,MAAM;IAIzB,YAAY,IAAI,MAAM;IAItB,cAAc,IAAI,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;IAYnD,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,MAAM,EAAE,GAAG,SAAS;IAIpD,OAAO,IAAI,OAAO,CAAC,OAAO,CAAC;CAGlC"}
@@ -0,0 +1,51 @@
1
+ export class ExpressAdapter {
2
+ req;
3
+ constructor(req) {
4
+ this.req = req;
5
+ }
6
+ getIpAddress() {
7
+ const forwarded = this.req.get("x-forwarded-for");
8
+ if (forwarded)
9
+ return forwarded.split(",")[0].trim();
10
+ return this.req.ip ?? null;
11
+ }
12
+ getHeader(name) {
13
+ return this.req.get(name);
14
+ }
15
+ getMethod() {
16
+ return this.req.method;
17
+ }
18
+ getPath() {
19
+ return this.req.path;
20
+ }
21
+ getUrl() {
22
+ return `${this.req.protocol}://${this.req.get("host")}${this.req.originalUrl}`;
23
+ }
24
+ getHost() {
25
+ return this.req.hostname;
26
+ }
27
+ getAcceptHeader() {
28
+ return this.req.get("Accept") ?? "";
29
+ }
30
+ getUserAgent() {
31
+ return this.req.get("User-Agent") ?? "";
32
+ }
33
+ getQueryParams() {
34
+ const result = {};
35
+ for (const [key, value] of Object.entries(this.req.query)) {
36
+ if (typeof value === "string") {
37
+ result[key] = value;
38
+ }
39
+ else if (Array.isArray(value)) {
40
+ result[key] = value.filter((v) => typeof v === "string");
41
+ }
42
+ }
43
+ return result;
44
+ }
45
+ getQueryParam(name) {
46
+ return this.getQueryParams()[name];
47
+ }
48
+ async getBody() {
49
+ return this.req.body;
50
+ }
51
+ }
@@ -0,0 +1,3 @@
1
+ export { foldset } from "./middleware";
2
+ export type { FoldsetOptions } from "@foldset/core";
3
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,cAAc,CAAC;AACvC,YAAY,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1 @@
1
+ export { foldset } from "./middleware";
@@ -0,0 +1,4 @@
1
+ import type { RequestHandler } from "express";
2
+ import type { FoldsetOptions } from "@foldset/core";
3
+ export declare function foldset(options: FoldsetOptions): RequestHandler;
4
+ //# sourceMappingURL=middleware.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../src/middleware.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAmC,cAAc,EAAE,MAAM,SAAS,CAAC;AAC/E,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAYpD,wBAAgB,OAAO,CAAC,OAAO,EAAE,cAAc,GAAG,cAAc,CAiF/D"}
@@ -0,0 +1,70 @@
1
+ import { WorkerCore, reportError } from "@foldset/core";
2
+ import packageJson from "../package.json" with { type: "json" };
3
+ import { ExpressAdapter } from "./adapter";
4
+ function setHeaders(res, headers) {
5
+ for (const [key, value] of Object.entries(headers)) {
6
+ res.setHeader(key, value);
7
+ }
8
+ }
9
+ export function foldset(options) {
10
+ if (!options.apiKey) {
11
+ console.warn("[foldset] No API key provided, middleware disabled");
12
+ return (_req, _res, next) => next();
13
+ }
14
+ const opts = { ...options, platform: "express", sdkVersion: packageJson.version };
15
+ return async function foldsetMiddleware(req, res, next) {
16
+ try {
17
+ const core = await WorkerCore.fromOptions(opts);
18
+ const adapter = new ExpressAdapter(req);
19
+ const result = await core.processRequest(adapter);
20
+ switch (result.type) {
21
+ case "health-check":
22
+ setHeaders(res, result.response.headers);
23
+ return res.status(result.response.status).send(result.response.body);
24
+ case "no-payment-required":
25
+ if (result.headers) {
26
+ setHeaders(res, result.headers);
27
+ }
28
+ return next();
29
+ case "payment-error":
30
+ setHeaders(res, result.response.headers);
31
+ return res.status(result.response.status).send(result.response.body);
32
+ case "payment-verified": {
33
+ const originalEnd = res.end.bind(res);
34
+ res.end = function (chunk, encoding, cb) {
35
+ core
36
+ .processSettlement(adapter, result.paymentPayload, result.paymentRequirements, res.statusCode, result.metadata.request_id)
37
+ .then((settlement) => {
38
+ if (settlement.success) {
39
+ setHeaders(res, settlement.headers);
40
+ }
41
+ else {
42
+ res.statusCode = 402;
43
+ res.setHeader("Content-Type", "application/json");
44
+ chunk = JSON.stringify({ error: "Settlement failed", details: settlement.errorReason });
45
+ }
46
+ })
47
+ .finally(() => {
48
+ if (typeof encoding === "function") {
49
+ originalEnd(chunk, encoding);
50
+ }
51
+ else if (encoding) {
52
+ originalEnd(chunk, encoding, cb);
53
+ }
54
+ else {
55
+ originalEnd(chunk, cb);
56
+ }
57
+ });
58
+ return res;
59
+ };
60
+ return next();
61
+ }
62
+ }
63
+ }
64
+ catch (error) {
65
+ // On any error, allow the request through rather than blocking the user.
66
+ reportError(opts.apiKey, error, new ExpressAdapter(req));
67
+ return next();
68
+ }
69
+ };
70
+ }
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@foldset/express",
3
+ "version": "0.1.0",
4
+ "description": "Express middleware for Foldset payment gating",
5
+ "license": "MIT",
6
+ "type": "module",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "exports": {
10
+ ".": {
11
+ "types": "./dist/index.d.ts",
12
+ "default": "./dist/index.js"
13
+ }
14
+ },
15
+ "files": [
16
+ "dist"
17
+ ],
18
+ "publishConfig": {
19
+ "access": "public"
20
+ },
21
+ "repository": {
22
+ "type": "git",
23
+ "url": "https://github.com/foldset/sdks.git",
24
+ "directory": "typescript/express"
25
+ },
26
+ "homepage": "https://docs.foldset.com",
27
+ "keywords": [
28
+ "foldset",
29
+ "express",
30
+ "middleware",
31
+ "micropayments",
32
+ "ai",
33
+ "agents"
34
+ ],
35
+ "dependencies": {
36
+ "@foldset/core": "0.1.0"
37
+ },
38
+ "peerDependencies": {
39
+ "express": ">=4"
40
+ },
41
+ "devDependencies": {
42
+ "@types/express": "^5.0.6",
43
+ "typescript": "^5.9.3"
44
+ },
45
+ "scripts": {
46
+ "build": "tsc",
47
+ "typecheck": "tsc --noEmit"
48
+ }
49
+ }