@olane/o-core 0.8.3 → 0.8.5
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 +101 -31
- package/dist/src/auth/file-token-store.d.ts +15 -0
- package/dist/src/auth/file-token-store.d.ts.map +1 -0
- package/dist/src/auth/file-token-store.js +55 -0
- package/dist/src/auth/index.d.ts +6 -0
- package/dist/src/auth/index.d.ts.map +1 -0
- package/dist/src/auth/index.js +5 -0
- package/dist/src/auth/o-refresh-token-provider.d.ts +31 -0
- package/dist/src/auth/o-refresh-token-provider.d.ts.map +1 -0
- package/dist/src/auth/o-refresh-token-provider.js +61 -0
- package/dist/src/auth/o-token-manager.d.ts +46 -0
- package/dist/src/auth/o-token-manager.d.ts.map +1 -0
- package/dist/src/auth/o-token-manager.js +211 -0
- package/dist/src/auth/o-token-provider.d.ts +16 -0
- package/dist/src/auth/o-token-provider.d.ts.map +1 -0
- package/dist/src/auth/o-token-provider.js +1 -0
- package/dist/src/auth/o-token-store.d.ts +17 -0
- package/dist/src/auth/o-token-store.d.ts.map +1 -0
- package/dist/src/auth/o-token-store.js +1 -0
- package/dist/src/context/index.d.ts +2 -0
- package/dist/src/context/index.d.ts.map +1 -0
- package/dist/src/context/index.js +1 -0
- package/dist/src/context/o-request-context.d.ts +22 -0
- package/dist/src/context/o-request-context.d.ts.map +1 -0
- package/dist/src/context/o-request-context.js +47 -0
- package/dist/src/core/interfaces/use-data.config.d.ts +7 -0
- package/dist/src/core/interfaces/use-data.config.d.ts.map +1 -1
- package/dist/src/core/o-core.d.ts +5 -0
- package/dist/src/core/o-core.d.ts.map +1 -1
- package/dist/src/core/o-core.js +28 -6
- package/dist/src/index.d.ts +2 -0
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +2 -0
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -35,22 +35,24 @@ This is **NOT** a network framework or API library - it's the abstract operating
|
|
|
35
35
|
## Installation
|
|
36
36
|
|
|
37
37
|
```bash
|
|
38
|
-
|
|
38
|
+
pnpm install @olane/o-core @olane/o-protocol
|
|
39
39
|
```
|
|
40
40
|
|
|
41
41
|
## Quick Start
|
|
42
42
|
|
|
43
43
|
### Creating Your First Tool Node
|
|
44
44
|
|
|
45
|
+
> **Note**: `oCore` is an abstract base class. For production use, extend higher-level packages like `oNodeTool` (from `@olane/o-node`), `oLaneTool` (from `@olane/o-lane`), or `McpTool` (from `@olane/o-mcp`). The example below demonstrates the core concepts.
|
|
46
|
+
|
|
45
47
|
```typescript
|
|
46
48
|
import { oCore, oAddress, NodeType, NodeState } from '@olane/o-core';
|
|
47
49
|
import { oRequest, oResponse } from '@olane/o-core';
|
|
48
50
|
|
|
49
51
|
// Extend oCore to create your tool node
|
|
50
52
|
class MyToolNode extends oCore {
|
|
51
|
-
constructor(address:
|
|
53
|
+
constructor(config: { address: oAddress }) {
|
|
52
54
|
super({
|
|
53
|
-
address:
|
|
55
|
+
address: config.address,
|
|
54
56
|
type: NodeType.AGENT, // Type remains AGENT for now (legacy naming)
|
|
55
57
|
description: 'My first tool node',
|
|
56
58
|
methods: {
|
|
@@ -68,11 +70,11 @@ class MyToolNode extends oCore {
|
|
|
68
70
|
// Implement required abstract methods
|
|
69
71
|
async execute(request: oRequest): Promise<any> {
|
|
70
72
|
const { method, params } = request;
|
|
71
|
-
|
|
73
|
+
|
|
72
74
|
if (method === 'greet') {
|
|
73
75
|
return { message: `Hello, ${params.name}!` };
|
|
74
76
|
}
|
|
75
|
-
|
|
77
|
+
|
|
76
78
|
throw new Error(`Unknown method: ${method}`);
|
|
77
79
|
}
|
|
78
80
|
|
|
@@ -103,19 +105,30 @@ class MyToolNode extends oCore {
|
|
|
103
105
|
}
|
|
104
106
|
|
|
105
107
|
// Create and start your tool node
|
|
106
|
-
|
|
108
|
+
// IMPORTANT: Use simple (non-nested) addresses in constructors.
|
|
109
|
+
// Nested addresses like 'o://company/customer-service' are created
|
|
110
|
+
// automatically at runtime during parent-child registration.
|
|
111
|
+
const toolNode = new MyToolNode({
|
|
112
|
+
address: new oAddress('o://customer-service')
|
|
113
|
+
});
|
|
107
114
|
await toolNode.start();
|
|
108
115
|
|
|
109
116
|
// AI agents can now use this tool node via its o:// address
|
|
110
117
|
const response = await toolNode.use(
|
|
111
|
-
new oAddress('o://
|
|
118
|
+
new oAddress('o://customer-service'),
|
|
112
119
|
{
|
|
113
120
|
method: 'greet',
|
|
114
121
|
params: { name: 'Alice' }
|
|
115
122
|
}
|
|
116
123
|
);
|
|
117
124
|
|
|
118
|
-
|
|
125
|
+
// Response follows the standard wrapping structure:
|
|
126
|
+
// response.result.success - boolean indicating success/failure
|
|
127
|
+
// response.result.data - the returned data on success
|
|
128
|
+
// response.result.error - error details on failure
|
|
129
|
+
if (response.result.success) {
|
|
130
|
+
console.log(response.result.data); // { message: "Hello, Alice!" }
|
|
131
|
+
}
|
|
119
132
|
|
|
120
133
|
// Stop the tool node gracefully
|
|
121
134
|
await toolNode.stop();
|
|
@@ -125,15 +138,16 @@ await toolNode.stop();
|
|
|
125
138
|
|
|
126
139
|
```typescript
|
|
127
140
|
// Tool Node A can communicate with Tool Node B using o:// addresses
|
|
128
|
-
|
|
129
|
-
const
|
|
141
|
+
// Use simple addresses in constructors; nested addresses are created at runtime
|
|
142
|
+
const salesTool = new MyToolNode({ address: new oAddress('o://sales') });
|
|
143
|
+
const analyticsTool = new MyToolNode({ address: new oAddress('o://analytics') });
|
|
130
144
|
|
|
131
145
|
await salesTool.start();
|
|
132
146
|
await analyticsTool.start();
|
|
133
147
|
|
|
134
148
|
// Sales tool calls analytics tool (inter-process communication)
|
|
135
149
|
const result = await salesTool.use(
|
|
136
|
-
new oAddress('o://
|
|
150
|
+
new oAddress('o://analytics'),
|
|
137
151
|
{
|
|
138
152
|
method: 'analyze',
|
|
139
153
|
params: { data: salesData }
|
|
@@ -145,19 +159,25 @@ const result = await salesTool.use(
|
|
|
145
159
|
|
|
146
160
|
```typescript
|
|
147
161
|
// Create a parent-child hierarchy of tool nodes
|
|
148
|
-
|
|
149
|
-
const
|
|
150
|
-
|
|
162
|
+
// Use simple addresses in constructors - nested addresses are created at runtime
|
|
163
|
+
const parent = new MyToolNode({ address: new oAddress('o://company') });
|
|
164
|
+
|
|
165
|
+
// Children use simple addresses with a parent reference
|
|
166
|
+
// During registration, child addresses become nested (e.g., 'o://company/sales')
|
|
167
|
+
const child1 = new MyToolNode({ address: new oAddress('o://sales') });
|
|
168
|
+
const child2 = new MyToolNode({ address: new oAddress('o://marketing') });
|
|
151
169
|
|
|
152
170
|
await parent.start();
|
|
153
171
|
await child1.start();
|
|
154
172
|
await child2.start();
|
|
155
173
|
|
|
156
|
-
// Register children with parent
|
|
174
|
+
// Register children with parent - this creates the nested addresses
|
|
157
175
|
parent.addChildNode(child1);
|
|
158
176
|
parent.addChildNode(child2);
|
|
159
177
|
|
|
160
|
-
//
|
|
178
|
+
// After registration:
|
|
179
|
+
// child1.address -> 'o://company/sales'
|
|
180
|
+
// child2.address -> 'o://company/marketing'
|
|
161
181
|
// Routing happens automatically through the hierarchy
|
|
162
182
|
```
|
|
163
183
|
|
|
@@ -185,7 +205,9 @@ console.log(toolNode.state); // NodeState.STOPPED
|
|
|
185
205
|
Addresses in Olane OS follow a hierarchical filesystem-like pattern:
|
|
186
206
|
|
|
187
207
|
```typescript
|
|
188
|
-
// Hierarchical addresses
|
|
208
|
+
// Hierarchical addresses exist at runtime after parent-child registration.
|
|
209
|
+
// They are created by the system, not by constructors directly.
|
|
210
|
+
// For example, after registration a child address may become:
|
|
189
211
|
const address1 = new oAddress('o://company/finance/accounting');
|
|
190
212
|
const address2 = new oAddress('o://users/alice/inbox');
|
|
191
213
|
|
|
@@ -197,6 +219,12 @@ console.log(address1.validate()); // true
|
|
|
197
219
|
// Static vs dynamic addresses
|
|
198
220
|
const staticAddr = address1.toStaticAddress();
|
|
199
221
|
console.log(staticAddr.toString()); // "o://accounting"
|
|
222
|
+
|
|
223
|
+
// IMPORTANT: When creating nodes in constructors, always use simple
|
|
224
|
+
// (non-nested) addresses. Nested addresses are created automatically
|
|
225
|
+
// during parent-child registration at runtime.
|
|
226
|
+
// ✅ new oAddress('o://my-tool')
|
|
227
|
+
// ❌ new oAddress('o://parent/my-tool') -- violates validateNotNested()
|
|
200
228
|
```
|
|
201
229
|
|
|
202
230
|
**📖 For complete details on address resolution, routing algorithms, and custom resolvers, see the [Router System documentation](./src/router/README.md).**
|
|
@@ -207,8 +235,9 @@ All inter-process communication (IPC) follows a request/response pattern using J
|
|
|
207
235
|
|
|
208
236
|
```typescript
|
|
209
237
|
// Making a request from one tool node to another
|
|
238
|
+
// Full signature: use(address: oAddress, data?: { method: string, params: any, id?: string }, options?: UseOptions)
|
|
210
239
|
const response: oResponse = await toolNode.use(
|
|
211
|
-
new oAddress('o://target
|
|
240
|
+
new oAddress('o://target-toolnode'),
|
|
212
241
|
{
|
|
213
242
|
method: 'processData',
|
|
214
243
|
params: { key: 'value' },
|
|
@@ -216,19 +245,58 @@ const response: oResponse = await toolNode.use(
|
|
|
216
245
|
}
|
|
217
246
|
);
|
|
218
247
|
|
|
219
|
-
//
|
|
248
|
+
// Always check the response structure
|
|
249
|
+
if (response.result.success) {
|
|
250
|
+
console.log('Data:', response.result.data);
|
|
251
|
+
} else {
|
|
252
|
+
console.error('Error:', response.result.error);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Transport-level errors throw exceptions
|
|
220
256
|
try {
|
|
221
257
|
const response = await toolNode.use(targetAddress, requestData);
|
|
222
|
-
|
|
258
|
+
// Check response.result.success for application-level errors
|
|
223
259
|
} catch (error) {
|
|
224
260
|
if (error instanceof oError) {
|
|
225
|
-
console.error(`
|
|
261
|
+
console.error(`Transport error ${error.code}: ${error.message}`);
|
|
226
262
|
}
|
|
227
263
|
}
|
|
228
264
|
```
|
|
229
265
|
|
|
230
266
|
**📖 Learn more about JSON-RPC messaging, request states, and connection lifecycle in the [Connection System documentation](./src/connection/README.md).**
|
|
231
267
|
|
|
268
|
+
### Response Structure
|
|
269
|
+
|
|
270
|
+
When you call `use()`, the response follows a standard wrapping structure created by the `ResponseBuilder`. In higher-level packages (`@olane/o-node`, `@olane/o-tool`, `@olane/o-lane`), responses are wrapped with `success`, `data`, and `error` fields:
|
|
271
|
+
|
|
272
|
+
```typescript
|
|
273
|
+
const response = await toolNode.use(targetAddress, {
|
|
274
|
+
method: 'processData',
|
|
275
|
+
params: { key: 'value' }
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
// Standard response structure:
|
|
279
|
+
// {
|
|
280
|
+
// jsonrpc: "2.0",
|
|
281
|
+
// id: "request-id",
|
|
282
|
+
// result: {
|
|
283
|
+
// success: boolean, // Whether the operation succeeded
|
|
284
|
+
// data: any, // The returned data (on success)
|
|
285
|
+
// error?: string // Error details (on failure)
|
|
286
|
+
// }
|
|
287
|
+
// }
|
|
288
|
+
|
|
289
|
+
// Always check success before accessing data
|
|
290
|
+
if (response.result.success) {
|
|
291
|
+
const data = response.result.data;
|
|
292
|
+
console.log('Result:', data);
|
|
293
|
+
} else {
|
|
294
|
+
console.error('Error:', response.result.error);
|
|
295
|
+
}
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
> **Important**: Access data via `response.result.data`, not `response.result` directly. The `result` object contains the wrapping fields (`success`, `data`, `error`), not the raw return value.
|
|
299
|
+
|
|
232
300
|
### Metrics and Observability
|
|
233
301
|
|
|
234
302
|
Every tool node tracks metrics automatically:
|
|
@@ -252,7 +320,7 @@ toolNode.logger.error('Error message');
|
|
|
252
320
|
`oCore` is an abstract base class that provides:
|
|
253
321
|
|
|
254
322
|
- **Lifecycle Management**: `start()`, `stop()`, `initialize()`, `teardown()`
|
|
255
|
-
- **Communication**: `use()`, `
|
|
323
|
+
- **Communication**: `use()`, `useDirect()`, `connect()`
|
|
256
324
|
- **Routing**: `router`, `initializeRouter()`
|
|
257
325
|
- **Hierarchy**: `addChildNode()`, `removeChildNode()`, `hierarchyManager`
|
|
258
326
|
- **State Management**: `state`, `NodeState` enum
|
|
@@ -401,7 +469,7 @@ async execute(request: oRequest): Promise<any> {
|
|
|
401
469
|
```typescript
|
|
402
470
|
import { setupGracefulShutdown } from '@olane/o-core';
|
|
403
471
|
|
|
404
|
-
const toolNode = new MyToolNode('o://my
|
|
472
|
+
const toolNode = new MyToolNode({ address: new oAddress('o://my-toolnode') });
|
|
405
473
|
await toolNode.start();
|
|
406
474
|
|
|
407
475
|
// Setup graceful shutdown handlers
|
|
@@ -430,7 +498,9 @@ Abstract base class for building tool nodes.
|
|
|
430
498
|
#### Methods
|
|
431
499
|
- `async start(): Promise<void>` - Start the tool node
|
|
432
500
|
- `async stop(): Promise<void>` - Stop the tool node gracefully
|
|
433
|
-
- `async use(address, data
|
|
501
|
+
- `async use(address: oAddress, data?: UseDataConfig, options?: UseOptions): Promise<oResponse>` - Communicate with another tool node (IPC). The `options` parameter supports `noRouting`, `isStream`, `onChunk`, `readTimeoutMs`, `drainTimeoutMs`, and `abortSignal`.
|
|
502
|
+
- `async useDirect(address: oAddress, data?: UseDataConfig): Promise<oResponse>` - Send a request without routing (equivalent to `use()` with `{ noRouting: true }`)
|
|
503
|
+
- `async useStream(address: oAddress, data: UseDataConfig, options: UseStreamOptions): Promise<oResponse>` - Send a streaming request to another tool node
|
|
434
504
|
- `async execute(request): Promise<any>` - Execute a request (abstract - you implement this)
|
|
435
505
|
- `addChildNode(node): void` - Add a child tool node
|
|
436
506
|
- `removeChildNode(node): void` - Remove a child tool node
|
|
@@ -460,29 +530,29 @@ new oError(code: oErrorCodes, message: string, data?: any)
|
|
|
460
530
|
|
|
461
531
|
```bash
|
|
462
532
|
# Run tests
|
|
463
|
-
|
|
533
|
+
pnpm test
|
|
464
534
|
|
|
465
535
|
# Run tests in Node.js
|
|
466
|
-
|
|
536
|
+
pnpm run test:node
|
|
467
537
|
|
|
468
538
|
# Run tests in browser
|
|
469
|
-
|
|
539
|
+
pnpm run test:browser
|
|
470
540
|
```
|
|
471
541
|
|
|
472
542
|
## Development
|
|
473
543
|
|
|
474
544
|
```bash
|
|
475
545
|
# Install dependencies
|
|
476
|
-
|
|
546
|
+
pnpm install
|
|
477
547
|
|
|
478
548
|
# Build the package
|
|
479
|
-
|
|
549
|
+
pnpm run build
|
|
480
550
|
|
|
481
551
|
# Run in development mode
|
|
482
|
-
|
|
552
|
+
pnpm run dev
|
|
483
553
|
|
|
484
554
|
# Lint the code
|
|
485
|
-
|
|
555
|
+
pnpm run lint
|
|
486
556
|
```
|
|
487
557
|
|
|
488
558
|
## Use Cases
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import type { oTokenStore, oTokenStoreEntry } from './o-token-store.js';
|
|
2
|
+
export interface FileTokenStoreConfig {
|
|
3
|
+
directory: string;
|
|
4
|
+
}
|
|
5
|
+
export declare class FileTokenStore implements oTokenStore {
|
|
6
|
+
private directory;
|
|
7
|
+
private initialized;
|
|
8
|
+
constructor(config: FileTokenStoreConfig);
|
|
9
|
+
get(key: string): Promise<oTokenStoreEntry | null>;
|
|
10
|
+
set(key: string, entry: oTokenStoreEntry): Promise<void>;
|
|
11
|
+
delete(key: string): Promise<void>;
|
|
12
|
+
private keyToPath;
|
|
13
|
+
private ensureDirectory;
|
|
14
|
+
}
|
|
15
|
+
//# sourceMappingURL=file-token-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"file-token-store.d.ts","sourceRoot":"","sources":["../../../src/auth/file-token-store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAExE,MAAM,WAAW,oBAAoB;IACnC,SAAS,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,cAAe,YAAW,WAAW;IAChD,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,WAAW,CAAS;gBAEhB,MAAM,EAAE,oBAAoB;IAIlC,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC;IAqBlD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC;IAWxD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAOxC,OAAO,CAAC,SAAS;YAKH,eAAe;CAK9B"}
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
import { readFile, writeFile, rename, unlink, mkdir } from 'node:fs/promises';
|
|
2
|
+
import { join } from 'node:path';
|
|
3
|
+
export class FileTokenStore {
|
|
4
|
+
constructor(config) {
|
|
5
|
+
this.initialized = false;
|
|
6
|
+
this.directory = config.directory;
|
|
7
|
+
}
|
|
8
|
+
async get(key) {
|
|
9
|
+
await this.ensureDirectory();
|
|
10
|
+
const filePath = this.keyToPath(key);
|
|
11
|
+
let raw;
|
|
12
|
+
try {
|
|
13
|
+
raw = await readFile(filePath, 'utf-8');
|
|
14
|
+
}
|
|
15
|
+
catch (err) {
|
|
16
|
+
if (err.code === 'ENOENT')
|
|
17
|
+
return null;
|
|
18
|
+
throw err;
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
return JSON.parse(raw);
|
|
22
|
+
}
|
|
23
|
+
catch {
|
|
24
|
+
// Corrupted file — remove it and return null
|
|
25
|
+
await unlink(filePath).catch(() => { });
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
async set(key, entry) {
|
|
30
|
+
await this.ensureDirectory();
|
|
31
|
+
const filePath = this.keyToPath(key);
|
|
32
|
+
const tmpPath = filePath + '.tmp';
|
|
33
|
+
const data = JSON.stringify(entry, null, 2);
|
|
34
|
+
// Atomic write: write to tmp, then rename
|
|
35
|
+
await writeFile(tmpPath, data, { encoding: 'utf-8', mode: 0o600 });
|
|
36
|
+
await rename(tmpPath, filePath);
|
|
37
|
+
}
|
|
38
|
+
async delete(key) {
|
|
39
|
+
const filePath = this.keyToPath(key);
|
|
40
|
+
await unlink(filePath).catch((err) => {
|
|
41
|
+
if (err.code !== 'ENOENT')
|
|
42
|
+
throw err;
|
|
43
|
+
});
|
|
44
|
+
}
|
|
45
|
+
keyToPath(key) {
|
|
46
|
+
const sanitized = key.replace(/[^a-zA-Z0-9_\-\.]/g, '_');
|
|
47
|
+
return join(this.directory, `${sanitized}.token.json`);
|
|
48
|
+
}
|
|
49
|
+
async ensureDirectory() {
|
|
50
|
+
if (this.initialized)
|
|
51
|
+
return;
|
|
52
|
+
await mkdir(this.directory, { recursive: true, mode: 0o700 });
|
|
53
|
+
this.initialized = true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/auth/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,sBAAsB,CAAC;AACrC,cAAc,oBAAoB,CAAC;AACnC,cAAc,+BAA+B,CAAC;AAC9C,cAAc,uBAAuB,CAAC"}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { oTokenProvider, oTokenResult } from './o-token-provider.js';
|
|
2
|
+
export interface OAuth2TokenResponse {
|
|
3
|
+
access_token: string;
|
|
4
|
+
expires_in?: number;
|
|
5
|
+
refresh_token?: string;
|
|
6
|
+
token_type?: string;
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
}
|
|
9
|
+
export interface RefreshTokenProviderConfig {
|
|
10
|
+
tokenEndpoint: string;
|
|
11
|
+
refreshToken: string;
|
|
12
|
+
clientId?: string;
|
|
13
|
+
clientSecret?: string;
|
|
14
|
+
headers?: Record<string, string>;
|
|
15
|
+
additionalParams?: Record<string, string>;
|
|
16
|
+
parseResponse?: (body: any) => oTokenResult;
|
|
17
|
+
}
|
|
18
|
+
export declare class RefreshTokenProvider implements oTokenProvider {
|
|
19
|
+
private tokenEndpoint;
|
|
20
|
+
private refreshToken;
|
|
21
|
+
private clientId?;
|
|
22
|
+
private clientSecret?;
|
|
23
|
+
private headers;
|
|
24
|
+
private additionalParams;
|
|
25
|
+
private parseResponse;
|
|
26
|
+
constructor(config: RefreshTokenProviderConfig);
|
|
27
|
+
acquireToken(): Promise<oTokenResult>;
|
|
28
|
+
updateRefreshToken(token: string): void;
|
|
29
|
+
static defaultParseResponse(body: OAuth2TokenResponse): oTokenResult;
|
|
30
|
+
}
|
|
31
|
+
//# sourceMappingURL=o-refresh-token-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"o-refresh-token-provider.d.ts","sourceRoot":"","sources":["../../../src/auth/o-refresh-token-provider.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAE1E,MAAM,WAAW,mBAAmB;IAClC,YAAY,EAAE,MAAM,CAAC;IACrB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,MAAM,WAAW,0BAA0B;IACzC,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACjC,gBAAgB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAC1C,aAAa,CAAC,EAAE,CAAC,IAAI,EAAE,GAAG,KAAK,YAAY,CAAC;CAC7C;AAED,qBAAa,oBAAqB,YAAW,cAAc;IACzD,OAAO,CAAC,aAAa,CAAS;IAC9B,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAC,CAAS;IAC1B,OAAO,CAAC,YAAY,CAAC,CAAS;IAC9B,OAAO,CAAC,OAAO,CAAyB;IACxC,OAAO,CAAC,gBAAgB,CAAyB;IACjD,OAAO,CAAC,aAAa,CAA8B;gBAEvC,MAAM,EAAE,0BAA0B;IAUxC,YAAY,IAAI,OAAO,CAAC,YAAY,CAAC;IAyC3C,kBAAkB,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI;IAIvC,MAAM,CAAC,oBAAoB,CAAC,IAAI,EAAE,mBAAmB,GAAG,YAAY;CAmBrE"}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
export class RefreshTokenProvider {
|
|
2
|
+
constructor(config) {
|
|
3
|
+
this.tokenEndpoint = config.tokenEndpoint;
|
|
4
|
+
this.refreshToken = config.refreshToken;
|
|
5
|
+
this.clientId = config.clientId;
|
|
6
|
+
this.clientSecret = config.clientSecret;
|
|
7
|
+
this.headers = config.headers ?? {};
|
|
8
|
+
this.additionalParams = config.additionalParams ?? {};
|
|
9
|
+
this.parseResponse = config.parseResponse ?? RefreshTokenProvider.defaultParseResponse;
|
|
10
|
+
}
|
|
11
|
+
async acquireToken() {
|
|
12
|
+
const body = new URLSearchParams({
|
|
13
|
+
grant_type: 'refresh_token',
|
|
14
|
+
refresh_token: this.refreshToken,
|
|
15
|
+
...this.additionalParams,
|
|
16
|
+
});
|
|
17
|
+
if (this.clientId) {
|
|
18
|
+
body.set('client_id', this.clientId);
|
|
19
|
+
}
|
|
20
|
+
if (this.clientSecret) {
|
|
21
|
+
body.set('client_secret', this.clientSecret);
|
|
22
|
+
}
|
|
23
|
+
const response = await fetch(this.tokenEndpoint, {
|
|
24
|
+
method: 'POST',
|
|
25
|
+
headers: {
|
|
26
|
+
'Content-Type': 'application/x-www-form-urlencoded',
|
|
27
|
+
...this.headers,
|
|
28
|
+
},
|
|
29
|
+
body: body.toString(),
|
|
30
|
+
});
|
|
31
|
+
if (!response.ok) {
|
|
32
|
+
const text = await response.text().catch(() => '');
|
|
33
|
+
throw new Error(`Token refresh failed: ${response.status} ${response.statusText}${text ? ` - ${text}` : ''}`);
|
|
34
|
+
}
|
|
35
|
+
const json = await response.json();
|
|
36
|
+
const result = this.parseResponse(json);
|
|
37
|
+
// Rotate stored refresh token if the provider returned a new one
|
|
38
|
+
if (result.refreshToken) {
|
|
39
|
+
this.refreshToken = result.refreshToken;
|
|
40
|
+
}
|
|
41
|
+
return result;
|
|
42
|
+
}
|
|
43
|
+
updateRefreshToken(token) {
|
|
44
|
+
this.refreshToken = token;
|
|
45
|
+
}
|
|
46
|
+
static defaultParseResponse(body) {
|
|
47
|
+
if (!body.access_token) {
|
|
48
|
+
throw new Error('Token response missing access_token');
|
|
49
|
+
}
|
|
50
|
+
const result = {
|
|
51
|
+
token: body.access_token,
|
|
52
|
+
};
|
|
53
|
+
if (body.expires_in != null) {
|
|
54
|
+
result.expiresAt = Math.floor(Date.now() / 1000) + body.expires_in;
|
|
55
|
+
}
|
|
56
|
+
if (body.refresh_token) {
|
|
57
|
+
result.refreshToken = body.refresh_token;
|
|
58
|
+
}
|
|
59
|
+
return result;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import type { oTokenProvider, oTokenResult } from './o-token-provider.js';
|
|
2
|
+
import type { oTokenStore } from './o-token-store.js';
|
|
3
|
+
import type { ORequestAuthContext } from '../context/o-request-context.js';
|
|
4
|
+
export interface oTokenManagerConfig {
|
|
5
|
+
provider: oTokenProvider;
|
|
6
|
+
autoRefresh?: boolean;
|
|
7
|
+
refreshBufferMs?: number;
|
|
8
|
+
defaultLifetimeMs?: number;
|
|
9
|
+
maxRefreshRetries?: number;
|
|
10
|
+
onRefreshFailure?: (error: Error) => void;
|
|
11
|
+
store?: oTokenStore;
|
|
12
|
+
storeKey?: string;
|
|
13
|
+
}
|
|
14
|
+
export declare class oTokenManager {
|
|
15
|
+
private provider;
|
|
16
|
+
private autoRefresh;
|
|
17
|
+
private refreshBufferMs;
|
|
18
|
+
private defaultLifetimeMs;
|
|
19
|
+
private maxRefreshRetries;
|
|
20
|
+
private onRefreshFailure?;
|
|
21
|
+
private store;
|
|
22
|
+
private storeKey;
|
|
23
|
+
private storeLoaded;
|
|
24
|
+
private currentResult;
|
|
25
|
+
private acquiredAt;
|
|
26
|
+
private refreshPromise;
|
|
27
|
+
private refreshTimer;
|
|
28
|
+
private destroyed;
|
|
29
|
+
constructor(config: oTokenManagerConfig);
|
|
30
|
+
getToken(forceRefresh?: boolean): Promise<string>;
|
|
31
|
+
getTokenResult(forceRefresh?: boolean): Promise<oTokenResult>;
|
|
32
|
+
refresh(): Promise<oTokenResult>;
|
|
33
|
+
isExpired(): boolean;
|
|
34
|
+
isCloseToExpiration(): boolean;
|
|
35
|
+
getTimeUntilExpiration(): number | null;
|
|
36
|
+
toAuthContext(): ORequestAuthContext | null;
|
|
37
|
+
destroy(): Promise<void>;
|
|
38
|
+
private loadFromStore;
|
|
39
|
+
private saveToStore;
|
|
40
|
+
private executeRefreshWithRetry;
|
|
41
|
+
private scheduleAutoRefresh;
|
|
42
|
+
private clearRefreshTimer;
|
|
43
|
+
private getExpiresAtMs;
|
|
44
|
+
private sleep;
|
|
45
|
+
}
|
|
46
|
+
//# sourceMappingURL=o-token-manager.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"o-token-manager.d.ts","sourceRoot":"","sources":["../../../src/auth/o-token-manager.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,cAAc,EAAE,YAAY,EAAE,MAAM,uBAAuB,CAAC;AAC1E,OAAO,KAAK,EAAE,WAAW,EAAoB,MAAM,oBAAoB,CAAC;AACxE,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAE3E,MAAM,WAAW,mBAAmB;IAClC,QAAQ,EAAE,cAAc,CAAC;IACzB,WAAW,CAAC,EAAE,OAAO,CAAC;IACtB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,iBAAiB,CAAC,EAAE,MAAM,CAAC;IAC3B,gBAAgB,CAAC,EAAE,CAAC,KAAK,EAAE,KAAK,KAAK,IAAI,CAAC;IAC1C,KAAK,CAAC,EAAE,WAAW,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,qBAAa,aAAa;IACxB,OAAO,CAAC,QAAQ,CAAiB;IACjC,OAAO,CAAC,WAAW,CAAU;IAC7B,OAAO,CAAC,eAAe,CAAS;IAChC,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,gBAAgB,CAAC,CAAyB;IAElD,OAAO,CAAC,KAAK,CAAqB;IAClC,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,WAAW,CAAS;IAE5B,OAAO,CAAC,aAAa,CAA6B;IAClD,OAAO,CAAC,UAAU,CAAuB;IACzC,OAAO,CAAC,cAAc,CAAsC;IAC5D,OAAO,CAAC,YAAY,CAA8C;IAClE,OAAO,CAAC,SAAS,CAAS;gBAEd,MAAM,EAAE,mBAAmB;IAWjC,QAAQ,CAAC,YAAY,UAAQ,GAAG,OAAO,CAAC,MAAM,CAAC;IAK/C,cAAc,CAAC,YAAY,UAAQ,GAAG,OAAO,CAAC,YAAY,CAAC;IAoB3D,OAAO,IAAI,OAAO,CAAC,YAAY,CAAC;IAoBtC,SAAS,IAAI,OAAO;IAOpB,mBAAmB,IAAI,OAAO;IAO9B,sBAAsB,IAAI,MAAM,GAAG,IAAI;IAOvC,aAAa,IAAI,mBAAmB,GAAG,IAAI;IAarC,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC;YAgBhB,aAAa;YA4Bb,WAAW;YAiBX,uBAAuB;IA2BrC,OAAO,CAAC,mBAAmB;IAwB3B,OAAO,CAAC,iBAAiB;IAOzB,OAAO,CAAC,cAAc;IAetB,OAAO,CAAC,KAAK;CAGd"}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
export class oTokenManager {
|
|
2
|
+
constructor(config) {
|
|
3
|
+
this.storeLoaded = false;
|
|
4
|
+
this.currentResult = null;
|
|
5
|
+
this.acquiredAt = null;
|
|
6
|
+
this.refreshPromise = null;
|
|
7
|
+
this.refreshTimer = null;
|
|
8
|
+
this.destroyed = false;
|
|
9
|
+
this.provider = config.provider;
|
|
10
|
+
this.autoRefresh = config.autoRefresh ?? true;
|
|
11
|
+
this.refreshBufferMs = config.refreshBufferMs ?? 60000;
|
|
12
|
+
this.defaultLifetimeMs = config.defaultLifetimeMs ?? 3600000;
|
|
13
|
+
this.maxRefreshRetries = config.maxRefreshRetries ?? 3;
|
|
14
|
+
this.onRefreshFailure = config.onRefreshFailure;
|
|
15
|
+
this.store = config.store ?? null;
|
|
16
|
+
this.storeKey = config.storeKey ?? 'default';
|
|
17
|
+
}
|
|
18
|
+
async getToken(forceRefresh = false) {
|
|
19
|
+
const result = await this.getTokenResult(forceRefresh);
|
|
20
|
+
return result.token;
|
|
21
|
+
}
|
|
22
|
+
async getTokenResult(forceRefresh = false) {
|
|
23
|
+
if (this.destroyed) {
|
|
24
|
+
throw new Error('oTokenManager has been destroyed');
|
|
25
|
+
}
|
|
26
|
+
if (!forceRefresh && this.currentResult && !this.isExpired()) {
|
|
27
|
+
return this.currentResult;
|
|
28
|
+
}
|
|
29
|
+
// On first call, try to restore from persistent store
|
|
30
|
+
if (!forceRefresh && !this.currentResult && this.store && !this.storeLoaded) {
|
|
31
|
+
const restored = await this.loadFromStore();
|
|
32
|
+
if (restored && !this.isExpired()) {
|
|
33
|
+
return this.currentResult;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return this.refresh();
|
|
37
|
+
}
|
|
38
|
+
async refresh() {
|
|
39
|
+
if (this.destroyed) {
|
|
40
|
+
throw new Error('oTokenManager has been destroyed');
|
|
41
|
+
}
|
|
42
|
+
// Concurrent deduplication: share a single in-flight refresh
|
|
43
|
+
if (this.refreshPromise) {
|
|
44
|
+
return this.refreshPromise;
|
|
45
|
+
}
|
|
46
|
+
this.refreshPromise = this.executeRefreshWithRetry();
|
|
47
|
+
try {
|
|
48
|
+
const result = await this.refreshPromise;
|
|
49
|
+
return result;
|
|
50
|
+
}
|
|
51
|
+
finally {
|
|
52
|
+
this.refreshPromise = null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
isExpired() {
|
|
56
|
+
if (!this.currentResult)
|
|
57
|
+
return true;
|
|
58
|
+
const expiresAt = this.getExpiresAtMs();
|
|
59
|
+
if (expiresAt === null)
|
|
60
|
+
return false;
|
|
61
|
+
return Date.now() >= expiresAt;
|
|
62
|
+
}
|
|
63
|
+
isCloseToExpiration() {
|
|
64
|
+
if (!this.currentResult)
|
|
65
|
+
return true;
|
|
66
|
+
const expiresAt = this.getExpiresAtMs();
|
|
67
|
+
if (expiresAt === null)
|
|
68
|
+
return false;
|
|
69
|
+
return Date.now() >= expiresAt - this.refreshBufferMs;
|
|
70
|
+
}
|
|
71
|
+
getTimeUntilExpiration() {
|
|
72
|
+
if (!this.currentResult)
|
|
73
|
+
return null;
|
|
74
|
+
const expiresAt = this.getExpiresAtMs();
|
|
75
|
+
if (expiresAt === null)
|
|
76
|
+
return null;
|
|
77
|
+
return Math.max(0, expiresAt - Date.now());
|
|
78
|
+
}
|
|
79
|
+
toAuthContext() {
|
|
80
|
+
if (!this.currentResult)
|
|
81
|
+
return null;
|
|
82
|
+
return {
|
|
83
|
+
token: this.currentResult.token,
|
|
84
|
+
claims: {
|
|
85
|
+
sub: this.currentResult.claims?.sub,
|
|
86
|
+
iss: this.currentResult.claims?.iss,
|
|
87
|
+
...this.currentResult.claims,
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
async destroy() {
|
|
92
|
+
this.destroyed = true;
|
|
93
|
+
this.clearRefreshTimer();
|
|
94
|
+
// Persist latest state before clearing memory
|
|
95
|
+
await this.saveToStore();
|
|
96
|
+
this.currentResult = null;
|
|
97
|
+
this.acquiredAt = null;
|
|
98
|
+
this.refreshPromise = null;
|
|
99
|
+
if (this.provider.destroy) {
|
|
100
|
+
await this.provider.destroy();
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
async loadFromStore() {
|
|
104
|
+
this.storeLoaded = true;
|
|
105
|
+
try {
|
|
106
|
+
const entry = await this.store.get(this.storeKey);
|
|
107
|
+
if (!entry)
|
|
108
|
+
return false;
|
|
109
|
+
this.currentResult = {
|
|
110
|
+
token: entry.token,
|
|
111
|
+
expiresAt: entry.expiresAt,
|
|
112
|
+
claims: entry.claims,
|
|
113
|
+
refreshToken: entry.refreshToken,
|
|
114
|
+
};
|
|
115
|
+
this.acquiredAt = entry.acquiredAt;
|
|
116
|
+
// Feed persisted refresh token back to provider
|
|
117
|
+
if (entry.refreshToken && this.provider.updateRefreshToken) {
|
|
118
|
+
this.provider.updateRefreshToken(entry.refreshToken);
|
|
119
|
+
}
|
|
120
|
+
this.scheduleAutoRefresh();
|
|
121
|
+
return true;
|
|
122
|
+
}
|
|
123
|
+
catch {
|
|
124
|
+
// Store failures are non-fatal — degrade to in-memory
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
async saveToStore() {
|
|
129
|
+
if (!this.store || !this.currentResult || this.acquiredAt === null)
|
|
130
|
+
return;
|
|
131
|
+
try {
|
|
132
|
+
const entry = {
|
|
133
|
+
token: this.currentResult.token,
|
|
134
|
+
expiresAt: this.currentResult.expiresAt,
|
|
135
|
+
claims: this.currentResult.claims,
|
|
136
|
+
refreshToken: this.currentResult.refreshToken,
|
|
137
|
+
acquiredAt: this.acquiredAt,
|
|
138
|
+
};
|
|
139
|
+
await this.store.set(this.storeKey, entry);
|
|
140
|
+
}
|
|
141
|
+
catch {
|
|
142
|
+
// Store failures are non-fatal
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
async executeRefreshWithRetry() {
|
|
146
|
+
let lastError = null;
|
|
147
|
+
for (let attempt = 0; attempt <= this.maxRefreshRetries; attempt++) {
|
|
148
|
+
try {
|
|
149
|
+
const result = await this.provider.acquireToken();
|
|
150
|
+
this.currentResult = result;
|
|
151
|
+
this.acquiredAt = Date.now();
|
|
152
|
+
this.scheduleAutoRefresh();
|
|
153
|
+
await this.saveToStore();
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
156
|
+
catch (err) {
|
|
157
|
+
lastError = err instanceof Error ? err : new Error(String(err));
|
|
158
|
+
if (attempt < this.maxRefreshRetries) {
|
|
159
|
+
// Exponential backoff: 1s, 2s, 4s, ...
|
|
160
|
+
const delayMs = Math.min(1000 * Math.pow(2, attempt), 30000);
|
|
161
|
+
await this.sleep(delayMs);
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
const error = lastError ?? new Error('Token refresh failed');
|
|
166
|
+
this.onRefreshFailure?.(error);
|
|
167
|
+
throw error;
|
|
168
|
+
}
|
|
169
|
+
scheduleAutoRefresh() {
|
|
170
|
+
this.clearRefreshTimer();
|
|
171
|
+
if (!this.autoRefresh || this.destroyed)
|
|
172
|
+
return;
|
|
173
|
+
const expiresAt = this.getExpiresAtMs();
|
|
174
|
+
if (expiresAt === null)
|
|
175
|
+
return;
|
|
176
|
+
const refreshAt = expiresAt - this.refreshBufferMs;
|
|
177
|
+
const delay = Math.max(0, refreshAt - Date.now());
|
|
178
|
+
this.refreshTimer = setTimeout(() => {
|
|
179
|
+
if (this.destroyed)
|
|
180
|
+
return;
|
|
181
|
+
this.refresh().catch((err) => {
|
|
182
|
+
// onRefreshFailure already called in executeRefreshWithRetry
|
|
183
|
+
});
|
|
184
|
+
}, delay);
|
|
185
|
+
// Don't block process exit
|
|
186
|
+
if (this.refreshTimer && typeof this.refreshTimer === 'object' && 'unref' in this.refreshTimer) {
|
|
187
|
+
this.refreshTimer.unref();
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
clearRefreshTimer() {
|
|
191
|
+
if (this.refreshTimer !== null) {
|
|
192
|
+
clearTimeout(this.refreshTimer);
|
|
193
|
+
this.refreshTimer = null;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
getExpiresAtMs() {
|
|
197
|
+
if (!this.currentResult)
|
|
198
|
+
return null;
|
|
199
|
+
if (this.currentResult.expiresAt != null) {
|
|
200
|
+
return this.currentResult.expiresAt * 1000; // convert unix seconds to ms
|
|
201
|
+
}
|
|
202
|
+
// No expiry info — fall back to defaultLifetimeMs from acquisition time
|
|
203
|
+
if (this.acquiredAt != null) {
|
|
204
|
+
return this.acquiredAt + this.defaultLifetimeMs;
|
|
205
|
+
}
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
sleep(ms) {
|
|
209
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
210
|
+
}
|
|
211
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
export interface oTokenResult {
|
|
2
|
+
token: string;
|
|
3
|
+
expiresAt?: number;
|
|
4
|
+
claims?: {
|
|
5
|
+
sub?: string;
|
|
6
|
+
iss?: string;
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
};
|
|
9
|
+
refreshToken?: string;
|
|
10
|
+
}
|
|
11
|
+
export interface oTokenProvider {
|
|
12
|
+
acquireToken(): Promise<oTokenResult>;
|
|
13
|
+
destroy?(): Promise<void>;
|
|
14
|
+
updateRefreshToken?(token: string): void;
|
|
15
|
+
}
|
|
16
|
+
//# sourceMappingURL=o-token-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"o-token-provider.d.ts","sourceRoot":"","sources":["../../../src/auth/o-token-provider.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB;AAED,MAAM,WAAW,cAAc;IAC7B,YAAY,IAAI,OAAO,CAAC,YAAY,CAAC,CAAC;IACtC,OAAO,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1B,kBAAkB,CAAC,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;CAC1C"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export interface oTokenStoreEntry {
|
|
2
|
+
token: string;
|
|
3
|
+
expiresAt?: number;
|
|
4
|
+
claims?: {
|
|
5
|
+
sub?: string;
|
|
6
|
+
iss?: string;
|
|
7
|
+
[key: string]: any;
|
|
8
|
+
};
|
|
9
|
+
refreshToken?: string;
|
|
10
|
+
acquiredAt: number;
|
|
11
|
+
}
|
|
12
|
+
export interface oTokenStore {
|
|
13
|
+
get(key: string): Promise<oTokenStoreEntry | null>;
|
|
14
|
+
set(key: string, entry: oTokenStoreEntry): Promise<void>;
|
|
15
|
+
delete(key: string): Promise<void>;
|
|
16
|
+
}
|
|
17
|
+
//# sourceMappingURL=o-token-store.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"o-token-store.d.ts","sourceRoot":"","sources":["../../../src/auth/o-token-store.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,MAAM,CAAC;IACd,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,MAAM,CAAC,EAAE;QAAE,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,CAAC;QAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;IAC5D,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,WAAW;IAC1B,GAAG,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,gBAAgB,GAAG,IAAI,CAAC,CAAC;IACnD,GAAG,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,gBAAgB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACzD,MAAM,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACpC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/context/index.ts"],"names":[],"mappings":"AAAA,cAAc,wBAAwB,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './o-request-context.js';
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { oTokenManager } from '../auth/o-token-manager.js';
|
|
2
|
+
export interface ORequestAuthContext {
|
|
3
|
+
token: string;
|
|
4
|
+
claims: {
|
|
5
|
+
sub?: string;
|
|
6
|
+
iss?: string;
|
|
7
|
+
aud?: string | string[];
|
|
8
|
+
exp?: number;
|
|
9
|
+
[key: string]: any;
|
|
10
|
+
};
|
|
11
|
+
}
|
|
12
|
+
export interface ORequestStore {
|
|
13
|
+
auth?: ORequestAuthContext;
|
|
14
|
+
tokenManager?: oTokenManager;
|
|
15
|
+
}
|
|
16
|
+
export declare const oRequestContext: {
|
|
17
|
+
run<T>(store: ORequestStore, fn: () => T): T;
|
|
18
|
+
getStore(): ORequestStore | undefined;
|
|
19
|
+
getAuth(): ORequestAuthContext | undefined;
|
|
20
|
+
getTokenManager(): oTokenManager | undefined;
|
|
21
|
+
};
|
|
22
|
+
//# sourceMappingURL=o-request-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"o-request-context.d.ts","sourceRoot":"","sources":["../../../src/context/o-request-context.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAEhE,MAAM,WAAW,mBAAmB;IAClC,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE;QACN,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC;QACxB,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;CACH;AAED,MAAM,WAAW,aAAa;IAC5B,IAAI,CAAC,EAAE,mBAAmB,CAAC;IAC3B,YAAY,CAAC,EAAE,aAAa,CAAC;CAC9B;AAgBD,eAAO,MAAM,eAAe;QACtB,CAAC,SAAS,aAAa,MAAM,MAAM,CAAC,GAAG,CAAC;gBAoBhC,aAAa,GAAG,SAAS;eAO1B,mBAAmB,GAAG,SAAS;uBAIvB,aAAa,GAAG,SAAS;CAG7C,CAAC"}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
// Runtime detection: use native AsyncLocalStorage if available (Node, Deno, Bun, CF Workers).
|
|
2
|
+
// Falls back to a simple variable for browsers/React Native where concurrent
|
|
3
|
+
// multi-user requests don't happen.
|
|
4
|
+
let nativeALS = null;
|
|
5
|
+
try {
|
|
6
|
+
const mod = await import('node:async_hooks');
|
|
7
|
+
nativeALS = new mod.AsyncLocalStorage();
|
|
8
|
+
}
|
|
9
|
+
catch {
|
|
10
|
+
// Not available — browser or React Native runtime
|
|
11
|
+
}
|
|
12
|
+
// Browser fallback state
|
|
13
|
+
let currentStore;
|
|
14
|
+
export const oRequestContext = {
|
|
15
|
+
run(store, fn) {
|
|
16
|
+
if (nativeALS) {
|
|
17
|
+
return nativeALS.run(store, fn);
|
|
18
|
+
}
|
|
19
|
+
// Browser fallback: simple variable swap (safe for single-user environments)
|
|
20
|
+
const prev = currentStore;
|
|
21
|
+
currentStore = store;
|
|
22
|
+
try {
|
|
23
|
+
const result = fn();
|
|
24
|
+
if (result instanceof Promise) {
|
|
25
|
+
return result.finally(() => { currentStore = prev; });
|
|
26
|
+
}
|
|
27
|
+
currentStore = prev;
|
|
28
|
+
return result;
|
|
29
|
+
}
|
|
30
|
+
catch (e) {
|
|
31
|
+
currentStore = prev;
|
|
32
|
+
throw e;
|
|
33
|
+
}
|
|
34
|
+
},
|
|
35
|
+
getStore() {
|
|
36
|
+
if (nativeALS) {
|
|
37
|
+
return nativeALS.getStore();
|
|
38
|
+
}
|
|
39
|
+
return currentStore;
|
|
40
|
+
},
|
|
41
|
+
getAuth() {
|
|
42
|
+
return oRequestContext.getStore()?.auth;
|
|
43
|
+
},
|
|
44
|
+
getTokenManager() {
|
|
45
|
+
return oRequestContext.getStore()?.tokenManager;
|
|
46
|
+
},
|
|
47
|
+
};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"use-data.config.d.ts","sourceRoot":"","sources":["../../../../src/core/interfaces/use-data.config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE;
|
|
1
|
+
{"version":3,"file":"use-data.config.d.ts","sourceRoot":"","sources":["../../../../src/core/interfaces/use-data.config.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,aAAa;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE;QACP,KAAK,CAAC,EAAE;YAAE,KAAK,EAAE,MAAM,CAAC;YAAC,MAAM,EAAE;gBAAE,GAAG,CAAC,EAAE,MAAM,CAAC;gBAAC,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;aAAE,CAAA;SAAE,CAAC;QACxE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;KACpB,CAAC;IACF,EAAE,CAAC,EAAE,MAAM,CAAC;CACb"}
|
|
@@ -96,6 +96,11 @@ export declare abstract class oCore extends oObject {
|
|
|
96
96
|
* @throws Error if node is not running
|
|
97
97
|
*/
|
|
98
98
|
private validateRunning;
|
|
99
|
+
/**
|
|
100
|
+
* Injects _auth from AsyncLocalStorage into request params if not already present.
|
|
101
|
+
* This enables automatic auth propagation across node.use() calls.
|
|
102
|
+
*/
|
|
103
|
+
private injectAuthContext;
|
|
99
104
|
useSelf(data?: {
|
|
100
105
|
method?: string;
|
|
101
106
|
params?: {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"o-core.d.ts","sourceRoot":"","sources":["../../../src/core/o-core.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,MAAM,+BAA+B,CAAC;AAC5D,OAAO,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAC;AACvD,OAAO,EAAE,QAAQ,EAAE,MAAM,wBAAwB,CAAC;AAClD,OAAO,EAAE,QAAQ,EAAE,MAAM,gCAAgC,CAAC;AAC1D,OAAO,EAAE,kBAAkB,EAAE,MAAM,uCAAuC,CAAC;AAC3E,OAAO,EAAE,SAAS,EAAE,MAAM,6BAA6B,CAAC;AACxD,OAAO,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AACxC,OAAO,EAAE,QAAQ,EAAE,MAAM,oBAAoB,CAAC;AAC9C,OAAO,EAAE,iBAAiB,EAAE,MAAM,8BAA8B,CAAC;AACjE,OAAO,EAAE,eAAe,EAAE,MAAM,4BAA4B,CAAC;AAC7D,OAAO,EAAE,UAAU,EAAE,MAAM,8BAA8B,CAAC;AAC1D,OAAO,EAAE,OAAO,EAAE,MAAM,uBAAuB,CAAC;AAChD,OAAO,EAAE,QAAQ,EAAE,MAAM,4BAA4B,CAAC;AAEtD,OAAO,EAAE,oBAAoB,EAAE,MAAM,iCAAiC,CAAC;AACvE,OAAO,EACL,kBAAkB,EAClB,WAAW,EACX,mBAAmB,EACnB,YAAY,EACb,MAAM,uBAAuB,CAAC;AAC/B,OAAO,EAAE,UAAU,EAAE,MAAM,uCAAuC,CAAC;AACnE,OAAO,EAAE,gBAAgB,EAAE,MAAM,8CAA8C,CAAC;AAChF,OAAO,EAAE,aAAa,EAAE,MAAM,iCAAiC,CAAC;
|
|
1
|
+
{"version":3,"file":"o-core.d.ts","sourceRoot":"","sources":["../../../src/core/o-core.ts"],"names":[],"mappings":"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"}
|
package/dist/src/core/o-core.js
CHANGED
|
@@ -6,6 +6,7 @@ import { oObject } from './o-object.js';
|
|
|
6
6
|
import { oMetrics } from './lib/o-metrics.js';
|
|
7
7
|
import { oRequest } from '../connection/o-request.js';
|
|
8
8
|
import { ResponseBuilder } from '../response/response-builder.js';
|
|
9
|
+
import { oRequestContext } from '../context/o-request-context.js';
|
|
9
10
|
export class oCore extends oObject {
|
|
10
11
|
constructor(config) {
|
|
11
12
|
super((config.name ? `:${config.name}` : '') + ':' + config.address.toString());
|
|
@@ -99,10 +100,11 @@ export class oCore extends oObject {
|
|
|
99
100
|
if (!this.requestManager) {
|
|
100
101
|
throw new Error('Request manager is not initialized');
|
|
101
102
|
}
|
|
103
|
+
const enriched = this.injectAuthContext(data);
|
|
102
104
|
if (address?.toStaticAddress().equals(this.address.toStaticAddress())) {
|
|
103
|
-
return this.useSelf(
|
|
105
|
+
return this.useSelf(enriched);
|
|
104
106
|
}
|
|
105
|
-
return this.requestManager.send(address,
|
|
107
|
+
return this.requestManager.send(address, enriched, options, this);
|
|
106
108
|
}
|
|
107
109
|
/**
|
|
108
110
|
* Helper method to validate node is running
|
|
@@ -114,14 +116,33 @@ export class oCore extends oObject {
|
|
|
114
116
|
throw new Error('Node is not running');
|
|
115
117
|
}
|
|
116
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* Injects _auth from AsyncLocalStorage into request params if not already present.
|
|
121
|
+
* This enables automatic auth propagation across node.use() calls.
|
|
122
|
+
*/
|
|
123
|
+
injectAuthContext(data) {
|
|
124
|
+
if (!data)
|
|
125
|
+
return data;
|
|
126
|
+
const auth = oRequestContext.getAuth();
|
|
127
|
+
if (!auth || data.params?._auth)
|
|
128
|
+
return data;
|
|
129
|
+
return {
|
|
130
|
+
...data,
|
|
131
|
+
params: {
|
|
132
|
+
...data.params,
|
|
133
|
+
_auth: auth,
|
|
134
|
+
},
|
|
135
|
+
};
|
|
136
|
+
}
|
|
117
137
|
async useSelf(data) {
|
|
118
138
|
this.validateRunning();
|
|
139
|
+
const enriched = this.injectAuthContext(data);
|
|
119
140
|
const request = new oRequest({
|
|
120
|
-
method:
|
|
141
|
+
method: enriched?.method,
|
|
121
142
|
params: {
|
|
122
143
|
_connectionId: 0,
|
|
123
|
-
_requestMethod:
|
|
124
|
-
...
|
|
144
|
+
_requestMethod: enriched?.method,
|
|
145
|
+
...enriched?.params,
|
|
125
146
|
},
|
|
126
147
|
id: 0,
|
|
127
148
|
});
|
|
@@ -150,6 +171,7 @@ export class oCore extends oObject {
|
|
|
150
171
|
if (!this.requestManager) {
|
|
151
172
|
throw new Error('Request manager is not initialized');
|
|
152
173
|
}
|
|
174
|
+
const enriched = this.injectAuthContext(data);
|
|
153
175
|
// extract child address with transports
|
|
154
176
|
if (!childAddress.transports) {
|
|
155
177
|
const child = this.hierarchyManager.getChild(childAddress);
|
|
@@ -161,7 +183,7 @@ export class oCore extends oObject {
|
|
|
161
183
|
childAddress.setTransports(child?.transports || []);
|
|
162
184
|
}
|
|
163
185
|
}
|
|
164
|
-
return this.requestManager.send(childAddress,
|
|
186
|
+
return this.requestManager.send(childAddress, enriched, options, this);
|
|
165
187
|
}
|
|
166
188
|
// hierarchy
|
|
167
189
|
addChildNode(node) {
|
package/dist/src/index.d.ts
CHANGED
package/dist/src/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,uBAAuB,CAAC;AACtC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AAAA,cAAc,iBAAiB,CAAC;AAChC,cAAc,uBAAuB,CAAC;AACtC,cAAc,oBAAoB,CAAC;AACnC,cAAc,iBAAiB,CAAC;AAChC,cAAc,kBAAkB,CAAC;AACjC,cAAc,qBAAqB,CAAC;AACpC,cAAc,mBAAmB,CAAC;AAClC,cAAc,uBAAuB,CAAC;AACtC,cAAc,kBAAkB,CAAC"}
|
package/dist/src/index.js
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@olane/o-core",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"main": "dist/src/index.js",
|
|
6
6
|
"types": "dist/src/index.d.ts",
|
|
@@ -63,12 +63,12 @@
|
|
|
63
63
|
"typescript": "^5.8.3"
|
|
64
64
|
},
|
|
65
65
|
"dependencies": {
|
|
66
|
-
"@olane/o-protocol": "0.8.
|
|
66
|
+
"@olane/o-protocol": "0.8.5",
|
|
67
67
|
"chalk": "^5.4.1",
|
|
68
68
|
"debug": "^4.4.1",
|
|
69
69
|
"dotenv": "^16.5.0",
|
|
70
70
|
"multiformats": "^13.3.7",
|
|
71
71
|
"stream-json": "^1.9.1"
|
|
72
72
|
},
|
|
73
|
-
"gitHead": "
|
|
73
|
+
"gitHead": "e88f1e55dcc92d9a410d28200e4220697116f82f"
|
|
74
74
|
}
|