@epsbv/oauth-sdk 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,57 @@
1
+ import { TcpNetConnectOpts } from "net"
2
+ import { Language, Status } from "../types"
3
+
4
+ // export enum TenantType {
5
+ // Admin = "admin",
6
+ // Distributor = "distributor",
7
+ // Builder = "builder"
8
+ // }
9
+
10
+ export enum TenantRole {
11
+ Guest = "guest",
12
+ Member = "member",
13
+ Admin = "admin",
14
+ Owner = "owner",
15
+ }
16
+
17
+ export interface TenantUser {
18
+ id: string,
19
+ uid: string,
20
+ email: string,
21
+ role: TenantRole,
22
+ avatar: string | undefined
23
+ first_name: string,
24
+ last_name: string,
25
+ language: Language
26
+ created_at: Date,
27
+ updated_at: Date,
28
+ }
29
+
30
+ export interface Tenant {
31
+ id: string
32
+ name: string
33
+ // type: TenantType
34
+ email: string
35
+ avatar: string | undefined
36
+ status: Status
37
+ parent: string,
38
+ language: Language,
39
+ created_at: Date,
40
+ updated_at: Date,
41
+ }
42
+
43
+ export interface Client {
44
+ id: string,
45
+ name: string
46
+ status: Status,
47
+ secret: string,
48
+ type: ClientType,
49
+ created_at: Date,
50
+ updated_at: Date,
51
+ redirect_uri: string
52
+ }
53
+
54
+ export enum ClientType {
55
+ Web = "web",
56
+ Public = "public"
57
+ }
package/src/types.ts ADDED
@@ -0,0 +1,17 @@
1
+ export interface ClientOptions {
2
+ token: string,
3
+ baseUrl: string
4
+ }
5
+
6
+ export enum Language {
7
+ NL = "NL",
8
+ DE = "DE",
9
+ FR = "FR",
10
+ EN = "EN"
11
+ }
12
+
13
+ export enum Status{
14
+ Pending = "pending",
15
+ Rejected = "rejected",
16
+ Accepted = "accepted",
17
+ }
@@ -0,0 +1,161 @@
1
+ export type FetchMethod = "GET" | "POST" | "DELETE" | "PUT" | 'PATCH';
2
+
3
+ export interface FetchOptions {
4
+ body?: any,
5
+ headers?: HeadersInit
6
+ }
7
+
8
+ export async function fetchJson<T>(url: string, method: FetchMethod, options: FetchOptions) {
9
+ options.headers = new Headers(options.headers)
10
+
11
+ if (method != 'GET' && options.body != undefined) {
12
+ options.body = JSON.stringify(options.body);
13
+ options.headers.append('Content-Type', 'application/json');
14
+ }
15
+
16
+ try {
17
+ // Make the fetch request
18
+ const response = await fetch(url, {
19
+ method,
20
+ headers: options.headers,
21
+ body: options.body
22
+ });
23
+
24
+ const responseText = await response.text()
25
+
26
+ // Attempt to parse JSON response
27
+ try {
28
+ return JSON.parse(responseText) as T;
29
+ }
30
+ catch (_) {
31
+ throw new Error(responseText)
32
+ }
33
+ }
34
+ catch ({ message }: any) {
35
+ throw new Error(message)
36
+ }
37
+ }
38
+
39
+ export async function fetchUrlEncoded<T>(endpoint: string, method: FetchMethod, options: FetchOptions) {
40
+ let headers = new Headers(options.headers)
41
+ let body: string | undefined;
42
+
43
+ if (options.body != undefined) {
44
+ headers.append('Content-Type', 'application/x-www-form-urlencoded');
45
+ body = new URLSearchParams(options.body).toString()
46
+ }
47
+
48
+ try {
49
+ // Make the fetch request
50
+ const getBody = method == 'GET' && body != undefined;
51
+ const url = getBody ? `${endpoint}?${body}` : endpoint;
52
+
53
+ const response = await fetch(url, {
54
+ method,
55
+ headers,
56
+ body: getBody ? null : body
57
+ });
58
+
59
+ const responseText = await response.text()
60
+
61
+ // Attempt to parse JSON response
62
+ try {
63
+ return JSON.parse(responseText) as T;
64
+ }
65
+ catch (_) {
66
+ throw new Error(responseText)
67
+ }
68
+ }
69
+ catch ({ message }: any) {
70
+ throw new Error(message)
71
+ }
72
+ }
73
+
74
+ export async function fetchMultipart<T>(endpoint: string, method: FetchMethod, options: FetchOptions) {
75
+ let formData = new FormData();
76
+
77
+ // Helper function to recursively append to FormData
78
+ const appendData = (data: any, parentKey?: string) => {
79
+ if (data === null || data === undefined) {
80
+ return;
81
+ }
82
+
83
+ // If it's a File or Blob, append directly
84
+ if (data instanceof File || data instanceof Blob) {
85
+ formData.append(parentKey!, data);
86
+ return;
87
+ }
88
+
89
+ // If it's an array
90
+ if (Array.isArray(data)) {
91
+ data.forEach((item, index) => {
92
+ const key = parentKey ? `${parentKey}[${index}]` : `[${index}]`;
93
+
94
+ if (item instanceof File || item instanceof Blob) {
95
+ formData.append(key, item);
96
+ } else if (typeof item === 'object' && item !== null) {
97
+ appendData(item, key);
98
+ } else {
99
+ formData.append(key, String(item));
100
+ }
101
+ });
102
+ return;
103
+ }
104
+
105
+ // If it's an object
106
+ if (typeof data === 'object') {
107
+ Object.entries(data).forEach(([key, value]) => {
108
+ const fullKey = parentKey ? `${parentKey}[${key}]` : key;
109
+
110
+ if (value instanceof File || value instanceof Blob) {
111
+ formData.append(fullKey, value);
112
+ } else if (value instanceof Date) {
113
+ formData.append(fullKey, value.toISOString());
114
+ } else if (typeof value === 'object' && value !== null) {
115
+ appendData(value, fullKey);
116
+ } else if (value !== undefined && value !== null) {
117
+ formData.append(fullKey, String(value));
118
+ }
119
+ });
120
+ return;
121
+ }
122
+
123
+ // For primitive values
124
+ if (parentKey) {
125
+ formData.append(parentKey, String(data));
126
+ }
127
+ }
128
+
129
+ // Convert body to FormData
130
+ if (options.body) {
131
+ appendData(options.body);
132
+ }
133
+
134
+ console.log(formData);
135
+
136
+ try {
137
+ // Don't set Content-Type header - browser will set it with boundary
138
+ const headers = new Headers(options.headers);
139
+ headers.delete('Content-Type');
140
+
141
+ const response = await fetch(endpoint, {
142
+ method,
143
+ headers,
144
+ body: formData
145
+ });
146
+
147
+ const responseText = await response.text()
148
+
149
+ // Attempt to parse JSON response
150
+ try {
151
+ return JSON.parse(responseText) as T;
152
+ }
153
+ catch (_) {
154
+ throw new Error(responseText)
155
+ }
156
+ }
157
+ catch ({ message }: any) {
158
+ throw new Error(message)
159
+ }
160
+
161
+ }
@@ -0,0 +1,28 @@
1
+ import * as encoding from "@oslojs/encoding";
2
+ import * as sha2 from "@oslojs/crypto/sha2";
3
+
4
+ export function createS256CodeChallenge(codeVerifier: string): string {
5
+ const codeChallengeBytes = sha2.sha256(new TextEncoder().encode(codeVerifier));
6
+
7
+ return encoding.encodeBase64urlNoPadding(codeChallengeBytes);
8
+ }
9
+
10
+ export function generateCodeVerifier(): string {
11
+ const randomValues = new Uint8Array(32);
12
+
13
+ crypto.getRandomValues(randomValues);
14
+
15
+ return encoding.encodeBase64urlNoPadding(randomValues);
16
+ }
17
+
18
+ export function generateState(): string {
19
+ const randomValues = new Uint8Array(32);
20
+
21
+ crypto.getRandomValues(randomValues);
22
+
23
+ return encoding.encodeBase64urlNoPadding(randomValues);
24
+ }
25
+
26
+ export function encodeCredentials(key: string, secret: string): string {
27
+ return encoding.encodeBase64NoPadding(new TextEncoder().encode(`${key}:${secret}`))
28
+ }
package/tsconfig.json ADDED
@@ -0,0 +1,16 @@
1
+ {
2
+ "compilerOptions": {
3
+ "incremental": true, /* Enable incremental compilation */
4
+ "target": "ES2022", /* Specify ECMAScript target version: */
5
+ "module": "ESNext", /* 'none', 'commonjs', 'amd', 'system', etc */
6
+ "declaration": true, /* Concatenate & emit output to single file.*/
7
+ "outDir": "build", /* Redirect output to the directory. */
8
+ "moduleResolution": "node",
9
+ "esModuleInterop": true, /* Enables intero between CommonJS and ES */
10
+ "skipLibCheck": true, /* Skip type checking of declaration files. */
11
+ "forceConsistentCasingInFileNames": true /* Disallow inconsistently */
12
+ },
13
+ "include": [
14
+ "src"
15
+ ]
16
+ }