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/c12/LICENSE generated vendored Normal file
View file

@ -0,0 +1,21 @@
MIT License
Copyright (c) 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.

493
Frontend-Learner/node_modules/c12/README.md generated vendored Normal file
View file

@ -0,0 +1,493 @@
# ⚙️ c12
<!-- automd:badges color=yellow codecov -->
[![npm version](https://img.shields.io/npm/v/c12?color=yellow)](https://npmjs.com/package/c12)
[![npm downloads](https://img.shields.io/npm/dm/c12?color=yellow)](https://npm.chart.dev/c12)
[![codecov](https://img.shields.io/codecov/c/gh/unjs/c12?color=yellow)](https://codecov.io/gh/unjs/c12)
<!-- /automd -->
c12 (pronounced as /siːtwelv/, like c-twelve) is a smart configuration loader.
## ✅ Features
- `.js`, `.ts`, `.mjs`, `.cjs`, `.mts`, `.cts` `.json` config loader with [unjs/jiti](https://jiti.unjs.io)
- `.jsonc`, `.json5`, `.yaml`, `.yml`, `.toml` config loader with [unjs/confbox](https://confbox.unjs.io)
- `.config/` directory support ([config dir proposal](https://github.com/pi0/config-dir))
- `.rc` config support with [unjs/rc9](https://github.com/unjs/rc9)
- `.env` support with [dotenv](https://www.npmjs.com/package/dotenv)
- Multiple sources merged with [unjs/defu](https://github.com/unjs/defu)
- Reads config from the nearest `package.json` file
- [Extends configurations](https://github.com/unjs/c12#extending-configuration) from multiple local or git sources
- Overwrite with [environment-specific configuration](#environment-specific-configuration)
- Config watcher with auto-reload and HMR support
- Create or update configuration files with [magicast](https://github.com/unjs/magicast)
## 🦴 Used by
- [Hey API](https://github.com/hey-api/openapi-ts)
- [Kysely](https://github.com/kysely-org/kysely-ctl)
- [Nitro](https://nitro.build/)
- [Nuxt](https://nuxt.com/)
- [Prisma](https://github.com/prisma/prisma)
- [Trigger.dev](https://github.com/triggerdotdev/trigger.dev)
- [UnJS](https://github.com/unjs)
- [WXT](https://github.com/wxt-dev/wxt)
## Usage
Install package:
```sh
# ✨ Auto-detect
npx nypm install c12
```
Import:
```js
// ESM import
import { loadConfig, watchConfig } from "c12";
// or using dynamic import
const { loadConfig, watchConfig } = await import("c12");
```
Load configuration:
```js
// Get loaded config
const { config } = await loadConfig({});
// Get resolved config and extended layers
const { config, configFile, layers } = await loadConfig({});
```
## Loading priority
c12 merged config sources with [unjs/defu](https://github.com/unjs/defu) by below order:
1. Config overrides passed by options
2. Config file in CWD
3. RC file in CWD
4. Global RC file in the user's home directory
5. Config from `package.json`
6. Default config passed by options
7. Extended config layers
## Options
### `cwd`
Resolve configuration from this working directory. The default is `process.cwd()`
### `name`
Configuration base name. The default is `config`.
### `configFile`
Configuration file name without extension. Default is generated from `name` (f.e., if `name` is `foo`, the config file will be => `foo.config`).
### `rcFile`
RC Config file name. Default is generated from `name` (name=foo => `.foorc`).
Set to `false` to disable loading RC config.
### `globalRc`
Load RC config from the workspace directory and the user's home directory. Only enabled when `rcFile` is provided. Set to `false` to disable this functionality.
### `dotenv`
Loads `.env` file when `true` or an options object is passed. It is disabled by default.
Supports loading multiple files that extend eachother in left-to-right order when a `fileName`s array of relative/absolute paths is passed in the options object.
**Example:**
```ini
# .env
CONNECTION_POOL_MAX="10"
DATABASE_URL="<...rds...>"
```
```ini
# .env.local
DATABASE_URL="<...localhost...>"
```
```js
export default {
connectionPoolMax: process.env.CONNECTION_POOL_MAX,
databaseURL: process.env.DATABASE_URL,
};
```
```ts
import { loadConfig } from "c12";
const config = await loadConfig({
dotenv: {
fileName: [".env", ".env.local"],
},
});
console.log(config.config.connectionPoolMax); // "10"
console.log(config.config.databaseURL); // "<...localhost...>"
```
### `packageJson`
Loads config from nearest `package.json` file. It is disabled by default.
If `true` value is passed, c12 uses `name` field from `package.json`.
You can also pass either a string or an array of strings as a value to use those fields.
### `defaults`
Specify default configuration. It has the **lowest** priority and is applied **after extending** config.
### `defaultConfig`
Specify default configuration. It is applied **before** extending config.
### `overrides`
Specify override configuration. It has the **highest** priority and is applied **before extending** config.
### `omit$Keys`
Exclude environment-specific and built-in keys start with `$` in the resolved config. The default is `false`.
### `jiti`
Custom [unjs/jiti](https://github.com/unjs/jiti) instance used to import configuration files.
### `jitiOptions`
Custom [unjs/jiti](https://github.com/unjs/jiti) options to import configuration files.
### `giget`
Options passed to [unjs/giget](https://github.com/unjs/giget) when extending layer from git source.
### `merger`
Custom options merger function. Default is [defu](https://github.com/unjs/defu).
**Note:** Custom merge function should deeply merge options with arguments high -> low priority.
### `envName`
Environment name used for [environment specific configuration](#environment-specific-configuration).
The default is `process.env.NODE_ENV`. You can set `envName` to `false` or an empty string to disable the feature.
### `context`
Context object passed to dynamic config functions.
### `resolve`
You can define a custom function that resolves the config.
### `configFileRequired`
If this option is set to `true`, loader fails if the main config file does not exists.
## Extending configuration
If resolved config contains a `extends` key, it will be used to extend the configuration.
Extending can be nested and each layer can extend from one base or more.
The final config is merged result of extended options and user options with [unjs/defu](https://github.com/unjs/defu).
Each item in extends is a string that can be either an absolute or relative path to the current config file pointing to a config file for extending or the directory containing the config file.
If it starts with either `github:`, `gitlab:`, `bitbucket:`, or `https:`, c12 automatically clones it.
For custom merging strategies, you can directly access each layer with `layers` property.
**Example:**
```js
// config.ts
export default {
colors: {
primary: "user_primary",
},
extends: ["./theme"],
};
```
```js
// config.dev.ts
export default {
dev: true,
};
```
```js
// theme/config.ts
export default {
extends: "../base",
colors: {
primary: "theme_primary",
secondary: "theme_secondary",
},
};
```
```js
// base/config.ts
export default {
colors: {
primary: "base_primary",
text: "base_text",
},
};
```
The loaded configuration would look like this:
```js
const config = {
dev: true,
colors: {
primary: "user_primary",
secondary: "theme_secondary",
text: "base_text",
},
};
```
Layers:
```js
[
{
config: {
/* theme config */
},
configFile: "/path/to/theme/config.ts",
cwd: "/path/to/theme ",
},
{
config: {
/* base config */
},
configFile: "/path/to/base/config.ts",
cwd: "/path/to/base",
},
{
config: {
/* dev config */
},
configFile: "/path/to/config.dev.ts",
cwd: "/path/",
},
];
```
## Extending config layer from remote sources
You can also extend configuration from remote sources such as npm or github.
In the repo, there should be a `config.ts` (or `config.{name}.ts`) file to be considered as a valid config layer.
**Example:** Extend from a github repository
```js
// config.ts
export default {
extends: "gh:user/repo",
};
```
**Example:** Extend from a github repository with branch and subpath
```js
// config.ts
export default {
extends: "gh:user/repo/theme#dev",
};
```
**Example:** Extend a private repository and install dependencies:
```js
// config.ts
export default {
extends: ["gh:user/repo", { auth: process.env.GITHUB_TOKEN, install: true }],
};
```
You can pass more options to `giget: {}` in layer config or disable it by setting it to `false`.
Refer to [unjs/giget](https://giget.unjs.io) for more information.
## Environment-specific configuration
Users can define environment-specific configuration using these config keys:
- `$test: {...}`
- `$development: {...}`
- `$production: {...}`
- `$env: { [env]: {...} }`
c12 tries to match [`envName`](#envname) and override environment config if specified.
**Note:** Environment will be applied when extending each configuration layer. This way layers can provide environment-specific configuration.
**Example:**
```js
export default {
// Default configuration
logLevel: "info",
// Environment overrides
$test: { logLevel: "silent" },
$development: { logLevel: "warning" },
$production: { logLevel: "error" },
$env: {
staging: { logLevel: "debug" },
},
};
```
## Watching configuration
you can use `watchConfig` instead of `loadConfig` to load config and watch for changes, add and removals in all expected configuration paths and auto reload with new config.
### Lifecycle hooks
- `onWatch`: This function is always called when config is updated, added, or removed before attempting to reload the config.
- `acceptHMR`: By implementing this function, you can compare old and new functions and return `true` if a full reload is not needed.
- `onUpdate`: This function is always called after the new config is updated. If `acceptHMR` returns true, it will be skipped.
```ts
import { watchConfig } from "c12";
const config = watchConfig({
cwd: ".",
// chokidarOptions: {}, // Default is { ignoreInitial: true }
// debounce: 200 // Default is 100. You can set it to false to disable debounced watcher
onWatch: (event) => {
console.log("[watcher]", event.type, event.path);
},
acceptHMR({ oldConfig, newConfig, getDiff }) {
const diff = getDiff();
if (diff.length === 0) {
console.log("No config changed detected!");
return true; // No changes!
}
},
onUpdate({ oldConfig, newConfig, getDiff }) {
const diff = getDiff();
console.log("Config updated:\n" + diff.map((i) => i.toJSON()).join("\n"));
},
});
console.log("watching config files:", config.watchingFiles);
console.log("initial config", config.config);
// Stop watcher when not needed anymore
// await config.unwatch();
```
## Updating config
> [!NOTE]
> This feature is experimental
Update or create a new configuration files.
Add `magicast` peer dependency:
```sh
# ✨ Auto-detect
npx nypm install -D magicast
```
Import util from `c12/update`
```js
const { configFile, created } = await updateConfig({
cwd: ".",
configFile: "foo.config",
onCreate: ({ configFile }) => {
// You can prompt user if wants to create a new config file and return false to cancel
console.log(`Creating new config file in ${configFile}...`);
return "export default { test: true }";
},
onUpdate: (config) => {
// You can update the config contents just like an object
config.test2 = false;
},
});
console.log(`Config file ${created ? "created" : "updated"} in ${configFile}`);
```
## Configuration functions
You can use a function to define your configuration dynamically based on context.
```ts
// config.ts
export default (ctx) => {
return {
apiUrl: ctx?.dev ? "http://localhost:3000" : "https://api.example.com",
};
};
```
```ts
// Usage
import { loadConfig } from "c12";
const config = await loadConfig({
context: { dev: true },
});
```
## Contribution
<details>
<summary>Local development</summary>
- Clone this repository
- Install the latest LTS version of [Node.js](https://nodejs.org/en/)
- Enable [Corepack](https://github.com/nodejs/corepack) using `corepack enable`
- Install dependencies using `pnpm install`
- Run tests using `pnpm dev` or `pnpm test`
</details>
<!-- /automd -->
## License
<!-- automd:contributors license=MIT author="pi0" -->
Published under the [MIT](https://github.com/unjs/c12/blob/main/LICENSE) license.
Made by [@pi0](https://github.com/pi0) and [community](https://github.com/unjs/c12/graphs/contributors) 💛
<br><br>
<a href="https://github.com/unjs/c12/graphs/contributors">
<img src="https://contrib.rocks/image?repo=unjs/c12" />
</a>
<!-- /automd -->
<!-- automd:with-automd -->
---
_🤖 auto updated with [automd](https://automd.unjs.io)_
<!-- /automd -->

170
Frontend-Learner/node_modules/c12/dist/index.d.mts generated vendored Normal file
View file

@ -0,0 +1,170 @@
import { Jiti, JitiOptions } from "jiti";
import { ChokidarOptions } from "chokidar";
import { DownloadTemplateOptions } from "giget";
import { diff } from "ohash/utils";
//#region src/dotenv.d.ts
interface DotenvOptions {
/**
* The project root directory (either absolute or relative to the current working directory).
*
* Defaults to `options.cwd` in `loadConfig` context, or `process.cwd()` when used as standalone.
*/
cwd?: string;
/**
* What file or files to look in for environment variables (either absolute or relative
* to the current working directory). For example, `.env`.
* With the array type, the order enforce the env loading priority (last one overrides).
*/
fileName?: string | string[];
/**
* Whether to interpolate variables within .env.
*
* @example
* ```env
* BASE_DIR="/test"
* # resolves to "/test/further"
* ANOTHER_DIR="${BASE_DIR}/further"
* ```
*/
interpolate?: boolean;
/**
* An object describing environment variables (key, value pairs).
*/
env?: NodeJS.ProcessEnv;
}
type Env = typeof process.env;
/**
* Load and interpolate environment variables into `process.env`.
* If you need more control (or access to the values), consider using `loadDotenv` instead
*
*/
declare function setupDotenv(options: DotenvOptions): Promise<Env>;
/** Load environment variables into an object. */
declare function loadDotenv(options: DotenvOptions): Promise<Env>;
declare global {
var __c12_dotenv_vars__: Map<Record<string, any>, Set<string>>;
}
//#endregion
//#region src/types.d.ts
interface ConfigLayerMeta {
name?: string;
[key: string]: any;
}
type UserInputConfig = Record<string, any>;
interface C12InputConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
$test?: T;
$development?: T;
$production?: T;
$env?: Record<string, T>;
$meta?: MT;
}
type InputConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = C12InputConfig<T, MT> & T;
interface SourceOptions<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
/** Custom meta for layer */
meta?: MT;
/** Layer config overrides */
overrides?: T;
[key: string]: any;
/**
* Options for cloning remote sources
*
* @see https://giget.unjs.io
*/
giget?: DownloadTemplateOptions;
/**
* Install dependencies after cloning
*
* @see https://nypm.unjs.io
*/
install?: boolean;
/**
* Token for cloning private sources
*
* @see https://giget.unjs.io#providing-token-for-private-repositories
*/
auth?: string;
}
interface ConfigLayer<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
config: T | null;
source?: string;
sourceOptions?: SourceOptions<T, MT>;
meta?: MT;
cwd?: string;
configFile?: string;
}
interface ResolvedConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> extends ConfigLayer<T, MT> {
config: T;
layers?: ConfigLayer<T, MT>[];
cwd?: string;
_configFile?: string;
}
type ConfigSource = "overrides" | "main" | "rc" | "packageJson" | "defaultConfig";
interface ConfigFunctionContext {
[key: string]: any;
}
interface ResolvableConfigContext<T extends UserInputConfig = UserInputConfig> {
configs: Record<ConfigSource, T | null | undefined>;
rawConfigs: Record<ConfigSource, ResolvableConfig<T> | null | undefined>;
}
type MaybePromise<T> = T | Promise<T>;
type ResolvableConfig<T extends UserInputConfig = UserInputConfig> = MaybePromise<T | null | undefined> | ((ctx: ResolvableConfigContext<T>) => MaybePromise<T | null | undefined>);
interface LoadConfigOptions<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> {
name?: string;
cwd?: string;
configFile?: string;
rcFile?: false | string;
globalRc?: boolean;
dotenv?: boolean | DotenvOptions;
envName?: string | false;
packageJson?: boolean | string | string[];
defaults?: T;
defaultConfig?: ResolvableConfig<T>;
overrides?: ResolvableConfig<T>;
omit$Keys?: boolean;
/** Context passed to config functions */
context?: ConfigFunctionContext;
resolve?: (id: string, options: LoadConfigOptions<T, MT>) => null | undefined | ResolvedConfig<T, MT> | Promise<ResolvedConfig<T, MT> | undefined | null>;
jiti?: Jiti;
jitiOptions?: JitiOptions;
giget?: false | DownloadTemplateOptions;
merger?: (...sources: Array<T | null | undefined>) => T;
extend?: false | {
extendKey?: string | string[];
};
configFileRequired?: boolean;
}
type DefineConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = (input: InputConfig<T, MT>) => InputConfig<T, MT>;
declare function createDefineConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(): DefineConfig<T, MT>;
//#endregion
//#region src/loader.d.ts
declare const SUPPORTED_EXTENSIONS: string[];
declare function loadConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(options: LoadConfigOptions<T, MT>): Promise<ResolvedConfig<T, MT>>;
//#endregion
//#region src/watch.d.ts
type DiffEntries = ReturnType<typeof diff>;
type ConfigWatcher<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> = ResolvedConfig<T, MT> & {
watchingFiles: string[];
unwatch: () => Promise<void>;
};
interface WatchConfigOptions<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta> extends LoadConfigOptions<T, MT> {
chokidarOptions?: ChokidarOptions;
debounce?: false | number;
onWatch?: (event: {
type: "created" | "updated" | "removed";
path: string;
}) => void | Promise<void>;
acceptHMR?: (context: {
getDiff: () => DiffEntries;
newConfig: ResolvedConfig<T, MT>;
oldConfig: ResolvedConfig<T, MT>;
}) => void | boolean | Promise<void | boolean>;
onUpdate?: (context: {
getDiff: () => ReturnType<typeof diff>;
newConfig: ResolvedConfig<T, MT>;
oldConfig: ResolvedConfig<T, MT>;
}) => void | Promise<void>;
}
declare function watchConfig<T extends UserInputConfig = UserInputConfig, MT extends ConfigLayerMeta = ConfigLayerMeta>(options: WatchConfigOptions<T, MT>): Promise<ConfigWatcher<T, MT>>;
//#endregion
export { C12InputConfig, ConfigFunctionContext, ConfigLayer, ConfigLayerMeta, ConfigSource, ConfigWatcher, DefineConfig, DotenvOptions, Env, InputConfig, LoadConfigOptions, ResolvableConfig, ResolvableConfigContext, ResolvedConfig, SUPPORTED_EXTENSIONS, SourceOptions, UserInputConfig, WatchConfigOptions, createDefineConfig, loadConfig, loadDotenv, setupDotenv, watchConfig };

419
Frontend-Learner/node_modules/c12/dist/index.mjs generated vendored Normal file
View file

@ -0,0 +1,419 @@
import { existsSync, promises, statSync } from "node:fs";
import { basename, dirname, extname, join, normalize, resolve } from "pathe";
import * as dotenv from "dotenv";
import { readFile, rm } from "node:fs/promises";
import { pathToFileURL } from "node:url";
import { homedir } from "node:os";
import { resolveModulePath } from "exsolve";
import { createJiti } from "jiti";
import * as rc9 from "rc9";
import { defu } from "defu";
import { findWorkspaceDir, readPackageJSON } from "pkg-types";
import { debounce } from "perfect-debounce";
//#region src/dotenv.ts
/**
* Load and interpolate environment variables into `process.env`.
* If you need more control (or access to the values), consider using `loadDotenv` instead
*
*/
async function setupDotenv(options) {
const targetEnvironment = options.env ?? process.env;
const environment = await loadDotenv({
cwd: options.cwd,
fileName: options.fileName ?? ".env",
env: targetEnvironment,
interpolate: options.interpolate ?? true
});
const dotenvVars = getDotEnvVars(targetEnvironment);
for (const key in environment) {
if (key.startsWith("_")) continue;
if (targetEnvironment[key] === void 0 || dotenvVars.has(key)) targetEnvironment[key] = environment[key];
}
return environment;
}
/** Load environment variables into an object. */
async function loadDotenv(options) {
const environment = Object.create(null);
const cwd = resolve(options.cwd || ".");
const _fileName = options.fileName || ".env";
const dotenvFiles = typeof _fileName === "string" ? [_fileName] : _fileName;
const dotenvVars = getDotEnvVars(options.env || {});
Object.assign(environment, options.env);
for (const file of dotenvFiles) {
const dotenvFile = resolve(cwd, file);
if (!statSync(dotenvFile, { throwIfNoEntry: false })?.isFile()) continue;
const parsed = dotenv.parse(await promises.readFile(dotenvFile, "utf8"));
for (const key in parsed) {
if (key in environment && !dotenvVars.has(key)) continue;
environment[key] = parsed[key];
dotenvVars.add(key);
}
}
if (options.interpolate) interpolate(environment);
return environment;
}
function interpolate(target, source = {}, parse = (v) => v) {
function getValue(key) {
return source[key] === void 0 ? target[key] : source[key];
}
function interpolate$1(value, parents = []) {
if (typeof value !== "string") return value;
return parse((value.match(/(.?\${?(?:[\w:]+)?}?)/g) || []).reduce((newValue, match) => {
const parts = /(.?)\${?([\w:]+)?}?/g.exec(match) || [];
const prefix = parts[1];
let value$1, replacePart;
if (prefix === "\\") {
replacePart = parts[0] || "";
value$1 = replacePart.replace(String.raw`\$`, "$");
} else {
const key = parts[2];
replacePart = (parts[0] || "").slice(prefix.length);
if (parents.includes(key)) {
console.warn(`Please avoid recursive environment variables ( loop: ${parents.join(" > ")} > ${key} )`);
return "";
}
value$1 = getValue(key);
value$1 = interpolate$1(value$1, [...parents, key]);
}
return value$1 === void 0 ? newValue : newValue.replace(replacePart, value$1);
}, value));
}
for (const key in target) target[key] = interpolate$1(getValue(key));
}
function getDotEnvVars(targetEnvironment) {
const globalRegistry = globalThis.__c12_dotenv_vars__ ||= /* @__PURE__ */ new Map();
if (!globalRegistry.has(targetEnvironment)) globalRegistry.set(targetEnvironment, /* @__PURE__ */ new Set());
return globalRegistry.get(targetEnvironment);
}
//#endregion
//#region src/loader.ts
const _normalize = (p) => p?.replace(/\\/g, "/");
const ASYNC_LOADERS = {
".yaml": () => import("confbox/yaml").then((r) => r.parseYAML),
".yml": () => import("confbox/yaml").then((r) => r.parseYAML),
".jsonc": () => import("confbox/jsonc").then((r) => r.parseJSONC),
".json5": () => import("confbox/json5").then((r) => r.parseJSON5),
".toml": () => import("confbox/toml").then((r) => r.parseTOML)
};
const SUPPORTED_EXTENSIONS = Object.freeze([
".js",
".ts",
".mjs",
".cjs",
".mts",
".cts",
".json",
".jsonc",
".json5",
".yaml",
".yml",
".toml"
]);
async function loadConfig(options) {
options.cwd = resolve(process.cwd(), options.cwd || ".");
options.name = options.name || "config";
options.envName = options.envName ?? process.env.NODE_ENV;
options.configFile = options.configFile ?? (options.name === "config" ? "config" : `${options.name}.config`);
options.rcFile = options.rcFile ?? `.${options.name}rc`;
if (options.extend !== false) options.extend = {
extendKey: "extends",
...options.extend
};
const _merger = options.merger || defu;
options.jiti = options.jiti || createJiti(join(options.cwd, options.configFile), {
interopDefault: true,
moduleCache: false,
extensions: [...SUPPORTED_EXTENSIONS],
...options.jitiOptions
});
const r = {
config: {},
cwd: options.cwd,
configFile: resolve(options.cwd, options.configFile),
layers: [],
_configFile: void 0
};
const rawConfigs = {
overrides: options.overrides,
main: void 0,
rc: void 0,
packageJson: void 0,
defaultConfig: options.defaultConfig
};
if (options.dotenv) await setupDotenv({
cwd: options.cwd,
...options.dotenv === true ? {} : options.dotenv
});
const _mainConfig = await resolveConfig(".", options);
if (_mainConfig.configFile) {
rawConfigs.main = _mainConfig.config;
r.configFile = _mainConfig.configFile;
r._configFile = _mainConfig._configFile;
}
if (_mainConfig.meta) r.meta = _mainConfig.meta;
if (options.rcFile) {
const rcSources = [];
rcSources.push(rc9.read({
name: options.rcFile,
dir: options.cwd
}));
if (options.globalRc) {
const workspaceDir = await findWorkspaceDir(options.cwd).catch(() => {});
if (workspaceDir) rcSources.push(rc9.read({
name: options.rcFile,
dir: workspaceDir
}));
rcSources.push(rc9.readUser({
name: options.rcFile,
dir: options.cwd
}));
}
rawConfigs.rc = _merger({}, ...rcSources);
}
if (options.packageJson) {
const keys = (Array.isArray(options.packageJson) ? options.packageJson : [typeof options.packageJson === "string" ? options.packageJson : options.name]).filter((t) => t && typeof t === "string");
const pkgJsonFile = await readPackageJSON(options.cwd).catch(() => {});
rawConfigs.packageJson = _merger({}, ...keys.map((key) => pkgJsonFile?.[key]));
}
const configs = {};
for (const key in rawConfigs) {
const value = rawConfigs[key];
configs[key] = await (typeof value === "function" ? value({
configs,
rawConfigs
}) : value);
}
if (Array.isArray(configs.main)) r.config = configs.main;
else {
r.config = _merger(configs.overrides, configs.main, configs.rc, configs.packageJson, configs.defaultConfig);
if (options.extend) {
await extendConfig(r.config, options);
r.layers = r.config._layers;
delete r.config._layers;
r.config = _merger(r.config, ...r.layers.map((e) => e.config));
}
}
r.layers = [...[
configs.overrides && {
config: configs.overrides,
configFile: void 0,
cwd: void 0
},
{
config: configs.main,
configFile: options.configFile,
cwd: options.cwd
},
configs.rc && {
config: configs.rc,
configFile: options.rcFile
},
configs.packageJson && {
config: configs.packageJson,
configFile: "package.json"
}
].filter((l) => l && l.config), ...r.layers];
if (options.defaults) r.config = _merger(r.config, options.defaults);
if (options.omit$Keys) {
for (const key in r.config) if (key.startsWith("$")) delete r.config[key];
}
if (options.configFileRequired && !r._configFile) throw new Error(`Required config (${r.configFile}) cannot be resolved.`);
return r;
}
async function extendConfig(config, options) {
config._layers = config._layers || [];
if (!options.extend) return;
let keys = options.extend.extendKey;
if (typeof keys === "string") keys = [keys];
const extendSources = [];
for (const key of keys) {
extendSources.push(...(Array.isArray(config[key]) ? config[key] : [config[key]]).filter(Boolean));
delete config[key];
}
for (let extendSource of extendSources) {
const originalExtendSource = extendSource;
let sourceOptions = {};
if (extendSource.source) {
sourceOptions = extendSource.options || {};
extendSource = extendSource.source;
}
if (Array.isArray(extendSource)) {
sourceOptions = extendSource[1] || {};
extendSource = extendSource[0];
}
if (typeof extendSource !== "string") {
console.warn(`Cannot extend config from \`${JSON.stringify(originalExtendSource)}\` in ${options.cwd}`);
continue;
}
const _config = await resolveConfig(extendSource, options, sourceOptions);
if (!_config.config) {
console.warn(`Cannot extend config from \`${extendSource}\` in ${options.cwd}`);
continue;
}
await extendConfig(_config.config, {
...options,
cwd: _config.cwd
});
config._layers.push(_config);
if (_config.config._layers) {
config._layers.push(..._config.config._layers);
delete _config.config._layers;
}
}
}
const GIGET_PREFIXES = [
"gh:",
"github:",
"gitlab:",
"bitbucket:",
"https://",
"http://"
];
const NPM_PACKAGE_RE = /^(@[\da-z~-][\d._a-z~-]*\/)?[\da-z~-][\d._a-z~-]*($|\/.*)/;
async function resolveConfig(source, options, sourceOptions = {}) {
if (options.resolve) {
const res$1 = await options.resolve(source, options);
if (res$1) return res$1;
}
const _merger = options.merger || defu;
const customProviderKeys = Object.keys(sourceOptions.giget?.providers || {}).map((key) => `${key}:`);
const gigetPrefixes = customProviderKeys.length > 0 ? [...new Set([...customProviderKeys, ...GIGET_PREFIXES])] : GIGET_PREFIXES;
if (options.giget !== false && gigetPrefixes.some((prefix) => source.startsWith(prefix))) {
const { downloadTemplate } = await import("giget");
const { digest } = await import("ohash");
const cloneName = source.replace(/\W+/g, "_").split("_").splice(0, 3).join("_") + "_" + digest(source).slice(0, 10).replace(/[-_]/g, "");
let cloneDir;
const localNodeModules = resolve(options.cwd, "node_modules");
const parentDir = dirname(options.cwd);
if (basename(parentDir) === ".c12") cloneDir = join(parentDir, cloneName);
else if (existsSync(localNodeModules)) cloneDir = join(localNodeModules, ".c12", cloneName);
else cloneDir = process.env.XDG_CACHE_HOME ? resolve(process.env.XDG_CACHE_HOME, "c12", cloneName) : resolve(homedir(), ".cache/c12", cloneName);
if (existsSync(cloneDir) && !sourceOptions.install) await rm(cloneDir, { recursive: true });
source = (await downloadTemplate(source, {
dir: cloneDir,
install: sourceOptions.install,
force: sourceOptions.install,
auth: sourceOptions.auth,
...options.giget,
...sourceOptions.giget
})).dir;
}
if (NPM_PACKAGE_RE.test(source)) source = tryResolve(source, options) || source;
const ext = extname(source);
const isDir = !ext || ext === basename(source);
const cwd = resolve(options.cwd, isDir ? source : dirname(source));
if (isDir) source = options.configFile;
const res = {
config: void 0,
configFile: void 0,
cwd,
source,
sourceOptions
};
res.configFile = tryResolve(resolve(cwd, source), options) || tryResolve(resolve(cwd, ".config", source.replace(/\.config$/, "")), options) || tryResolve(resolve(cwd, ".config", source), options) || source;
if (!existsSync(res.configFile)) return res;
res._configFile = res.configFile;
const configFileExt = extname(res.configFile) || "";
if (configFileExt in ASYNC_LOADERS) res.config = (await ASYNC_LOADERS[configFileExt]())(await readFile(res.configFile, "utf8"));
else res.config = await options.jiti.import(res.configFile, { default: true });
if (typeof res.config === "function") res.config = await res.config(options.context);
if (options.envName) {
const envConfig = {
...res.config["$" + options.envName],
...res.config.$env?.[options.envName]
};
if (Object.keys(envConfig).length > 0) res.config = _merger(envConfig, res.config);
}
res.meta = defu(res.sourceOptions.meta, res.config.$meta);
delete res.config.$meta;
if (res.sourceOptions.overrides) res.config = _merger(res.sourceOptions.overrides, res.config);
res.configFile = _normalize(res.configFile);
res.source = _normalize(res.source);
return res;
}
function tryResolve(id, options) {
const res = resolveModulePath(id, {
try: true,
from: pathToFileURL(join(options.cwd || ".", options.configFile || "/")),
suffixes: ["", "/index"],
extensions: SUPPORTED_EXTENSIONS,
cache: false
});
return res ? normalize(res) : void 0;
}
//#endregion
//#region src/types.ts
function createDefineConfig() {
return (input) => input;
}
//#endregion
//#region src/watch.ts
const eventMap = {
add: "created",
change: "updated",
unlink: "removed"
};
async function watchConfig(options) {
let config = await loadConfig(options);
const configName = options.name || "config";
const configFileName = options.configFile ?? (options.name === "config" ? "config" : `${options.name}.config`);
const watchingFiles = [...new Set((config.layers || []).filter((l) => l.cwd).flatMap((l) => [
...SUPPORTED_EXTENSIONS.flatMap((ext) => [
resolve(l.cwd, configFileName + ext),
resolve(l.cwd, ".config", configFileName + ext),
resolve(l.cwd, ".config", configFileName.replace(/\.config$/, "") + ext)
]),
l.source && resolve(l.cwd, l.source),
options.rcFile && resolve(l.cwd, typeof options.rcFile === "string" ? options.rcFile : `.${configName}rc`),
options.packageJson && resolve(l.cwd, "package.json")
]).filter(Boolean))];
const watch = await import("chokidar").then((r) => r.watch || r.default || r);
const { diff } = await import("ohash/utils");
const _fswatcher = watch(watchingFiles, {
ignoreInitial: true,
...options.chokidarOptions
});
const onChange = async (event, path) => {
const type = eventMap[event];
if (!type) return;
if (options.onWatch) await options.onWatch({
type,
path
});
const oldConfig = config;
try {
config = await loadConfig(options);
} catch (error) {
console.warn(`Failed to load config ${path}\n${error}`);
return;
}
const changeCtx = {
newConfig: config,
oldConfig,
getDiff: () => diff(oldConfig.config, config.config)
};
if (options.acceptHMR) {
if (await options.acceptHMR(changeCtx)) return;
}
if (options.onUpdate) await options.onUpdate(changeCtx);
};
if (options.debounce === false) _fswatcher.on("all", onChange);
else _fswatcher.on("all", debounce(onChange, options.debounce ?? 100));
const utils = {
watchingFiles,
unwatch: async () => {
await _fswatcher.close();
}
};
return new Proxy(utils, { get(_, prop) {
if (prop in utils) return utils[prop];
return config[prop];
} });
}
//#endregion
export { SUPPORTED_EXTENSIONS, createDefineConfig, loadConfig, loadDotenv, setupDotenv, watchConfig };

53
Frontend-Learner/node_modules/c12/dist/update.d.mts generated vendored Normal file
View file

@ -0,0 +1,53 @@
import * as magicast0 from "magicast";
//#region src/update.d.ts
/**
* @experimental Update a config file or create a new one.
*/
declare function updateConfig(opts: UpdateConfigOptions): Promise<UpdateConfigResult>;
interface UpdateConfigResult {
configFile?: string;
created?: boolean;
}
type MaybePromise<T> = T | Promise<T>;
type MagicAstOptions = Exclude<Parameters<(typeof magicast0)["parseModule"]>[1], undefined>;
interface UpdateConfigOptions {
/**
* Current working directory
*/
cwd: string;
/**
* Config file name
*/
configFile: string;
/**
* Extension used for new config file.
*/
createExtension?: string;
/**
* Magicast options
*/
magicast?: MagicAstOptions;
/**
* Update function.
*/
onUpdate?: (config: any) => MaybePromise<void>;
/**
* Handle default config creation.
*
* Tip: you can use this option as a hook to prompt users about config creation.
*
* Context object:
* - path: determined full path to the config file
*
* Returns types:
* - string: custom config template
* - true: write the template
* - false: abort the operation
*/
onCreate?: (ctx: {
configFile: string;
}) => MaybePromise<string | boolean>;
}
//#endregion
export { UpdateConfigOptions, UpdateConfigResult, updateConfig };

80
Frontend-Learner/node_modules/c12/dist/update.mjs generated vendored Normal file
View file

@ -0,0 +1,80 @@
import { resolveModulePath } from "exsolve";
import "node:fs";
import { mkdir, readFile, writeFile } from "node:fs/promises";
import "node:url";
import "node:os";
import { join, normalize } from "pathe";
import "jiti";
import "rc9";
import "defu";
import "pkg-types";
import { dirname, extname } from "node:path";
//#region src/loader.ts
const SUPPORTED_EXTENSIONS = Object.freeze([
".js",
".ts",
".mjs",
".cjs",
".mts",
".cts",
".json",
".jsonc",
".json5",
".yaml",
".yml",
".toml"
]);
//#endregion
//#region src/update.ts
const UPDATABLE_EXTS = [
".js",
".ts",
".mjs",
".cjs",
".mts",
".cts"
];
/**
* @experimental Update a config file or create a new one.
*/
async function updateConfig(opts) {
const { parseModule } = await import("magicast");
let configFile = tryResolve(`./${opts.configFile}`, opts.cwd, SUPPORTED_EXTENSIONS) || tryResolve(`./.config/${opts.configFile}`, opts.cwd, SUPPORTED_EXTENSIONS) || tryResolve(`./.config/${opts.configFile.split(".")[0]}`, opts.cwd, SUPPORTED_EXTENSIONS);
let created = false;
if (!configFile) {
configFile = join(opts.cwd, opts.configFile + (opts.createExtension || ".ts"));
const createResult = await opts.onCreate?.({ configFile }) ?? true;
if (!createResult) throw new Error("Config file creation aborted.");
const content = typeof createResult === "string" ? createResult : `export default {}\n`;
await mkdir(dirname(configFile), { recursive: true });
await writeFile(configFile, content, "utf8");
created = true;
}
const ext = extname(configFile);
if (!UPDATABLE_EXTS.includes(ext)) throw new Error(`Unsupported config file extension: ${ext} (${configFile}) (supported: ${UPDATABLE_EXTS.join(", ")})`);
const _module = parseModule(await readFile(configFile, "utf8"), opts.magicast);
const defaultExport = _module.exports.default;
if (!defaultExport) throw new Error("Default export is missing in the config file!");
const configObj = defaultExport.$type === "function-call" ? defaultExport.$args[0] : defaultExport;
await opts.onUpdate?.(configObj);
await writeFile(configFile, _module.generate().code);
return {
configFile,
created
};
}
function tryResolve(path, cwd, extensions) {
const res = resolveModulePath(path, {
try: true,
from: join(cwd, "/"),
extensions,
suffixes: ["", "/index"],
cache: false
});
return res ? normalize(res) : void 0;
}
//#endregion
export { updateConfig };

69
Frontend-Learner/node_modules/c12/package.json generated vendored Normal file
View file

@ -0,0 +1,69 @@
{
"name": "c12",
"version": "3.3.3",
"description": "Smart Config Loader",
"repository": "unjs/c12",
"license": "MIT",
"sideEffects": false,
"type": "module",
"exports": {
".": {
"types": "./dist/index.d.mts",
"default": "./dist/index.mjs"
},
"./update": {
"types": "./dist/update.d.mts",
"default": "./dist/update.mjs"
}
},
"types": "./dist/index.d.mts",
"files": [
"dist"
],
"scripts": {
"build": "obuild",
"dev": "vitest dev",
"lint": "eslint . && prettier -c src test",
"lint:fix": "automd && eslint . --fix && prettier -w src test",
"release": "pnpm build && pnpm test && changelogen --release --push --publish",
"test": "pnpm lint && vitest run --coverage && pnpm test:types",
"test:types": "tsc --noEmit"
},
"dependencies": {
"chokidar": "^5.0.0",
"confbox": "^0.2.2",
"defu": "^6.1.4",
"dotenv": "^17.2.3",
"exsolve": "^1.0.8",
"giget": "^2.0.0",
"jiti": "^2.6.1",
"ohash": "^2.0.11",
"pathe": "^2.0.3",
"perfect-debounce": "^2.0.0",
"pkg-types": "^2.3.0",
"rc9": "^2.1.2"
},
"devDependencies": {
"@types/node": "^25.0.2",
"@vitest/coverage-v8": "^4.0.15",
"automd": "^0.4.2",
"changelogen": "^0.6.2",
"eslint": "^9.39.2",
"eslint-config-unjs": "^0.5.0",
"expect-type": "^1.3.0",
"magicast": "^0.5.1",
"obuild": "^0.4.8",
"prettier": "^3.7.4",
"typescript": "^5.9.3",
"vitest": "^4.0.15"
},
"peerDependencies": {
"magicast": "*"
},
"peerDependenciesMeta": {
"magicast": {
"optional": true
}
},
"packageManager": "pnpm@10.26.0"
}