@hamak/ui-remote-resource 0.5.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/dist/api/actions/entity-action-factory.d.ts +28 -0
- package/dist/api/actions/entity-action-factory.d.ts.map +1 -0
- package/dist/api/actions/entity-action-factory.js +62 -0
- package/dist/api/actions/entity-action-types.d.ts +104 -0
- package/dist/api/actions/entity-action-types.d.ts.map +1 -0
- package/dist/api/actions/entity-action-types.js +16 -0
- package/dist/api/actions/resource-action-factory.d.ts +40 -0
- package/dist/api/actions/resource-action-factory.d.ts.map +1 -0
- package/dist/api/actions/resource-action-factory.js +93 -0
- package/dist/api/actions/resource-action-types.d.ts +105 -0
- package/dist/api/actions/resource-action-types.d.ts.map +1 -0
- package/dist/api/actions/resource-action-types.js +13 -0
- package/dist/api/constants.d.ts +6 -0
- package/dist/api/constants.d.ts.map +1 -0
- package/dist/api/constants.js +5 -0
- package/dist/api/contracts/i-entity-registry.d.ts +19 -0
- package/dist/api/contracts/i-entity-registry.d.ts.map +1 -0
- package/dist/api/contracts/i-entity-registry.js +1 -0
- package/dist/api/contracts/i-resource-registry.d.ts +19 -0
- package/dist/api/contracts/i-resource-registry.d.ts.map +1 -0
- package/dist/api/contracts/i-resource-registry.js +1 -0
- package/dist/api/index.d.ts +12 -0
- package/dist/api/index.d.ts.map +1 -0
- package/dist/api/index.js +15 -0
- package/dist/api/types/action-types.d.ts +34 -0
- package/dist/api/types/action-types.d.ts.map +1 -0
- package/dist/api/types/action-types.js +1 -0
- package/dist/api/types/resource-attributes.d.ts +43 -0
- package/dist/api/types/resource-attributes.d.ts.map +1 -0
- package/dist/api/types/resource-attributes.js +1 -0
- package/dist/api/types/resource-types.d.ts +20 -0
- package/dist/api/types/resource-types.d.ts.map +1 -0
- package/dist/api/types/resource-types.js +1 -0
- package/dist/api/utils/resource-attributes-util.d.ts +183 -0
- package/dist/api/utils/resource-attributes-util.d.ts.map +1 -0
- package/dist/api/utils/resource-attributes-util.js +280 -0
- package/dist/impl/autosave/index.d.ts +5 -0
- package/dist/impl/autosave/index.d.ts.map +1 -0
- package/dist/impl/autosave/index.js +4 -0
- package/dist/impl/autosave/resource-autosave-provider.d.ts +49 -0
- package/dist/impl/autosave/resource-autosave-provider.d.ts.map +1 -0
- package/dist/impl/autosave/resource-autosave-provider.js +112 -0
- package/dist/impl/index.d.ts +20 -0
- package/dist/impl/index.d.ts.map +1 -0
- package/dist/impl/index.js +20 -0
- package/dist/impl/middleware/entity-middleware.d.ts +13 -0
- package/dist/impl/middleware/entity-middleware.d.ts.map +1 -0
- package/dist/impl/middleware/entity-middleware.js +221 -0
- package/dist/impl/middleware/entity-sync-middleware.d.ts +7 -0
- package/dist/impl/middleware/entity-sync-middleware.d.ts.map +1 -0
- package/dist/impl/middleware/entity-sync-middleware.js +32 -0
- package/dist/impl/middleware/resource-middleware.d.ts +13 -0
- package/dist/impl/middleware/resource-middleware.d.ts.map +1 -0
- package/dist/impl/middleware/resource-middleware.js +97 -0
- package/dist/impl/middleware/sync-middleware.d.ts +12 -0
- package/dist/impl/middleware/sync-middleware.d.ts.map +1 -0
- package/dist/impl/middleware/sync-middleware.js +80 -0
- package/dist/impl/plugin/resource-plugin-factory.d.ts +31 -0
- package/dist/impl/plugin/resource-plugin-factory.d.ts.map +1 -0
- package/dist/impl/plugin/resource-plugin-factory.js +131 -0
- package/dist/impl/providers/mock-resource-provider.d.ts +147 -0
- package/dist/impl/providers/mock-resource-provider.d.ts.map +1 -0
- package/dist/impl/providers/mock-resource-provider.js +242 -0
- package/dist/impl/providers/rest-resource-provider.d.ts +51 -0
- package/dist/impl/providers/rest-resource-provider.d.ts.map +1 -0
- package/dist/impl/providers/rest-resource-provider.js +128 -0
- package/dist/impl/registry/entity-registry.d.ts +54 -0
- package/dist/impl/registry/entity-registry.d.ts.map +1 -0
- package/dist/impl/registry/entity-registry.js +51 -0
- package/dist/impl/registry/resource-registry.d.ts +80 -0
- package/dist/impl/registry/resource-registry.d.ts.map +1 -0
- package/dist/impl/registry/resource-registry.js +74 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +5 -0
- package/dist/spi/config/endpoint-definition.d.ts +46 -0
- package/dist/spi/config/endpoint-definition.d.ts.map +1 -0
- package/dist/spi/config/endpoint-definition.js +1 -0
- package/dist/spi/config/entity-definition.d.ts +50 -0
- package/dist/spi/config/entity-definition.d.ts.map +1 -0
- package/dist/spi/config/entity-definition.js +1 -0
- package/dist/spi/config/plugin-config.d.ts +21 -0
- package/dist/spi/config/plugin-config.d.ts.map +1 -0
- package/dist/spi/config/plugin-config.js +1 -0
- package/dist/spi/index.d.ts +6 -0
- package/dist/spi/index.d.ts.map +1 -0
- package/dist/spi/index.js +7 -0
- package/dist/spi/providers/i-resource-provider.d.ts +42 -0
- package/dist/spi/providers/i-resource-provider.d.ts.map +1 -0
- package/dist/spi/providers/i-resource-provider.js +1 -0
- package/package.json +71 -0
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import type { ResourcePluginConfig } from '../../spi';
|
|
2
|
+
/**
|
|
3
|
+
* Microkernel plugin module interface
|
|
4
|
+
*/
|
|
5
|
+
export interface PluginModule {
|
|
6
|
+
initialize(ctx: InitializationContext): Promise<void>;
|
|
7
|
+
activate(ctx: ActivateContext): Promise<void>;
|
|
8
|
+
deactivate?(): Promise<void>;
|
|
9
|
+
}
|
|
10
|
+
interface InitializationContext {
|
|
11
|
+
provide(provider: any): void;
|
|
12
|
+
[key: string]: any;
|
|
13
|
+
}
|
|
14
|
+
interface ActivateContext {
|
|
15
|
+
resolve(token: any): any;
|
|
16
|
+
hooks: {
|
|
17
|
+
emit(event: string, data?: any): void;
|
|
18
|
+
};
|
|
19
|
+
[key: string]: any;
|
|
20
|
+
}
|
|
21
|
+
export declare const RESOURCE_REGISTRY_TOKEN = "RESOURCE_REGISTRY";
|
|
22
|
+
export declare const ENTITY_REGISTRY_TOKEN = "ENTITY_REGISTRY";
|
|
23
|
+
/**
|
|
24
|
+
* Create remote resource plugin
|
|
25
|
+
*
|
|
26
|
+
* @param config - Plugin configuration
|
|
27
|
+
* @returns Plugin module for microkernel registration
|
|
28
|
+
*/
|
|
29
|
+
export declare function createResourcePlugin(config?: ResourcePluginConfig): PluginModule;
|
|
30
|
+
export {};
|
|
31
|
+
//# sourceMappingURL=resource-plugin-factory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"resource-plugin-factory.d.ts","sourceRoot":"","sources":["../../../src/impl/plugin/resource-plugin-factory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AActD;;GAEG;AACH,MAAM,WAAW,YAAY;IAC3B,UAAU,CAAC,GAAG,EAAE,qBAAqB,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACtD,QAAQ,CAAC,GAAG,EAAE,eAAe,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9C,UAAU,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC9B;AAED,UAAU,qBAAqB;IAC7B,OAAO,CAAC,QAAQ,EAAE,GAAG,GAAG,IAAI,CAAC;IAC7B,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAED,UAAU,eAAe;IACvB,OAAO,CAAC,KAAK,EAAE,GAAG,GAAG,GAAG,CAAC;IACzB,KAAK,EAAE;QACL,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,EAAE,GAAG,GAAG,IAAI,CAAC;KACvC,CAAC;IACF,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAC;CACpB;AAGD,eAAO,MAAM,uBAAuB,sBAAsB,CAAC;AAC3D,eAAO,MAAM,qBAAqB,oBAAoB,CAAC;AAEvD;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,GAAE,oBAAyB,GAChC,YAAY,CAgId"}
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
import { MIDDLEWARE_REGISTRY_TOKEN } from '@hamak/ui-store-api';
|
|
2
|
+
import { FILESYSTEM_ADAPTER_TOKEN } from '@hamak/ui-store-impl';
|
|
3
|
+
import { ResourceRegistry } from '../registry/resource-registry';
|
|
4
|
+
import { EntityRegistry } from '../registry/entity-registry';
|
|
5
|
+
import { RestResourceProvider } from '../providers/rest-resource-provider';
|
|
6
|
+
import { MockResourceProvider } from '../providers/mock-resource-provider';
|
|
7
|
+
import { createResourceMiddleware } from '../middleware/resource-middleware';
|
|
8
|
+
import { createSyncMiddleware } from '../middleware/sync-middleware';
|
|
9
|
+
import { createEntityMiddleware } from '../middleware/entity-middleware';
|
|
10
|
+
import { createEntitySyncMiddleware } from '../middleware/entity-sync-middleware';
|
|
11
|
+
// Dependency injection tokens (for local use)
|
|
12
|
+
export const RESOURCE_REGISTRY_TOKEN = 'RESOURCE_REGISTRY';
|
|
13
|
+
export const ENTITY_REGISTRY_TOKEN = 'ENTITY_REGISTRY';
|
|
14
|
+
/**
|
|
15
|
+
* Create remote resource plugin
|
|
16
|
+
*
|
|
17
|
+
* @param config - Plugin configuration
|
|
18
|
+
* @returns Plugin module for microkernel registration
|
|
19
|
+
*/
|
|
20
|
+
export function createResourcePlugin(config = {}) {
|
|
21
|
+
const resourceRegistry = new ResourceRegistry();
|
|
22
|
+
const entityRegistry = new EntityRegistry();
|
|
23
|
+
return {
|
|
24
|
+
async initialize(ctx) {
|
|
25
|
+
// Register default providers
|
|
26
|
+
const restProvider = new RestResourceProvider();
|
|
27
|
+
const mockProvider = new MockResourceProvider();
|
|
28
|
+
resourceRegistry.registerProvider(restProvider);
|
|
29
|
+
resourceRegistry.registerProvider(mockProvider);
|
|
30
|
+
// Register custom providers
|
|
31
|
+
if (config.providers) {
|
|
32
|
+
config.providers.forEach((provider) => {
|
|
33
|
+
resourceRegistry.registerProvider(provider);
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
// Register endpoints
|
|
37
|
+
if (config.endpoints) {
|
|
38
|
+
config.endpoints.forEach((endpoint) => {
|
|
39
|
+
resourceRegistry.registerEndpoint(endpoint);
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
// Register entities
|
|
43
|
+
if (config.entities) {
|
|
44
|
+
config.entities.forEach((entity) => {
|
|
45
|
+
entityRegistry.registerEntity(entity);
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
// Provide registries via DI
|
|
49
|
+
ctx.provide({
|
|
50
|
+
provide: RESOURCE_REGISTRY_TOKEN,
|
|
51
|
+
useValue: resourceRegistry
|
|
52
|
+
});
|
|
53
|
+
ctx.provide({
|
|
54
|
+
provide: ENTITY_REGISTRY_TOKEN,
|
|
55
|
+
useValue: entityRegistry
|
|
56
|
+
});
|
|
57
|
+
// Register middleware during initialization
|
|
58
|
+
try {
|
|
59
|
+
// Access resolve method if available on context
|
|
60
|
+
const resolve = ctx.resolve;
|
|
61
|
+
if (resolve) {
|
|
62
|
+
// Resolve FileSystemAdapter from DI
|
|
63
|
+
const fsAdapter = resolve(FILESYSTEM_ADAPTER_TOKEN);
|
|
64
|
+
if (!fsAdapter) {
|
|
65
|
+
console.warn('[ui-remote-resource] FileSystemAdapter not available in DI');
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
const fsActions = fsAdapter.getActions();
|
|
69
|
+
const fsSliceName = fsAdapter.sliceName;
|
|
70
|
+
// Create middleware with FileSystemAdapter actions
|
|
71
|
+
const entityMiddleware = createEntityMiddleware({
|
|
72
|
+
entityRegistry,
|
|
73
|
+
fsSliceName,
|
|
74
|
+
onError: config.onError
|
|
75
|
+
});
|
|
76
|
+
const resourceMiddleware = createResourceMiddleware({
|
|
77
|
+
registry: resourceRegistry,
|
|
78
|
+
onError: config.onError,
|
|
79
|
+
onSuccess: config.onSuccess
|
|
80
|
+
});
|
|
81
|
+
const entitySyncMiddleware = createEntitySyncMiddleware();
|
|
82
|
+
const resourceSyncMiddleware = createSyncMiddleware({
|
|
83
|
+
fsActions
|
|
84
|
+
});
|
|
85
|
+
const middlewareRegistry = resolve(MIDDLEWARE_REGISTRY_TOKEN);
|
|
86
|
+
middlewareRegistry.register({
|
|
87
|
+
id: 'entity-middleware',
|
|
88
|
+
middleware: entityMiddleware,
|
|
89
|
+
priority: 110,
|
|
90
|
+
plugin: 'ui-remote-resource'
|
|
91
|
+
});
|
|
92
|
+
middlewareRegistry.register({
|
|
93
|
+
id: 'resource-middleware',
|
|
94
|
+
middleware: resourceMiddleware,
|
|
95
|
+
priority: 100,
|
|
96
|
+
plugin: 'ui-remote-resource'
|
|
97
|
+
});
|
|
98
|
+
middlewareRegistry.register({
|
|
99
|
+
id: 'entity-sync-middleware',
|
|
100
|
+
middleware: entitySyncMiddleware,
|
|
101
|
+
priority: 60,
|
|
102
|
+
plugin: 'ui-remote-resource'
|
|
103
|
+
});
|
|
104
|
+
middlewareRegistry.register({
|
|
105
|
+
id: 'resource-sync-middleware',
|
|
106
|
+
middleware: resourceSyncMiddleware,
|
|
107
|
+
priority: 50,
|
|
108
|
+
plugin: 'ui-remote-resource'
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
else {
|
|
112
|
+
console.warn('Resolve method not available in initialization context');
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
catch (error) {
|
|
116
|
+
console.warn('Failed to register middleware during initialization:', error);
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
async activate(ctx) {
|
|
120
|
+
// Emit ready event
|
|
121
|
+
ctx.hooks?.emit('ui-remote-resource:ready', {
|
|
122
|
+
resourceRegistry,
|
|
123
|
+
entityRegistry
|
|
124
|
+
});
|
|
125
|
+
},
|
|
126
|
+
async deactivate() {
|
|
127
|
+
// Cleanup if needed
|
|
128
|
+
// For now, no cleanup required
|
|
129
|
+
}
|
|
130
|
+
};
|
|
131
|
+
}
|
|
@@ -0,0 +1,147 @@
|
|
|
1
|
+
import type { IResourceProvider, ResourceCallParams, ResourceCallResult } from '../../spi';
|
|
2
|
+
import type { ResourceOperation } from '../../api';
|
|
3
|
+
/**
|
|
4
|
+
* Configuration for a single endpoint mock
|
|
5
|
+
*/
|
|
6
|
+
export interface EndpointMockConfig {
|
|
7
|
+
/** Mock response data */
|
|
8
|
+
data?: any;
|
|
9
|
+
/** Mock metadata */
|
|
10
|
+
metadata?: any;
|
|
11
|
+
/** Simulate delay in ms */
|
|
12
|
+
delay?: number;
|
|
13
|
+
/** Simulate error */
|
|
14
|
+
error?: {
|
|
15
|
+
message: string;
|
|
16
|
+
code?: string;
|
|
17
|
+
details?: any;
|
|
18
|
+
};
|
|
19
|
+
/** Dynamic response generator */
|
|
20
|
+
responseGenerator?: (endpoint: string, params: ResourceCallParams, operation: ResourceOperation) => Promise<ResourceCallResult> | ResourceCallResult;
|
|
21
|
+
/** Callback invoked when this endpoint is called */
|
|
22
|
+
onCall?: (endpoint: string, params: ResourceCallParams, operation: ResourceOperation) => void;
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Mock configuration map: endpoint pattern -> config
|
|
26
|
+
*/
|
|
27
|
+
export type MockConfigMap = Record<string, EndpointMockConfig>;
|
|
28
|
+
/**
|
|
29
|
+
* Call history entry
|
|
30
|
+
*/
|
|
31
|
+
export interface MockCallHistoryEntry {
|
|
32
|
+
timestamp: number;
|
|
33
|
+
endpoint: string;
|
|
34
|
+
params: ResourceCallParams;
|
|
35
|
+
operation: ResourceOperation;
|
|
36
|
+
result?: ResourceCallResult;
|
|
37
|
+
error?: any;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Mock provider configuration
|
|
41
|
+
*/
|
|
42
|
+
export interface MockProviderConfig {
|
|
43
|
+
/** Predefined mocks for specific endpoints */
|
|
44
|
+
mocks?: MockConfigMap;
|
|
45
|
+
/** Default delay for all calls (can be overridden per endpoint) */
|
|
46
|
+
defaultDelay?: number;
|
|
47
|
+
/** Default response for unmocked endpoints */
|
|
48
|
+
defaultResponse?: any;
|
|
49
|
+
/** Whether to track call history */
|
|
50
|
+
trackHistory?: boolean;
|
|
51
|
+
/** Global error to simulate (overrides all endpoint configs) */
|
|
52
|
+
globalError?: {
|
|
53
|
+
message: string;
|
|
54
|
+
code?: string;
|
|
55
|
+
details?: any;
|
|
56
|
+
};
|
|
57
|
+
/** Callback for all calls */
|
|
58
|
+
onAnyCall?: (endpoint: string, params: ResourceCallParams, operation: ResourceOperation) => void;
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* Mock Resource Provider for testing
|
|
62
|
+
*/
|
|
63
|
+
export declare class MockResourceProvider implements IResourceProvider {
|
|
64
|
+
readonly type = "mock";
|
|
65
|
+
private mocks;
|
|
66
|
+
private defaultDelay;
|
|
67
|
+
private defaultResponse;
|
|
68
|
+
private trackHistory;
|
|
69
|
+
private globalError?;
|
|
70
|
+
private onAnyCall?;
|
|
71
|
+
private callHistory;
|
|
72
|
+
constructor(config?: MockProviderConfig);
|
|
73
|
+
call<TData = any>(endpoint: string, params: ResourceCallParams, operation: ResourceOperation): Promise<ResourceCallResult<TData>>;
|
|
74
|
+
/**
|
|
75
|
+
* Find mock config for endpoint (supports pattern matching)
|
|
76
|
+
*/
|
|
77
|
+
private findMockConfig;
|
|
78
|
+
/**
|
|
79
|
+
* Simple pattern matching for endpoints
|
|
80
|
+
*/
|
|
81
|
+
private matchesPattern;
|
|
82
|
+
/**
|
|
83
|
+
* Generate response based on config
|
|
84
|
+
*/
|
|
85
|
+
private generateResponse;
|
|
86
|
+
/**
|
|
87
|
+
* Create error object
|
|
88
|
+
*/
|
|
89
|
+
private createError;
|
|
90
|
+
/**
|
|
91
|
+
* Sleep helper
|
|
92
|
+
*/
|
|
93
|
+
private sleep;
|
|
94
|
+
/**
|
|
95
|
+
* Get call history
|
|
96
|
+
*/
|
|
97
|
+
getCallHistory(): MockCallHistoryEntry[];
|
|
98
|
+
/**
|
|
99
|
+
* Get calls for specific endpoint
|
|
100
|
+
*/
|
|
101
|
+
getCallsForEndpoint(endpoint: string): MockCallHistoryEntry[];
|
|
102
|
+
/**
|
|
103
|
+
* Get calls for specific operation
|
|
104
|
+
*/
|
|
105
|
+
getCallsForOperation(operation: ResourceOperation): MockCallHistoryEntry[];
|
|
106
|
+
/**
|
|
107
|
+
* Clear call history
|
|
108
|
+
*/
|
|
109
|
+
clearHistory(): void;
|
|
110
|
+
/**
|
|
111
|
+
* Get last call
|
|
112
|
+
*/
|
|
113
|
+
getLastCall(): MockCallHistoryEntry | undefined;
|
|
114
|
+
/**
|
|
115
|
+
* Check if endpoint was called
|
|
116
|
+
*/
|
|
117
|
+
wasEndpointCalled(endpoint: string, operation?: ResourceOperation): boolean;
|
|
118
|
+
/**
|
|
119
|
+
* Get call count for endpoint
|
|
120
|
+
*/
|
|
121
|
+
getCallCount(endpoint?: string, operation?: ResourceOperation): number;
|
|
122
|
+
/**
|
|
123
|
+
* Add or update mock configuration
|
|
124
|
+
*/
|
|
125
|
+
setMock(endpoint: string, config: EndpointMockConfig): void;
|
|
126
|
+
/**
|
|
127
|
+
* Remove mock configuration
|
|
128
|
+
*/
|
|
129
|
+
removeMock(endpoint: string): void;
|
|
130
|
+
/**
|
|
131
|
+
* Set global error (all calls will fail)
|
|
132
|
+
*/
|
|
133
|
+
setGlobalError(error?: {
|
|
134
|
+
message: string;
|
|
135
|
+
code?: string;
|
|
136
|
+
details?: any;
|
|
137
|
+
}): void;
|
|
138
|
+
/**
|
|
139
|
+
* Clear global error
|
|
140
|
+
*/
|
|
141
|
+
clearGlobalError(): void;
|
|
142
|
+
/**
|
|
143
|
+
* Reset provider to initial state
|
|
144
|
+
*/
|
|
145
|
+
reset(): void;
|
|
146
|
+
}
|
|
147
|
+
//# sourceMappingURL=mock-resource-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mock-resource-provider.d.ts","sourceRoot":"","sources":["../../../src/impl/providers/mock-resource-provider.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,242 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Mock Resource Provider for testing
|
|
3
|
+
*/
|
|
4
|
+
export class MockResourceProvider {
|
|
5
|
+
constructor(config = {}) {
|
|
6
|
+
Object.defineProperty(this, "type", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
configurable: true,
|
|
9
|
+
writable: true,
|
|
10
|
+
value: 'mock'
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(this, "mocks", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
configurable: true,
|
|
15
|
+
writable: true,
|
|
16
|
+
value: void 0
|
|
17
|
+
});
|
|
18
|
+
Object.defineProperty(this, "defaultDelay", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
configurable: true,
|
|
21
|
+
writable: true,
|
|
22
|
+
value: void 0
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(this, "defaultResponse", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
configurable: true,
|
|
27
|
+
writable: true,
|
|
28
|
+
value: void 0
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(this, "trackHistory", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
configurable: true,
|
|
33
|
+
writable: true,
|
|
34
|
+
value: void 0
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(this, "globalError", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
configurable: true,
|
|
39
|
+
writable: true,
|
|
40
|
+
value: void 0
|
|
41
|
+
});
|
|
42
|
+
Object.defineProperty(this, "onAnyCall", {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
configurable: true,
|
|
45
|
+
writable: true,
|
|
46
|
+
value: void 0
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(this, "callHistory", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
configurable: true,
|
|
51
|
+
writable: true,
|
|
52
|
+
value: []
|
|
53
|
+
});
|
|
54
|
+
this.mocks = config.mocks || {};
|
|
55
|
+
this.defaultDelay = config.defaultDelay || 0;
|
|
56
|
+
this.defaultResponse = config.defaultResponse || { message: 'Mock response' };
|
|
57
|
+
this.trackHistory = config.trackHistory !== false; // Default true
|
|
58
|
+
this.globalError = config.globalError;
|
|
59
|
+
this.onAnyCall = config.onAnyCall;
|
|
60
|
+
}
|
|
61
|
+
async call(endpoint, params, operation) {
|
|
62
|
+
// Invoke global callback
|
|
63
|
+
this.onAnyCall?.(endpoint, params, operation);
|
|
64
|
+
// Find matching mock config
|
|
65
|
+
const mockConfig = this.findMockConfig(endpoint);
|
|
66
|
+
// Determine delay
|
|
67
|
+
const delay = mockConfig?.delay ?? this.defaultDelay;
|
|
68
|
+
// Simulate delay
|
|
69
|
+
if (delay > 0) {
|
|
70
|
+
await this.sleep(delay);
|
|
71
|
+
}
|
|
72
|
+
// Record call start
|
|
73
|
+
const historyEntry = {
|
|
74
|
+
timestamp: Date.now(),
|
|
75
|
+
endpoint,
|
|
76
|
+
params,
|
|
77
|
+
operation
|
|
78
|
+
};
|
|
79
|
+
try {
|
|
80
|
+
// Check for global error
|
|
81
|
+
if (this.globalError) {
|
|
82
|
+
throw this.createError(this.globalError);
|
|
83
|
+
}
|
|
84
|
+
// Check for endpoint-specific error
|
|
85
|
+
if (mockConfig?.error) {
|
|
86
|
+
throw this.createError(mockConfig.error);
|
|
87
|
+
}
|
|
88
|
+
// Invoke endpoint callback
|
|
89
|
+
mockConfig?.onCall?.(endpoint, params, operation);
|
|
90
|
+
// Generate response
|
|
91
|
+
const result = await this.generateResponse(endpoint, params, operation, mockConfig);
|
|
92
|
+
// Record success
|
|
93
|
+
if (this.trackHistory) {
|
|
94
|
+
historyEntry.result = result;
|
|
95
|
+
this.callHistory.push(historyEntry);
|
|
96
|
+
}
|
|
97
|
+
return result;
|
|
98
|
+
}
|
|
99
|
+
catch (error) {
|
|
100
|
+
// Record error
|
|
101
|
+
if (this.trackHistory) {
|
|
102
|
+
historyEntry.error = error;
|
|
103
|
+
this.callHistory.push(historyEntry);
|
|
104
|
+
}
|
|
105
|
+
throw error;
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* Find mock config for endpoint (supports pattern matching)
|
|
110
|
+
*/
|
|
111
|
+
findMockConfig(endpoint) {
|
|
112
|
+
// Exact match
|
|
113
|
+
if (this.mocks[endpoint]) {
|
|
114
|
+
return this.mocks[endpoint];
|
|
115
|
+
}
|
|
116
|
+
// Pattern matching (e.g., "/api/users/:id" matches "/api/users/123")
|
|
117
|
+
for (const [pattern, config] of Object.entries(this.mocks)) {
|
|
118
|
+
if (this.matchesPattern(endpoint, pattern)) {
|
|
119
|
+
return config;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return undefined;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Simple pattern matching for endpoints
|
|
126
|
+
*/
|
|
127
|
+
matchesPattern(endpoint, pattern) {
|
|
128
|
+
const patternRegex = pattern.replace(/:[^/]+/g, '[^/]+');
|
|
129
|
+
const regex = new RegExp(`^${patternRegex}$`);
|
|
130
|
+
return regex.test(endpoint);
|
|
131
|
+
}
|
|
132
|
+
/**
|
|
133
|
+
* Generate response based on config
|
|
134
|
+
*/
|
|
135
|
+
async generateResponse(endpoint, params, operation, mockConfig) {
|
|
136
|
+
// Use custom response generator if provided
|
|
137
|
+
if (mockConfig?.responseGenerator) {
|
|
138
|
+
const result = await mockConfig.responseGenerator(endpoint, params, operation);
|
|
139
|
+
return result;
|
|
140
|
+
}
|
|
141
|
+
// Use configured data
|
|
142
|
+
const data = mockConfig?.data ?? this.defaultResponse;
|
|
143
|
+
const metadata = mockConfig?.metadata ?? {
|
|
144
|
+
status: 200,
|
|
145
|
+
headers: { 'content-type': 'application/json' }
|
|
146
|
+
};
|
|
147
|
+
return { data, metadata };
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Create error object
|
|
151
|
+
*/
|
|
152
|
+
createError(errorConfig) {
|
|
153
|
+
const error = new Error(errorConfig.message);
|
|
154
|
+
error.code = errorConfig.code;
|
|
155
|
+
error.details = errorConfig.details;
|
|
156
|
+
return error;
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Sleep helper
|
|
160
|
+
*/
|
|
161
|
+
sleep(ms) {
|
|
162
|
+
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
163
|
+
}
|
|
164
|
+
// ========== Testing Utilities ==========
|
|
165
|
+
/**
|
|
166
|
+
* Get call history
|
|
167
|
+
*/
|
|
168
|
+
getCallHistory() {
|
|
169
|
+
return [...this.callHistory];
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Get calls for specific endpoint
|
|
173
|
+
*/
|
|
174
|
+
getCallsForEndpoint(endpoint) {
|
|
175
|
+
return this.callHistory.filter((entry) => entry.endpoint === endpoint);
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Get calls for specific operation
|
|
179
|
+
*/
|
|
180
|
+
getCallsForOperation(operation) {
|
|
181
|
+
return this.callHistory.filter((entry) => entry.operation === operation);
|
|
182
|
+
}
|
|
183
|
+
/**
|
|
184
|
+
* Clear call history
|
|
185
|
+
*/
|
|
186
|
+
clearHistory() {
|
|
187
|
+
this.callHistory = [];
|
|
188
|
+
}
|
|
189
|
+
/**
|
|
190
|
+
* Get last call
|
|
191
|
+
*/
|
|
192
|
+
getLastCall() {
|
|
193
|
+
return this.callHistory[this.callHistory.length - 1];
|
|
194
|
+
}
|
|
195
|
+
/**
|
|
196
|
+
* Check if endpoint was called
|
|
197
|
+
*/
|
|
198
|
+
wasEndpointCalled(endpoint, operation) {
|
|
199
|
+
return this.callHistory.some((entry) => entry.endpoint === endpoint && (!operation || entry.operation === operation));
|
|
200
|
+
}
|
|
201
|
+
/**
|
|
202
|
+
* Get call count for endpoint
|
|
203
|
+
*/
|
|
204
|
+
getCallCount(endpoint, operation) {
|
|
205
|
+
if (!endpoint) {
|
|
206
|
+
return this.callHistory.length;
|
|
207
|
+
}
|
|
208
|
+
return this.callHistory.filter((entry) => entry.endpoint === endpoint && (!operation || entry.operation === operation)).length;
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* Add or update mock configuration
|
|
212
|
+
*/
|
|
213
|
+
setMock(endpoint, config) {
|
|
214
|
+
this.mocks[endpoint] = config;
|
|
215
|
+
}
|
|
216
|
+
/**
|
|
217
|
+
* Remove mock configuration
|
|
218
|
+
*/
|
|
219
|
+
removeMock(endpoint) {
|
|
220
|
+
delete this.mocks[endpoint];
|
|
221
|
+
}
|
|
222
|
+
/**
|
|
223
|
+
* Set global error (all calls will fail)
|
|
224
|
+
*/
|
|
225
|
+
setGlobalError(error) {
|
|
226
|
+
this.globalError = error;
|
|
227
|
+
}
|
|
228
|
+
/**
|
|
229
|
+
* Clear global error
|
|
230
|
+
*/
|
|
231
|
+
clearGlobalError() {
|
|
232
|
+
this.globalError = undefined;
|
|
233
|
+
}
|
|
234
|
+
/**
|
|
235
|
+
* Reset provider to initial state
|
|
236
|
+
*/
|
|
237
|
+
reset() {
|
|
238
|
+
this.clearHistory();
|
|
239
|
+
this.clearGlobalError();
|
|
240
|
+
this.mocks = {};
|
|
241
|
+
}
|
|
242
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { type AxiosInstance } from 'axios';
|
|
2
|
+
import type { IResourceProvider, ResourceCallParams, ResourceCallResult } from '../../spi';
|
|
3
|
+
import type { ResourceOperation } from '../../api';
|
|
4
|
+
/**
|
|
5
|
+
* Configuration for REST resource provider
|
|
6
|
+
*/
|
|
7
|
+
export interface RestProviderConfig {
|
|
8
|
+
/** Base URL for API requests */
|
|
9
|
+
baseUrl?: string;
|
|
10
|
+
/** Request timeout in milliseconds */
|
|
11
|
+
timeout?: number;
|
|
12
|
+
/** Default headers for all requests */
|
|
13
|
+
headers?: Record<string, string>;
|
|
14
|
+
/** Custom axios instance (if not provided, one will be created) */
|
|
15
|
+
axiosInstance?: AxiosInstance;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* REST API resource provider using Axios
|
|
19
|
+
*/
|
|
20
|
+
export declare class RestResourceProvider implements IResourceProvider {
|
|
21
|
+
readonly type = "rest";
|
|
22
|
+
private axios;
|
|
23
|
+
constructor(config?: RestProviderConfig);
|
|
24
|
+
/**
|
|
25
|
+
* Execute a resource call
|
|
26
|
+
*/
|
|
27
|
+
call<TData = any>(endpoint: string, params: ResourceCallParams, operation: ResourceOperation): Promise<ResourceCallResult<TData>>;
|
|
28
|
+
/**
|
|
29
|
+
* Execute fetch operation (GET)
|
|
30
|
+
*/
|
|
31
|
+
private executeFetch;
|
|
32
|
+
/**
|
|
33
|
+
* Execute create operation (POST)
|
|
34
|
+
*/
|
|
35
|
+
private executeCreate;
|
|
36
|
+
/**
|
|
37
|
+
* Execute update operation (PUT)
|
|
38
|
+
*/
|
|
39
|
+
private executeUpdate;
|
|
40
|
+
/**
|
|
41
|
+
* Execute delete operation (DELETE)
|
|
42
|
+
*/
|
|
43
|
+
private executeDelete;
|
|
44
|
+
/**
|
|
45
|
+
* Build URL with path parameters
|
|
46
|
+
* Replaces :param placeholders with actual values
|
|
47
|
+
* Example: /users/:id + { id: "123" } → /users/123
|
|
48
|
+
*/
|
|
49
|
+
private buildUrl;
|
|
50
|
+
}
|
|
51
|
+
//# sourceMappingURL=rest-resource-provider.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rest-resource-provider.d.ts","sourceRoot":"","sources":["../../../src/impl/providers/rest-resource-provider.ts"],"names":[],"mappings":"AAAA,OAAc,EAAE,KAAK,aAAa,EAAE,MAAM,OAAO,CAAC;AAClD,OAAO,KAAK,EACV,iBAAiB,EACjB,kBAAkB,EAClB,kBAAkB,EACnB,MAAM,WAAW,CAAC;AACnB,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,WAAW,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC,gCAAgC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,sCAAsC;IACtC,OAAO,CAAC,EAAE,MAAM,CAAC;IAEjB,uCAAuC;IACvC,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAEjC,mEAAmE;IACnE,aAAa,CAAC,EAAE,aAAa,CAAC;CAC/B;AAED;;GAEG;AACH,qBAAa,oBAAqB,YAAW,iBAAiB;IAC5D,QAAQ,CAAC,IAAI,UAAU;IACvB,OAAO,CAAC,KAAK,CAAgB;gBAEjB,MAAM,GAAE,kBAAuB;IAa3C;;OAEG;IACG,IAAI,CAAC,KAAK,GAAG,GAAG,EACpB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,kBAAkB,EAC1B,SAAS,EAAE,iBAAiB,GAC3B,OAAO,CAAC,kBAAkB,CAAC,KAAK,CAAC,CAAC;IAerC;;OAEG;YACW,YAAY;IAmB1B;;OAEG;YACW,aAAa;IAkB3B;;OAEG;YACW,aAAa;IAmB3B;;OAEG;YACW,aAAa;IAmB3B;;;;OAIG;IACH,OAAO,CAAC,QAAQ;CAUjB"}
|