treble-hook
Advanced tools
Comparing version 1.0.13 to 2.0.0-alpha.1
@@ -1,29 +0,14 @@ | ||
/*!* | ||
* Copyright (c) Igneous, Inc. All Rights Reserved. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
import React, { Dispatch, SetStateAction } from 'react'; | ||
declare const _default: { | ||
addTopic<T>(topicName: string, defaultValue: T): void; | ||
getPublisher(): React.FunctionComponent<{ | ||
children?: React.ReactNode; | ||
}>; | ||
}; | ||
export default _default; | ||
export declare function usePubSub<T>(topic: string): [T, React.Dispatch<React.SetStateAction<T>>]; | ||
export declare type Publish<T> = Dispatch<SetStateAction<T>>; | ||
export declare enum PubSubTupleIndex { | ||
State = 0, | ||
Publish = 1, | ||
Unsubscribe = 2, | ||
DeleteTopic = 3 | ||
Publish = 1 | ||
} | ||
export declare type Publish<T> = (newState: T) => void; | ||
export interface TrebleHookConfig { | ||
suppressDupeStateWarning?: boolean; | ||
topicConfig?: TopicConfigMap; | ||
} | ||
export interface TopicConfig { | ||
allowDupeState?: boolean; | ||
} | ||
export interface TopicConfigMap { | ||
[topic: string]: TopicConfig; | ||
} | ||
export declare function configPubSub(config: TrebleHookConfig): void; | ||
export declare function usePubSub<T>(topic: string, defaultState: T, publishDefaultState?: boolean): SubscriptionTuple<T>; | ||
declare type PublicUnsubscribe = () => void; | ||
declare type PublicDeleteTopic = () => void; | ||
declare type SubscriptionTuple<T> = [T, Publish<T>, PublicUnsubscribe, PublicDeleteTopic]; | ||
export {}; |
165
lib/index.js
"use strict"; | ||
/*!* | ||
* Copyright (c) Igneous, Inc. All Rights Reserved. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
var __importStar = (this && this.__importStar) || function (mod) { | ||
@@ -17,2 +11,45 @@ if (mod && mod.__esModule) return mod; | ||
const react_1 = __importStar(require("react")); | ||
const topics = {}; | ||
exports.default = (function TrebleHookPublisherFactory() { | ||
return { | ||
addTopic(topicName, defaultValue) { | ||
if (topics[topicName]) { | ||
throw new Error(`The topic "${topicName}" has already been added.`); | ||
} | ||
const context = createPublishContext(); | ||
const provider = createPublishProvider(context, defaultValue); | ||
topics[topicName] = { | ||
context, | ||
provider, | ||
}; | ||
}, | ||
getPublisher() { | ||
const TrebleHookPublisher = ({ children, }) => { | ||
const ProviderNest = Object.keys(topics).reduce((tally, topicName) => { | ||
const topic = topics[topicName]; | ||
if (!topic) { | ||
throw new Error(getNoTopicErrorMessage(topicName)); | ||
} | ||
const Provider = topic.provider; | ||
return react_1.default.createElement(Provider, null, tally); | ||
}, react_1.default.createElement(react_1.default.Fragment, null, children)); | ||
return ProviderNest; | ||
}; | ||
return TrebleHookPublisher; | ||
}, | ||
}; | ||
})(); | ||
function usePubSub(topic) { | ||
if (!topics[topic]) { | ||
throw new Error(getNoTopicErrorMessage(topic)); | ||
} | ||
const topicDef = topics[topic]; | ||
const context = react_1.useContext(topicDef.context); | ||
if (!context) { | ||
throw new Error(`The "${topic} topic must be used within the context of a TrebleHook publisher. | ||
Please wrap your App component with a TrebleHook publisher.`); | ||
} | ||
return context; | ||
} | ||
exports.usePubSub = usePubSub; | ||
var PubSubTupleIndex; | ||
@@ -22,112 +59,16 @@ (function (PubSubTupleIndex) { | ||
PubSubTupleIndex[PubSubTupleIndex["Publish"] = 1] = "Publish"; | ||
PubSubTupleIndex[PubSubTupleIndex["Unsubscribe"] = 2] = "Unsubscribe"; | ||
PubSubTupleIndex[PubSubTupleIndex["DeleteTopic"] = 3] = "DeleteTopic"; | ||
})(PubSubTupleIndex = exports.PubSubTupleIndex || (exports.PubSubTupleIndex = {})); | ||
const getUUID = (a, b) => { | ||
for (b = a = ''; a++ < 36; b += 4 << ~a * 6.5 ? (a ^ 15 ? 8 ^ Math.random() * (a ^ 20 ? 16 : 4) : 4).toString(16) : '-') | ||
; | ||
return b; | ||
}; | ||
let trebleHookConfig = {}; | ||
const topics = {}; | ||
const getCurrentState = (topic) => { | ||
const topicRecord = topics[topic]; | ||
if (topicRecord && topicRecord.hasBeenPublished) { | ||
return topicRecord.currentState; | ||
} | ||
else { | ||
return undefined; | ||
} | ||
}; | ||
const publish = (topic) => (newState) => { | ||
const topicRecord = topics[topic]; | ||
if (topicRecord) { | ||
const allowDupeState = Boolean(trebleHookConfig.topicConfig | ||
&& trebleHookConfig.topicConfig[topic] | ||
&& trebleHookConfig.topicConfig[topic].allowDupeState); | ||
let proceed = true; | ||
if (!allowDupeState) { | ||
const currentStateCompare = JSON.stringify(topicRecord.currentState); | ||
const newStateCompare = JSON.stringify(newState); | ||
proceed = newStateCompare !== currentStateCompare; | ||
} | ||
if (proceed) { | ||
Object.values(topicRecord.subscriptionMap).forEach(publicHook => publicHook[PubSubTupleIndex.Publish](newState)); | ||
topicRecord.currentState = newState; | ||
topicRecord.hasBeenPublished = true; | ||
} | ||
else if (!trebleHookConfig.suppressDupeStateWarning) { | ||
const logWarning = process && process.env && process.env.NODE_ENV ? process.env.NODE_ENV === 'development' : true; | ||
if (logWarning) { | ||
console.warn('[treble-hook] A publish of unchanged state was attempted for topic:', topic, '\n\n\t- If this is desired behavior then set the "allowDupeState" flag to true', '\n\t-To suppress this warning, set either "allowDupeState" for topic to true ' + | ||
'or set the global "suppressDupeStateWarning" flag to true'); | ||
} | ||
} | ||
} | ||
else { | ||
throw new Error(`Cannot publish to non-existent topic "${topic}"`); | ||
} | ||
}; | ||
const unsubscribe = (topic, subscriptionId) => () => { | ||
const topicRecord = topics[topic]; | ||
if (topicRecord && subscriptionId) { | ||
delete topicRecord.subscriptionMap[subscriptionId]; | ||
} | ||
}; | ||
const deleteTopic = (topic) => () => { | ||
delete topics[topic]; | ||
console.warn(`[treble-hook] The topic "${topic}" was just deleted.`, '\n\n\t- If any component attempts to access state for the deleted topic, errors/side-effects may occur.', '\n\t- To mitigate this possibility, make sure that only top-level components delete topics'); | ||
}; | ||
function configPubSub(config) { | ||
trebleHookConfig = { ...trebleHookConfig, ...config }; | ||
function createPublishContext() { | ||
return react_1.createContext(); | ||
} | ||
exports.configPubSub = configPubSub; | ||
function usePubSub(topic, defaultState, publishDefaultState = false) { | ||
if (arguments.length > 3) { | ||
throw new Error(`Invalid hook usage; hook must be initialized with either two or three arguments. The first | ||
argument is the topic, the second argument is the default state value for the topic, and the | ||
optional third argument determines whether or not to publish default state, which defaults to true.`); | ||
} | ||
const [state, setState] = react_1.useState(); | ||
const [subscriptionId, setSubscriptionId] = react_1.useState(); | ||
const publishTopic = react_1.default.useMemo(() => publish(topic), [topic]); | ||
const internalUsePubSubState = () => { | ||
const currentState = getCurrentState(topic); | ||
if (typeof state === 'undefined' && typeof currentState !== 'undefined') { | ||
setState(currentState); | ||
} | ||
return [state, setState]; | ||
function createPublishProvider(TrebleHookContext, defaultValue) { | ||
return (props) => { | ||
const contextState = react_1.useState(defaultValue); | ||
return react_1.default.createElement(TrebleHookContext.Provider, Object.assign({ value: contextState }, props)); | ||
}; | ||
let internalTuple; | ||
if (!subscriptionId) { | ||
internalTuple = internalUsePubSubState(); | ||
} | ||
react_1.useEffect(() => { | ||
const newSubscriptionId = getUUID(); | ||
setSubscriptionId(newSubscriptionId); | ||
if (!topics[topic]) { | ||
topics[topic] = { | ||
currentState: state, | ||
hasBeenPublished: false, | ||
subscriptionMap: {}, | ||
}; | ||
} | ||
topics[topic].subscriptionMap[newSubscriptionId] = internalTuple; | ||
if (typeof state === 'undefined' && publishDefaultState) { | ||
publishTopic(defaultState); | ||
} | ||
return () => { | ||
unsubscribe(topic, newSubscriptionId)(); | ||
}; | ||
}, []); | ||
return [ | ||
typeof state !== 'undefined' | ||
? state | ||
: defaultState, | ||
publishTopic, | ||
unsubscribe(topic, subscriptionId), | ||
deleteTopic(topic), | ||
]; | ||
} | ||
exports.usePubSub = usePubSub; | ||
function getNoTopicErrorMessage(topicName) { | ||
return `The topic "${topicName}" has not been added. | ||
Please use the addTopic function to do so before getting the Publisher.`; | ||
} | ||
//# sourceMappingURL=index.js.map |
{ | ||
"name": "treble-hook", | ||
"version": "1.0.13", | ||
"version": "2.0.0-alpha.1", | ||
"description": "Get hooked on simple subscribe-and-publish in ReactJS.", | ||
@@ -23,6 +23,6 @@ "main": "./lib/index.js", | ||
"build": "yarn lint && tsc", | ||
"lint": "tslint -c ./tslint.json ./src/**/*.ts", | ||
"lint": "tslint -c ./tslint.json ./src/**/*.tsx", | ||
"prepublishOnly": "yarn test", | ||
"pretest": "yarn build", | ||
"test": "yarn jest" | ||
"test": "yarn jest --passWithNoTests" | ||
}, | ||
@@ -29,0 +29,0 @@ "files": [ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
No v1
QualityPackage is not semver >=1. This means it is not stable and does not support ^ ranges.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
1
10614
85
2
1