Skip to content

Commit c005dbe

Browse files
committed
feat: add skills at the root directory for skills cli
1 parent 532acd2 commit c005dbe

File tree

271 files changed

+27042
-11
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

271 files changed

+27042
-11
lines changed

.vscode/settings.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,12 @@
2424
],
2525
"typescript.tsdk": "node_modules/typescript/lib",
2626

27+
"search.exclude": {
28+
"**/node_modules": true,
29+
"**/dist": true,
30+
"**/skills": true
31+
},
32+
2733
// Enable the flat config support
2834
"eslint.useFlatConfig": true,
2935

eslint.config.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@ export default antfu(
3838
ignores: [
3939
'patches',
4040
'playgrounds',
41+
'**/skills/**',
4142
'**/types',
4243
'**/cache',
4344
'**/*.svg',

packages/skills/README.md

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,17 @@ First, add a `prepare` script to your `package.json` so the skills are symlinked
3030
Then, install both `skills-npm` and `@vueuse/skills`:
3131

3232
```bash
33-
npm i -D skills-npm
34-
npm i -D @vueuse/skills
33+
npm i -D @vueuse/skills skills-npm
3534
```
3635

36+
## Install via [skills](https://github.com/vercel-labs/skills)
37+
38+
```bash
39+
npx skills add vueuse/vueuse
40+
```
41+
42+
Install skills via [skills](https://github.com/vercel-labs/skills) you need to be careful about the potential version mismatch between the skill and your local VueUse version.
43+
3744
## Example Usage
3845

3946
Install VueUse in your Vue or Nuxt project, then instruct the agent. It will automatically leverage VueUse to assist development.

packages/skills/build.ts

Lines changed: 14 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/* eslint-disable no-console */
2-
import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
2+
import { cpSync, existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs'
33
import path from 'node:path'
44
import { fileURLToPath } from 'node:url'
55
import * as metadata from '@vueuse/metadata'
@@ -13,12 +13,13 @@ interface FunctionReference {
1313
reference: string
1414
}
1515

16-
const __dirname = fileURLToPath(new URL('.', import.meta.url))
16+
const r = (path: string) => fileURLToPath(new URL(path, import.meta.url))
1717

18-
const SKILL_DIR = path.join(__dirname, './skills/vueuse-functions')
18+
const SKILL_DIR = r('./skills/vueuse-functions')
19+
const SKILL_COPY_DIR = r('../../skills/vueuse-functions')
1920
const SKILL_REFERENCE_DIR = './references'
20-
const SKILLS_TEMPLATE_PATH = path.join(__dirname, './templates/vueuse-functions-skills.md')
21-
const VUEUSE_ROOT = path.join(__dirname, '../..')
21+
const SKILLS_TEMPLATE_PATH = r('./templates/vueuse-functions-skills.md')
22+
const VUEUSE_ROOT = r('../..')
2223

2324
const EXPLICIT_ONLY_FUNCTIONS = new Set([
2425
'get',
@@ -38,6 +39,10 @@ const EXPLICIT_ONLY_FUNCTIONS = new Set([
3839
writeFileSync(outputPath, templateContent)
3940

4041
console.log(`Generated skills documentation at: ${outputPath}`)
42+
43+
// Copy to project root skills directory
44+
cpSync(SKILL_DIR, SKILL_COPY_DIR, { recursive: true, force: true })
45+
console.log(`Copied skills to: ${SKILL_COPY_DIR}`)
4146
})()
4247

4348
// Utils
@@ -47,13 +52,13 @@ async function prepareFunctionReferences(outDir: string, referenceDir = SKILL_RE
4752

4853
const categories: Record<string, FunctionReference[]> = {}
4954

50-
for (const catagory of metadata.categoryNames) {
51-
if (catagory.startsWith('_'))
55+
for (const category of metadata.categoryNames) {
56+
if (category.startsWith('_'))
5257
continue
5358

5459
const refs: FunctionReference[] = []
5560

56-
const functions = metadata.functions.filter(i => i.category === catagory && !i.internal)
61+
const functions = metadata.functions.filter(i => i.category === category && !i.internal)
5762
for (const fn of functions) {
5863
const description = toTitleCase(fn.description?.replace(/\|/g, '\\|') ?? '')
5964

@@ -74,7 +79,7 @@ async function prepareFunctionReferences(outDir: string, referenceDir = SKILL_RE
7479
}
7580
}
7681

77-
categories[catagory] = refs
82+
categories[category] = refs
7883
}
7984
return categories
8085
}

skills/README.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
For contributors: Skills are auto-generated by the `build.ts` script in the `packages/skills` folder.
2+
3+
DO NOT manually edit the skills files.

skills/vueuse-functions/SKILL.md

Lines changed: 419 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 195 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,195 @@
1+
---
2+
category: Reactivity
3+
alias: asyncComputed
4+
---
5+
6+
# computedAsync
7+
8+
Computed for async functions.
9+
10+
## Usage
11+
12+
```ts
13+
import { computedAsync } from '@vueuse/core'
14+
import { shallowRef } from 'vue'
15+
16+
const name = shallowRef('jack')
17+
18+
const userInfo = computedAsync(
19+
async () => {
20+
return await mockLookUp(name.value)
21+
},
22+
null, // initial state
23+
)
24+
```
25+
26+
### Evaluation State
27+
28+
Pass a ref to track if the async function is currently evaluating.
29+
30+
```ts
31+
import { computedAsync } from '@vueuse/core'
32+
import { shallowRef } from 'vue'
33+
34+
const evaluating = shallowRef(false)
35+
36+
const userInfo = computedAsync(
37+
async () => { /* your logic */ },
38+
null,
39+
evaluating, // can also be passed via options: { evaluating }
40+
)
41+
```
42+
43+
### onCancel
44+
45+
When the computed source changes before the previous async function resolves, you may want to cancel the previous one. Here is an example showing how to incorporate with the fetch API.
46+
47+
```ts
48+
import { computedAsync } from '@vueuse/core'
49+
import { shallowRef } from 'vue'
50+
51+
const packageName = shallowRef('@vueuse/core')
52+
53+
const downloads = computedAsync(async (onCancel) => {
54+
const abortController = new AbortController()
55+
56+
onCancel(() => abortController.abort())
57+
58+
return await fetch(
59+
`https://api.npmjs.org/downloads/point/last-week/${packageName.value}`,
60+
{ signal: abortController.signal },
61+
)
62+
.then(response => response.ok ? response.json() : { downloads: '' })
63+
.then(result => result.downloads)
64+
}, 0)
65+
```
66+
67+
### Lazy
68+
69+
By default, `computedAsync` will start resolving immediately on creation. Specify `lazy: true` to make it start resolving on the first access.
70+
71+
```ts
72+
import { computedAsync } from '@vueuse/core'
73+
import { shallowRef } from 'vue'
74+
75+
const evaluating = shallowRef(false)
76+
77+
const userInfo = computedAsync(
78+
async () => { /* your logic */ },
79+
null,
80+
{ lazy: true, evaluating },
81+
)
82+
```
83+
84+
### Error Handling
85+
86+
Use the `onError` callback to handle errors from the async function.
87+
88+
```ts
89+
import { computedAsync } from '@vueuse/core'
90+
import { shallowRef } from 'vue'
91+
92+
const name = shallowRef('jack')
93+
94+
const userInfo = computedAsync(
95+
async () => {
96+
return await mockLookUp(name.value)
97+
},
98+
null,
99+
{
100+
onError(e) {
101+
console.error('Failed to fetch user info', e)
102+
},
103+
},
104+
)
105+
```
106+
107+
### Shallow Ref
108+
109+
By default, `computedAsync` uses `shallowRef` internally. Set `shallow: false` to use a deep ref instead.
110+
111+
```ts
112+
import { computedAsync } from '@vueuse/core'
113+
import { shallowRef } from 'vue'
114+
115+
const name = shallowRef('jack')
116+
117+
const userInfo = computedAsync(
118+
async () => {
119+
return await fetchNestedData(name.value)
120+
},
121+
null,
122+
{ shallow: false }, // enables deep reactivity
123+
)
124+
```
125+
126+
## Caveats
127+
128+
- Just like Vue's built-in `computed` function, `computedAsync` does dependency tracking and is automatically re-evaluated when dependencies change. Note however that only dependencies referenced in the first call stack are considered for this. In other words: **Dependencies that are accessed asynchronously will not trigger re-evaluation of the async computed value.**
129+
130+
- As opposed to Vue's built-in `computed` function, re-evaluation of the async computed value is triggered whenever dependencies are changing, regardless of whether its result is currently being tracked or not.
131+
132+
## Type Declarations
133+
134+
```ts
135+
/**
136+
* Handle overlapping async evaluations.
137+
*
138+
* @param cancelCallback The provided callback is invoked when a re-evaluation of the computed value is triggered before the previous one finished
139+
*/
140+
export type AsyncComputedOnCancel = (cancelCallback: Fn) => void
141+
export interface AsyncComputedOptions<
142+
Lazy = boolean,
143+
> extends ConfigurableFlushSync {
144+
/**
145+
* Should value be evaluated lazily
146+
*
147+
* @default false
148+
*/
149+
lazy?: Lazy
150+
/**
151+
* Ref passed to receive the updated of async evaluation
152+
*/
153+
evaluating?: Ref<boolean>
154+
/**
155+
* Use shallowRef
156+
*
157+
* @default true
158+
*/
159+
shallow?: boolean
160+
/**
161+
* Callback when error is caught.
162+
*/
163+
onError?: (e: unknown) => void
164+
}
165+
/**
166+
* Create an asynchronous computed dependency.
167+
*
168+
* @see https://vueuse.org/computedAsync
169+
* @param evaluationCallback The promise-returning callback which generates the computed value
170+
* @param initialState The initial state, used until the first evaluation finishes
171+
* @param optionsOrRef Additional options or a ref passed to receive the updates of the async evaluation
172+
*/
173+
export declare function computedAsync<T>(
174+
evaluationCallback: (onCancel: AsyncComputedOnCancel) => T | Promise<T>,
175+
initialState: T,
176+
optionsOrRef: AsyncComputedOptions<true>,
177+
): ComputedRef<T>
178+
export declare function computedAsync<T>(
179+
evaluationCallback: (onCancel: AsyncComputedOnCancel) => T | Promise<T>,
180+
initialState: undefined,
181+
optionsOrRef: AsyncComputedOptions<true>,
182+
): ComputedRef<T | undefined>
183+
export declare function computedAsync<T>(
184+
evaluationCallback: (onCancel: AsyncComputedOnCancel) => T | Promise<T>,
185+
initialState: T,
186+
optionsOrRef?: Ref<boolean> | AsyncComputedOptions,
187+
): Ref<T>
188+
export declare function computedAsync<T>(
189+
evaluationCallback: (onCancel: AsyncComputedOnCancel) => T | Promise<T>,
190+
initialState?: undefined,
191+
optionsOrRef?: Ref<boolean> | AsyncComputedOptions,
192+
): Ref<T | undefined>
193+
/** @deprecated use `computedAsync` instead */
194+
export declare const asyncComputed: typeof computedAsync
195+
```
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
---
2+
category: Reactivity
3+
alias: eagerComputed
4+
---
5+
6+
# computedEager
7+
8+
Eager computed without lazy evaluation.
9+
10+
::: info
11+
This function will be removed in future version.
12+
:::
13+
14+
::: tip
15+
Note💡: If you are using Vue 3.4+, you can use `computed` right away, you no longer need this function.
16+
In Vue 3.4+, if the computed new value does not change, `computed`, `effect`, `watch`, `watchEffect`, `render` dependencies will not be triggered.
17+
See: https://github.com/vuejs/core/pull/5912
18+
:::
19+
20+
Learn more at [Vue: When a computed property can be the wrong tool](https://dev.to/linusborg/vue-when-a-computed-property-can-be-the-wrong-tool-195j).
21+
22+
- Use `computed()` when you have a complex calculation going on, which can actually profit from caching and lazy evaluation and should only be (re-)calculated if really necessary.
23+
- Use `computedEager()` when you have a simple operation, with a rarely changing return value – often a boolean.
24+
25+
## Usage
26+
27+
```ts
28+
import { computedEager } from '@vueuse/core'
29+
30+
const todos = ref([])
31+
const hasOpenTodos = computedEager(() => !!todos.length)
32+
33+
console.log(hasOpenTodos.value) // false
34+
toTodos.value.push({ title: 'Learn Vue' })
35+
console.log(hasOpenTodos.value) // true
36+
```
37+
38+
## Type Declarations
39+
40+
```ts
41+
export type ComputedEagerOptions = WatchOptionsBase
42+
export type ComputedEagerReturn<T = any> = Readonly<ShallowRef<T>>
43+
/**
44+
*
45+
* @deprecated This function will be removed in future version.
46+
*
47+
* Note: If you are using Vue 3.4+, you can straight use computed instead.
48+
* Because in Vue 3.4+, if computed new value does not change,
49+
* computed, effect, watch, watchEffect, render dependencies will not be triggered.
50+
* refer: https://github.com/vuejs/core/pull/5912
51+
*
52+
* @param fn effect function
53+
* @param options WatchOptionsBase
54+
* @returns readonly shallowRef
55+
*/
56+
export declare function computedEager<T>(
57+
fn: () => T,
58+
options?: ComputedEagerOptions,
59+
): ComputedEagerReturn<T>
60+
/** @deprecated use `computedEager` instead */
61+
export declare const eagerComputed: typeof computedEager
62+
```

0 commit comments

Comments
 (0)