@karpeleslab/klbfw 0.1.13 → 0.2.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/README.md +199 -35
- package/cookies.js +107 -41
- package/fw-wrapper.js +221 -26
- package/index.d.ts +81 -0
- package/index.js +16 -2
- package/internal.js +186 -102
- package/package.json +28 -3
- package/rest.js +129 -81
- package/upload.js +987 -421
- package/util.js +59 -21
package/README.md
CHANGED
|
@@ -1,95 +1,259 @@
|
|
|
1
1
|
# klbfw
|
|
2
2
|
|
|
3
|
-
Karpeles Lab
|
|
3
|
+
Karpeles Lab Frontend Framework - A JavaScript library for communicating with KLB API.
|
|
4
4
|
|
|
5
|
-
This
|
|
5
|
+
This library provides a unified interface for interacting with KLB API services from both browser and Node.js environments.
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Cross-environment compatibility**: Works in both browser and Node.js environments
|
|
10
|
+
- **REST API client**: Simple and consistent interface for API requests
|
|
11
|
+
- **File upload**: Supports file uploads in any environment with both direct PUT and AWS S3 multipart protocols
|
|
12
|
+
- **Context handling**: Manages authentication, locale, and other contextual information
|
|
13
|
+
- **Cookie management**: Cross-platform cookie handling that works in SSR mode
|
|
14
|
+
- **Internationalization**: Easy access to i18n data
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install @karpeleslab/klbfw
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
For Node.js environments with file upload support, install optional dependencies:
|
|
23
|
+
|
|
24
|
+
```bash
|
|
25
|
+
npm install @karpeleslab/klbfw node-fetch xmldom
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Development
|
|
29
|
+
|
|
30
|
+
```bash
|
|
31
|
+
# Install dependencies
|
|
32
|
+
npm install
|
|
33
|
+
|
|
34
|
+
# Run tests
|
|
35
|
+
npm test
|
|
36
|
+
|
|
37
|
+
# Run tests with coverage
|
|
38
|
+
npm run test:coverage
|
|
39
|
+
|
|
40
|
+
# Run integration tests (requires KLB API server)
|
|
41
|
+
npm run test:integration
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
## Version 0.2.0 Changes
|
|
45
|
+
|
|
46
|
+
- **Modern JavaScript**: Refactored to use ES6+ features (arrow functions, const/let, template literals)
|
|
47
|
+
- **Improved Documentation**: Added comprehensive JSDoc comments for all modules and functions
|
|
48
|
+
- **Better Code Organization**: Restructured code for improved readability and maintainability
|
|
49
|
+
- **Cross-Platform Support**: Enhanced environment detection and compatibility
|
|
50
|
+
- **Standardized Naming**: Consistent use of camelCase with backward compatibility for legacy APIs
|
|
51
|
+
- **Enhanced Error Handling**: More robust error handling and reporting
|
|
6
52
|
|
|
7
53
|
# API
|
|
8
54
|
|
|
9
|
-
##
|
|
55
|
+
## REST API Methods
|
|
56
|
+
|
|
57
|
+
### rest(api, method, params, context)
|
|
58
|
+
|
|
59
|
+
Performs a REST query and returns a promise to the response.
|
|
60
|
+
|
|
61
|
+
### rest_get(name, params) / restGet(name, params)
|
|
62
|
+
|
|
63
|
+
Simplified version of rest() that uses HTTP GET. Takes a REST API endpoint name and optional parameters, returning a Promise with the response.
|
|
64
|
+
|
|
65
|
+
Note: Starting from version 0.2.0, camelCase method names are also available (e.g., `restGet` instead of `rest_get`).
|
|
66
|
+
|
|
67
|
+
### upload
|
|
68
|
+
|
|
69
|
+
The upload module provides cross-platform file upload capabilities, supporting both browser and Node.js environments.
|
|
70
|
+
|
|
71
|
+
#### Browser Usage
|
|
72
|
+
|
|
73
|
+
```javascript
|
|
74
|
+
// Open file picker and upload selected files
|
|
75
|
+
upload.upload.init('Misc/Debug:testUpload')()
|
|
76
|
+
.then(result => console.log('Upload complete', result));
|
|
77
|
+
|
|
78
|
+
// Upload a specific File object
|
|
79
|
+
upload.upload.append('Misc/Debug:testUpload', fileObject)
|
|
80
|
+
.then(result => console.log('Upload complete', result));
|
|
81
|
+
|
|
82
|
+
// Track progress
|
|
83
|
+
upload.upload.onprogress = (status) => {
|
|
84
|
+
console.log('Progress:', status.running.map(i => i.status));
|
|
85
|
+
};
|
|
86
|
+
|
|
87
|
+
// Cancel an upload
|
|
88
|
+
upload.upload.cancelItem(uploadId);
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
#### Node.js Usage
|
|
92
|
+
|
|
93
|
+
```javascript
|
|
94
|
+
// For Node.js environments, first install dependencies:
|
|
95
|
+
// npm install node-fetch xmldom
|
|
96
|
+
|
|
97
|
+
// Initialize upload with specific file paths
|
|
98
|
+
upload.upload.init('Misc/Debug:testUpload')(['./file1.txt', './file2.jpg'])
|
|
99
|
+
.then(result => console.log('Upload complete', result));
|
|
100
|
+
|
|
101
|
+
// Or create a custom file object with path
|
|
102
|
+
const file = {
|
|
103
|
+
name: 'test.txt',
|
|
104
|
+
size: 1024,
|
|
105
|
+
type: 'text/plain',
|
|
106
|
+
path: '/path/to/file.txt'
|
|
107
|
+
};
|
|
108
|
+
upload.upload.append('Misc/Debug:testUpload', file)
|
|
109
|
+
.then(result => console.log('Upload complete', result));
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
#### Upload Management
|
|
113
|
+
|
|
114
|
+
The upload module provides methods to manage active uploads:
|
|
115
|
+
|
|
116
|
+
- `upload.getStatus()`: Get current upload status (queue, running, failed)
|
|
117
|
+
- `upload.cancelItem(uploadId)`: Cancel an upload
|
|
118
|
+
- `upload.pauseItem(uploadId)`: Pause an active upload
|
|
119
|
+
- `upload.resumeItem(uploadId)`: Resume a paused upload
|
|
120
|
+
- `upload.retryItem(uploadId)`: Retry a failed upload
|
|
121
|
+
- `upload.deleteItem(uploadId)`: Remove an upload from the queue or failed list
|
|
122
|
+
|
|
123
|
+
## Query Parameter Methods
|
|
124
|
+
|
|
125
|
+
### GET
|
|
10
126
|
|
|
11
|
-
|
|
127
|
+
Object containing all URL query parameters parsed from the request.
|
|
12
128
|
|
|
13
|
-
|
|
129
|
+
### Get(key)
|
|
14
130
|
|
|
15
|
-
|
|
131
|
+
Retrieves a specific query parameter value by key. If no key is provided, returns the entire GET object.
|
|
16
132
|
|
|
17
|
-
|
|
133
|
+
### flushGet()
|
|
134
|
+
|
|
135
|
+
Clears the GET parameters by resetting the internal GET object to an empty object.
|
|
136
|
+
|
|
137
|
+
## URL and Path Methods
|
|
138
|
+
|
|
139
|
+
### getPrefix()
|
|
18
140
|
|
|
19
141
|
Returns the language/etc prefix part of the URL, for example `/l/en-US`. The prefix should be inserted before the path in the URL.
|
|
20
142
|
|
|
21
|
-
|
|
143
|
+
### getUrl()
|
|
144
|
+
|
|
145
|
+
Returns the active URL.
|
|
146
|
+
|
|
147
|
+
### getPath()
|
|
148
|
+
|
|
149
|
+
Returns the non-prefixed request path.
|
|
150
|
+
|
|
151
|
+
### trimPrefix(url)
|
|
152
|
+
|
|
153
|
+
Processes a URL to separate the prefix parts from the main path. Returns an array with two elements: an object containing the identified prefixes and the remaining path.
|
|
154
|
+
|
|
155
|
+
## Context and State Methods
|
|
156
|
+
|
|
157
|
+
### getSettings()
|
|
22
158
|
|
|
23
159
|
Returns active settings if any.
|
|
24
160
|
|
|
25
|
-
|
|
161
|
+
### getRealm()
|
|
26
162
|
|
|
27
163
|
Returns realm information.
|
|
28
164
|
|
|
29
|
-
|
|
165
|
+
### getContext()
|
|
30
166
|
|
|
31
167
|
Returns current context.
|
|
32
168
|
|
|
33
|
-
|
|
169
|
+
### setContext(ctx)
|
|
34
170
|
|
|
35
171
|
Modifies the current context.
|
|
36
172
|
|
|
37
|
-
|
|
173
|
+
### getInitialState()
|
|
174
|
+
|
|
175
|
+
Returns the initial state passed from SSR execution (or null if no SSR was performed).
|
|
176
|
+
|
|
177
|
+
### getMode()
|
|
38
178
|
|
|
39
|
-
Returns the current
|
|
179
|
+
Returns the current rendering mode `ssr`, `js` etc.
|
|
40
180
|
|
|
41
|
-
|
|
181
|
+
### getHostname()
|
|
42
182
|
|
|
43
183
|
Returns the hostname part of the current URL.
|
|
44
184
|
|
|
45
|
-
|
|
185
|
+
### getRegistry()
|
|
46
186
|
|
|
47
187
|
Returns data from the registry.
|
|
48
188
|
|
|
49
|
-
|
|
189
|
+
### getLocale()
|
|
50
190
|
|
|
51
191
|
Returns the currently active locale, for example `en-US`.
|
|
52
192
|
|
|
53
|
-
|
|
193
|
+
### getUserGroup()
|
|
54
194
|
|
|
55
195
|
Returns `g` from context, which is the current active user group.
|
|
56
196
|
|
|
57
|
-
|
|
197
|
+
### getCurrency()
|
|
58
198
|
|
|
59
199
|
Returns the currently selected currency, such as `USD`.
|
|
60
200
|
|
|
61
|
-
|
|
201
|
+
### getToken()
|
|
62
202
|
|
|
63
203
|
Returns the CSRF token.
|
|
64
204
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
Returns the active URL.
|
|
68
|
-
|
|
69
|
-
## getPath()
|
|
70
|
-
|
|
71
|
-
Returns the non-prefixed request path.
|
|
72
|
-
|
|
73
|
-
## getUuid()
|
|
205
|
+
### getUuid()
|
|
74
206
|
|
|
75
207
|
Returns the UUID of the request.
|
|
76
208
|
|
|
77
|
-
|
|
209
|
+
### getI18N(language)
|
|
78
210
|
|
|
79
|
-
|
|
211
|
+
Retrieves internationalization (i18n) data for a specified language. If no language is provided, uses the current locale.
|
|
80
212
|
|
|
81
|
-
|
|
213
|
+
## Cookie Methods
|
|
82
214
|
|
|
83
|
-
|
|
215
|
+
These methods are required as using things like `document.cookie` will not work in SSR mode. The methods described here will work when SSR is enabled, and will cause cookies to be added to the HTTP response.
|
|
84
216
|
|
|
85
|
-
|
|
217
|
+
### getCookie(cookie)
|
|
86
218
|
|
|
87
219
|
Get the value of a specific cookie.
|
|
88
220
|
|
|
89
|
-
|
|
221
|
+
### setCookie(cookie, value)
|
|
90
222
|
|
|
91
223
|
Sets value for a cookie.
|
|
92
224
|
|
|
93
|
-
|
|
225
|
+
### hasCookie(cookie)
|
|
94
226
|
|
|
95
227
|
Checks for presence of a given cookie.
|
|
228
|
+
|
|
229
|
+
## Cross-Platform Support
|
|
230
|
+
|
|
231
|
+
As of version 0.2.0, klbfw includes improved environment detection and cross-platform utilities to support both browser and Node.js environments.
|
|
232
|
+
|
|
233
|
+
### Environment Detection
|
|
234
|
+
|
|
235
|
+
The library automatically detects the current environment:
|
|
236
|
+
|
|
237
|
+
```javascript
|
|
238
|
+
const env = {
|
|
239
|
+
isBrowser: typeof window !== 'undefined' && typeof document !== 'undefined',
|
|
240
|
+
isNode: typeof process !== 'undefined' && process.versions && process.versions.node
|
|
241
|
+
};
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
### Cross-Platform Utilities
|
|
245
|
+
|
|
246
|
+
Several utilities have been designed to work across environments:
|
|
247
|
+
|
|
248
|
+
- **Fetch**: Uses the browser's native `fetch` or `node-fetch` in Node.js
|
|
249
|
+
- **XML Parsing**: Uses the browser's `DOMParser` or `xmldom` in Node.js
|
|
250
|
+
- **File Reading**: Uses `FileReader` in the browser or `fs` in Node.js
|
|
251
|
+
- **Event Dispatching**: Uses `CustomEvent` in the browser or `EventEmitter` in Node.js
|
|
252
|
+
|
|
253
|
+
### Node.js Requirements
|
|
254
|
+
|
|
255
|
+
To use klbfw with full functionality in Node.js, install the optional dependencies:
|
|
256
|
+
|
|
257
|
+
```bash
|
|
258
|
+
npm install node-fetch xmldom
|
|
259
|
+
```
|
package/cookies.js
CHANGED
|
@@ -1,70 +1,136 @@
|
|
|
1
|
-
'use strict'
|
|
2
|
-
|
|
1
|
+
'use strict';
|
|
2
|
+
/**
|
|
3
|
+
* @fileoverview Cookie handling utilities for KLB Frontend Framework
|
|
4
|
+
*
|
|
5
|
+
* This module provides functions for getting, setting, and checking cookies
|
|
6
|
+
* in both browser and server-side rendering environments.
|
|
7
|
+
*/
|
|
3
8
|
|
|
4
|
-
|
|
9
|
+
/**
|
|
10
|
+
* Parses cookies from document.cookie
|
|
11
|
+
* @private
|
|
12
|
+
* @returns {Object} Parsed cookies as key-value pairs
|
|
13
|
+
*/
|
|
14
|
+
const parseCookies = () => {
|
|
15
|
+
if (typeof document === "undefined") {
|
|
16
|
+
return {};
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
const cookies = {};
|
|
20
|
+
const decodedCookie = decodeURIComponent(document.cookie);
|
|
21
|
+
const cookieParts = decodedCookie.split(';');
|
|
22
|
+
|
|
23
|
+
for (const part of cookieParts) {
|
|
24
|
+
let cookiePart = part.trim();
|
|
25
|
+
const equalsIndex = cookiePart.indexOf('=');
|
|
26
|
+
|
|
27
|
+
if (equalsIndex > 0) {
|
|
28
|
+
const name = cookiePart.substring(0, equalsIndex);
|
|
29
|
+
const value = cookiePart.substring(equalsIndex + 1);
|
|
30
|
+
cookies[name] = value;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
return cookies;
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Gets a cookie value by name
|
|
39
|
+
* @param {string} name - Cookie name
|
|
40
|
+
* @returns {string|undefined} Cookie value or undefined if not found
|
|
41
|
+
*/
|
|
42
|
+
const getCookie = (name) => {
|
|
43
|
+
// Check for framework cookie handling
|
|
5
44
|
if (typeof FW !== "undefined") {
|
|
6
|
-
return FW.cookies[
|
|
45
|
+
return FW.cookies[name];
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
// Server-side rendering without framework
|
|
49
|
+
if (typeof document === "undefined") {
|
|
50
|
+
return undefined;
|
|
7
51
|
}
|
|
8
52
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
return c.substring(name.length, c.length);
|
|
53
|
+
// Browser environment without framework
|
|
54
|
+
const cookieName = name + "=";
|
|
55
|
+
const decodedCookie = decodeURIComponent(document.cookie);
|
|
56
|
+
const cookieParts = decodedCookie.split(';');
|
|
57
|
+
|
|
58
|
+
for (const part of cookieParts) {
|
|
59
|
+
let c = part.trim();
|
|
60
|
+
if (c.indexOf(cookieName) === 0) {
|
|
61
|
+
return c.substring(cookieName.length);
|
|
19
62
|
}
|
|
20
63
|
}
|
|
64
|
+
|
|
21
65
|
return undefined;
|
|
22
66
|
};
|
|
23
67
|
|
|
24
|
-
|
|
68
|
+
/**
|
|
69
|
+
* Checks if a cookie exists
|
|
70
|
+
* @param {string} name - Cookie name
|
|
71
|
+
* @returns {boolean} Whether the cookie exists
|
|
72
|
+
*/
|
|
73
|
+
const hasCookie = (name) => {
|
|
74
|
+
// Check for framework cookie handling
|
|
25
75
|
if (typeof FW !== "undefined") {
|
|
26
|
-
return (
|
|
76
|
+
return (FW.cookies.hasOwnProperty(name) && FW.cookies[name] !== undefined);
|
|
27
77
|
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
for(var i = 0; i <ca.length; i++) {
|
|
33
|
-
var c = ca[i];
|
|
34
|
-
while (c.charAt(0) == ' ') {
|
|
35
|
-
c = c.substring(1);
|
|
36
|
-
}
|
|
37
|
-
if (c.indexOf(name) == 0) {
|
|
38
|
-
return true;
|
|
39
|
-
}
|
|
78
|
+
|
|
79
|
+
// Server-side rendering without framework
|
|
80
|
+
if (typeof document === "undefined") {
|
|
81
|
+
return false;
|
|
40
82
|
}
|
|
41
|
-
|
|
83
|
+
|
|
84
|
+
// Browser environment without framework
|
|
85
|
+
return getCookie(name) !== undefined;
|
|
42
86
|
};
|
|
43
87
|
|
|
44
|
-
|
|
88
|
+
/**
|
|
89
|
+
* Sets a cookie
|
|
90
|
+
* @param {string} name - Cookie name
|
|
91
|
+
* @param {string} value - Cookie value
|
|
92
|
+
* @param {number} exdays - Expiration days (0 or negative for session cookie)
|
|
93
|
+
*/
|
|
94
|
+
const setCookie = (name, value, exdays) => {
|
|
95
|
+
// Check for framework cookie handling
|
|
45
96
|
if (typeof FW !== "undefined") {
|
|
46
|
-
//
|
|
47
|
-
FW.cookies[
|
|
97
|
+
// Always override value
|
|
98
|
+
FW.cookies[name] = value;
|
|
48
99
|
}
|
|
49
100
|
|
|
50
|
-
|
|
101
|
+
// Calculate expiration if needed
|
|
102
|
+
let d;
|
|
51
103
|
if (exdays > 0) {
|
|
52
104
|
d = new Date();
|
|
53
|
-
d.setTime(d.getTime() + (exdays*24*60*60*1000));
|
|
105
|
+
d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000));
|
|
54
106
|
}
|
|
107
|
+
|
|
108
|
+
// Server-side rendering
|
|
55
109
|
if (typeof __platformSetCookie !== "undefined") {
|
|
56
|
-
|
|
57
|
-
return __platformSetCookie(cname, value, d);
|
|
110
|
+
return __platformSetCookie(name, value, d);
|
|
58
111
|
}
|
|
112
|
+
|
|
113
|
+
// Server-side without cookie handling
|
|
114
|
+
if (typeof document === "undefined") {
|
|
115
|
+
return;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Handle cookie deletion
|
|
59
119
|
if (typeof value === "undefined") {
|
|
60
|
-
|
|
61
|
-
document.cookie = cname+"=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/";
|
|
120
|
+
document.cookie = name + "=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/";
|
|
62
121
|
return;
|
|
63
122
|
}
|
|
64
123
|
|
|
65
|
-
|
|
124
|
+
// Set cookie in browser
|
|
125
|
+
let expires = "";
|
|
66
126
|
if (d) {
|
|
67
|
-
expires = "expires="+ d.toUTCString();
|
|
127
|
+
expires = "expires=" + d.toUTCString();
|
|
68
128
|
}
|
|
69
|
-
|
|
129
|
+
|
|
130
|
+
document.cookie = name + "=" + value + ";" + expires + ";path=/;secure;samesite=none";
|
|
70
131
|
};
|
|
132
|
+
|
|
133
|
+
// Export functions
|
|
134
|
+
module.exports.getCookie = getCookie;
|
|
135
|
+
module.exports.hasCookie = hasCookie;
|
|
136
|
+
module.exports.setCookie = setCookie;
|