UNPKG

react-antd-admin-panel

Version:

Modern TypeScript-first React admin panel builder with Ant Design 6

166 lines 4.74 kB
/** * Loader - Data pre-fetching orchestrator for page lifecycle * Manages multiple HTTP requests with dependencies and conditions * * @example * const loader = new Loader() * .add('user', new Get().target('/api/user')) * .add('posts', new Get().target('/api/posts'), { * condition: (data) => data.user?.isAdmin * }) * .onLoad((data) => console.log('Loaded:', data)) * .execute(); */ export class Loader { _requests = []; _hooks = {}; _parallel = true; _abortOnError = false; /** * Add a request to the loader */ add(key, request, options) { this._requests.push({ key, request, required: options?.required ?? false, condition: options?.condition, }); return this; } /** * Set whether requests execute in parallel (default) or sequentially */ parallel(value = true) { this._parallel = value; return this; } /** * Set whether to abort on first error (default: false) */ abortOnError(value = true) { this._abortOnError = value; return this; } /** * Hook called before any requests are made */ onBeforeLoad(callback) { this._hooks.onBeforeLoad = callback; return this; } /** * Hook called after all requests complete successfully */ onLoad(callback) { this._hooks.onLoad = callback; return this; } /** * Hook called after onLoad (useful for side effects) */ onAfterLoad(callback) { this._hooks.onAfterLoad = callback; return this; } /** * Hook called if any request fails */ onError(callback) { this._hooks.onError = callback; return this; } /** * Execute all requests with lifecycle management */ async execute() { const data = {}; try { // Before load hook if (this._hooks.onBeforeLoad) { await this._hooks.onBeforeLoad(); } if (this._parallel) { // Execute all requests in parallel await this._executeParallel(data); } else { // Execute requests sequentially (allows conditions to check previous results) await this._executeSequential(data); } // On load hook if (this._hooks.onLoad) { await this._hooks.onLoad(data); } // After load hook if (this._hooks.onAfterLoad) { await this._hooks.onAfterLoad(data); } return data; } catch (error) { // Error hook if (this._hooks.onError) { await this._hooks.onError(error); } throw error; } } /** * Execute requests in parallel */ async _executeParallel(data) { const promises = this._requests.map(async (req) => { // Check condition if (req.condition && !req.condition(data)) { return; } try { const result = await req.request.execute(); data[req.key] = result; } catch (error) { if (req.required || this._abortOnError) { throw error; } // Non-required request failed, continue data[req.key] = null; } }); await Promise.all(promises); } /** * Execute requests sequentially (allows conditions to depend on previous results) */ async _executeSequential(data) { for (const req of this._requests) { // Check condition based on already-loaded data if (req.condition && !req.condition(data)) { continue; } try { const result = await req.request.execute(); data[req.key] = result; } catch (error) { if (req.required || this._abortOnError) { throw error; } // Non-required request failed, continue data[req.key] = null; } } } /** * Create a loader from a configuration object */ static from(config) { const loader = new Loader(); loader._requests = config.requests; loader._hooks = config.hooks || {}; loader._parallel = config.parallel ?? true; loader._abortOnError = config.abortOnError ?? false; return loader; } } //# sourceMappingURL=Loader.js.map