Website Structure

This commit is contained in:
supalerk-ar66 2026-01-13 10:46:40 +07:00
parent 62812f2090
commit 71f0676a62
22365 changed files with 4265753 additions and 791 deletions

21
Frontend-Learner/node_modules/unctx/LICENSE generated vendored Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2022 - Pooya Parsa <pooya@pi0.io>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

225
Frontend-Learner/node_modules/unctx/README.md generated vendored Normal file
View file

@ -0,0 +1,225 @@
# 🍦 unctx
> Composition-API in Vanilla js
[![npm version][npm-v-src]][npm-v-href]
[![npm downloads][npm-dm-src]][npm-dm-href]
[![package phobia][packagephobia-src]][packagephobia-href]
[![bundle phobia][bundlephobia-src]][bundlephobia-href]
[![codecov][codecov-src]][codecov-href]
## What is unctx?
[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.
## Usage
In your **awesome** library:
```bash
yarn add unctx
# or
npm install unctx
```
```js
import { createContext } from "unctx";
const ctx = createContext();
export const useAwesome = ctx.use;
// ...
ctx.call({ test: 1 }, () => {
// This is similar to the vue setup function
// Any function called here can use `useAwesome` to get { test: 1 }
});
```
User code:
```js
import { useAwesome } from "awesome-lib";
// ...
function setup() {
const ctx = useAwesome();
}
```
**Note:** When no context is presented `ctx.use` will throw an error. Use `ctx.tryUse` for tolerant usages (return nullable context).
### Using Namespaces
To avoid issues with multiple version of the 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 the key to avoid conflict with other js libraries. Using the npm package name is recommended. Using symbols has no effect since it still causes multiple context issues.
```js
import { useContext, getContext } from "unctx";
const useAwesome = useContext("awesome-lib");
// or
// const awesomeContext = getContext('awesome-lib')
```
You can also create your internal namespace with `createNamespace` utility for more advanced use cases.
## Async Context
Using context is only possible in non-async usages and only before the first await statement. This is to make sure context is not shared between concurrent calls.
```js
async function setup() {
console.log(useAwesome()); // Returns context
setTimeout(() => {
console.log(useAwesome());
}, 1); // Returns null
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log(useAwesome()); // Returns null
}
```
A simple workaround is caching context into a local variable:
```js
async function setup() {
const ctx = useAwesome(); // We can directly access cached version of ctx
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log(ctx);
}
```
This is not always an elegant and easy way by making a variable and passing it around. After all, this is the purpose of unctx to make sure context is magically available everywhere in composables!
### Native Async Context
Unctx supports Node.js [`AsyncLocalStorage`](https://nodejs.org/api/async_context.html#class-asynclocalstorage) as a native way to preserve and track async contexts. To enable this mode, you need to set `asyncContext: true` option and also provides an implementation for `AsyncLocalStorage` (or provide `globalThis.AsyncLocalStorage` polyfill).
See [tc39 proposal for async context](https://github.com/tc39/proposal-async-context) and [cloudflare docs](https://developers.cloudflare.com/workers/runtime-apis/nodejs/asynclocalstorage/) for relevant platform specific docs.
```ts
import { createContext } from "unctx";
import { AsyncLocalStorage } from "node:async_hooks";
const ctx = createContext({
asyncContext: true,
AsyncLocalStorage,
});
ctx.call("123", () => {
setTimeout(() => {
// Prints 123
console.log(ctx.use());
}, 100);
});
```
### Async Transform
Since native async context is not supported in all platforms yet, unctx provides a build-time solution that transforms async syntax to automatically restore context after each async/await statement. This requires using a bundler such as Rollup, Vite, or Webpack.
Import and register transform plugin:
```js
import { unctxPlugin } from "unctx/plugin";
// Rollup
// TODO: Add to rollup configuration
unctxPlugin.rollup();
// Vite
// TODO: Add to vite configuration
unctxPlugin.vite();
// Webpack
// TODO: Add to webpack configuration
unctxPlugin.webpack();
```
Use `ctx.callAsync` instead of `ctx.call`:
```js
await ctx.callAsync("test", setup);
```
**_NOTE:_** `callAsync` is not transformed by default. You need to add it to the plugin's `asyncFunctions: []` option to transform it.
Any async function that requires context, should be wrapped with `withAsyncContext`:
```js
import { withAsyncContext } from "unctx";
const setup = withAsyncContext(async () => {
console.log(useAwesome()); // Returns context
await new Promise((resolve) => setTimeout(resolve, 1000));
console.log(useAwesome()); // Still returns context with dark magic!
});
```
## Singleton Pattern
If 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).
**Note:** You cannot combine `set` with `call`. Always use `unset` before replacing the instance otherwise you will get `Context conflict` error.
```js
import { createContext } from "unctx";
const ctx = createContext();
ctx.set(new Awesome());
// Replacing instance without unset
// ctx.set(new Awesome(), true)
export const useAwesome = ctx.use;
```
## Typed Context
A generic type exists on all utilities to be set for instance/context type for typescript support.
```ts
// Return type of useAwesome is Awesome | null
const { use: useAwesome } = createContext<Awesome>();
```
## Under the hood
The composition 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 the instance by using `ctx.use` (or `useAwesome`)
## Pitfalls
**context can be only used before first await**:
Please check [Async Context](#async-context) section.
**`Context conflict` error**:
In your library, you should only keep one `call()` running at a time (unless calling with the same reference for the first argument)
For instance, this makes an error:
```js
ctx.call({ test: 1 }, () => {
ctx.call({ test: 2 }, () => {
// Throws error!
});
});
```
## License
MIT. Made with 💖
<!-- Refs -->
[npm-v-src]: https://flat.badgen.net/npm/v/unctx/latest
[npm-v-href]: https://npmjs.com/package/unctx
[npm-dm-src]: https://flat.badgen.net/npm/dm/unctx
[npm-dm-href]: https://npmjs.com/package/unctx
[packagephobia-src]: https://flat.badgen.net/packagephobia/install/unctx
[packagephobia-href]: https://packagephobia.now.sh/result?p=unctx
[bundlephobia-src]: https://flat.badgen.net/bundlephobia/min/unctx
[bundlephobia-href]: https://bundlephobia.com/result?p=unctx
[codecov-src]: https://flat.badgen.net/codecov/c/github/unjs/unctx/master
[codecov-href]: https://codecov.io/gh/unjs/unctx

139
Frontend-Learner/node_modules/unctx/dist/index.cjs generated vendored Normal file
View file

@ -0,0 +1,139 @@
'use strict';
function createContext(opts = {}) {
let currentInstance;
let isSingleton = false;
const checkConflict = (instance) => {
if (currentInstance && currentInstance !== instance) {
throw new Error("Context conflict");
}
};
let als;
if (opts.asyncContext) {
const _AsyncLocalStorage = opts.AsyncLocalStorage || globalThis.AsyncLocalStorage;
if (_AsyncLocalStorage) {
als = new _AsyncLocalStorage();
} else {
console.warn("[unctx] `AsyncLocalStorage` is not provided.");
}
}
const _getCurrentInstance = () => {
if (als) {
const instance = als.getStore();
if (instance !== void 0) {
return instance;
}
}
return currentInstance;
};
return {
use: () => {
const _instance = _getCurrentInstance();
if (_instance === void 0) {
throw new Error("Context is not available");
}
return _instance;
},
tryUse: () => {
return _getCurrentInstance();
},
set: (instance, replace) => {
if (!replace) {
checkConflict(instance);
}
currentInstance = instance;
isSingleton = true;
},
unset: () => {
currentInstance = void 0;
isSingleton = false;
},
call: (instance, callback) => {
checkConflict(instance);
currentInstance = instance;
try {
return als ? als.run(instance, callback) : callback();
} finally {
if (!isSingleton) {
currentInstance = void 0;
}
}
},
async callAsync(instance, callback) {
currentInstance = instance;
const onRestore = () => {
currentInstance = instance;
};
const onLeave = () => currentInstance === instance ? onRestore : void 0;
asyncHandlers.add(onLeave);
try {
const r = als ? als.run(instance, callback) : callback();
if (!isSingleton) {
currentInstance = void 0;
}
return await r;
} finally {
asyncHandlers.delete(onLeave);
}
}
};
}
function createNamespace(defaultOpts = {}) {
const contexts = {};
return {
get(key, opts = {}) {
if (!contexts[key]) {
contexts[key] = createContext({ ...defaultOpts, ...opts });
}
return contexts[key];
}
};
}
const _globalThis = typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : typeof window !== "undefined" ? window : {};
const globalKey = "__unctx__";
const defaultNamespace = _globalThis[globalKey] || (_globalThis[globalKey] = createNamespace());
const getContext = (key, opts = {}) => defaultNamespace.get(key, opts);
const useContext = (key, opts = {}) => getContext(key, opts).use;
const asyncHandlersKey = "__unctx_async_handlers__";
const asyncHandlers = _globalThis[asyncHandlersKey] || (_globalThis[asyncHandlersKey] = /* @__PURE__ */ new Set());
function executeAsync(function_) {
const restores = [];
for (const leaveHandler of asyncHandlers) {
const restore2 = leaveHandler();
if (restore2) {
restores.push(restore2);
}
}
const restore = () => {
for (const restore2 of restores) {
restore2();
}
};
let awaitable = function_();
if (awaitable && typeof awaitable === "object" && "catch" in awaitable) {
awaitable = awaitable.catch((error) => {
restore();
throw error;
});
}
return [awaitable, restore];
}
function withAsyncContext(function_, transformed) {
if (!transformed) {
console.warn(
"[unctx] `withAsyncContext` needs transformation for async context support in",
function_,
"\n",
function_.toString()
);
}
return function_;
}
exports.createContext = createContext;
exports.createNamespace = createNamespace;
exports.defaultNamespace = defaultNamespace;
exports.executeAsync = executeAsync;
exports.getContext = getContext;
exports.useContext = useContext;
exports.withAsyncContext = withAsyncContext;

49
Frontend-Learner/node_modules/unctx/dist/index.d.cts generated vendored Normal file
View file

@ -0,0 +1,49 @@
import { AsyncLocalStorage } from 'node:async_hooks';
interface UseContext<T> {
/**
* 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, callback: () => R) => R;
/**
* Exclude an asynchronous function with the provided context.
* Requires installing the transform plugin to work properly.
*/
callAsync: <R>(instance: T, callback: () => R | Promise<R>) => Promise<R>;
}
interface ContextOptions {
asyncContext?: boolean;
AsyncLocalStorage?: typeof AsyncLocalStorage;
}
declare function createContext<T = any>(opts?: ContextOptions): UseContext<T>;
interface ContextNamespace {
get: <T>(key: string, opts?: ContextOptions) => UseContext<T>;
}
declare function createNamespace<T = any>(defaultOpts?: ContextOptions): {
get(key: string, opts?: ContextOptions): UseContext<T>;
};
declare const defaultNamespace: ContextNamespace;
declare const getContext: <T>(key: string, opts?: ContextOptions) => UseContext<T>;
declare const useContext: <T>(key: string, opts?: ContextOptions) => () => T;
type AsyncFunction<T> = () => Promise<T>;
declare function executeAsync<T>(function_: AsyncFunction<T>): [Promise<T>, () => void];
declare function withAsyncContext<T = any>(function_: AsyncFunction<T>, transformed?: boolean): AsyncFunction<T>;
export { createContext, createNamespace, defaultNamespace, executeAsync, getContext, useContext, withAsyncContext };
export type { ContextNamespace, ContextOptions, UseContext };

49
Frontend-Learner/node_modules/unctx/dist/index.d.mts generated vendored Normal file
View file

@ -0,0 +1,49 @@
import { AsyncLocalStorage } from 'node:async_hooks';
interface UseContext<T> {
/**
* 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, callback: () => R) => R;
/**
* Exclude an asynchronous function with the provided context.
* Requires installing the transform plugin to work properly.
*/
callAsync: <R>(instance: T, callback: () => R | Promise<R>) => Promise<R>;
}
interface ContextOptions {
asyncContext?: boolean;
AsyncLocalStorage?: typeof AsyncLocalStorage;
}
declare function createContext<T = any>(opts?: ContextOptions): UseContext<T>;
interface ContextNamespace {
get: <T>(key: string, opts?: ContextOptions) => UseContext<T>;
}
declare function createNamespace<T = any>(defaultOpts?: ContextOptions): {
get(key: string, opts?: ContextOptions): UseContext<T>;
};
declare const defaultNamespace: ContextNamespace;
declare const getContext: <T>(key: string, opts?: ContextOptions) => UseContext<T>;
declare const useContext: <T>(key: string, opts?: ContextOptions) => () => T;
type AsyncFunction<T> = () => Promise<T>;
declare function executeAsync<T>(function_: AsyncFunction<T>): [Promise<T>, () => void];
declare function withAsyncContext<T = any>(function_: AsyncFunction<T>, transformed?: boolean): AsyncFunction<T>;
export { createContext, createNamespace, defaultNamespace, executeAsync, getContext, useContext, withAsyncContext };
export type { ContextNamespace, ContextOptions, UseContext };

49
Frontend-Learner/node_modules/unctx/dist/index.d.ts generated vendored Normal file
View file

@ -0,0 +1,49 @@
import { AsyncLocalStorage } from 'node:async_hooks';
interface UseContext<T> {
/**
* 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, callback: () => R) => R;
/**
* Exclude an asynchronous function with the provided context.
* Requires installing the transform plugin to work properly.
*/
callAsync: <R>(instance: T, callback: () => R | Promise<R>) => Promise<R>;
}
interface ContextOptions {
asyncContext?: boolean;
AsyncLocalStorage?: typeof AsyncLocalStorage;
}
declare function createContext<T = any>(opts?: ContextOptions): UseContext<T>;
interface ContextNamespace {
get: <T>(key: string, opts?: ContextOptions) => UseContext<T>;
}
declare function createNamespace<T = any>(defaultOpts?: ContextOptions): {
get(key: string, opts?: ContextOptions): UseContext<T>;
};
declare const defaultNamespace: ContextNamespace;
declare const getContext: <T>(key: string, opts?: ContextOptions) => UseContext<T>;
declare const useContext: <T>(key: string, opts?: ContextOptions) => () => T;
type AsyncFunction<T> = () => Promise<T>;
declare function executeAsync<T>(function_: AsyncFunction<T>): [Promise<T>, () => void];
declare function withAsyncContext<T = any>(function_: AsyncFunction<T>, transformed?: boolean): AsyncFunction<T>;
export { createContext, createNamespace, defaultNamespace, executeAsync, getContext, useContext, withAsyncContext };
export type { ContextNamespace, ContextOptions, UseContext };

131
Frontend-Learner/node_modules/unctx/dist/index.mjs generated vendored Normal file
View file

@ -0,0 +1,131 @@
function createContext(opts = {}) {
let currentInstance;
let isSingleton = false;
const checkConflict = (instance) => {
if (currentInstance && currentInstance !== instance) {
throw new Error("Context conflict");
}
};
let als;
if (opts.asyncContext) {
const _AsyncLocalStorage = opts.AsyncLocalStorage || globalThis.AsyncLocalStorage;
if (_AsyncLocalStorage) {
als = new _AsyncLocalStorage();
} else {
console.warn("[unctx] `AsyncLocalStorage` is not provided.");
}
}
const _getCurrentInstance = () => {
if (als) {
const instance = als.getStore();
if (instance !== void 0) {
return instance;
}
}
return currentInstance;
};
return {
use: () => {
const _instance = _getCurrentInstance();
if (_instance === void 0) {
throw new Error("Context is not available");
}
return _instance;
},
tryUse: () => {
return _getCurrentInstance();
},
set: (instance, replace) => {
if (!replace) {
checkConflict(instance);
}
currentInstance = instance;
isSingleton = true;
},
unset: () => {
currentInstance = void 0;
isSingleton = false;
},
call: (instance, callback) => {
checkConflict(instance);
currentInstance = instance;
try {
return als ? als.run(instance, callback) : callback();
} finally {
if (!isSingleton) {
currentInstance = void 0;
}
}
},
async callAsync(instance, callback) {
currentInstance = instance;
const onRestore = () => {
currentInstance = instance;
};
const onLeave = () => currentInstance === instance ? onRestore : void 0;
asyncHandlers.add(onLeave);
try {
const r = als ? als.run(instance, callback) : callback();
if (!isSingleton) {
currentInstance = void 0;
}
return await r;
} finally {
asyncHandlers.delete(onLeave);
}
}
};
}
function createNamespace(defaultOpts = {}) {
const contexts = {};
return {
get(key, opts = {}) {
if (!contexts[key]) {
contexts[key] = createContext({ ...defaultOpts, ...opts });
}
return contexts[key];
}
};
}
const _globalThis = typeof globalThis !== "undefined" ? globalThis : typeof self !== "undefined" ? self : typeof global !== "undefined" ? global : typeof window !== "undefined" ? window : {};
const globalKey = "__unctx__";
const defaultNamespace = _globalThis[globalKey] || (_globalThis[globalKey] = createNamespace());
const getContext = (key, opts = {}) => defaultNamespace.get(key, opts);
const useContext = (key, opts = {}) => getContext(key, opts).use;
const asyncHandlersKey = "__unctx_async_handlers__";
const asyncHandlers = _globalThis[asyncHandlersKey] || (_globalThis[asyncHandlersKey] = /* @__PURE__ */ new Set());
function executeAsync(function_) {
const restores = [];
for (const leaveHandler of asyncHandlers) {
const restore2 = leaveHandler();
if (restore2) {
restores.push(restore2);
}
}
const restore = () => {
for (const restore2 of restores) {
restore2();
}
};
let awaitable = function_();
if (awaitable && typeof awaitable === "object" && "catch" in awaitable) {
awaitable = awaitable.catch((error) => {
restore();
throw error;
});
}
return [awaitable, restore];
}
function withAsyncContext(function_, transformed) {
if (!transformed) {
console.warn(
"[unctx] `withAsyncContext` needs transformation for async context support in",
function_,
"\n",
function_.toString()
);
}
return function_;
}
export { createContext, createNamespace, defaultNamespace, executeAsync, getContext, useContext, withAsyncContext };

35
Frontend-Learner/node_modules/unctx/dist/plugin.cjs generated vendored Normal file
View file

@ -0,0 +1,35 @@
'use strict';
const unplugin = require('unplugin');
const transform = require('./transform.cjs');
require('acorn');
require('magic-string');
require('estree-walker');
const unctxPlugin = unplugin.createUnplugin(
(options = {}) => {
const transformer = transform.createTransformer(options);
return {
name: "unctx:transform",
enforce: "post",
transformInclude: options.transformInclude,
transform: {
filter: options.transformFilter ?? transformer.filter,
handler(code, id) {
const result = transformer.transform(code);
if (result) {
return {
code: result.code,
map: result.magicString.generateMap({
source: id,
includeContent: true
})
};
}
}
}
};
}
);
exports.unctxPlugin = unctxPlugin;

17
Frontend-Learner/node_modules/unctx/dist/plugin.d.cts generated vendored Normal file
View file

@ -0,0 +1,17 @@
import * as unplugin from 'unplugin';
import { HookFilter } from 'unplugin';
import { TransformerOptions } from './transform.cjs';
import 'magic-string';
interface UnctxPluginOptions extends TransformerOptions {
/** Plugin Hook Filter for the transform hook
* @see https://unplugin.unjs.io/guide/#filters
*/
transformFilter?: HookFilter;
/** Function to determine whether a file should be transformed. If possible, use `transformFilter` instead for better performance. */
transformInclude?: (id: string) => boolean;
}
declare const unctxPlugin: unplugin.UnpluginInstance<UnctxPluginOptions, boolean>;
export { unctxPlugin };
export type { UnctxPluginOptions };

17
Frontend-Learner/node_modules/unctx/dist/plugin.d.mts generated vendored Normal file
View file

@ -0,0 +1,17 @@
import * as unplugin from 'unplugin';
import { HookFilter } from 'unplugin';
import { TransformerOptions } from './transform.mjs';
import 'magic-string';
interface UnctxPluginOptions extends TransformerOptions {
/** Plugin Hook Filter for the transform hook
* @see https://unplugin.unjs.io/guide/#filters
*/
transformFilter?: HookFilter;
/** Function to determine whether a file should be transformed. If possible, use `transformFilter` instead for better performance. */
transformInclude?: (id: string) => boolean;
}
declare const unctxPlugin: unplugin.UnpluginInstance<UnctxPluginOptions, boolean>;
export { unctxPlugin };
export type { UnctxPluginOptions };

17
Frontend-Learner/node_modules/unctx/dist/plugin.d.ts generated vendored Normal file
View file

@ -0,0 +1,17 @@
import * as unplugin from 'unplugin';
import { HookFilter } from 'unplugin';
import { TransformerOptions } from './transform.js';
import 'magic-string';
interface UnctxPluginOptions extends TransformerOptions {
/** Plugin Hook Filter for the transform hook
* @see https://unplugin.unjs.io/guide/#filters
*/
transformFilter?: HookFilter;
/** Function to determine whether a file should be transformed. If possible, use `transformFilter` instead for better performance. */
transformInclude?: (id: string) => boolean;
}
declare const unctxPlugin: unplugin.UnpluginInstance<UnctxPluginOptions, boolean>;
export { unctxPlugin };
export type { UnctxPluginOptions };

33
Frontend-Learner/node_modules/unctx/dist/plugin.mjs generated vendored Normal file
View file

@ -0,0 +1,33 @@
import { createUnplugin } from 'unplugin';
import { createTransformer } from './transform.mjs';
import 'acorn';
import 'magic-string';
import 'estree-walker';
const unctxPlugin = createUnplugin(
(options = {}) => {
const transformer = createTransformer(options);
return {
name: "unctx:transform",
enforce: "post",
transformInclude: options.transformInclude,
transform: {
filter: options.transformFilter ?? transformer.filter,
handler(code, id) {
const result = transformer.transform(code);
if (result) {
return {
code: result.code,
map: result.magicString.generateMap({
source: id,
includeContent: true
})
};
}
}
}
};
}
);
export { unctxPlugin };

171
Frontend-Learner/node_modules/unctx/dist/transform.cjs generated vendored Normal file
View file

@ -0,0 +1,171 @@
'use strict';
const acorn = require('acorn');
const MagicString = require('magic-string');
const estreeWalker = require('estree-walker');
function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
function _interopNamespaceCompat(e) {
if (e && typeof e === 'object' && 'default' in e) return e;
const n = Object.create(null);
if (e) {
for (const k in e) {
n[k] = e[k];
}
}
n.default = e;
return n;
}
const acorn__namespace = /*#__PURE__*/_interopNamespaceCompat(acorn);
const MagicString__default = /*#__PURE__*/_interopDefaultCompat(MagicString);
const kInjected = "__unctx_injected__";
function createTransformer(options = {}) {
options = {
asyncFunctions: ["withAsyncContext"],
helperModule: "unctx",
helperName: "executeAsync",
objectDefinitions: {},
...options
};
const objectDefinitionFunctions = Object.keys(options.objectDefinitions);
const matchRE = new RegExp(
`\\b(${[...options.asyncFunctions, ...objectDefinitionFunctions].join(
"|"
)})\\(`
);
function shouldTransform(code) {
return typeof code === "string" && matchRE.test(code);
}
const filter = {
code: matchRE
};
function transform(code, options_ = {}) {
if (!options_.force && !shouldTransform(code)) {
return;
}
const ast = acorn__namespace.parse(code, {
sourceType: "module",
ecmaVersion: "latest",
locations: true
});
const s = new MagicString__default(code);
const lines = code.split("\n");
let detected = false;
estreeWalker.walk(ast, {
enter(node) {
if (node.type === "CallExpression") {
const functionName = _getFunctionName(node.callee);
if (options.asyncFunctions.includes(functionName)) {
transformFunctionArguments(node);
if (functionName !== "callAsync") {
const lastArgument = node.arguments[node.arguments.length - 1];
if (lastArgument && lastArgument.loc) {
s.appendRight(toIndex(lastArgument.loc.end), ",1");
}
}
}
if (objectDefinitionFunctions.includes(functionName)) {
for (const argument of node.arguments) {
if (argument.type !== "ObjectExpression") {
continue;
}
for (const property of argument.properties) {
if (property.type !== "Property" || property.key.type !== "Identifier") {
continue;
}
if (options.objectDefinitions[functionName]?.includes(
property.key?.name
)) {
transformFunctionBody(property.value);
}
}
}
}
}
}
});
if (!detected) {
return;
}
s.appendLeft(
0,
`import { ${options.helperName} as __executeAsync } from "${options.helperModule}";`
);
return {
code: s.toString(),
magicString: s
};
function toIndex(pos) {
return lines.slice(0, pos.line - 1).join("\n").length + pos.column + 1;
}
function transformFunctionBody(function_) {
if (function_.type !== "ArrowFunctionExpression" && function_.type !== "FunctionExpression") {
return;
}
if (!function_.async) {
return;
}
const body = function_.body;
let injectVariable = false;
estreeWalker.walk(body, {
enter(node, parent) {
if (node.type === "AwaitExpression" && !node[kInjected]) {
detected = true;
injectVariable = true;
injectForNode(node, parent);
} else if (node.type === "IfStatement" && node.consequent.type === "ExpressionStatement" && node.consequent.expression.type === "AwaitExpression") {
detected = true;
injectVariable = true;
node.consequent.expression[kInjected] = true;
injectForNode(node.consequent.expression, node);
}
if (node.type === "ArrowFunctionExpression" || node.type === "FunctionExpression" || node.type === "FunctionDeclaration") {
return this.skip();
}
}
});
if (injectVariable && body.loc) {
s.appendLeft(toIndex(body.loc.start) + 1, "let __temp, __restore;");
}
}
function transformFunctionArguments(node) {
for (const function_ of node.arguments) {
transformFunctionBody(function_);
}
}
function injectForNode(node, parent) {
const isStatement = parent?.type === "ExpressionStatement";
if (!node.loc || !node.argument.loc) {
return;
}
s.remove(toIndex(node.loc.start), toIndex(node.argument.loc.start));
s.remove(toIndex(node.loc.end), toIndex(node.argument.loc.end));
s.appendLeft(
toIndex(node.argument.loc.start),
isStatement ? `;(([__temp,__restore]=__executeAsync(()=>` : `(([__temp,__restore]=__executeAsync(()=>`
);
s.appendRight(
toIndex(node.argument.loc.end),
isStatement ? `)),await __temp,__restore());` : `)),__temp=await __temp,__restore(),__temp)`
);
}
}
return {
transform,
filter,
shouldTransform
};
}
function _getFunctionName(node) {
if (node.type === "Identifier") {
return node.name;
} else if (node.type === "MemberExpression") {
return _getFunctionName(node.property);
}
return "";
}
exports.createTransformer = createTransformer;

View file

@ -0,0 +1,40 @@
import MagicString from 'magic-string';
interface TransformerOptions {
/**
* The function names to be transformed.
*
* @default ['withAsyncContext']
*/
asyncFunctions?: string[];
/**
* @default 'unctx'
*/
helperModule?: string;
/**
* @default 'executeAsync'
*/
helperName?: string;
/**
* Whether to transform properties of an object defined with a helper function. For example,
* to transform key `middleware` within the object defined with function `defineMeta`, you would pass:
* `{ defineMeta: ['middleware'] }`.
* @default {}
*/
objectDefinitions?: Record<string, string[]>;
}
declare function createTransformer(options?: TransformerOptions): {
transform: (code: string, options_?: {
force?: false;
}) => {
code: string;
magicString: MagicString;
} | undefined;
filter: {
code: RegExp;
};
shouldTransform: (code: string) => boolean;
};
export { createTransformer };
export type { TransformerOptions };

View file

@ -0,0 +1,40 @@
import MagicString from 'magic-string';
interface TransformerOptions {
/**
* The function names to be transformed.
*
* @default ['withAsyncContext']
*/
asyncFunctions?: string[];
/**
* @default 'unctx'
*/
helperModule?: string;
/**
* @default 'executeAsync'
*/
helperName?: string;
/**
* Whether to transform properties of an object defined with a helper function. For example,
* to transform key `middleware` within the object defined with function `defineMeta`, you would pass:
* `{ defineMeta: ['middleware'] }`.
* @default {}
*/
objectDefinitions?: Record<string, string[]>;
}
declare function createTransformer(options?: TransformerOptions): {
transform: (code: string, options_?: {
force?: false;
}) => {
code: string;
magicString: MagicString;
} | undefined;
filter: {
code: RegExp;
};
shouldTransform: (code: string) => boolean;
};
export { createTransformer };
export type { TransformerOptions };

View file

@ -0,0 +1,40 @@
import MagicString from 'magic-string';
interface TransformerOptions {
/**
* The function names to be transformed.
*
* @default ['withAsyncContext']
*/
asyncFunctions?: string[];
/**
* @default 'unctx'
*/
helperModule?: string;
/**
* @default 'executeAsync'
*/
helperName?: string;
/**
* Whether to transform properties of an object defined with a helper function. For example,
* to transform key `middleware` within the object defined with function `defineMeta`, you would pass:
* `{ defineMeta: ['middleware'] }`.
* @default {}
*/
objectDefinitions?: Record<string, string[]>;
}
declare function createTransformer(options?: TransformerOptions): {
transform: (code: string, options_?: {
force?: false;
}) => {
code: string;
magicString: MagicString;
} | undefined;
filter: {
code: RegExp;
};
shouldTransform: (code: string) => boolean;
};
export { createTransformer };
export type { TransformerOptions };

152
Frontend-Learner/node_modules/unctx/dist/transform.mjs generated vendored Normal file
View file

@ -0,0 +1,152 @@
import * as acorn from 'acorn';
import MagicString from 'magic-string';
import { walk } from 'estree-walker';
const kInjected = "__unctx_injected__";
function createTransformer(options = {}) {
options = {
asyncFunctions: ["withAsyncContext"],
helperModule: "unctx",
helperName: "executeAsync",
objectDefinitions: {},
...options
};
const objectDefinitionFunctions = Object.keys(options.objectDefinitions);
const matchRE = new RegExp(
`\\b(${[...options.asyncFunctions, ...objectDefinitionFunctions].join(
"|"
)})\\(`
);
function shouldTransform(code) {
return typeof code === "string" && matchRE.test(code);
}
const filter = {
code: matchRE
};
function transform(code, options_ = {}) {
if (!options_.force && !shouldTransform(code)) {
return;
}
const ast = acorn.parse(code, {
sourceType: "module",
ecmaVersion: "latest",
locations: true
});
const s = new MagicString(code);
const lines = code.split("\n");
let detected = false;
walk(ast, {
enter(node) {
if (node.type === "CallExpression") {
const functionName = _getFunctionName(node.callee);
if (options.asyncFunctions.includes(functionName)) {
transformFunctionArguments(node);
if (functionName !== "callAsync") {
const lastArgument = node.arguments[node.arguments.length - 1];
if (lastArgument && lastArgument.loc) {
s.appendRight(toIndex(lastArgument.loc.end), ",1");
}
}
}
if (objectDefinitionFunctions.includes(functionName)) {
for (const argument of node.arguments) {
if (argument.type !== "ObjectExpression") {
continue;
}
for (const property of argument.properties) {
if (property.type !== "Property" || property.key.type !== "Identifier") {
continue;
}
if (options.objectDefinitions[functionName]?.includes(
property.key?.name
)) {
transformFunctionBody(property.value);
}
}
}
}
}
}
});
if (!detected) {
return;
}
s.appendLeft(
0,
`import { ${options.helperName} as __executeAsync } from "${options.helperModule}";`
);
return {
code: s.toString(),
magicString: s
};
function toIndex(pos) {
return lines.slice(0, pos.line - 1).join("\n").length + pos.column + 1;
}
function transformFunctionBody(function_) {
if (function_.type !== "ArrowFunctionExpression" && function_.type !== "FunctionExpression") {
return;
}
if (!function_.async) {
return;
}
const body = function_.body;
let injectVariable = false;
walk(body, {
enter(node, parent) {
if (node.type === "AwaitExpression" && !node[kInjected]) {
detected = true;
injectVariable = true;
injectForNode(node, parent);
} else if (node.type === "IfStatement" && node.consequent.type === "ExpressionStatement" && node.consequent.expression.type === "AwaitExpression") {
detected = true;
injectVariable = true;
node.consequent.expression[kInjected] = true;
injectForNode(node.consequent.expression, node);
}
if (node.type === "ArrowFunctionExpression" || node.type === "FunctionExpression" || node.type === "FunctionDeclaration") {
return this.skip();
}
}
});
if (injectVariable && body.loc) {
s.appendLeft(toIndex(body.loc.start) + 1, "let __temp, __restore;");
}
}
function transformFunctionArguments(node) {
for (const function_ of node.arguments) {
transformFunctionBody(function_);
}
}
function injectForNode(node, parent) {
const isStatement = parent?.type === "ExpressionStatement";
if (!node.loc || !node.argument.loc) {
return;
}
s.remove(toIndex(node.loc.start), toIndex(node.argument.loc.start));
s.remove(toIndex(node.loc.end), toIndex(node.argument.loc.end));
s.appendLeft(
toIndex(node.argument.loc.start),
isStatement ? `;(([__temp,__restore]=__executeAsync(()=>` : `(([__temp,__restore]=__executeAsync(()=>`
);
s.appendRight(
toIndex(node.argument.loc.end),
isStatement ? `)),await __temp,__restore());` : `)),__temp=await __temp,__restore(),__temp)`
);
}
}
return {
transform,
filter,
shouldTransform
};
}
function _getFunctionName(node) {
if (node.type === "Identifier") {
return node.name;
} else if (node.type === "MemberExpression") {
return _getFunctionName(node.property);
}
return "";
}
export { createTransformer };

View file

@ -0,0 +1,7 @@
Copyright (c) 2015-20 [these people](https://github.com/Rich-Harris/estree-walker/graphs/contributors)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View file

@ -0,0 +1,48 @@
# estree-walker
Simple utility for walking an [ESTree](https://github.com/estree/estree)-compliant AST, such as one generated by [acorn](https://github.com/marijnh/acorn).
## Installation
```bash
npm i estree-walker
```
## Usage
```js
var walk = require('estree-walker').walk;
var acorn = require('acorn');
ast = acorn.parse(sourceCode, options); // https://github.com/acornjs/acorn
walk(ast, {
enter(node, parent, prop, index) {
// some code happens
},
leave(node, parent, prop, index) {
// some code happens
}
});
```
Inside the `enter` function, calling `this.skip()` will prevent the node's children being walked, or the `leave` function (which is optional) being called.
Call `this.replace(new_node)` in either `enter` or `leave` to replace the current node with a new one.
Call `this.remove()` in either `enter` or `leave` to remove the current node.
## Why not use estraverse?
The ESTree spec is evolving to accommodate ES6/7. I've had a couple of experiences where [estraverse](https://github.com/estools/estraverse) was unable to handle an AST generated by recent versions of acorn, because it hard-codes visitor keys.
estree-walker, by contrast, simply enumerates a node's properties to find child nodes (and child lists of nodes), and is therefore resistant to spec changes. It's also much smaller. (The performance, if you're wondering, is basically identical.)
None of which should be taken as criticism of estraverse, which has more features and has been battle-tested in many more situations, and for which I'm very grateful.
## License
MIT

View file

@ -0,0 +1,38 @@
{
"name": "estree-walker",
"description": "Traverse an ESTree-compliant AST",
"version": "3.0.3",
"private": false,
"author": "Rich Harris",
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/Rich-Harris/estree-walker"
},
"type": "module",
"module": "./src/index.js",
"exports": {
"./package.json": "./package.json",
".": {
"types": "./types/index.d.ts",
"import": "./src/index.js"
}
},
"types": "types/index.d.ts",
"scripts": {
"prepublishOnly": "tsc && npm test",
"test": "uvu test"
},
"dependencies": {
"@types/estree": "^1.0.0"
},
"devDependencies": {
"typescript": "^4.9.0",
"uvu": "^0.5.1"
},
"files": [
"src",
"types",
"README.md"
]
}

View file

@ -0,0 +1,152 @@
import { WalkerBase } from './walker.js';
/**
* @typedef { import('estree').Node} Node
* @typedef { import('./walker.js').WalkerContext} WalkerContext
* @typedef {(
* this: WalkerContext,
* node: Node,
* parent: Node | null,
* key: string | number | symbol | null | undefined,
* index: number | null | undefined
* ) => Promise<void>} AsyncHandler
*/
export class AsyncWalker extends WalkerBase {
/**
*
* @param {AsyncHandler} [enter]
* @param {AsyncHandler} [leave]
*/
constructor(enter, leave) {
super();
/** @type {boolean} */
this.should_skip = false;
/** @type {boolean} */
this.should_remove = false;
/** @type {Node | null} */
this.replacement = null;
/** @type {WalkerContext} */
this.context = {
skip: () => (this.should_skip = true),
remove: () => (this.should_remove = true),
replace: (node) => (this.replacement = node)
};
/** @type {AsyncHandler | undefined} */
this.enter = enter;
/** @type {AsyncHandler | undefined} */
this.leave = leave;
}
/**
* @template {Node} Parent
* @param {Node} node
* @param {Parent | null} parent
* @param {keyof Parent} [prop]
* @param {number | null} [index]
* @returns {Promise<Node | null>}
*/
async visit(node, parent, prop, index) {
if (node) {
if (this.enter) {
const _should_skip = this.should_skip;
const _should_remove = this.should_remove;
const _replacement = this.replacement;
this.should_skip = false;
this.should_remove = false;
this.replacement = null;
await this.enter.call(this.context, node, parent, prop, index);
if (this.replacement) {
node = this.replacement;
this.replace(parent, prop, index, node);
}
if (this.should_remove) {
this.remove(parent, prop, index);
}
const skipped = this.should_skip;
const removed = this.should_remove;
this.should_skip = _should_skip;
this.should_remove = _should_remove;
this.replacement = _replacement;
if (skipped) return node;
if (removed) return null;
}
/** @type {keyof Node} */
let key;
for (key in node) {
/** @type {unknown} */
const value = node[key];
if (value && typeof value === 'object') {
if (Array.isArray(value)) {
const nodes = /** @type {Array<unknown>} */ (value);
for (let i = 0; i < nodes.length; i += 1) {
const item = nodes[i];
if (isNode(item)) {
if (!(await this.visit(item, node, key, i))) {
// removed
i--;
}
}
}
} else if (isNode(value)) {
await this.visit(value, node, key, null);
}
}
}
if (this.leave) {
const _replacement = this.replacement;
const _should_remove = this.should_remove;
this.replacement = null;
this.should_remove = false;
await this.leave.call(this.context, node, parent, prop, index);
if (this.replacement) {
node = this.replacement;
this.replace(parent, prop, index, node);
}
if (this.should_remove) {
this.remove(parent, prop, index);
}
const removed = this.should_remove;
this.replacement = _replacement;
this.should_remove = _should_remove;
if (removed) return null;
}
}
return node;
}
}
/**
* Ducktype a node.
*
* @param {unknown} value
* @returns {value is Node}
*/
function isNode(value) {
return (
value !== null && typeof value === 'object' && 'type' in value && typeof value.type === 'string'
);
}

View file

@ -0,0 +1,34 @@
import { SyncWalker } from './sync.js';
import { AsyncWalker } from './async.js';
/**
* @typedef {import('estree').Node} Node
* @typedef {import('./sync.js').SyncHandler} SyncHandler
* @typedef {import('./async.js').AsyncHandler} AsyncHandler
*/
/**
* @param {Node} ast
* @param {{
* enter?: SyncHandler
* leave?: SyncHandler
* }} walker
* @returns {Node | null}
*/
export function walk(ast, { enter, leave }) {
const instance = new SyncWalker(enter, leave);
return instance.visit(ast, null);
}
/**
* @param {Node} ast
* @param {{
* enter?: AsyncHandler
* leave?: AsyncHandler
* }} walker
* @returns {Promise<Node | null>}
*/
export async function asyncWalk(ast, { enter, leave }) {
const instance = new AsyncWalker(enter, leave);
return await instance.visit(ast, null);
}

View file

@ -0,0 +1,152 @@
import { WalkerBase } from './walker.js';
/**
* @typedef { import('estree').Node} Node
* @typedef { import('./walker.js').WalkerContext} WalkerContext
* @typedef {(
* this: WalkerContext,
* node: Node,
* parent: Node | null,
* key: string | number | symbol | null | undefined,
* index: number | null | undefined
* ) => void} SyncHandler
*/
export class SyncWalker extends WalkerBase {
/**
*
* @param {SyncHandler} [enter]
* @param {SyncHandler} [leave]
*/
constructor(enter, leave) {
super();
/** @type {boolean} */
this.should_skip = false;
/** @type {boolean} */
this.should_remove = false;
/** @type {Node | null} */
this.replacement = null;
/** @type {WalkerContext} */
this.context = {
skip: () => (this.should_skip = true),
remove: () => (this.should_remove = true),
replace: (node) => (this.replacement = node)
};
/** @type {SyncHandler | undefined} */
this.enter = enter;
/** @type {SyncHandler | undefined} */
this.leave = leave;
}
/**
* @template {Node} Parent
* @param {Node} node
* @param {Parent | null} parent
* @param {keyof Parent} [prop]
* @param {number | null} [index]
* @returns {Node | null}
*/
visit(node, parent, prop, index) {
if (node) {
if (this.enter) {
const _should_skip = this.should_skip;
const _should_remove = this.should_remove;
const _replacement = this.replacement;
this.should_skip = false;
this.should_remove = false;
this.replacement = null;
this.enter.call(this.context, node, parent, prop, index);
if (this.replacement) {
node = this.replacement;
this.replace(parent, prop, index, node);
}
if (this.should_remove) {
this.remove(parent, prop, index);
}
const skipped = this.should_skip;
const removed = this.should_remove;
this.should_skip = _should_skip;
this.should_remove = _should_remove;
this.replacement = _replacement;
if (skipped) return node;
if (removed) return null;
}
/** @type {keyof Node} */
let key;
for (key in node) {
/** @type {unknown} */
const value = node[key];
if (value && typeof value === 'object') {
if (Array.isArray(value)) {
const nodes = /** @type {Array<unknown>} */ (value);
for (let i = 0; i < nodes.length; i += 1) {
const item = nodes[i];
if (isNode(item)) {
if (!this.visit(item, node, key, i)) {
// removed
i--;
}
}
}
} else if (isNode(value)) {
this.visit(value, node, key, null);
}
}
}
if (this.leave) {
const _replacement = this.replacement;
const _should_remove = this.should_remove;
this.replacement = null;
this.should_remove = false;
this.leave.call(this.context, node, parent, prop, index);
if (this.replacement) {
node = this.replacement;
this.replace(parent, prop, index, node);
}
if (this.should_remove) {
this.remove(parent, prop, index);
}
const removed = this.should_remove;
this.replacement = _replacement;
this.should_remove = _should_remove;
if (removed) return null;
}
}
return node;
}
}
/**
* Ducktype a node.
*
* @param {unknown} value
* @returns {value is Node}
*/
function isNode(value) {
return (
value !== null && typeof value === 'object' && 'type' in value && typeof value.type === 'string'
);
}

View file

@ -0,0 +1,61 @@
/**
* @typedef { import('estree').Node} Node
* @typedef {{
* skip: () => void;
* remove: () => void;
* replace: (node: Node) => void;
* }} WalkerContext
*/
export class WalkerBase {
constructor() {
/** @type {boolean} */
this.should_skip = false;
/** @type {boolean} */
this.should_remove = false;
/** @type {Node | null} */
this.replacement = null;
/** @type {WalkerContext} */
this.context = {
skip: () => (this.should_skip = true),
remove: () => (this.should_remove = true),
replace: (node) => (this.replacement = node)
};
}
/**
* @template {Node} Parent
* @param {Parent | null | undefined} parent
* @param {keyof Parent | null | undefined} prop
* @param {number | null | undefined} index
* @param {Node} node
*/
replace(parent, prop, index, node) {
if (parent && prop) {
if (index != null) {
/** @type {Array<Node>} */ (parent[prop])[index] = node;
} else {
/** @type {Node} */ (parent[prop]) = node;
}
}
}
/**
* @template {Node} Parent
* @param {Parent | null | undefined} parent
* @param {keyof Parent | null | undefined} prop
* @param {number | null | undefined} index
*/
remove(parent, prop, index) {
if (parent && prop) {
if (index !== null && index !== undefined) {
/** @type {Array<Node>} */ (parent[prop]).splice(index, 1);
} else {
delete parent[prop];
}
}
}
}

View file

@ -0,0 +1,36 @@
/**
* @typedef { import('estree').Node} Node
* @typedef { import('./walker.js').WalkerContext} WalkerContext
* @typedef {(
* this: WalkerContext,
* node: Node,
* parent: Node | null,
* key: string | number | symbol | null | undefined,
* index: number | null | undefined
* ) => Promise<void>} AsyncHandler
*/
export class AsyncWalker extends WalkerBase {
/**
*
* @param {AsyncHandler} [enter]
* @param {AsyncHandler} [leave]
*/
constructor(enter?: AsyncHandler | undefined, leave?: AsyncHandler | undefined);
/** @type {AsyncHandler | undefined} */
enter: AsyncHandler | undefined;
/** @type {AsyncHandler | undefined} */
leave: AsyncHandler | undefined;
/**
* @template {Node} Parent
* @param {Node} node
* @param {Parent | null} parent
* @param {keyof Parent} [prop]
* @param {number | null} [index]
* @returns {Promise<Node | null>}
*/
visit<Parent extends import("estree").Node>(node: Node, parent: Parent | null, prop?: keyof Parent | undefined, index?: number | null | undefined): Promise<Node | null>;
}
export type Node = import('estree').Node;
export type WalkerContext = import('./walker.js').WalkerContext;
export type AsyncHandler = (this: WalkerContext, node: Node, parent: Node | null, key: string | number | symbol | null | undefined, index: number | null | undefined) => Promise<void>;
import { WalkerBase } from "./walker.js";

View file

@ -0,0 +1,32 @@
/**
* @typedef {import('estree').Node} Node
* @typedef {import('./sync.js').SyncHandler} SyncHandler
* @typedef {import('./async.js').AsyncHandler} AsyncHandler
*/
/**
* @param {Node} ast
* @param {{
* enter?: SyncHandler
* leave?: SyncHandler
* }} walker
* @returns {Node | null}
*/
export function walk(ast: Node, { enter, leave }: {
enter?: SyncHandler;
leave?: SyncHandler;
}): Node | null;
/**
* @param {Node} ast
* @param {{
* enter?: AsyncHandler
* leave?: AsyncHandler
* }} walker
* @returns {Promise<Node | null>}
*/
export function asyncWalk(ast: Node, { enter, leave }: {
enter?: AsyncHandler;
leave?: AsyncHandler;
}): Promise<Node | null>;
export type Node = import('estree').Node;
export type SyncHandler = import('./sync.js').SyncHandler;
export type AsyncHandler = import('./async.js').AsyncHandler;

View file

@ -0,0 +1,36 @@
/**
* @typedef { import('estree').Node} Node
* @typedef { import('./walker.js').WalkerContext} WalkerContext
* @typedef {(
* this: WalkerContext,
* node: Node,
* parent: Node | null,
* key: string | number | symbol | null | undefined,
* index: number | null | undefined
* ) => void} SyncHandler
*/
export class SyncWalker extends WalkerBase {
/**
*
* @param {SyncHandler} [enter]
* @param {SyncHandler} [leave]
*/
constructor(enter?: SyncHandler | undefined, leave?: SyncHandler | undefined);
/** @type {SyncHandler | undefined} */
enter: SyncHandler | undefined;
/** @type {SyncHandler | undefined} */
leave: SyncHandler | undefined;
/**
* @template {Node} Parent
* @param {Node} node
* @param {Parent | null} parent
* @param {keyof Parent} [prop]
* @param {number | null} [index]
* @returns {Node | null}
*/
visit<Parent extends import("estree").Node>(node: Node, parent: Parent | null, prop?: keyof Parent | undefined, index?: number | null | undefined): Node | null;
}
export type Node = import('estree').Node;
export type WalkerContext = import('./walker.js').WalkerContext;
export type SyncHandler = (this: WalkerContext, node: Node, parent: Node | null, key: string | number | symbol | null | undefined, index: number | null | undefined) => void;
import { WalkerBase } from "./walker.js";

View file

@ -0,0 +1,39 @@
/**
* @typedef { import('estree').Node} Node
* @typedef {{
* skip: () => void;
* remove: () => void;
* replace: (node: Node) => void;
* }} WalkerContext
*/
export class WalkerBase {
/** @type {boolean} */
should_skip: boolean;
/** @type {boolean} */
should_remove: boolean;
/** @type {Node | null} */
replacement: Node | null;
/** @type {WalkerContext} */
context: WalkerContext;
/**
* @template {Node} Parent
* @param {Parent | null | undefined} parent
* @param {keyof Parent | null | undefined} prop
* @param {number | null | undefined} index
* @param {Node} node
*/
replace<Parent extends import("estree").Node>(parent: Parent | null | undefined, prop: keyof Parent | null | undefined, index: number | null | undefined, node: Node): void;
/**
* @template {Node} Parent
* @param {Parent | null | undefined} parent
* @param {keyof Parent | null | undefined} prop
* @param {number | null | undefined} index
*/
remove<Parent_1 extends import("estree").Node>(parent: Parent_1 | null | undefined, prop: keyof Parent_1 | null | undefined, index: number | null | undefined): void;
}
export type Node = import('estree').Node;
export type WalkerContext = {
skip: () => void;
remove: () => void;
replace: (node: Node) => void;
};

67
Frontend-Learner/node_modules/unctx/package.json generated vendored Normal file
View file

@ -0,0 +1,67 @@
{
"name": "unctx",
"version": "2.5.0",
"description": "Composition-api in Vanilla js",
"repository": "unjs/unctx",
"license": "MIT",
"sideEffects": false,
"exports": {
".": {
"types": "./dist/index.d.ts",
"import": "./dist/index.mjs",
"require": "./dist/index.cjs"
},
"./transform": {
"types": "./dist/transform.d.ts",
"import": "./dist/transform.mjs"
},
"./plugin": {
"types": "./dist/plugin.d.ts",
"import": "./dist/plugin.mjs"
}
},
"main": "./dist/index.cjs",
"module": "./dist/index.mjs",
"types": "./dist/index.d.ts",
"typesVersions": {
"*": {
"*": [
"./dist/*",
"./dist/index.d.ts"
]
}
},
"files": [
"dist"
],
"scripts": {
"build": "unbuild",
"dev": "vitest",
"lint": "eslint . && prettier -c src test",
"lint:fix": "eslint --fix . && prettier -w src test",
"prepack": "unbuild",
"release": "pnpm test && changelogen --release && npm publish && git push --follow-tags",
"test": "pnpm lint && pnpm test:types && vitest run --coverage",
"test:types": "tsc --noEmit"
},
"dependencies": {
"acorn": "^8.15.0",
"estree-walker": "^3.0.3",
"magic-string": "^0.30.21",
"unplugin": "^2.3.11"
},
"devDependencies": {
"@types/estree": "^1.0.8",
"@types/node": "^25.0.2",
"@vitest/coverage-v8": "^4.0.16",
"changelogen": "^0.6.2",
"eslint": "^9.39.2",
"eslint-config-unjs": "^0.5.0",
"jiti": "^2.6.1",
"prettier": "^3.7.4",
"typescript": "^5.9.3",
"unbuild": "^3.6.1",
"vitest": "^4.0.16"
},
"packageManager": "pnpm@10.26.0"
}