var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
    function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
    return new (P || (P = Promise))(function (resolve, reject) {
        function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
        function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
        function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
        step((generator = generator.apply(thisArg, _arguments || [])).next());
    });
};
import { createTrait } from '@meta-ui/core';
import { Type } from '@sinclair/typebox';
import { FetchTraitPropertiesSchema } from '../../types/TraitPropertiesSchema';
const hasFetchedMap = new Map();
const useFetchTrait = ({ url, method, lazy: _lazy, headers: _headers, body, mergeState, services, subscribeMethods, componentId, onComplete, }) => {
    const hashId = `#${componentId}@${'fetch'}`;
    const hasFetched = hasFetchedMap.get(hashId);
    const lazy = undefined ? method.toLowerCase() !== 'get' : _lazy;
    const fetchData = () => {
        hasFetchedMap.set(hashId, true);
        const headers = new Headers();
        if (_headers) {
            for (const key in _headers) {
                headers.append(key, _headers[key]);
            }
        }
        mergeState({
            fetch: {
                loading: true,
                data: undefined,
                error: undefined,
            },
        });
        fetch(url, {
            method,
            headers,
            body: method === 'get' ? undefined : JSON.stringify(body),
        }).then((response) => __awaiter(void 0, void 0, void 0, function* () {
            if (response.ok) {
                const data = yield response.json();
                mergeState({
                    fetch: {
                        loading: false,
                        data,
                        error: undefined,
                    },
                });
                onComplete === null || onComplete === void 0 ? void 0 : onComplete.forEach(event => {
                    services.apiService.send('uiMethod', {
                        componentId: event.componentId,
                        name: event.method.name,
                        parameters: event.method.parameters,
                    });
                });
            }
            else {
                const error = new Error(`HTTP${response.status}: ${response.statusText}`);
                console.warn(error);
                mergeState({
                    fetch: {
                        loading: false,
                        data: undefined,
                        error,
                    },
                });
            }
        }), (error) => __awaiter(void 0, void 0, void 0, function* () {
            console.warn(error);
            mergeState({
                fetch: {
                    loading: false,
                    data: undefined,
                    error: error instanceof Error ? error : new Error(error),
                },
            });
        }));
    };
    if (!lazy && url && !hasFetched) {
        fetchData();
    }
    subscribeMethods({
        triggerFetch() {
            fetchData();
        },
    });
    return {
        props: {
            effects: [
                () => {
                    hasFetchedMap.set(hashId, false);
                },
            ],
        },
    };
};
export default Object.assign(Object.assign({}, createTrait({
    version: 'core/v1',
    metadata: {
        name: 'fetch',
        description: 'fetch data to store',
    },
    spec: {
        properties: FetchTraitPropertiesSchema,
        state: Type.Object({
            fetch: Type.Object({
                loading: Type.Boolean(),
                data: Type.Any(),
                error: Type.Any(),
            }),
        }),
        methods: [],
    },
})), { impl: useFetchTrait });
//# sourceMappingURL=fetch.js.map