trustline 0.0.1 → 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.
Files changed (62) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +339 -0
  3. package/dist/adapters/mysql/index.cjs +199 -0
  4. package/dist/adapters/mysql/index.cjs.map +1 -0
  5. package/dist/adapters/mysql/index.d.cts +6 -0
  6. package/dist/adapters/mysql/index.d.ts +6 -0
  7. package/dist/adapters/mysql/index.js +21 -0
  8. package/dist/adapters/mysql/index.js.map +1 -0
  9. package/dist/adapters/postgres/index.cjs +199 -0
  10. package/dist/adapters/postgres/index.cjs.map +1 -0
  11. package/dist/adapters/postgres/index.d.cts +6 -0
  12. package/dist/adapters/postgres/index.d.ts +6 -0
  13. package/dist/adapters/postgres/index.js +21 -0
  14. package/dist/adapters/postgres/index.js.map +1 -0
  15. package/dist/adapters/sqlite/index.cjs +216 -0
  16. package/dist/adapters/sqlite/index.cjs.map +1 -0
  17. package/dist/adapters/sqlite/index.d.cts +6 -0
  18. package/dist/adapters/sqlite/index.d.ts +6 -0
  19. package/dist/adapters/sqlite/index.js +28 -0
  20. package/dist/adapters/sqlite/index.js.map +1 -0
  21. package/dist/chunk-CTPFKR4O.js +157 -0
  22. package/dist/chunk-CTPFKR4O.js.map +1 -0
  23. package/dist/chunk-GF3NKEEK.js +18 -0
  24. package/dist/chunk-GF3NKEEK.js.map +1 -0
  25. package/dist/client/index.cjs +141 -0
  26. package/dist/client/index.cjs.map +1 -0
  27. package/dist/client/index.d.cts +18 -0
  28. package/dist/client/index.d.ts +18 -0
  29. package/dist/client/index.js +104 -0
  30. package/dist/client/index.js.map +1 -0
  31. package/dist/frameworks/express/index.cjs +121 -0
  32. package/dist/frameworks/express/index.cjs.map +1 -0
  33. package/dist/frameworks/express/index.d.cts +18 -0
  34. package/dist/frameworks/express/index.d.ts +18 -0
  35. package/dist/frameworks/express/index.js +83 -0
  36. package/dist/frameworks/express/index.js.map +1 -0
  37. package/dist/frameworks/fastify/index.cjs +158 -0
  38. package/dist/frameworks/fastify/index.cjs.map +1 -0
  39. package/dist/frameworks/fastify/index.d.cts +25 -0
  40. package/dist/frameworks/fastify/index.d.ts +25 -0
  41. package/dist/frameworks/fastify/index.js +120 -0
  42. package/dist/frameworks/fastify/index.js.map +1 -0
  43. package/dist/frameworks/hono/index.cjs +117 -0
  44. package/dist/frameworks/hono/index.cjs.map +1 -0
  45. package/dist/frameworks/hono/index.d.cts +17 -0
  46. package/dist/frameworks/hono/index.d.ts +17 -0
  47. package/dist/frameworks/hono/index.js +79 -0
  48. package/dist/frameworks/hono/index.js.map +1 -0
  49. package/dist/index-Dc4GFume.d.ts +34 -0
  50. package/dist/index-DqkKZOlH.d.cts +34 -0
  51. package/dist/index.cjs +571 -0
  52. package/dist/index.cjs.map +1 -0
  53. package/dist/index.d.cts +14 -0
  54. package/dist/index.d.ts +14 -0
  55. package/dist/index.js +537 -0
  56. package/dist/index.js.map +1 -0
  57. package/dist/interface-BzT_DC3u.d.cts +38 -0
  58. package/dist/interface-BzT_DC3u.d.ts +38 -0
  59. package/dist/token-BtfYGd9K.d.cts +33 -0
  60. package/dist/token-BtfYGd9K.d.ts +33 -0
  61. package/package.json +125 -3
  62. package/index.js +0 -1
@@ -0,0 +1,157 @@
1
+ // src/storage/sql.ts
2
+ import { sql } from "kysely";
3
+ function createSqlStorage(database, dialect, options) {
4
+ const tables = resolveTables(options);
5
+ let schemaPromise = null;
6
+ async function ensureSchema() {
7
+ if (!schemaPromise) {
8
+ schemaPromise = createSchema(database, dialect, tables);
9
+ }
10
+ await schemaPromise;
11
+ }
12
+ return {
13
+ async findClient(clientId) {
14
+ await ensureSchema();
15
+ const row = await database.selectFrom(tables.clients).selectAll().where("client_id", "=", clientId).executeTakeFirst();
16
+ return row ? mapClientRow(row) : null;
17
+ },
18
+ async createClient(client) {
19
+ await ensureSchema();
20
+ await database.insertInto(tables.clients).values({
21
+ id: client.id,
22
+ client_id: client.clientId,
23
+ client_secret: client.clientSecret,
24
+ name: client.name,
25
+ scopes: JSON.stringify(client.scopes),
26
+ created_at: client.createdAt.toISOString(),
27
+ last_seen_at: client.lastSeenAt?.toISOString() ?? null
28
+ }).execute();
29
+ },
30
+ async deleteClient(clientId) {
31
+ await ensureSchema();
32
+ await database.deleteFrom(tables.clients).where("client_id", "=", clientId).execute();
33
+ },
34
+ async listClients() {
35
+ await ensureSchema();
36
+ const rows = await database.selectFrom(tables.clients).selectAll().orderBy("created_at", "asc").execute();
37
+ return rows.map(mapClientRow);
38
+ },
39
+ async touchClient(clientId, lastSeenAt) {
40
+ await ensureSchema();
41
+ await database.updateTable(tables.clients).set({
42
+ last_seen_at: lastSeenAt.toISOString()
43
+ }).where("client_id", "=", clientId).execute();
44
+ },
45
+ async getSigningKeys() {
46
+ await ensureSchema();
47
+ const rows = await database.selectFrom(tables.signingKeys).selectAll().orderBy("created_at", "asc").execute();
48
+ return rows.map(mapSigningKeyRow);
49
+ },
50
+ async addSigningKey(key) {
51
+ await ensureSchema();
52
+ await database.insertInto(tables.signingKeys).values({
53
+ key_id: key.keyId,
54
+ algorithm: key.algorithm,
55
+ private_key: key.privateKey,
56
+ public_key: key.publicKey,
57
+ created_at: key.createdAt.toISOString(),
58
+ retired_at: key.retiredAt?.toISOString() ?? null
59
+ }).execute();
60
+ },
61
+ async retireKey(keyId) {
62
+ await ensureSchema();
63
+ await database.updateTable(tables.signingKeys).set({
64
+ retired_at: (/* @__PURE__ */ new Date()).toISOString()
65
+ }).where("key_id", "=", keyId).execute();
66
+ }
67
+ };
68
+ }
69
+ function resolveTables(options) {
70
+ const prefix = options?.tablePrefix ?? "trustline_";
71
+ return {
72
+ clients: options?.tables?.clients ?? `${prefix}clients`,
73
+ signingKeys: options?.tables?.signingKeys ?? `${prefix}signing_keys`
74
+ };
75
+ }
76
+ async function createSchema(database, dialect, tables) {
77
+ await createClientsTable(database, dialect, tables.clients);
78
+ await createSigningKeysTable(database, dialect, tables.signingKeys);
79
+ }
80
+ async function createClientsTable(database, dialect, tableName) {
81
+ if (dialect === "mysql") {
82
+ await sql`
83
+ create table if not exists ${sql.table(tableName)} (
84
+ id varchar(255) not null,
85
+ client_id varchar(255) not null primary key,
86
+ client_secret text not null,
87
+ name varchar(255) not null,
88
+ scopes text not null,
89
+ created_at varchar(64) not null,
90
+ last_seen_at varchar(64) null
91
+ )
92
+ `.execute(database);
93
+ return;
94
+ }
95
+ await sql`
96
+ create table if not exists ${sql.table(tableName)} (
97
+ id varchar(255) not null,
98
+ client_id varchar(255) not null primary key,
99
+ client_secret text not null,
100
+ name varchar(255) not null,
101
+ scopes text not null,
102
+ created_at varchar(64) not null,
103
+ last_seen_at varchar(64)
104
+ )
105
+ `.execute(database);
106
+ }
107
+ async function createSigningKeysTable(database, dialect, tableName) {
108
+ if (dialect === "mysql") {
109
+ await sql`
110
+ create table if not exists ${sql.table(tableName)} (
111
+ key_id varchar(255) not null primary key,
112
+ algorithm varchar(32) not null,
113
+ private_key text not null,
114
+ public_key text not null,
115
+ created_at varchar(64) not null,
116
+ retired_at varchar(64) null
117
+ )
118
+ `.execute(database);
119
+ return;
120
+ }
121
+ await sql`
122
+ create table if not exists ${sql.table(tableName)} (
123
+ key_id varchar(255) not null primary key,
124
+ algorithm varchar(32) not null,
125
+ private_key text not null,
126
+ public_key text not null,
127
+ created_at varchar(64) not null,
128
+ retired_at varchar(64)
129
+ )
130
+ `.execute(database);
131
+ }
132
+ function mapClientRow(row) {
133
+ return {
134
+ id: row.id,
135
+ clientId: row.client_id,
136
+ clientSecret: row.client_secret,
137
+ name: row.name,
138
+ scopes: JSON.parse(row.scopes),
139
+ createdAt: new Date(row.created_at),
140
+ lastSeenAt: row.last_seen_at ? new Date(row.last_seen_at) : null
141
+ };
142
+ }
143
+ function mapSigningKeyRow(row) {
144
+ return {
145
+ keyId: row.key_id,
146
+ algorithm: row.algorithm,
147
+ privateKey: row.private_key,
148
+ publicKey: row.public_key,
149
+ createdAt: new Date(row.created_at),
150
+ retiredAt: row.retired_at ? new Date(row.retired_at) : null
151
+ };
152
+ }
153
+
154
+ export {
155
+ createSqlStorage
156
+ };
157
+ //# sourceMappingURL=chunk-CTPFKR4O.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/storage/sql.ts"],"sourcesContent":["import { type Kysely, sql } from \"kysely\";\n\nimport type {\n ServiceClient,\n SigningKey,\n SqlStorageOptions,\n StorageAdapter,\n} from \"./interface\";\n\ntype SqlDialect = \"mysql\" | \"postgres\" | \"sqlite\";\n\ninterface SqlTables {\n clients: string;\n signingKeys: string;\n}\n\ninterface SqlDatabase {\n [tableName: string]: SqlRow;\n}\n\ninterface SqlRow {\n algorithm?: SigningKey[\"algorithm\"];\n client_id?: string;\n client_secret?: string;\n created_at: string;\n id?: string;\n key_id?: string;\n last_seen_at?: string | null;\n name?: string;\n private_key?: string;\n public_key?: string;\n retired_at?: string | null;\n scopes?: string;\n}\n\ninterface ClientRow {\n id: string;\n client_id: string;\n client_secret: string;\n name: string;\n scopes: string;\n created_at: string;\n last_seen_at: string | null;\n}\n\ninterface SigningKeyRow {\n key_id: string;\n algorithm: SigningKey[\"algorithm\"];\n private_key: string;\n public_key: string;\n created_at: string;\n retired_at: string | null;\n}\n\nexport function createSqlStorage(\n database: Kysely<SqlDatabase>,\n dialect: SqlDialect,\n options?: SqlStorageOptions,\n): StorageAdapter {\n const tables = resolveTables(options);\n let schemaPromise: Promise<void> | null = null;\n\n async function ensureSchema(): Promise<void> {\n if (!schemaPromise) {\n schemaPromise = createSchema(database, dialect, tables);\n }\n\n await schemaPromise;\n }\n\n return {\n async findClient(clientId) {\n await ensureSchema();\n\n const row = (await database\n .selectFrom(tables.clients)\n .selectAll()\n .where(\"client_id\", \"=\", clientId)\n .executeTakeFirst()) as ClientRow | undefined;\n\n return row ? mapClientRow(row) : null;\n },\n async createClient(client) {\n await ensureSchema();\n\n await database\n .insertInto(tables.clients)\n .values({\n id: client.id,\n client_id: client.clientId,\n client_secret: client.clientSecret,\n name: client.name,\n scopes: JSON.stringify(client.scopes),\n created_at: client.createdAt.toISOString(),\n last_seen_at: client.lastSeenAt?.toISOString() ?? null,\n })\n .execute();\n },\n async deleteClient(clientId) {\n await ensureSchema();\n\n await database\n .deleteFrom(tables.clients)\n .where(\"client_id\", \"=\", clientId)\n .execute();\n },\n async listClients() {\n await ensureSchema();\n\n const rows = (await database\n .selectFrom(tables.clients)\n .selectAll()\n .orderBy(\"created_at\", \"asc\")\n .execute()) as ClientRow[];\n\n return rows.map(mapClientRow);\n },\n async touchClient(clientId, lastSeenAt) {\n await ensureSchema();\n\n await database\n .updateTable(tables.clients)\n .set({\n last_seen_at: lastSeenAt.toISOString(),\n })\n .where(\"client_id\", \"=\", clientId)\n .execute();\n },\n async getSigningKeys() {\n await ensureSchema();\n\n const rows = (await database\n .selectFrom(tables.signingKeys)\n .selectAll()\n .orderBy(\"created_at\", \"asc\")\n .execute()) as SigningKeyRow[];\n\n return rows.map(mapSigningKeyRow);\n },\n async addSigningKey(key) {\n await ensureSchema();\n\n await database\n .insertInto(tables.signingKeys)\n .values({\n key_id: key.keyId,\n algorithm: key.algorithm,\n private_key: key.privateKey,\n public_key: key.publicKey,\n created_at: key.createdAt.toISOString(),\n retired_at: key.retiredAt?.toISOString() ?? null,\n })\n .execute();\n },\n async retireKey(keyId) {\n await ensureSchema();\n\n await database\n .updateTable(tables.signingKeys)\n .set({\n retired_at: new Date().toISOString(),\n })\n .where(\"key_id\", \"=\", keyId)\n .execute();\n },\n };\n}\n\nfunction resolveTables(options?: SqlStorageOptions): SqlTables {\n const prefix = options?.tablePrefix ?? \"trustline_\";\n\n return {\n clients: options?.tables?.clients ?? `${prefix}clients`,\n signingKeys: options?.tables?.signingKeys ?? `${prefix}signing_keys`,\n };\n}\n\nasync function createSchema(\n database: Kysely<SqlDatabase>,\n dialect: SqlDialect,\n tables: SqlTables,\n): Promise<void> {\n await createClientsTable(database, dialect, tables.clients);\n await createSigningKeysTable(database, dialect, tables.signingKeys);\n}\n\nasync function createClientsTable(\n database: Kysely<SqlDatabase>,\n dialect: SqlDialect,\n tableName: string,\n): Promise<void> {\n if (dialect === \"mysql\") {\n await sql`\n create table if not exists ${sql.table(tableName)} (\n id varchar(255) not null,\n client_id varchar(255) not null primary key,\n client_secret text not null,\n name varchar(255) not null,\n scopes text not null,\n created_at varchar(64) not null,\n last_seen_at varchar(64) null\n )\n `.execute(database);\n return;\n }\n\n await sql`\n create table if not exists ${sql.table(tableName)} (\n id varchar(255) not null,\n client_id varchar(255) not null primary key,\n client_secret text not null,\n name varchar(255) not null,\n scopes text not null,\n created_at varchar(64) not null,\n last_seen_at varchar(64)\n )\n `.execute(database);\n}\n\nasync function createSigningKeysTable(\n database: Kysely<SqlDatabase>,\n dialect: SqlDialect,\n tableName: string,\n): Promise<void> {\n if (dialect === \"mysql\") {\n await sql`\n create table if not exists ${sql.table(tableName)} (\n key_id varchar(255) not null primary key,\n algorithm varchar(32) not null,\n private_key text not null,\n public_key text not null,\n created_at varchar(64) not null,\n retired_at varchar(64) null\n )\n `.execute(database);\n return;\n }\n\n await sql`\n create table if not exists ${sql.table(tableName)} (\n key_id varchar(255) not null primary key,\n algorithm varchar(32) not null,\n private_key text not null,\n public_key text not null,\n created_at varchar(64) not null,\n retired_at varchar(64)\n )\n `.execute(database);\n}\n\nfunction mapClientRow(row: ClientRow): ServiceClient {\n return {\n id: row.id,\n clientId: row.client_id,\n clientSecret: row.client_secret,\n name: row.name,\n scopes: JSON.parse(row.scopes) as string[],\n createdAt: new Date(row.created_at),\n lastSeenAt: row.last_seen_at ? new Date(row.last_seen_at) : null,\n };\n}\n\nfunction mapSigningKeyRow(row: SigningKeyRow): SigningKey {\n return {\n keyId: row.key_id,\n algorithm: row.algorithm,\n privateKey: row.private_key,\n publicKey: row.public_key,\n createdAt: new Date(row.created_at),\n retiredAt: row.retired_at ? new Date(row.retired_at) : null,\n };\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,18 @@
1
+ // src/core/errors.ts
2
+ var AuthError = class extends Error {
3
+ code;
4
+ status;
5
+ cause;
6
+ constructor(code, message, status, cause) {
7
+ super(message);
8
+ this.name = "AuthError";
9
+ this.code = code;
10
+ this.status = status;
11
+ this.cause = cause;
12
+ }
13
+ };
14
+
15
+ export {
16
+ AuthError
17
+ };
18
+ //# sourceMappingURL=chunk-GF3NKEEK.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/core/errors.ts"],"sourcesContent":["export type AuthErrorCode =\n | \"missing_token\"\n | \"invalid_token\"\n | \"invalid_issuer\"\n | \"invalid_audience\"\n | \"invalid_scope\"\n | \"invalid_env\"\n | \"jwks_fetch_failed\";\n\nexport class AuthError extends Error {\n public readonly code: AuthErrorCode;\n public readonly status: number;\n public readonly cause?: unknown;\n\n constructor(\n code: AuthErrorCode,\n message: string,\n status: number,\n cause?: unknown,\n ) {\n super(message);\n this.name = \"AuthError\";\n this.code = code;\n this.status = status;\n this.cause = cause;\n }\n}\n"],"mappings":";AASO,IAAM,YAAN,cAAwB,MAAM;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EAEhB,YACE,MACA,SACA,QACA,OACA;AACA,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,QAAQ;AAAA,EACf;AACF;","names":[]}
@@ -0,0 +1,141 @@
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/client/index.ts
21
+ var client_exports = {};
22
+ __export(client_exports, {
23
+ createClient: () => createClient
24
+ });
25
+ module.exports = __toCommonJS(client_exports);
26
+
27
+ // src/core/errors.ts
28
+ var AuthError = class extends Error {
29
+ code;
30
+ status;
31
+ cause;
32
+ constructor(code, message, status, cause) {
33
+ super(message);
34
+ this.name = "AuthError";
35
+ this.code = code;
36
+ this.status = status;
37
+ this.cause = cause;
38
+ }
39
+ };
40
+
41
+ // src/client/index.ts
42
+ var DEFAULT_REFRESH_SKEW_SECONDS = 30;
43
+ function createClient(options) {
44
+ let cachedToken = null;
45
+ let inflight = null;
46
+ const fetchImpl = options.fetch ?? globalThis.fetch;
47
+ return {
48
+ async getToken() {
49
+ const now = Date.now();
50
+ if (cachedToken && cachedToken.refreshAt > now) {
51
+ return cachedToken.token;
52
+ }
53
+ if (inflight) {
54
+ return inflight;
55
+ }
56
+ inflight = fetchToken(options, fetchImpl).then((result) => {
57
+ cachedToken = result;
58
+ return result.token;
59
+ }).finally(() => {
60
+ inflight = null;
61
+ });
62
+ return inflight;
63
+ },
64
+ async getHeaders() {
65
+ return {
66
+ Authorization: `Bearer ${await this.getToken()}`
67
+ };
68
+ },
69
+ async fetch(input, init) {
70
+ const headers = new Headers(init?.headers);
71
+ headers.set("authorization", `Bearer ${await this.getToken()}`);
72
+ return fetchImpl(input, {
73
+ ...init,
74
+ headers
75
+ });
76
+ }
77
+ };
78
+ }
79
+ async function fetchToken(options, fetchImpl) {
80
+ const body = new URLSearchParams({
81
+ grant_type: "client_credentials"
82
+ });
83
+ if (options.audience) {
84
+ body.set("audience", options.audience);
85
+ }
86
+ const response = await fetchImpl(options.tokenUrl, {
87
+ method: "POST",
88
+ headers: {
89
+ authorization: createBasicAuthHeader(
90
+ options.clientId,
91
+ options.clientSecret
92
+ ),
93
+ "content-type": "application/x-www-form-urlencoded"
94
+ },
95
+ body: body.toString()
96
+ });
97
+ if (!response.ok) {
98
+ throw new AuthError(
99
+ "invalid_token",
100
+ `Token request failed with ${response.status}`,
101
+ response.status
102
+ );
103
+ }
104
+ const payload = await response.json();
105
+ if (!payload.access_token) {
106
+ throw new AuthError(
107
+ "invalid_token",
108
+ "Token response is missing access_token",
109
+ 500
110
+ );
111
+ }
112
+ const exp = getTokenExpiration(payload.access_token);
113
+ const refreshSkewSeconds = options.refreshSkewSeconds ?? DEFAULT_REFRESH_SKEW_SECONDS;
114
+ const refreshAt = exp ? (exp - refreshSkewSeconds) * 1e3 : Date.now() + Math.max((payload.expires_in ?? 60) - refreshSkewSeconds, 1) * 1e3;
115
+ return {
116
+ token: payload.access_token,
117
+ refreshAt
118
+ };
119
+ }
120
+ function createBasicAuthHeader(clientId, clientSecret) {
121
+ return `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`;
122
+ }
123
+ function getTokenExpiration(token) {
124
+ const parts = token.split(".");
125
+ if (parts.length < 2) {
126
+ return null;
127
+ }
128
+ try {
129
+ const payload = JSON.parse(
130
+ Buffer.from(parts[1], "base64url").toString("utf8")
131
+ );
132
+ return typeof payload.exp === "number" ? payload.exp : null;
133
+ } catch {
134
+ return null;
135
+ }
136
+ }
137
+ // Annotate the CommonJS export names for ESM import in node:
138
+ 0 && (module.exports = {
139
+ createClient
140
+ });
141
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/client/index.ts","../../src/core/errors.ts"],"sourcesContent":["import { AuthError } from \"../core/errors\";\n\nexport interface ClientOptions {\n tokenUrl: string;\n clientId: string;\n clientSecret: string;\n audience?: string;\n fetch?: typeof globalThis.fetch;\n refreshSkewSeconds?: number;\n}\n\nexport interface TrustlineClient {\n getToken(): Promise<string>;\n getHeaders(): Promise<{ Authorization: string }>;\n fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;\n}\n\ninterface CachedToken {\n token: string;\n refreshAt: number;\n}\n\nconst DEFAULT_REFRESH_SKEW_SECONDS = 30;\n\nexport function createClient(options: ClientOptions): TrustlineClient {\n let cachedToken: CachedToken | null = null;\n let inflight: Promise<string> | null = null;\n const fetchImpl = options.fetch ?? globalThis.fetch;\n\n return {\n async getToken() {\n const now = Date.now();\n if (cachedToken && cachedToken.refreshAt > now) {\n return cachedToken.token;\n }\n\n if (inflight) {\n return inflight;\n }\n\n inflight = fetchToken(options, fetchImpl)\n .then((result) => {\n cachedToken = result;\n return result.token;\n })\n .finally(() => {\n inflight = null;\n });\n\n return inflight;\n },\n async getHeaders() {\n return {\n Authorization: `Bearer ${await this.getToken()}`,\n };\n },\n async fetch(input, init) {\n const headers = new Headers(init?.headers);\n headers.set(\"authorization\", `Bearer ${await this.getToken()}`);\n\n return fetchImpl(input, {\n ...init,\n headers,\n });\n },\n };\n}\n\nasync function fetchToken(\n options: ClientOptions,\n fetchImpl: typeof globalThis.fetch,\n): Promise<CachedToken> {\n const body = new URLSearchParams({\n grant_type: \"client_credentials\",\n });\n\n if (options.audience) {\n body.set(\"audience\", options.audience);\n }\n\n const response = await fetchImpl(options.tokenUrl, {\n method: \"POST\",\n headers: {\n authorization: createBasicAuthHeader(\n options.clientId,\n options.clientSecret,\n ),\n \"content-type\": \"application/x-www-form-urlencoded\",\n },\n body: body.toString(),\n });\n\n if (!response.ok) {\n throw new AuthError(\n \"invalid_token\",\n `Token request failed with ${response.status}`,\n response.status,\n );\n }\n\n const payload = (await response.json()) as {\n access_token?: string;\n expires_in?: number;\n };\n\n if (!payload.access_token) {\n throw new AuthError(\n \"invalid_token\",\n \"Token response is missing access_token\",\n 500,\n );\n }\n\n const exp = getTokenExpiration(payload.access_token);\n const refreshSkewSeconds =\n options.refreshSkewSeconds ?? DEFAULT_REFRESH_SKEW_SECONDS;\n const refreshAt = exp\n ? (exp - refreshSkewSeconds) * 1000\n : Date.now() +\n Math.max((payload.expires_in ?? 60) - refreshSkewSeconds, 1) * 1000;\n\n return {\n token: payload.access_token,\n refreshAt,\n };\n}\n\nfunction createBasicAuthHeader(clientId: string, clientSecret: string): string {\n return `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString(\"base64\")}`;\n}\n\nfunction getTokenExpiration(token: string): number | null {\n const parts = token.split(\".\");\n if (parts.length < 2) {\n return null;\n }\n\n try {\n const payload = JSON.parse(\n Buffer.from(parts[1], \"base64url\").toString(\"utf8\"),\n ) as { exp?: number };\n return typeof payload.exp === \"number\" ? payload.exp : null;\n } catch {\n return null;\n }\n}\n","export type AuthErrorCode =\n | \"missing_token\"\n | \"invalid_token\"\n | \"invalid_issuer\"\n | \"invalid_audience\"\n | \"invalid_scope\"\n | \"invalid_env\"\n | \"jwks_fetch_failed\";\n\nexport class AuthError extends Error {\n public readonly code: AuthErrorCode;\n public readonly status: number;\n public readonly cause?: unknown;\n\n constructor(\n code: AuthErrorCode,\n message: string,\n status: number,\n cause?: unknown,\n ) {\n super(message);\n this.name = \"AuthError\";\n this.code = code;\n this.status = status;\n this.cause = cause;\n }\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,18 @@
1
+ interface ClientOptions {
2
+ tokenUrl: string;
3
+ clientId: string;
4
+ clientSecret: string;
5
+ audience?: string;
6
+ fetch?: typeof globalThis.fetch;
7
+ refreshSkewSeconds?: number;
8
+ }
9
+ interface TrustlineClient {
10
+ getToken(): Promise<string>;
11
+ getHeaders(): Promise<{
12
+ Authorization: string;
13
+ }>;
14
+ fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
15
+ }
16
+ declare function createClient(options: ClientOptions): TrustlineClient;
17
+
18
+ export { type ClientOptions, type TrustlineClient, createClient };
@@ -0,0 +1,18 @@
1
+ interface ClientOptions {
2
+ tokenUrl: string;
3
+ clientId: string;
4
+ clientSecret: string;
5
+ audience?: string;
6
+ fetch?: typeof globalThis.fetch;
7
+ refreshSkewSeconds?: number;
8
+ }
9
+ interface TrustlineClient {
10
+ getToken(): Promise<string>;
11
+ getHeaders(): Promise<{
12
+ Authorization: string;
13
+ }>;
14
+ fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;
15
+ }
16
+ declare function createClient(options: ClientOptions): TrustlineClient;
17
+
18
+ export { type ClientOptions, type TrustlineClient, createClient };
@@ -0,0 +1,104 @@
1
+ import {
2
+ AuthError
3
+ } from "../chunk-GF3NKEEK.js";
4
+
5
+ // src/client/index.ts
6
+ var DEFAULT_REFRESH_SKEW_SECONDS = 30;
7
+ function createClient(options) {
8
+ let cachedToken = null;
9
+ let inflight = null;
10
+ const fetchImpl = options.fetch ?? globalThis.fetch;
11
+ return {
12
+ async getToken() {
13
+ const now = Date.now();
14
+ if (cachedToken && cachedToken.refreshAt > now) {
15
+ return cachedToken.token;
16
+ }
17
+ if (inflight) {
18
+ return inflight;
19
+ }
20
+ inflight = fetchToken(options, fetchImpl).then((result) => {
21
+ cachedToken = result;
22
+ return result.token;
23
+ }).finally(() => {
24
+ inflight = null;
25
+ });
26
+ return inflight;
27
+ },
28
+ async getHeaders() {
29
+ return {
30
+ Authorization: `Bearer ${await this.getToken()}`
31
+ };
32
+ },
33
+ async fetch(input, init) {
34
+ const headers = new Headers(init?.headers);
35
+ headers.set("authorization", `Bearer ${await this.getToken()}`);
36
+ return fetchImpl(input, {
37
+ ...init,
38
+ headers
39
+ });
40
+ }
41
+ };
42
+ }
43
+ async function fetchToken(options, fetchImpl) {
44
+ const body = new URLSearchParams({
45
+ grant_type: "client_credentials"
46
+ });
47
+ if (options.audience) {
48
+ body.set("audience", options.audience);
49
+ }
50
+ const response = await fetchImpl(options.tokenUrl, {
51
+ method: "POST",
52
+ headers: {
53
+ authorization: createBasicAuthHeader(
54
+ options.clientId,
55
+ options.clientSecret
56
+ ),
57
+ "content-type": "application/x-www-form-urlencoded"
58
+ },
59
+ body: body.toString()
60
+ });
61
+ if (!response.ok) {
62
+ throw new AuthError(
63
+ "invalid_token",
64
+ `Token request failed with ${response.status}`,
65
+ response.status
66
+ );
67
+ }
68
+ const payload = await response.json();
69
+ if (!payload.access_token) {
70
+ throw new AuthError(
71
+ "invalid_token",
72
+ "Token response is missing access_token",
73
+ 500
74
+ );
75
+ }
76
+ const exp = getTokenExpiration(payload.access_token);
77
+ const refreshSkewSeconds = options.refreshSkewSeconds ?? DEFAULT_REFRESH_SKEW_SECONDS;
78
+ const refreshAt = exp ? (exp - refreshSkewSeconds) * 1e3 : Date.now() + Math.max((payload.expires_in ?? 60) - refreshSkewSeconds, 1) * 1e3;
79
+ return {
80
+ token: payload.access_token,
81
+ refreshAt
82
+ };
83
+ }
84
+ function createBasicAuthHeader(clientId, clientSecret) {
85
+ return `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString("base64")}`;
86
+ }
87
+ function getTokenExpiration(token) {
88
+ const parts = token.split(".");
89
+ if (parts.length < 2) {
90
+ return null;
91
+ }
92
+ try {
93
+ const payload = JSON.parse(
94
+ Buffer.from(parts[1], "base64url").toString("utf8")
95
+ );
96
+ return typeof payload.exp === "number" ? payload.exp : null;
97
+ } catch {
98
+ return null;
99
+ }
100
+ }
101
+ export {
102
+ createClient
103
+ };
104
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../src/client/index.ts"],"sourcesContent":["import { AuthError } from \"../core/errors\";\n\nexport interface ClientOptions {\n tokenUrl: string;\n clientId: string;\n clientSecret: string;\n audience?: string;\n fetch?: typeof globalThis.fetch;\n refreshSkewSeconds?: number;\n}\n\nexport interface TrustlineClient {\n getToken(): Promise<string>;\n getHeaders(): Promise<{ Authorization: string }>;\n fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response>;\n}\n\ninterface CachedToken {\n token: string;\n refreshAt: number;\n}\n\nconst DEFAULT_REFRESH_SKEW_SECONDS = 30;\n\nexport function createClient(options: ClientOptions): TrustlineClient {\n let cachedToken: CachedToken | null = null;\n let inflight: Promise<string> | null = null;\n const fetchImpl = options.fetch ?? globalThis.fetch;\n\n return {\n async getToken() {\n const now = Date.now();\n if (cachedToken && cachedToken.refreshAt > now) {\n return cachedToken.token;\n }\n\n if (inflight) {\n return inflight;\n }\n\n inflight = fetchToken(options, fetchImpl)\n .then((result) => {\n cachedToken = result;\n return result.token;\n })\n .finally(() => {\n inflight = null;\n });\n\n return inflight;\n },\n async getHeaders() {\n return {\n Authorization: `Bearer ${await this.getToken()}`,\n };\n },\n async fetch(input, init) {\n const headers = new Headers(init?.headers);\n headers.set(\"authorization\", `Bearer ${await this.getToken()}`);\n\n return fetchImpl(input, {\n ...init,\n headers,\n });\n },\n };\n}\n\nasync function fetchToken(\n options: ClientOptions,\n fetchImpl: typeof globalThis.fetch,\n): Promise<CachedToken> {\n const body = new URLSearchParams({\n grant_type: \"client_credentials\",\n });\n\n if (options.audience) {\n body.set(\"audience\", options.audience);\n }\n\n const response = await fetchImpl(options.tokenUrl, {\n method: \"POST\",\n headers: {\n authorization: createBasicAuthHeader(\n options.clientId,\n options.clientSecret,\n ),\n \"content-type\": \"application/x-www-form-urlencoded\",\n },\n body: body.toString(),\n });\n\n if (!response.ok) {\n throw new AuthError(\n \"invalid_token\",\n `Token request failed with ${response.status}`,\n response.status,\n );\n }\n\n const payload = (await response.json()) as {\n access_token?: string;\n expires_in?: number;\n };\n\n if (!payload.access_token) {\n throw new AuthError(\n \"invalid_token\",\n \"Token response is missing access_token\",\n 500,\n );\n }\n\n const exp = getTokenExpiration(payload.access_token);\n const refreshSkewSeconds =\n options.refreshSkewSeconds ?? DEFAULT_REFRESH_SKEW_SECONDS;\n const refreshAt = exp\n ? (exp - refreshSkewSeconds) * 1000\n : Date.now() +\n Math.max((payload.expires_in ?? 60) - refreshSkewSeconds, 1) * 1000;\n\n return {\n token: payload.access_token,\n refreshAt,\n };\n}\n\nfunction createBasicAuthHeader(clientId: string, clientSecret: string): string {\n return `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString(\"base64\")}`;\n}\n\nfunction getTokenExpiration(token: string): number | null {\n const parts = token.split(\".\");\n if (parts.length < 2) {\n return null;\n }\n\n try {\n const payload = JSON.parse(\n Buffer.from(parts[1], \"base64url\").toString(\"utf8\"),\n ) as { exp?: number };\n return typeof payload.exp === \"number\" ? payload.exp : null;\n } catch {\n return null;\n }\n}\n"],"mappings":";;;;;AAsBA,IAAM,+BAA+B;AAE9B,SAAS,aAAa,SAAyC;AACpE,MAAI,cAAkC;AACtC,MAAI,WAAmC;AACvC,QAAM,YAAY,QAAQ,SAAS,WAAW;AAE9C,SAAO;AAAA,IACL,MAAM,WAAW;AACf,YAAM,MAAM,KAAK,IAAI;AACrB,UAAI,eAAe,YAAY,YAAY,KAAK;AAC9C,eAAO,YAAY;AAAA,MACrB;AAEA,UAAI,UAAU;AACZ,eAAO;AAAA,MACT;AAEA,iBAAW,WAAW,SAAS,SAAS,EACrC,KAAK,CAAC,WAAW;AAChB,sBAAc;AACd,eAAO,OAAO;AAAA,MAChB,CAAC,EACA,QAAQ,MAAM;AACb,mBAAW;AAAA,MACb,CAAC;AAEH,aAAO;AAAA,IACT;AAAA,IACA,MAAM,aAAa;AACjB,aAAO;AAAA,QACL,eAAe,UAAU,MAAM,KAAK,SAAS,CAAC;AAAA,MAChD;AAAA,IACF;AAAA,IACA,MAAM,MAAM,OAAO,MAAM;AACvB,YAAM,UAAU,IAAI,QAAQ,MAAM,OAAO;AACzC,cAAQ,IAAI,iBAAiB,UAAU,MAAM,KAAK,SAAS,CAAC,EAAE;AAE9D,aAAO,UAAU,OAAO;AAAA,QACtB,GAAG;AAAA,QACH;AAAA,MACF,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,eAAe,WACb,SACA,WACsB;AACtB,QAAM,OAAO,IAAI,gBAAgB;AAAA,IAC/B,YAAY;AAAA,EACd,CAAC;AAED,MAAI,QAAQ,UAAU;AACpB,SAAK,IAAI,YAAY,QAAQ,QAAQ;AAAA,EACvC;AAEA,QAAM,WAAW,MAAM,UAAU,QAAQ,UAAU;AAAA,IACjD,QAAQ;AAAA,IACR,SAAS;AAAA,MACP,eAAe;AAAA,QACb,QAAQ;AAAA,QACR,QAAQ;AAAA,MACV;AAAA,MACA,gBAAgB;AAAA,IAClB;AAAA,IACA,MAAM,KAAK,SAAS;AAAA,EACtB,CAAC;AAED,MAAI,CAAC,SAAS,IAAI;AAChB,UAAM,IAAI;AAAA,MACR;AAAA,MACA,6BAA6B,SAAS,MAAM;AAAA,MAC5C,SAAS;AAAA,IACX;AAAA,EACF;AAEA,QAAM,UAAW,MAAM,SAAS,KAAK;AAKrC,MAAI,CAAC,QAAQ,cAAc;AACzB,UAAM,IAAI;AAAA,MACR;AAAA,MACA;AAAA,MACA;AAAA,IACF;AAAA,EACF;AAEA,QAAM,MAAM,mBAAmB,QAAQ,YAAY;AACnD,QAAM,qBACJ,QAAQ,sBAAsB;AAChC,QAAM,YAAY,OACb,MAAM,sBAAsB,MAC7B,KAAK,IAAI,IACT,KAAK,KAAK,QAAQ,cAAc,MAAM,oBAAoB,CAAC,IAAI;AAEnE,SAAO;AAAA,IACL,OAAO,QAAQ;AAAA,IACf;AAAA,EACF;AACF;AAEA,SAAS,sBAAsB,UAAkB,cAA8B;AAC7E,SAAO,SAAS,OAAO,KAAK,GAAG,QAAQ,IAAI,YAAY,EAAE,EAAE,SAAS,QAAQ,CAAC;AAC/E;AAEA,SAAS,mBAAmB,OAA8B;AACxD,QAAM,QAAQ,MAAM,MAAM,GAAG;AAC7B,MAAI,MAAM,SAAS,GAAG;AACpB,WAAO;AAAA,EACT;AAEA,MAAI;AACF,UAAM,UAAU,KAAK;AAAA,MACnB,OAAO,KAAK,MAAM,CAAC,GAAG,WAAW,EAAE,SAAS,MAAM;AAAA,IACpD;AACA,WAAO,OAAO,QAAQ,QAAQ,WAAW,QAAQ,MAAM;AAAA,EACzD,QAAQ;AACN,WAAO;AAAA,EACT;AACF;","names":[]}
@@ -0,0 +1,121 @@
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/frameworks/express/index.ts
21
+ var express_exports = {};
22
+ __export(express_exports, {
23
+ createExpressGuard: () => createExpressGuard,
24
+ createExpressProvider: () => createExpressProvider
25
+ });
26
+ module.exports = __toCommonJS(express_exports);
27
+
28
+ // src/provider/express.ts
29
+ function createExpressProvider(provider) {
30
+ return async function trustlineProvider(request, response) {
31
+ const origin = `${request.protocol}://${request.get("host") ?? "localhost"}`;
32
+ const url = new URL(request.originalUrl || request.url, origin);
33
+ const body = request.method === "GET" || request.method === "HEAD" ? void 0 : await readBody(request);
34
+ const providerResponse = await provider.handle(
35
+ new Request(url.toString(), {
36
+ method: request.method,
37
+ headers: request.headers,
38
+ body
39
+ })
40
+ );
41
+ response.status(providerResponse.status);
42
+ providerResponse.headers.forEach((value, key) => {
43
+ response.setHeader(key, value);
44
+ });
45
+ response.send(await providerResponse.text());
46
+ };
47
+ }
48
+ function readBody(request) {
49
+ return new Promise((resolve, reject) => {
50
+ const chunks = [];
51
+ request.on("data", (chunk) => {
52
+ chunks.push(typeof chunk === "string" ? Buffer.from(chunk) : chunk);
53
+ });
54
+ request.on("end", () => {
55
+ resolve(
56
+ chunks.length > 0 ? Buffer.concat(chunks).toString("utf8") : void 0
57
+ );
58
+ });
59
+ request.on("error", reject);
60
+ });
61
+ }
62
+
63
+ // src/core/errors.ts
64
+ var AuthError = class extends Error {
65
+ code;
66
+ status;
67
+ cause;
68
+ constructor(code, message, status, cause) {
69
+ super(message);
70
+ this.name = "AuthError";
71
+ this.code = code;
72
+ this.status = status;
73
+ this.cause = cause;
74
+ }
75
+ };
76
+
77
+ // src/middleware/express.ts
78
+ function createExpressGuard(guard) {
79
+ return async function trustlineGuard(request, response, next) {
80
+ const token = getBearerToken(request.headers.authorization);
81
+ if (!token) {
82
+ response.status(401).json({
83
+ error: "missing_token",
84
+ message: "Missing bearer token"
85
+ });
86
+ return;
87
+ }
88
+ try {
89
+ const identity = await guard.verify(token);
90
+ request.trustline = identity;
91
+ next();
92
+ } catch (error) {
93
+ const authError = error instanceof AuthError ? error : new AuthError(
94
+ "invalid_token",
95
+ "Token verification failed",
96
+ 401,
97
+ error
98
+ );
99
+ response.status(authError.status).json({
100
+ error: authError.code,
101
+ message: authError.message
102
+ });
103
+ }
104
+ };
105
+ }
106
+ function getBearerToken(header) {
107
+ if (!header) {
108
+ return null;
109
+ }
110
+ const [scheme, value] = header.split(/\s+/, 2);
111
+ if (scheme?.toLowerCase() !== "bearer" || !value) {
112
+ return null;
113
+ }
114
+ return value;
115
+ }
116
+ // Annotate the CommonJS export names for ESM import in node:
117
+ 0 && (module.exports = {
118
+ createExpressGuard,
119
+ createExpressProvider
120
+ });
121
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../../../src/frameworks/express/index.ts","../../../src/provider/express.ts","../../../src/core/errors.ts","../../../src/middleware/express.ts"],"sourcesContent":["export {\n createExpressProvider,\n type WebHandler,\n} from \"../../provider/express\";\nexport {\n createExpressGuard,\n type TrustlineRequest,\n} from \"../../middleware/express\";\n","import type {\n Request as ExpressRequest,\n Response as ExpressResponse,\n RequestHandler,\n} from \"express\";\n\nexport interface WebHandler {\n handle(request: Request): Promise<Response>;\n}\n\nexport function createExpressProvider(provider: WebHandler): RequestHandler {\n return async function trustlineProvider(\n request: ExpressRequest,\n response: ExpressResponse,\n ) {\n const origin = `${request.protocol}://${request.get(\"host\") ?? \"localhost\"}`;\n const url = new URL(request.originalUrl || request.url, origin);\n const body =\n request.method === \"GET\" || request.method === \"HEAD\"\n ? undefined\n : await readBody(request);\n\n const providerResponse = await provider.handle(\n new Request(url.toString(), {\n method: request.method,\n headers: request.headers as HeadersInit,\n body,\n }),\n );\n\n response.status(providerResponse.status);\n providerResponse.headers.forEach((value, key) => {\n response.setHeader(key, value);\n });\n response.send(await providerResponse.text());\n };\n}\n\nfunction readBody(request: ExpressRequest): Promise<string | undefined> {\n return new Promise((resolve, reject) => {\n const chunks: Uint8Array[] = [];\n request.on(\"data\", (chunk) => {\n chunks.push(typeof chunk === \"string\" ? Buffer.from(chunk) : chunk);\n });\n request.on(\"end\", () => {\n resolve(\n chunks.length > 0 ? Buffer.concat(chunks).toString(\"utf8\") : undefined,\n );\n });\n request.on(\"error\", reject);\n });\n}\n","export type AuthErrorCode =\n | \"missing_token\"\n | \"invalid_token\"\n | \"invalid_issuer\"\n | \"invalid_audience\"\n | \"invalid_scope\"\n | \"invalid_env\"\n | \"jwks_fetch_failed\";\n\nexport class AuthError extends Error {\n public readonly code: AuthErrorCode;\n public readonly status: number;\n public readonly cause?: unknown;\n\n constructor(\n code: AuthErrorCode,\n message: string,\n status: number,\n cause?: unknown,\n ) {\n super(message);\n this.name = \"AuthError\";\n this.code = code;\n this.status = status;\n this.cause = cause;\n }\n}\n","import type { Request, RequestHandler, Response } from \"express\";\n\nimport { AuthError } from \"../core/errors\";\nimport type { ServiceIdentity } from \"../core/token\";\n\nexport interface GuardVerifier {\n verify(token: string): Promise<ServiceIdentity>;\n}\n\nexport interface TrustlineRequest extends Request {\n trustline?: ServiceIdentity;\n}\n\nexport function createExpressGuard(guard: GuardVerifier): RequestHandler {\n return async function trustlineGuard(\n request: Request,\n response: Response,\n next,\n ) {\n const token = getBearerToken(request.headers.authorization);\n\n if (!token) {\n response.status(401).json({\n error: \"missing_token\",\n message: \"Missing bearer token\",\n });\n return;\n }\n\n try {\n const identity = await guard.verify(token);\n (request as TrustlineRequest).trustline = identity;\n next();\n } catch (error) {\n const authError =\n error instanceof AuthError\n ? error\n : new AuthError(\n \"invalid_token\",\n \"Token verification failed\",\n 401,\n error,\n );\n response.status(authError.status).json({\n error: authError.code,\n message: authError.message,\n });\n }\n };\n}\n\nfunction getBearerToken(header: string | undefined): string | null {\n if (!header) {\n return null;\n }\n\n const [scheme, value] = header.split(/\\s+/, 2);\n if (scheme?.toLowerCase() !== \"bearer\" || !value) {\n return null;\n }\n\n return value;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACUO,SAAS,sBAAsB,UAAsC;AAC1E,SAAO,eAAe,kBACpB,SACA,UACA;AACA,UAAM,SAAS,GAAG,QAAQ,QAAQ,MAAM,QAAQ,IAAI,MAAM,KAAK,WAAW;AAC1E,UAAM,MAAM,IAAI,IAAI,QAAQ,eAAe,QAAQ,KAAK,MAAM;AAC9D,UAAM,OACJ,QAAQ,WAAW,SAAS,QAAQ,WAAW,SAC3C,SACA,MAAM,SAAS,OAAO;AAE5B,UAAM,mBAAmB,MAAM,SAAS;AAAA,MACtC,IAAI,QAAQ,IAAI,SAAS,GAAG;AAAA,QAC1B,QAAQ,QAAQ;AAAA,QAChB,SAAS,QAAQ;AAAA,QACjB;AAAA,MACF,CAAC;AAAA,IACH;AAEA,aAAS,OAAO,iBAAiB,MAAM;AACvC,qBAAiB,QAAQ,QAAQ,CAAC,OAAO,QAAQ;AAC/C,eAAS,UAAU,KAAK,KAAK;AAAA,IAC/B,CAAC;AACD,aAAS,KAAK,MAAM,iBAAiB,KAAK,CAAC;AAAA,EAC7C;AACF;AAEA,SAAS,SAAS,SAAsD;AACtE,SAAO,IAAI,QAAQ,CAAC,SAAS,WAAW;AACtC,UAAM,SAAuB,CAAC;AAC9B,YAAQ,GAAG,QAAQ,CAAC,UAAU;AAC5B,aAAO,KAAK,OAAO,UAAU,WAAW,OAAO,KAAK,KAAK,IAAI,KAAK;AAAA,IACpE,CAAC;AACD,YAAQ,GAAG,OAAO,MAAM;AACtB;AAAA,QACE,OAAO,SAAS,IAAI,OAAO,OAAO,MAAM,EAAE,SAAS,MAAM,IAAI;AAAA,MAC/D;AAAA,IACF,CAAC;AACD,YAAQ,GAAG,SAAS,MAAM;AAAA,EAC5B,CAAC;AACH;;;AC1CO,IAAM,YAAN,cAAwB,MAAM;AAAA,EACnB;AAAA,EACA;AAAA,EACA;AAAA,EAEhB,YACE,MACA,SACA,QACA,OACA;AACA,UAAM,OAAO;AACb,SAAK,OAAO;AACZ,SAAK,OAAO;AACZ,SAAK,SAAS;AACd,SAAK,QAAQ;AAAA,EACf;AACF;;;ACbO,SAAS,mBAAmB,OAAsC;AACvE,SAAO,eAAe,eACpB,SACA,UACA,MACA;AACA,UAAM,QAAQ,eAAe,QAAQ,QAAQ,aAAa;AAE1D,QAAI,CAAC,OAAO;AACV,eAAS,OAAO,GAAG,EAAE,KAAK;AAAA,QACxB,OAAO;AAAA,QACP,SAAS;AAAA,MACX,CAAC;AACD;AAAA,IACF;AAEA,QAAI;AACF,YAAM,WAAW,MAAM,MAAM,OAAO,KAAK;AACzC,MAAC,QAA6B,YAAY;AAC1C,WAAK;AAAA,IACP,SAAS,OAAO;AACd,YAAM,YACJ,iBAAiB,YACb,QACA,IAAI;AAAA,QACF;AAAA,QACA;AAAA,QACA;AAAA,QACA;AAAA,MACF;AACN,eAAS,OAAO,UAAU,MAAM,EAAE,KAAK;AAAA,QACrC,OAAO,UAAU;AAAA,QACjB,SAAS,UAAU;AAAA,MACrB,CAAC;AAAA,IACH;AAAA,EACF;AACF;AAEA,SAAS,eAAe,QAA2C;AACjE,MAAI,CAAC,QAAQ;AACX,WAAO;AAAA,EACT;AAEA,QAAM,CAAC,QAAQ,KAAK,IAAI,OAAO,MAAM,OAAO,CAAC;AAC7C,MAAI,QAAQ,YAAY,MAAM,YAAY,CAAC,OAAO;AAChD,WAAO;AAAA,EACT;AAEA,SAAO;AACT;","names":[]}
@@ -0,0 +1,18 @@
1
+ import { RequestHandler, Request as Request$1 } from 'express';
2
+ import { S as ServiceIdentity } from '../../token-BtfYGd9K.cjs';
3
+ import 'jose';
4
+
5
+ interface WebHandler {
6
+ handle(request: Request): Promise<Response>;
7
+ }
8
+ declare function createExpressProvider(provider: WebHandler): RequestHandler;
9
+
10
+ interface GuardVerifier {
11
+ verify(token: string): Promise<ServiceIdentity>;
12
+ }
13
+ interface TrustlineRequest extends Request$1 {
14
+ trustline?: ServiceIdentity;
15
+ }
16
+ declare function createExpressGuard(guard: GuardVerifier): RequestHandler;
17
+
18
+ export { type TrustlineRequest, type WebHandler, createExpressGuard, createExpressProvider };