@intellegens/cornerstone-client 0.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.
- package/LICENSE.md +7 -0
- package/README.md +73 -0
- package/index.js +1 -0
- package/package.json +29 -0
- package/services/auth/index.js +92 -0
- package/services/auth/types/index.js +2 -0
- package/services/auth/types/user-info.js +1 -0
- package/services/auth/types/user.js +1 -0
- package/services/config/index.js +69 -0
- package/services/index.js +2 -0
package/LICENSE.md
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
Copyright (c) 2025 Intellegens
|
|
2
|
+
|
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
|
4
|
+
|
|
5
|
+
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
|
6
|
+
|
|
7
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Cornerstone TypeScript WebClient Services
|
|
2
|
+
|
|
3
|
+
This project includes services for easy communication from a Cornerstone client application to the Cornerstone API.
|
|
4
|
+
|
|
5
|
+
## Getting started
|
|
6
|
+
|
|
7
|
+
1. Install dependencies:
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npm install
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
2. Build the project:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm run build
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
3. Run Client demo HTTP server:
|
|
20
|
+
|
|
21
|
+
```bash
|
|
22
|
+
npm run demo
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
4. Open
|
|
26
|
+
|
|
27
|
+
http://localhost:3000
|
|
28
|
+
|
|
29
|
+
## API reference
|
|
30
|
+
|
|
31
|
+
### Config Service
|
|
32
|
+
|
|
33
|
+
This service provides way to load configuration for a Cornerstone client application.
|
|
34
|
+
|
|
35
|
+
```ts
|
|
36
|
+
import { Config } from './index.js';
|
|
37
|
+
await configAPI.initialize();
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
#### API base URL
|
|
41
|
+
|
|
42
|
+
Detected by checking the `CORNERSTONE-API-BASEURL` response header and the `websettings.json` file.
|
|
43
|
+
|
|
44
|
+
- First, it checks the response headers of the current URL for the 'CORNERSTONE-API-BASEURL ' header.
|
|
45
|
+
- If the header is not found, it attempts to load the `websettings.json` file and looks for an `api` field.
|
|
46
|
+
- If no API base URL is found, it defaults to `undefined`.
|
|
47
|
+
|
|
48
|
+
### Auth Service
|
|
49
|
+
|
|
50
|
+
This service provides authentication methods for managing user sessions in a Cornerstone client application.
|
|
51
|
+
|
|
52
|
+
#### Usage
|
|
53
|
+
|
|
54
|
+
To use the Auth service, first create an instance by passing the API URL. Then, you can use the login, logout, and whoAmI methods to authenticate and manage the user session.
|
|
55
|
+
|
|
56
|
+
```ts
|
|
57
|
+
import { Auth } from './index.js';
|
|
58
|
+
const authAPI = new Auth('https://your-api-url.com');
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
#### Methods
|
|
62
|
+
|
|
63
|
+
- login(username: string, password: string): Promise<User | undefined>
|
|
64
|
+
|
|
65
|
+
This method logs the user in by sending the provided username and password to the API. If the login is successful, it returns the authenticated User object.
|
|
66
|
+
|
|
67
|
+
- logout(): Promise<User | undefined>
|
|
68
|
+
|
|
69
|
+
This method logs the user out by sending a request to the API to end the session. It returns undefined if the logout is successful
|
|
70
|
+
|
|
71
|
+
- whoAmI(): Promise<User | undefined>
|
|
72
|
+
|
|
73
|
+
This method checks the current session and returns the User object for the logged-in user. If no user is logged in, it returns undefined.
|
package/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './services';
|
package/package.json
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@intellegens/cornerstone-client",
|
|
3
|
+
"version": "0.0.1",
|
|
4
|
+
"main": "index.js",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"demo": "tsc && npx vite build && npx tsx ./demo"
|
|
10
|
+
},
|
|
11
|
+
"author": "",
|
|
12
|
+
"license": "MIT",
|
|
13
|
+
"description": "",
|
|
14
|
+
"devDependencies": {
|
|
15
|
+
"@eslint/js": "^9.21.0",
|
|
16
|
+
"@types/express": "^5.0.0",
|
|
17
|
+
"@types/node": "^22.13.9",
|
|
18
|
+
"eslint": "^9.21.0",
|
|
19
|
+
"eslint-config-prettier": "^10.0.1",
|
|
20
|
+
"express": "^4.21.2",
|
|
21
|
+
"globals": "^16.0.0",
|
|
22
|
+
"prettier": "^3.5.2",
|
|
23
|
+
"typescript-eslint": "^8.26.0",
|
|
24
|
+
"vite": "^6.2.0"
|
|
25
|
+
},
|
|
26
|
+
"dependencies": {
|
|
27
|
+
"http-proxy-middleware": "^3.0.3"
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Auth class is responsible for managing user authentication operations.
|
|
3
|
+
* It supports login, logout, and checking the current user's details.
|
|
4
|
+
*
|
|
5
|
+
* @export
|
|
6
|
+
* @class Auth
|
|
7
|
+
*/
|
|
8
|
+
export class Auth {
|
|
9
|
+
_apiUrl;
|
|
10
|
+
user = undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Creates an instance of Auth.
|
|
13
|
+
*
|
|
14
|
+
* @param {string} apiUrl
|
|
15
|
+
* @memberof Auth
|
|
16
|
+
*/
|
|
17
|
+
constructor(apiUrl) {
|
|
18
|
+
this._apiUrl = apiUrl;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Retrieves the current user's details if they are logged in.
|
|
22
|
+
*
|
|
23
|
+
* @return {Promise<TUser>} Currently logged in user
|
|
24
|
+
* @throws {Error} Error if fetch fails
|
|
25
|
+
* @memberof Auth
|
|
26
|
+
*/
|
|
27
|
+
async whoAmI() {
|
|
28
|
+
try {
|
|
29
|
+
const response = await fetch(`${this._apiUrl}/auth/who-am-i`, { credentials: 'include' });
|
|
30
|
+
if (response.ok) {
|
|
31
|
+
const info = await response.json();
|
|
32
|
+
return (this.user = info.user);
|
|
33
|
+
}
|
|
34
|
+
else {
|
|
35
|
+
throw new Error('Failed checking authentication status');
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
throw error instanceof Error ? error : new Error('Failed checking authentication status');
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Logs in a user using their username and password, and retrieves the user data.
|
|
44
|
+
*
|
|
45
|
+
* @param {string} username Login credentials: username
|
|
46
|
+
* @param {string} password Login credentials: password
|
|
47
|
+
* @return {Promise<TUser>} Currently logged in user
|
|
48
|
+
* @throws {Error} Error if fetch fails
|
|
49
|
+
* @memberof Auth
|
|
50
|
+
*/
|
|
51
|
+
async login(username, password) {
|
|
52
|
+
try {
|
|
53
|
+
const response = await fetch(`${this._apiUrl}/auth/signin`, {
|
|
54
|
+
method: 'POST',
|
|
55
|
+
headers: { 'Content-Type': 'application/json' },
|
|
56
|
+
body: JSON.stringify({ username, password }),
|
|
57
|
+
credentials: 'include',
|
|
58
|
+
});
|
|
59
|
+
if (response.ok) {
|
|
60
|
+
return (this.user = await this.whoAmI());
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
throw new Error('Failed user login');
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
catch (error) {
|
|
67
|
+
throw error instanceof Error ? error : new Error('Failed user login');
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Logs out the current user and clears their authentication state.
|
|
72
|
+
*
|
|
73
|
+
* @return {Promise<void>}
|
|
74
|
+
* @throws {Error} Error if fetch fails
|
|
75
|
+
* @memberof Auth
|
|
76
|
+
*/
|
|
77
|
+
async logout() {
|
|
78
|
+
try {
|
|
79
|
+
const response = await fetch(`${this._apiUrl}/auth/logout`, { credentials: 'include' });
|
|
80
|
+
if (response.ok) {
|
|
81
|
+
this.user = undefined;
|
|
82
|
+
return;
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
throw new Error('Failed user logout');
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
throw error instanceof Error ? error : new Error('Failed user logout');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Configuration class for managing the API
|
|
3
|
+
*
|
|
4
|
+
* @export
|
|
5
|
+
* @class Config
|
|
6
|
+
*/
|
|
7
|
+
export class Config {
|
|
8
|
+
/**
|
|
9
|
+
* The base URL of the API. It is undefined by default and gets populated through the initialization process.
|
|
10
|
+
*
|
|
11
|
+
* @type {(string | undefined)}
|
|
12
|
+
* @memberof Config
|
|
13
|
+
*/
|
|
14
|
+
apiBaseUrl = undefined;
|
|
15
|
+
/**
|
|
16
|
+
* Initializes the configuration by detecting the API base URL.
|
|
17
|
+
*
|
|
18
|
+
* This method calls all methods that need to be called during the config phase.
|
|
19
|
+
*
|
|
20
|
+
* @async
|
|
21
|
+
* @return {Promise<void>} Resolves when the API base URL is detected.
|
|
22
|
+
* @memberof Config
|
|
23
|
+
*/
|
|
24
|
+
async initialize() {
|
|
25
|
+
await this.detectApiBaseUrl();
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Detects the API base URL by checking the `CORNERSTONE-API-BASEURL` header and the `websettings.json` file.
|
|
29
|
+
*
|
|
30
|
+
* First, it checks the response headers of the current URL for the 'CORNERSTONE-API-BASEURL' header.
|
|
31
|
+
* If the header is not found, it attempts to load the `websettings.json` file and looks for an `api` field.
|
|
32
|
+
* If no API base URL is found, it defaults to `undefined`.
|
|
33
|
+
*
|
|
34
|
+
* @return {Promise<string | undefined>} Returns the API base URL
|
|
35
|
+
* @throws {Error} Throws error if fetch fails
|
|
36
|
+
* @memberof Config
|
|
37
|
+
*/
|
|
38
|
+
async detectApiBaseUrl() {
|
|
39
|
+
// Initialize a globally tracked error
|
|
40
|
+
let error = undefined;
|
|
41
|
+
// Check CORNERSTONE-API-BASEURL header for API base URL
|
|
42
|
+
try {
|
|
43
|
+
const currentUrlResponse = await fetch(window.location.href, { method: 'GET' });
|
|
44
|
+
const apiHeader = currentUrlResponse.headers.get('CORNERSTONE-API-BASEURL');
|
|
45
|
+
if (apiHeader)
|
|
46
|
+
return (this.apiBaseUrl = apiHeader);
|
|
47
|
+
}
|
|
48
|
+
catch (err) {
|
|
49
|
+
error = err instanceof Error ? err : new Error('Failed loading configuration from response header!');
|
|
50
|
+
}
|
|
51
|
+
// Check ./websettings.json header for API base URL
|
|
52
|
+
try {
|
|
53
|
+
const webSettingsResponse = await fetch('./websettings.json', { method: 'GET' });
|
|
54
|
+
if (webSettingsResponse.status === 404)
|
|
55
|
+
return (this.apiBaseUrl = undefined);
|
|
56
|
+
const webSettings = await webSettingsResponse.json();
|
|
57
|
+
if (webSettings?.api)
|
|
58
|
+
return (this.apiBaseUrl = webSettings.api);
|
|
59
|
+
}
|
|
60
|
+
catch (err) {
|
|
61
|
+
error = err instanceof Error ? err : new Error('Failed loading configuration from settings file!');
|
|
62
|
+
}
|
|
63
|
+
// Check if error caught
|
|
64
|
+
if (error !== undefined)
|
|
65
|
+
throw error;
|
|
66
|
+
// Default to no API found
|
|
67
|
+
return (this.apiBaseUrl = undefined);
|
|
68
|
+
}
|
|
69
|
+
}
|