@smartsides/oracle-ebs-sdk 1.0.6 → 1.0.9
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 +280 -15
- package/dist/{OracleEBSClient-BE9XZUi1.d.mts → OracleEBSClient-BDnxW4cW.d.mts} +257 -16
- package/dist/{OracleEBSClient-BE9XZUi1.d.ts → OracleEBSClient-BDnxW4cW.d.ts} +257 -16
- package/dist/hooks/index.d.mts +1 -1
- package/dist/hooks/index.d.ts +1 -1
- package/dist/index.d.mts +3 -1
- package/dist/index.d.ts +3 -1
- package/dist/index.js +392 -31
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +370 -32
- package/dist/index.mjs.map +1 -1
- package/dist/server/index.d.mts +1 -1
- package/dist/server/index.d.ts +1 -1
- package/dist/server/index.js +171 -31
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +171 -31
- package/dist/server/index.mjs.map +1 -1
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -5,7 +5,10 @@ TypeScript SDK for Oracle EBS API - Optimized for Next.js 15+
|
|
|
5
5
|
## Features
|
|
6
6
|
|
|
7
7
|
- ✅ **Full TypeScript Support** - Complete type safety with autocomplete
|
|
8
|
-
- ✅ **All API Endpoints** -
|
|
8
|
+
- ✅ **All API Endpoints** - 10 modules covering all Oracle EBS functionality
|
|
9
|
+
- ✅ **AI Assistant** - ChatGPT-style chat with voice support ⭐ NEW
|
|
10
|
+
- ✅ **Auto User Context** - Stores full user object from login automatically
|
|
11
|
+
- ✅ **Smart Defaults** - Employee number auto-extracted for payslip/leave requests
|
|
9
12
|
- ✅ **Error Handling** - Typed errors with automatic retry logic
|
|
10
13
|
- ✅ **React Query Integration** - Built-in hooks for Next.js
|
|
11
14
|
- ✅ **Server Components** - Optimized for Next.js App Router
|
|
@@ -34,16 +37,17 @@ const client = new OracleEBSClient({
|
|
|
34
37
|
logging: { enabled: true },
|
|
35
38
|
});
|
|
36
39
|
|
|
37
|
-
// Login
|
|
38
|
-
const
|
|
40
|
+
// Login - automatically stores user object
|
|
41
|
+
const response = await client.auth.login({
|
|
39
42
|
username: 'your-username',
|
|
40
43
|
password: 'your-password',
|
|
41
44
|
});
|
|
45
|
+
// User info (EMPLOYEE_NUMBER, USER_ID, etc.) now available to all modules
|
|
42
46
|
|
|
43
47
|
// Get leave types
|
|
44
48
|
const types = await client.leaves.getRestrictedTypes();
|
|
45
49
|
|
|
46
|
-
// Create leave request
|
|
50
|
+
// Create leave request - employee number auto-extracted
|
|
47
51
|
const request = await client.leaves.createRequest({
|
|
48
52
|
absenceTypeId: '71',
|
|
49
53
|
startDate: '2026-01-20',
|
|
@@ -51,6 +55,11 @@ const request = await client.leaves.createRequest({
|
|
|
51
55
|
days: 3,
|
|
52
56
|
comments: 'Family vacation',
|
|
53
57
|
});
|
|
58
|
+
|
|
59
|
+
// Get payslip - employee number auto-extracted
|
|
60
|
+
const header = await client.payslip.getHeader({
|
|
61
|
+
periodName: '6 2025'
|
|
62
|
+
});
|
|
54
63
|
```
|
|
55
64
|
|
|
56
65
|
### Next.js App Router (Client Component)
|
|
@@ -123,8 +132,12 @@ export default async function Page() {
|
|
|
123
132
|
### Authentication
|
|
124
133
|
|
|
125
134
|
```typescript
|
|
126
|
-
// Login
|
|
127
|
-
await client.auth.login({ username, password });
|
|
135
|
+
// Login - automatically stores full user object
|
|
136
|
+
const response = await client.auth.login({ username, password });
|
|
137
|
+
// User object now available to all modules:
|
|
138
|
+
// - userName, ebsVersion
|
|
139
|
+
// - USER_ID, PERSON_ID, EMPLOYEE_NUMBER
|
|
140
|
+
// - responsibilities
|
|
128
141
|
|
|
129
142
|
// Get user context
|
|
130
143
|
const user = await client.auth.getUserContext();
|
|
@@ -133,6 +146,8 @@ const user = await client.auth.getUserContext();
|
|
|
133
146
|
await client.auth.logout();
|
|
134
147
|
```
|
|
135
148
|
|
|
149
|
+
**User Storage**: The SDK automatically stores the complete user object from the login response, making user information available to all modules without additional API calls.
|
|
150
|
+
|
|
136
151
|
### Leaves & Absences
|
|
137
152
|
|
|
138
153
|
```typescript
|
|
@@ -167,29 +182,85 @@ const result = await client.sitRequests.submit(data);
|
|
|
167
182
|
### Notifications
|
|
168
183
|
|
|
169
184
|
```typescript
|
|
170
|
-
// Get
|
|
185
|
+
// Get notification list (USER_ID auto-extracted from login)
|
|
171
186
|
const notifications = await client.notifications.getList();
|
|
172
187
|
|
|
173
|
-
// Get details
|
|
174
|
-
const details = await client.notifications.getDetails({
|
|
188
|
+
// Get notification details
|
|
189
|
+
const details = await client.notifications.getDetails({
|
|
190
|
+
notificationId: '9341634'
|
|
191
|
+
});
|
|
192
|
+
|
|
193
|
+
// Get all details (SSHR_SIT_REQDTLS)
|
|
194
|
+
const allDetails = await client.notifications.getAllDetails({
|
|
195
|
+
notificationId: '9288875',
|
|
196
|
+
itemKey: '756840',
|
|
197
|
+
analysisCriteriaId: '3643761',
|
|
198
|
+
idFlexNum: '50310'
|
|
199
|
+
});
|
|
200
|
+
|
|
201
|
+
// Get absence details (for FYI notifications)
|
|
202
|
+
const absenceDetails = await client.notifications.getAbsenceDetails({
|
|
203
|
+
itemKey: '760206'
|
|
204
|
+
});
|
|
205
|
+
|
|
206
|
+
// Get action history
|
|
207
|
+
const history = await client.notifications.getActionHistory({
|
|
208
|
+
notificationId: '9330566'
|
|
209
|
+
});
|
|
175
210
|
|
|
176
|
-
// Process approval
|
|
211
|
+
// Process approval (APPROVE or DECLINE)
|
|
177
212
|
await client.notifications.processApproval({
|
|
178
|
-
notificationId: '
|
|
213
|
+
notificationId: '9341634',
|
|
179
214
|
action: 'APPROVE',
|
|
215
|
+
comments: 'Approved for processing',
|
|
216
|
+
responderUserName: 'optional'
|
|
217
|
+
});
|
|
218
|
+
|
|
219
|
+
// Close FYI notification (USER_ID auto-extracted)
|
|
220
|
+
await client.notifications.closeFyi({
|
|
221
|
+
notificationId: '9336582'
|
|
180
222
|
});
|
|
181
223
|
```
|
|
182
224
|
|
|
225
|
+
**Auto User ID**: Notification methods automatically use USER_ID from the logged-in user where needed.
|
|
226
|
+
|
|
183
227
|
### Payslip
|
|
184
228
|
|
|
185
229
|
```typescript
|
|
186
|
-
// Get header
|
|
187
|
-
const header = await client.payslip.getHeader({
|
|
230
|
+
// Get header - employee number auto-extracted from login
|
|
231
|
+
const header = await client.payslip.getHeader({
|
|
232
|
+
periodName: '6 2025'
|
|
233
|
+
});
|
|
234
|
+
|
|
235
|
+
// Get details (earnings/deductions)
|
|
236
|
+
const details = await client.payslip.getDetails({
|
|
237
|
+
periodName: '6 2025'
|
|
238
|
+
});
|
|
239
|
+
|
|
240
|
+
// Get leave details
|
|
241
|
+
const leaveDetails = await client.payslip.getLeaveDetails({
|
|
242
|
+
periodName: '6 2025'
|
|
243
|
+
});
|
|
244
|
+
|
|
245
|
+
// Get run balances
|
|
246
|
+
const runBalances = await client.payslip.getRunBalances({
|
|
247
|
+
periodName: '6 2025'
|
|
248
|
+
});
|
|
188
249
|
|
|
189
|
-
// Get
|
|
190
|
-
const
|
|
250
|
+
// Get accrual balances
|
|
251
|
+
const accrualBalances = await client.accrualBalances.getBalances({
|
|
252
|
+
calculationDate: '2025-06-30'
|
|
253
|
+
});
|
|
254
|
+
|
|
255
|
+
// Optional: Override employee number (for admin/HR use)
|
|
256
|
+
const header = await client.payslip.getHeader({
|
|
257
|
+
employeeNumber: '12345',
|
|
258
|
+
periodName: '6 2025'
|
|
259
|
+
});
|
|
191
260
|
```
|
|
192
261
|
|
|
262
|
+
**Auto Employee Number**: All payslip methods automatically use the employee number from the logged-in user. No need to pass it explicitly unless you're querying for a different employee.
|
|
263
|
+
|
|
193
264
|
### Employee
|
|
194
265
|
|
|
195
266
|
```typescript
|
|
@@ -223,6 +294,101 @@ const health = await client.health.check();
|
|
|
223
294
|
const message = await client.health.ping();
|
|
224
295
|
```
|
|
225
296
|
|
|
297
|
+
### AI Assistant 🆕
|
|
298
|
+
|
|
299
|
+
The AI module provides ChatGPT-style conversational AI with persistent chat history.
|
|
300
|
+
|
|
301
|
+
```typescript
|
|
302
|
+
import { MessageRole } from '@smartsides/oracle-ebs-sdk';
|
|
303
|
+
|
|
304
|
+
// Send a chat message
|
|
305
|
+
const response = await client.ai.sendMessage({
|
|
306
|
+
message: 'Show my latest payslip',
|
|
307
|
+
language: 'en',
|
|
308
|
+
history: [
|
|
309
|
+
{ role: MessageRole.USER, content: 'Hello' },
|
|
310
|
+
{ role: MessageRole.ASSISTANT, content: 'Hi! How can I help?' }
|
|
311
|
+
],
|
|
312
|
+
threadId: 'optional-thread-id' // For continuing existing conversation
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
// Response includes:
|
|
316
|
+
// - message: AI response text
|
|
317
|
+
// - ctas: Call-to-action buttons (if any)
|
|
318
|
+
// - metadata: Intent, tokens used, etc.
|
|
319
|
+
// - threadId: Thread ID for conversation persistence
|
|
320
|
+
|
|
321
|
+
// Voice message with thread continuity ⭐ NEW
|
|
322
|
+
// First voice message - creates new thread
|
|
323
|
+
const voiceResponse1 = await client.ai.sendVoice(audioBlob, {
|
|
324
|
+
language: 'en'
|
|
325
|
+
});
|
|
326
|
+
const threadId = voiceResponse1.response.threadId;
|
|
327
|
+
|
|
328
|
+
// Second voice message - continues same thread
|
|
329
|
+
const voiceResponse2 = await client.ai.sendVoice(audioBlob, {
|
|
330
|
+
language: 'en',
|
|
331
|
+
threadId: threadId // Maintains conversation context!
|
|
332
|
+
});
|
|
333
|
+
|
|
334
|
+
// Arabic voice with thread continuity
|
|
335
|
+
const arabicResponse = await client.ai.sendVoice(audioBlob, {
|
|
336
|
+
language: 'ar',
|
|
337
|
+
threadId: threadId // Works with Arabic too!
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
// Thread management
|
|
341
|
+
const threads = await client.ai.getChatThreads();
|
|
342
|
+
const messages = await client.ai.getThreadMessages(threadId);
|
|
343
|
+
await client.ai.deleteThread(threadId);
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
**Voice Thread Continuity Benefits:**
|
|
347
|
+
- ✅ Multi-turn voice conversations (request → confirmation → submission)
|
|
348
|
+
- ✅ Maintains full conversation context across voice messages
|
|
349
|
+
- ✅ Works with both English and Arabic
|
|
350
|
+
- ✅ Automatic leave type mapping and date extraction
|
|
351
|
+
- ✅ Seamless voice-based leave request submission
|
|
352
|
+
|
|
353
|
+
// Transcribe voice to text
|
|
354
|
+
const transcription = await client.ai.transcribeVoice(audioBlob);
|
|
355
|
+
|
|
356
|
+
// Get all chat threads for current user
|
|
357
|
+
const threads = await client.ai.getChatThreads();
|
|
358
|
+
// Returns: Array of ChatThread objects with id, title, messageCount, etc.
|
|
359
|
+
|
|
360
|
+
// Get messages for a specific thread
|
|
361
|
+
const { thread, messages } = await client.ai.getThreadMessages(threadId);
|
|
362
|
+
// Returns: Thread metadata + array of ThreadMessage objects
|
|
363
|
+
|
|
364
|
+
// Create a new chat thread
|
|
365
|
+
const newThread = await client.ai.createThread();
|
|
366
|
+
// Returns: ChatThread object with new thread ID
|
|
367
|
+
|
|
368
|
+
// Delete a chat thread
|
|
369
|
+
await client.ai.deleteThread(threadId);
|
|
370
|
+
// Deletes thread and all associated messages
|
|
371
|
+
```
|
|
372
|
+
|
|
373
|
+
**Chat History Features:**
|
|
374
|
+
- ✅ **Persistent Threads**: All conversations saved to PostgreSQL
|
|
375
|
+
- ✅ **Auto-Title Generation**: Thread titles generated from first message
|
|
376
|
+
- ✅ **Message History**: Complete conversation history with timestamps
|
|
377
|
+
- ✅ **User-Scoped**: Each user only sees their own threads
|
|
378
|
+
- ✅ **Secure**: JWT authentication + ownership validation
|
|
379
|
+
|
|
380
|
+
**Available Types:**
|
|
381
|
+
```typescript
|
|
382
|
+
import {
|
|
383
|
+
MessageRole, // USER | ASSISTANT
|
|
384
|
+
ActionType, // Enum for action types
|
|
385
|
+
UserIntent, // Enum for user intents
|
|
386
|
+
ChatThread, // Thread metadata type
|
|
387
|
+
ThreadMessage, // Message type
|
|
388
|
+
CallToAction, // CTA button type
|
|
389
|
+
} from '@smartsides/oracle-ebs-sdk';
|
|
390
|
+
```
|
|
391
|
+
|
|
226
392
|
## Error Handling
|
|
227
393
|
|
|
228
394
|
```typescript
|
|
@@ -270,6 +436,69 @@ const client = new OracleEBSClient({
|
|
|
270
436
|
});
|
|
271
437
|
```
|
|
272
438
|
|
|
439
|
+
## 🔒 Security Best Practices
|
|
440
|
+
|
|
441
|
+
### CRITICAL: Never Decode JWT Tokens
|
|
442
|
+
|
|
443
|
+
**❌ NEVER do this in your application:**
|
|
444
|
+
|
|
445
|
+
```typescript
|
|
446
|
+
// DON'T decode JWT on the client side
|
|
447
|
+
const token = localStorage.getItem('token');
|
|
448
|
+
const payload = JSON.parse(atob(token.split('.')[1]));
|
|
449
|
+
const employeeNumber = payload.EMPLOYEE_NUMBER;
|
|
450
|
+
|
|
451
|
+
// DON'T pass user context to SDK methods
|
|
452
|
+
await client.payslip.getHeader({ periodName, employeeNumber });
|
|
453
|
+
```
|
|
454
|
+
|
|
455
|
+
**✅ ALWAYS do this instead:**
|
|
456
|
+
|
|
457
|
+
```typescript
|
|
458
|
+
// Just set the token and pass business parameters
|
|
459
|
+
client.setToken(token);
|
|
460
|
+
await client.payslip.getHeader({ periodName });
|
|
461
|
+
// Backend extracts employeeNumber from JWT automatically
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
### Why This Matters
|
|
465
|
+
|
|
466
|
+
1. **Security**: JWT payload is base64 encoded, NOT encrypted - anyone can read it
|
|
467
|
+
2. **Single Source of Truth**: Backend validates and extracts user context
|
|
468
|
+
3. **Prevents Tampering**: Users cannot access other users' data
|
|
469
|
+
4. **Maintainability**: JWT structure changes don't affect your code
|
|
470
|
+
5. **Consistency**: All endpoints follow the same pattern
|
|
471
|
+
|
|
472
|
+
### How It Works
|
|
473
|
+
|
|
474
|
+
The SDK sends the JWT token in the Authorization header. The backend:
|
|
475
|
+
1. Validates the token signature
|
|
476
|
+
2. Checks token expiration
|
|
477
|
+
3. Extracts user context (employeeNumber, userId, personId, etc.)
|
|
478
|
+
4. Uses this context to fetch user-specific data
|
|
479
|
+
|
|
480
|
+
### Affected Methods
|
|
481
|
+
|
|
482
|
+
All user-specific methods automatically use JWT context:
|
|
483
|
+
- ✅ `payslip.getHeader()` - Uses EMPLOYEE_NUMBER from JWT
|
|
484
|
+
- ✅ `payslip.getDetails()` - Uses EMPLOYEE_NUMBER from JWT
|
|
485
|
+
- ✅ `leaves.getRestrictedTypes()` - Uses USER_ID, PERSON_ID from JWT
|
|
486
|
+
- ✅ `leaves.createRequest()` - Uses PERSON_ID, USER_ID from JWT
|
|
487
|
+
- ✅ `notifications.getList()` - Uses USER_ID from JWT
|
|
488
|
+
- ✅ `notifications.closeFyi()` - Uses USER_ID from JWT
|
|
489
|
+
- ✅ `employee.getPersonalInfo()` - Uses context from JWT
|
|
490
|
+
- ✅ `accrualBalances.getBalances()` - Uses context from JWT
|
|
491
|
+
|
|
492
|
+
**You only pass business parameters** (periodName, dates, etc.) - never user context.
|
|
493
|
+
|
|
494
|
+
### Reference
|
|
495
|
+
|
|
496
|
+
For complete security documentation, see:
|
|
497
|
+
- [Backend JWT Security Pattern](../docs/JWT_SECURITY_PATTERN.md)
|
|
498
|
+
- [Backend Documentation](../docs/index.md#-core-security-principles)
|
|
499
|
+
|
|
500
|
+
---
|
|
501
|
+
|
|
273
502
|
## React Query Hooks
|
|
274
503
|
|
|
275
504
|
All hooks are available from `@smartsides/oracle-ebs-sdk/hooks`:
|
|
@@ -282,6 +511,10 @@ All hooks are available from `@smartsides/oracle-ebs-sdk/hooks`:
|
|
|
282
511
|
- `useSitSegments(client, params, options)`
|
|
283
512
|
- `useNotifications(client, options)`
|
|
284
513
|
- `usePayslipHeader(client, params, options)`
|
|
514
|
+
- `usePayslipDetails(client, params, options)`
|
|
515
|
+
- `usePayslipLeaveDetails(client, params, options)`
|
|
516
|
+
- `usePayslipRunBalances(client, params, options)`
|
|
517
|
+
- `useAccrualBalances(client, params, options)`
|
|
285
518
|
- `usePersonalInfo(client, options)`
|
|
286
519
|
- `useHealthCheck(client, options)`
|
|
287
520
|
- And more...
|
|
@@ -305,6 +538,38 @@ const client = createServerClientFromCookies(cookies());
|
|
|
305
538
|
const client = createServerClientFromHeaders(headers());
|
|
306
539
|
```
|
|
307
540
|
|
|
541
|
+
## Key Improvements (v1.0.6)
|
|
542
|
+
|
|
543
|
+
### Automatic User Context Storage
|
|
544
|
+
The SDK now automatically stores the complete user object from the login response, eliminating the need to:
|
|
545
|
+
- Make additional API calls for user information
|
|
546
|
+
- Pass employee number to every payslip/leave request
|
|
547
|
+
- Manually manage user context in your application
|
|
548
|
+
|
|
549
|
+
### Smart Employee Number Extraction
|
|
550
|
+
All payslip and leave methods automatically use the employee number from the logged-in user:
|
|
551
|
+
```typescript
|
|
552
|
+
// Before (v1.0.2)
|
|
553
|
+
await client.payslip.getHeader({
|
|
554
|
+
employeeNumber: '4446', // Had to pass manually
|
|
555
|
+
periodName: '6 2025'
|
|
556
|
+
});
|
|
557
|
+
|
|
558
|
+
// After (v1.0.6)
|
|
559
|
+
await client.payslip.getHeader({
|
|
560
|
+
periodName: '6 2025' // Employee number auto-extracted!
|
|
561
|
+
});
|
|
562
|
+
```
|
|
563
|
+
|
|
564
|
+
### Full User Object Access
|
|
565
|
+
All modules can now access the complete user object:
|
|
566
|
+
- `userName` - Username
|
|
567
|
+
- `ebsVersion` - Oracle EBS version
|
|
568
|
+
- `USER_ID` - User ID
|
|
569
|
+
- `PERSON_ID` - Person ID
|
|
570
|
+
- `EMPLOYEE_NUMBER` - Employee number
|
|
571
|
+
- `responsibilities` - User responsibilities
|
|
572
|
+
|
|
308
573
|
## License
|
|
309
574
|
|
|
310
575
|
PROPRIETARY - SmartSides Development Team
|