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.
- package/LICENSE +21 -0
- package/README.md +339 -0
- package/dist/adapters/mysql/index.cjs +199 -0
- package/dist/adapters/mysql/index.cjs.map +1 -0
- package/dist/adapters/mysql/index.d.cts +6 -0
- package/dist/adapters/mysql/index.d.ts +6 -0
- package/dist/adapters/mysql/index.js +21 -0
- package/dist/adapters/mysql/index.js.map +1 -0
- package/dist/adapters/postgres/index.cjs +199 -0
- package/dist/adapters/postgres/index.cjs.map +1 -0
- package/dist/adapters/postgres/index.d.cts +6 -0
- package/dist/adapters/postgres/index.d.ts +6 -0
- package/dist/adapters/postgres/index.js +21 -0
- package/dist/adapters/postgres/index.js.map +1 -0
- package/dist/adapters/sqlite/index.cjs +216 -0
- package/dist/adapters/sqlite/index.cjs.map +1 -0
- package/dist/adapters/sqlite/index.d.cts +6 -0
- package/dist/adapters/sqlite/index.d.ts +6 -0
- package/dist/adapters/sqlite/index.js +28 -0
- package/dist/adapters/sqlite/index.js.map +1 -0
- package/dist/chunk-CTPFKR4O.js +157 -0
- package/dist/chunk-CTPFKR4O.js.map +1 -0
- package/dist/chunk-GF3NKEEK.js +18 -0
- package/dist/chunk-GF3NKEEK.js.map +1 -0
- package/dist/client/index.cjs +141 -0
- package/dist/client/index.cjs.map +1 -0
- package/dist/client/index.d.cts +18 -0
- package/dist/client/index.d.ts +18 -0
- package/dist/client/index.js +104 -0
- package/dist/client/index.js.map +1 -0
- package/dist/frameworks/express/index.cjs +121 -0
- package/dist/frameworks/express/index.cjs.map +1 -0
- package/dist/frameworks/express/index.d.cts +18 -0
- package/dist/frameworks/express/index.d.ts +18 -0
- package/dist/frameworks/express/index.js +83 -0
- package/dist/frameworks/express/index.js.map +1 -0
- package/dist/frameworks/fastify/index.cjs +158 -0
- package/dist/frameworks/fastify/index.cjs.map +1 -0
- package/dist/frameworks/fastify/index.d.cts +25 -0
- package/dist/frameworks/fastify/index.d.ts +25 -0
- package/dist/frameworks/fastify/index.js +120 -0
- package/dist/frameworks/fastify/index.js.map +1 -0
- package/dist/frameworks/hono/index.cjs +117 -0
- package/dist/frameworks/hono/index.cjs.map +1 -0
- package/dist/frameworks/hono/index.d.cts +17 -0
- package/dist/frameworks/hono/index.d.ts +17 -0
- package/dist/frameworks/hono/index.js +79 -0
- package/dist/frameworks/hono/index.js.map +1 -0
- package/dist/index-Dc4GFume.d.ts +34 -0
- package/dist/index-DqkKZOlH.d.cts +34 -0
- package/dist/index.cjs +571 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +14 -0
- package/dist/index.d.ts +14 -0
- package/dist/index.js +537 -0
- package/dist/index.js.map +1 -0
- package/dist/interface-BzT_DC3u.d.cts +38 -0
- package/dist/interface-BzT_DC3u.d.ts +38 -0
- package/dist/token-BtfYGd9K.d.cts +33 -0
- package/dist/token-BtfYGd9K.d.ts +33 -0
- package/package.json +125 -3
- 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 };
|