Skip to content

Commit 05731b2

Browse files
committed
feat: add defineConfig and change factory method name
1 parent da95846 commit 05731b2

35 files changed

+930
-23
lines changed

.changeset/chilly-swans-begin.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"elysia-openid-client": patch
3+
---
4+
5+
Add defineConfig

.changeset/large-maps-fold.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"elysia-openid-client": patch
3+
---
4+
5+
Change factory method name from create to factory

.gitignore

+1-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
.env
22
.temp
3-
docs
43
*.js
5-
*.d.ts
4+
index.d.ts
65
.vscode/settings.json
76
node_modules

__mock__/const.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -146,7 +146,7 @@ export const mockStatus = {
146146

147147
export const mockBaseClient = {
148148
...mockBaseOptions,
149-
create: mock(),
149+
factory: mock(),
150150
initialize: mock(),
151151
validateOptions: mock(),
152152
createSession: mock(),

__scripts__/rebuildMockDatabases.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ if (fs.existsSync(lowMockFile)) {
2626
fs.unlinkSync(lowMockFile);
2727
}
2828

29-
const lowdb = await LowdbAdapter.create({
29+
const lowdb = await LowdbAdapter.factory({
3030
filename: lowMockFile,
3131
});
3232
await lowdb.insert(mockActiveSession);
@@ -38,7 +38,7 @@ if (fs.existsSync(lokiMockFile)) {
3838
fs.unlinkSync(lokiMockFile);
3939
}
4040

41-
const loki = await LokiFileAdapter.create({
41+
const loki = await LokiFileAdapter.factory({
4242
filename: lokiMockFile,
4343
autosaveInterval: 500,
4444
});

__test__/general.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ describe("Integration/general", async () => {
1717

1818
const client_id = "mock-client-id";
1919
const client_secret = "mock-client-secret";
20-
const oidcClient = await OidcClient.create({
20+
const oidcClient = await OidcClient.factory({
2121
baseUrl,
2222
issuerUrl,
2323
clientMetadata: {

package.json

+1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
"type": "module",
2323
"exports": {
2424
".": "./src/index.ts",
25+
"./config": "./src/config/index.ts",
2526
"./*": "./src/*.ts",
2627
"./package.json": "./package.json"
2728
},

src/config/index.ts

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import type { OIDCClientOptions } from "../types.js";
2+
3+
export const defineConfig = (
4+
config?: OIDCClientOptions,
5+
): OIDCClientOptions | undefined => config;

src/core/BaseOidcClient.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ export class BaseOidcClient {
3434
settings: OIDCClientSettings;
3535
/** Cookie settings */
3636
cookieSettings: OIDCClientCookieSettings;
37-
/** OIDC Issuer (Initialize at create()) */
37+
/** OIDC Issuer (Initialize at factory()) */
3838
issuer!: Issuer<BaseClient>;
39-
/** OIDC Issuer metadata (Initialize at create()) */
39+
/** OIDC Issuer metadata (Initialize at factory()) */
4040
issuerMetadata!: IssuerMetadata;
41-
/** OIDC Client (Initialize at create()) */
41+
/** OIDC Client (Initialize at factory()) */
4242
client!: BaseClient;
4343
/** Plugin database */
4444
sessions: OIDCClientDataAdapter;
@@ -93,7 +93,7 @@ export class BaseOidcClient {
9393
* @param options
9494
* @returns BaseOidcClient instance
9595
*/
96-
static async create(options: OIDCClientOptions) {
96+
static async factory(options: OIDCClientOptions) {
9797
const instance = new BaseOidcClient(options);
9898
await instance.initialize();
9999
return instance;

src/core/OidcClient.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ import { BaseOidcClient } from "./BaseOidcClient";
1616
/**
1717
* OpenID Connect client plugin for ElysiaJS
1818
* - Usage:
19-
* - `const client = await BaseOidcClient.create(options);`
19+
* - `const client = await BaseOidcClient.factory(options);`
2020
* - `const endpoints = client.getEndpoints();`
2121
* - `const hook = client.getAuthHook();`
2222
*/
@@ -27,7 +27,7 @@ export class OidcClient extends BaseOidcClient {
2727
* @static
2828
* @returns OidcClient instance
2929
*/
30-
static async create(options: OIDCClientOptions) {
30+
static async factory(options: OIDCClientOptions) {
3131
const instance = new OidcClient(options);
3232
await instance.initialize();
3333
return instance;

src/core/baseOidcClient.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ describe("Unit/core/BaseOidcClient", () => {
1414
});
1515

1616
const mockOptions = structuredClone(mockBaseOptions);
17-
const client = await BaseOidcClient.create({
17+
const client = await BaseOidcClient.factory({
1818
...mockOptions,
1919
issuerUrl: `http://localhost:${opPort}`,
2020
settings: defaultSettings,

src/dataAdapters/LokiFileAdapter.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ const defaultOptions: LokiFileAdapterOptions = {
2929

3030
/**
3131
* File-system data adapter using LokiJS
32-
* - Usage: `const dataAdapter = await LokiFileAdapter.create();`
32+
* - Usage: `const dataAdapter = await LokiFileAdapter.factory();`
3333
* - Requires: `bun add lokijs` and `bun add -D @types/lokijs`
3434
* @see [LokiJS](https://techfort.github.io/LokiJS/)
3535
*/
@@ -71,7 +71,7 @@ export class LokiFileAdapter extends BaseLokiAdapter {
7171
* @param options LokiFileAdapterOptions
7272
* @returns LokiFileAdapter instance
7373
*/
74-
static async create(options?: Partial<LokiFileAdapterOptions>) {
74+
static async factory(options?: Partial<LokiFileAdapterOptions>) {
7575
const instance = new LokiFileAdapter(options);
7676
await instance.initialize();
7777
return instance;

src/dataAdapters/LowdbAdapter.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export class LowdbAdapter implements OIDCClientDataAdapter {
3939
* @param options LokiFileAdapterOptions
4040
* @returns LokiFileAdapter instance
4141
*/
42-
static create = async (options?: Partial<LowdbAdapterOptions>) => {
42+
static factory = async (options?: Partial<LowdbAdapterOptions>) => {
4343
const instance = new LowdbAdapter(options);
4444
await instance.initialize();
4545
return instance;

src/dataAdapters/lokiFileAdapter.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import { LokiFileAdapter } from "./LokiFileAdapter";
66

77
describe("Unit/dataAdapter/LokiFileAdapter", () => {
88
test("Default", async () => {
9-
const db = await LokiFileAdapter.create({
9+
const db = await LokiFileAdapter.factory({
1010
filename: lokiTempFile,
1111
autosaveInterval: 1000,
1212
});
@@ -60,7 +60,7 @@ describe("Unit/dataAdapter/LokiFileAdapter", () => {
6060
});
6161

6262
test("Load existing database", async () => {
63-
const db = await LokiFileAdapter.create({
63+
const db = await LokiFileAdapter.factory({
6464
filename: lokiMockFile,
6565
});
6666
expect(db.fetch(mockActiveSession.sessionId)).toMatchObject(

src/dataAdapters/lowdbAdapter.test.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { LowdbAdapter } from "./LowdbAdapter";
55

66
describe("Unit/dataAdapter/LowdbAdapter", () => {
77
test("Default", async () => {
8-
const db = await LowdbAdapter.create();
8+
const db = await LowdbAdapter.factory();
99

1010
// Insert & fetch
1111
await db.insert({
@@ -45,7 +45,7 @@ describe("Unit/dataAdapter/LowdbAdapter", () => {
4545
// NOTES: Does not work only in test (due to Bun?)
4646
// biome-ignore lint/suspicious/noSkippedTests: <explanation>
4747
test.skip("Load existing database", async () => {
48-
const db = await LowdbAdapter.create({
48+
const db = await LowdbAdapter.factory({
4949
filename: lowMockFile,
5050
});
5151
expect(db.fetch(mockActiveSession.sessionId)).toMatchObject(

src/methods/getEndpoints.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ describe("Unit/methods/getEndpoints", async () => {
1717
.listen(opPort);
1818

1919
const mockOptions = structuredClone(mockBaseOptions);
20-
const rp = await OidcClient.create({
20+
const rp = await OidcClient.factory({
2121
...mockOptions,
2222
baseUrl: `http://localhost:${rpPort}`,
2323
issuerUrl: `http://localhost:${opPort}`,

src/methods/initialize.test.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ describe("Unit/methods/initialize", async () => {
1212

1313
test("Default", async () => {
1414
const mockOptions = structuredClone(mockBaseOptions);
15-
const mockClinet = await BaseOidcClient.create({
15+
const mockClinet = await BaseOidcClient.factory({
1616
...mockOptions,
1717
issuerUrl: `http://localhost:${opPort}`,
1818
});

src/types.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -105,7 +105,7 @@ export interface OIDCClientOptions {
105105
* @example
106106
* ```
107107
* import pino from "pino";
108-
* const rp = new OidcClient.create({ ..., logger: pino() });
108+
* const rp = new OidcClient.factory({ ..., logger: pino() });
109109
* ```
110110
*/
111111
logger?: OIDCClientLogger | null;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,80 @@
1+
---
2+
title: Multiple Issuer
3+
---
4+
5+
```typescript
6+
import Elysia from "elysia";
7+
import { OidcClient } from "../src";
8+
import { SQLiteAdapter } from "../src/dataAdapters/SQLiteAdapter";
9+
// import { OidcClient } from "elysia-openid-client";
10+
// import { SQLiteAdapter } from "elysia-openid-client/dataAdapters/SQLiteAdapter";
11+
12+
const baseUrl = "https://app.example.com";
13+
14+
// Use the same data adapter for all issuers
15+
const dataAdapter = new SQLiteAdapter();
16+
17+
// Callback URL: `https://app.example.com/auth/callback`
18+
const rp1 = await OidcClient.create({
19+
baseUrl,
20+
issuerUrl: "https://issuer.exmaple.com",
21+
clientMetadata: {
22+
client_id: "client-id",
23+
client_secret: "client-secret",
24+
},
25+
dataAdapter,
26+
});
27+
const endpoints1 = rp1.getEndpoints();
28+
29+
console.log(rp1.issuerMetadata);
30+
31+
// Callback URL: `https://app.example.com/another/callback`
32+
const rp2 = await OidcClient.create({
33+
baseUrl,
34+
issuerUrl: "https://another-issuer.exmaple.com",
35+
clientMetadata: {
36+
client_id: "another-client-id",
37+
client_secret: "another-client-secret",
38+
},
39+
dataAdapter,
40+
settings: {
41+
pathPrefix: "/another",
42+
},
43+
});
44+
const endpoints2 = rp2.getEndpoints();
45+
46+
console.log(rp2.issuerMetadata);
47+
48+
// No matter which RP hook is used
49+
const hook = rp1.getAuthHook({
50+
loginRedirectUrl: "/select",
51+
});
52+
53+
new Elysia()
54+
.use(endpoints1)
55+
.use(endpoints2)
56+
.guard((app) =>
57+
app
58+
.use(hook)
59+
.get("/", ({ sessionStatus }) =>
60+
sessionStatus ? "Logged in" : "Restricted",
61+
)
62+
.get("/status", ({ sessionStatus }) => sessionStatus)
63+
// Issuer can be identified from `sessionClaims.iss`
64+
.get("/claims", ({ sessionClaims }) => sessionClaims),
65+
)
66+
.get("/select", ({ set }) => {
67+
set.headers["Content-Type"] = "text/html";
68+
return `
69+
<html>
70+
<body>
71+
<p><a href="/auth/login">Issuer</a></p>
72+
<p><a href="/another/login">Another</a></p>
73+
</body>
74+
</html>
75+
`;
76+
})
77+
.get("/free", () => "Not restricted")
78+
.get("/logout", () => "Logout completed")
79+
.listen(80);
80+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
---
2+
title: Single Issuer
3+
---
4+
5+
```typescript
6+
import Elysia from "elysia";
7+
import { OidcClient } from "../src";
8+
// import { OidcClient } from "elysia-openid-client";
9+
10+
// Callback URL: `https://app.example.com/auth/callback`
11+
const rp = await OidcClient.create({
12+
baseUrl: "https://app.example.com",
13+
issuerUrl: "https://issuer.exmaple.com",
14+
clientMetadata: {
15+
client_id: "client-id",
16+
client_secret: "client-secret",
17+
},
18+
});
19+
const endpoints = rp.getEndpoints();
20+
const hook = rp.getAuthHook();
21+
22+
console.log(rp.issuerMetadata);
23+
24+
new Elysia()
25+
.use(endpoints)
26+
.guard((app) =>
27+
app
28+
.use(hook)
29+
.get("/", ({ sessionStatus }) =>
30+
sessionStatus ? "Logged in" : "Restricted",
31+
)
32+
.get("/status", ({ sessionStatus }) => sessionStatus)
33+
.get("/claims", ({ sessionClaims }) => sessionClaims),
34+
)
35+
.get("/free", () => "Not restricted")
36+
.get("/logout", () => "Logout completed")
37+
.listen(80);
38+
```
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
---
2+
title: Getting Started
3+
# description:
4+
---
5+
6+
```bash
7+
bun add elysia-openid-client
8+
```
9+
10+
```typescript
11+
import Elysia from "elysia";
12+
import { OidcClient } from "elysia-openid-client";
13+
14+
const rp = await OidcClient.create({
15+
baseUrl: "https://app.example.com", // RP URL
16+
issuerUrl: "https://issuer.example.com", // OP URL
17+
clientMetadata: {
18+
client_id: "client-id",
19+
client_secret: "client-secret",
20+
},
21+
});
22+
const endpoints = rp.getEndpoints(); // Endpoints plugin
23+
const hook = rp.getAuthHook(); // Auth hook plugin
24+
25+
console.log(rp.issuerMetadata); // Show OP metadata
26+
27+
new Elysia()
28+
.use(endpoints) // Add endpoints
29+
.guard((app) => // Define restricted area
30+
app
31+
.use(hook) // Add onBeforeHandle hook for authentication/authorization
32+
.onBeforeHandle(({ sessionStatus, sessionClaims }) => {
33+
// Authorization by name, mail, group, etc.
34+
})
35+
.get("/", ({ sessionStatus }) => sessionStatus ? "Logged in" : "Restricted")
36+
.get("/status", ({ sessionStatus }) => sessionStatus)
37+
.get("/claims", ({ sessionClaims }) => sessionClaims),
38+
)
39+
.get("/free", () => "Not restricted")
40+
.get("/logout", () => "Logout completed")
41+
.listen(80);
42+
```

0 commit comments

Comments
 (0)