Comparing version
interface UseContext<T> { | ||
use: () => T | null; | ||
/** | ||
* Get the current context. Throws if no context is set. | ||
*/ | ||
use: () => T; | ||
/** | ||
* Get the current context. Returns `null` when no context is set. | ||
*/ | ||
tryUse: () => T | null; | ||
/** | ||
* Set the context as Singleton Pattern. | ||
*/ | ||
set: (instance?: T, replace?: Boolean) => void; | ||
/** | ||
* Clear current context. | ||
*/ | ||
unset: () => void; | ||
/** | ||
* Exclude a synchronous function with the provided context. | ||
*/ | ||
call: <R>(instance: T, cb: () => R) => R; | ||
/** | ||
* Exclude an asynchronous function with the provided context. | ||
* Requires installing the transform plugin to work properly. | ||
*/ | ||
callAsync: <R>(instance: T, cb: () => R | Promise<R>) => Promise<R>; | ||
@@ -7,0 +27,0 @@ } |
{ | ||
"name": "unctx", | ||
"version": "1.1.4", | ||
"version": "2.0.0", | ||
"description": "Composition-api in Vanilla js", | ||
@@ -20,3 +20,2 @@ "repository": "unjs/unctx", | ||
"./plugin": { | ||
"require": "./dist/plugin.cjs", | ||
"import": "./dist/plugin.mjs", | ||
@@ -41,9 +40,10 @@ "types": "./dist/plugin.d.ts" | ||
"dependencies": { | ||
"acorn": "^8.7.0", | ||
"estree-walker": "^2.0.2", | ||
"magic-string": "^0.26.1", | ||
"unplugin": "^0.6.1" | ||
"acorn": "^8.8.0", | ||
"estree-walker": "^3.0.1", | ||
"magic-string": "^0.26.2", | ||
"unplugin": "^0.8.0" | ||
}, | ||
"devDependencies": { | ||
"@nuxtjs/eslint-config-typescript": "latest", | ||
"@types/estree": "latest", | ||
"@types/jest": "latest", | ||
@@ -53,2 +53,3 @@ "@types/node": "latest", | ||
"eslint": "latest", | ||
"jiti": "^1.14.0", | ||
"standard-version": "latest", | ||
@@ -59,3 +60,3 @@ "typescript": "latest", | ||
}, | ||
"packageManager": "pnpm@6.32.3", | ||
"packageManager": "pnpm@7.8.0", | ||
"scripts": { | ||
@@ -67,4 +68,3 @@ "build": "unbuild", | ||
"test": "pnpm lint && vitest run --coverage" | ||
}, | ||
"readme": "# 🍦 unctx\n\n> Composition-api in Vanilla js\n\n[![npm version][npm-v-src]][npm-v-href]\n[![npm downloads][npm-dm-src]][npm-dm-href]\n[![package phobia][packagephobia-src]][packagephobia-href]\n[![bundle phobia][bundlephobia-src]][bundlephobia-href]\n[![codecov][codecov-src]][codecov-href]\n\n## What is it?\n\n[Vue.js](https://vuejs.org) introduced an amazing pattern called [Composition API](https://v3.vuejs.org/guide/composition-api-introduction.html) that allows organizing complex logic by splitting it into reusable functions and grouping in logical order. `unctx` allows easily implementing composition api pattern in your javascript libraries without hassle.\n\n## Integration\n\nIn your **awesome** library:\n\n```bash\nyarn add unctx\n# or\nnpm install unctx\n```\n\n```js\nimport { createContext } from 'unctx'\n\nconst ctx = createContext()\n\nexport const useAwesome = ctx.use\n\n// ...\nctx.call({ test: 1 }, () => {\n // This is similar to vue setup function\n // Any function called here, can use `useAwesome` to get { test: 1 }\n})\n```\n\nUser code:\n\n```js\nimport { useAwesome } from 'awesome-lib'\n\n// ...\nfunction setup() {\n const ctx = useAwesome()\n}\n```\n\n## Using Namespaces\n\nTo avoid issues with multiple version of library, `unctx` provides a safe global namespace to access context by key (kept in [`globalThis`](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/globalThis)). **Important:** Please use a verbose name for key to avoid conflict with other js libraries. Using npm package name is recommended. Using symbols has no effect since it still causes multiple context issue.\n\n```js\nimport { useContext, getContext } from 'unctx'\n\nconst useAwesome = useContext('awesome-lib')\n\n// or\n// const awesomeContext = getContext('awesome-lib')\n```\n\nYou can also create your own internal namespace with `createNamespace` utility for more advanced use cases.\n\n## Singleton Pattern\n\nIf you are sure it is safe to use a shared instance (not depending to request), you can also use `ctx.set` and `ctx.unset` for a [singleton pattern](https://en.wikipedia.org/wiki/Singleton_pattern).\n\n**Note:** You cannot combine `set` with `call`. Always use `unset` before replacing instance otherwise you will get `Context conflict` error.\n\n```js\nimport { createContext } from 'unctx'\n\nconst ctx = createContext()\nctx.set(new Awesome())\n\n// Replacing instance without unset\n// ctx.set(new Awesome(), true)\n\nexport const useAwesome = ctx.use\n```\n\n## Typescript\n\nA generic type exists on all utilities to be set for instance/context type:\n\n```ts\n// Return type of useAwesome is Awesome | null\nconst { use: useAwesome } = createContext<Awesome>()\n```\n\n## Async Context\n\nNormally, using context is only possible before first await statement:\n\n```js\nasync function setup() {\n console.log(useAwesome()) // Returns context\n await new Promise(resolve => setTimeout(resolve, 1000))\n console.log(useAwesome()) // Returns null\n}\n```\n\nA simple workaround, is caching context before first await and use it directly:\n\n```js\nasync function setup() {\n const ctx = useAwesome()\n await new Promise(resolve => setTimeout(resolve, 1000))\n console.log(ctx) // We can directly access cached version of ctx\n}\n```\n\nHowever, this is not always as easy as making a variable when using nested composables.\n\nUnctx provides a better solution that transforms async to automatically restore context after each await call. This requires using a bundler such as Rollup, Vite or Webpack.\n\nImport and register transform plugin:\n\n```js\nimport { unctxPlugin } from 'unctx/plugin'\n\n// Rollup\n// TODO: Add to rollup configuration\nunctxPlugin.rollup()\n\n// Vite\n// TODO: Add to vite configuration\nunctxPlugin.vite()\n\n// Webpack\n// TODO: Add to webpack configuration\nunctxPlugin.webpack()\n```\n\nUse `ctx.callAsync` instead of `ctx.call`:\n\n```js\nawait ctx.callAsync('test', setup)\n```\n\nAny async function that requires context, should be wrapped with `withAsyncContext`:\n\n```js\nimport { withAsyncContext } from 'unctx'\n\nconst setup = withAsyncContext(async () => {\n console.log(useAwesome()) // Returns context\n await new Promise(resolve => setTimeout(resolve, 1000))\n console.log(useAwesome()) // Still returns context with dark magic!\n})\n```\n\n## Under the hood\n\nComposition of functions is possible using temporary context injection. When calling `ctx.call(instance, cb)`, `instance` argument will be stored in a temporary variable then `cb` is called. Any function inside `cb`, can then implicitly access instance by using `ctx.use` (or `useAwesome`)\n\n## Pitfalls\n\n**context can be only used before first await**:\n\nPlease check Async context section.\n\n**`Context conflict` error**:\n\nIn your library, you should only keep one `call()` running at a time (unless calling with same reference for first argument)\n\nFor instance this makes an error:\n\n```js\nctx.call({ test: 1 }, () => {\n ctx.call({ test: 2 }, () => {\n // Throws error!\n })\n})\n```\n\n## License\n\nMIT. Made with 💖\n\n<!-- Refs -->\n[npm-v-src]: https://flat.badgen.net/npm/v/unctx/latest\n[npm-v-href]: https://npmjs.com/package/unctx\n\n[npm-dm-src]: https://flat.badgen.net/npm/dm/unctx\n[npm-dm-href]: https://npmjs.com/package/unctx\n\n[packagephobia-src]: https://flat.badgen.net/packagephobia/install/unctx\n[packagephobia-href]: https://packagephobia.now.sh/result?p=unctx\n\n[bundlephobia-src]: https://flat.badgen.net/bundlephobia/min/unctx\n[bundlephobia-href]: https://bundlephobia.com/result?p=unctx\n\n[codecov-src]: https://flat.badgen.net/codecov/c/github/unjs/unctx/master\n[codecov-href]: https://codecov.io/gh/unjs/unctx\n" | ||
} | ||
} |
@@ -50,2 +50,4 @@ # 🍦 unctx | ||
**Note:** when no context is presented `ctx.use` will throw an error. Use `ctx.tryUse` for tolerant usages (return nullable context). | ||
## Using Namespaces | ||
@@ -84,3 +86,3 @@ | ||
## Typescript | ||
## TypeScript | ||
@@ -87,0 +89,0 @@ A generic type exists on all utilities to be set for instance/context type: |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
546
7.06%199
1.02%25453
-15.71%11
22.22%+ Added
+ Added
+ Added
- Removed
- Removed
Updated
Updated
Updated
Updated