react-async-states
Version:
A low-level multi paradigm state management library
113 lines (110 loc) • 4.29 kB
JavaScript
import { __DEV__, assign, emptyArray } from '../shared/index.js';
import { useCallerName } from '../helpers/useCallerName.js';
import { useData_internal } from '../hooks/useData_internal.js';
import { useAsync_internal } from '../hooks/useAsync_internal.js';
import { createContext, createSource } from 'async-states';
import { __DEV__setHookCallerName } from '../hooks/modules/HookSubscriptionUtils.js';
let didWarnAboutInitialShapeDeprecated = false;
function createApplication(initialShape, context) {
if (__DEV__) {
if (initialShape !== undefined && !didWarnAboutInitialShapeDeprecated) {
didWarnAboutInitialShapeDeprecated = true;
console.error("createApplication's first argument was removed, it doesn't" +
"accept the shape anymore. This was done to avoid creating and " +
"maintaining a plain javascript object and only rely on typescript." +
"\nAs migration strategy, do this:" +
"\n\nimport { createApplication, Api } from 'react-async-states';" +
"\n\ntype MyAppType = { resource: { api: Api<TData, TArgs, tError> } };" +
"\nconst app = createApplication<MyType>(undefined, context?);" +
"\n\nIf you had an eager API, just inline this manually." +
"\napp.eagerResource.eagerApi.define(producer, producerConfig);" +
"\nOr group them into a single function that initialize all eager APIs" +
"\n\nWhen v2 lands, this warning will be removed and createApplication " +
"will only accept the optional 'context' parameter.");
}
}
let app = {};
return new Proxy(app, {
get(_, property) {
let resourceName = property;
let existingResource = app[resourceName];
if (existingResource) {
return existingResource;
}
if (context) {
createContext(context);
}
let resource = createResource(resourceName, context);
app[resourceName] = resource;
return resource;
},
});
}
function createResource(resourceName, context) {
let resource = {};
return new Proxy(resource, {
get(_target, property) {
let apiName = property;
let exitingApi = resource[property];
if (exitingApi) {
return exitingApi;
}
let api = createApi(resourceName, apiName, context);
resource[apiName] = api;
return api;
},
});
}
function createApi(resourceName, apiName, context) {
let source = null;
function token() {
return getSource();
}
token.define = define;
token.useData = (useDataForApp).bind(null, getSource);
token.useAsync = (useAsyncForApp).bind(null, getSource);
Object.defineProperty(token, "source", {
get() {
return getSource();
}
});
function getSource() {
if (!source) {
let path = `app.${String(resourceName)}.${String(apiName)}`;
throw new Error(`Call ${path}.define(producer, config?) before using ${path}`);
}
return source;
}
return token;
function define(producer, config) {
if (!source) {
let key = `${String(resourceName)}_${String(apiName)}`;
let apiConfig = config;
if (context !== null) {
apiConfig = assign({}, apiConfig, { context });
}
source = createSource(key, producer, apiConfig);
}
else {
source.replaceProducer(producer);
source.patchConfig(config);
}
return token;
}
}
function useDataForApp(sourceGetter, config, deps) {
let source = sourceGetter();
if (__DEV__) {
__DEV__setHookCallerName(useCallerName(3));
}
return useData_internal(source, deps || emptyArray, config);
}
function useAsyncForApp(sourceGetter, config, deps) {
let source = sourceGetter();
if (__DEV__) {
__DEV__setHookCallerName(useCallerName(3));
}
return useAsync_internal(source, deps || emptyArray, config);
}
export { createApplication };
//# sourceMappingURL=Application.js.map