Full Code of Subwaytime/vite-aliases for AI

main 8da1b2113ab5 cached
29 files
26.1 KB
8.0k tokens
29 symbols
1 requests
Download .txt
Repository: Subwaytime/vite-aliases
Branch: main
Commit: 8da1b2113ab5
Files: 29
Total size: 26.1 KB

Directory structure:
gitextract_2w2y_h5y/

├── .gitattributes
├── .github/
│   └── FUNDING.yml
├── .gitignore
├── .prettierrc
├── LICENSE
├── README.md
├── example/
│   ├── index.html
│   ├── package.json
│   ├── src/
│   │   ├── app.vue
│   │   ├── components/
│   │   │   └── navigation.vue
│   │   ├── logs/
│   │   │   └── vite-aliases.json
│   │   ├── main.ts
│   │   ├── pages/
│   │   │   └── home.vue
│   │   └── utils/
│   │       └── random.ts
│   ├── tsconfig.json
│   ├── vite-aliases.json
│   └── vite.config.ts
├── package.json
├── src/
│   ├── constants.ts
│   ├── fs/
│   │   ├── config.ts
│   │   ├── glob.ts
│   │   ├── index.ts
│   │   └── log.ts
│   ├── generator.ts
│   ├── index.ts
│   ├── types.ts
│   └── utils.ts
├── tsconfig.json
└── tsup.config.ts

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitattributes
================================================
# Auto detect text files and perform LF normalization
* text=auto


================================================
FILE: .github/FUNDING.yml
================================================
github: subwaytime

================================================
FILE: .gitignore
================================================
node_modules
.DS_Store
dist
.prettierignore
.vscode
package-lock.json
example/jsconfig.json
exmaple/tsconfig.json

================================================
FILE: .prettierrc
================================================
{
  "endOfLine": "auto",
  "jsxBracketSameLine": true,
  "jsxSingleQuote": true,
  "printWidth": 120,
  "singleQuote": true,
  "tabWidth": 4,
  "trailingComma": "all",
  "useTabs": true,
  "vueIndentScriptAndStyle": false
}


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2020-PRESENT Leon Langer<https://github.com/subwaytime>

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.


================================================
FILE: README.md
================================================
<h2 align="left">vite-aliases</h2>

<p align="left">Alias auto generation for Vite 6</p>

<p align="left">
<a href="https://www.npmjs.com/package/vite-aliases">
<img src="https://img.shields.io/npm/v/vite-aliases?color=222&style=flat-square">
</a>
</p>

## Usage

Install

```bash
npm i vite-aliases -D
```

Add it to `vite.config.js`

```ts
// vite.config.js
import { ViteAliases } from 'vite-aliases'

export default {
  plugins: [
    ViteAliases()
  ]
};

```

Add this to `package.json` (Plugin is only available for ESM)
```json
{
  "type": "module"
}
```

That's it!

<p>
<br/>
Based on your Folderstructure, it will now automatically generate all needed aliases.
<br />
You can configure it to any desired Depth, but it is recommend to stay on the first Level!
<br />
Furthermore it will use your native OS filesystem, so it works on Linux, Mac, Windows and other OS.
</p>

<br />
This structure:

```
src
  assets
  components
  pages
  store
  utils
```

will generate the following:

```ts
[
  {
    find: '~',
    replacement: '${your_project_path}/src'
  },
  {
    find: '~assets',
    replacement: '${your_project_path}/src/assets'
  },
  {
    find: '~components',
    replacement: '${your_project_path}/src/components'
  },
  {
    find: '~pages',
    replacement: '${your_project_path}/src/pages'
  },
  {
    find: '~store',
    replacement: '${your_project_path}/src/store'
  },
  {
    find: '~utils',
    replacement: '${your_project_path}/src/utils'
  },
]
```

## Best Practice

`vite-aliases` is meant to simply take the first Layer of your folders and turn it into useful Shortcuts.
<br />
Therefore i advise you to use the default Configuration and not use folders with the same name, otherwise it will create an Error.

If however you need duplicate Foldernames, enable `adjustDuplicates`.
<br />
This will turn the entire Filepath of said duplicate into the alias itself, like shown in the Example below.

Example:
```
`src/components` -> `~components`
`src/pages/components` -> `~pagesComponents`
`src/test/new/partials/components` -> `~testNewPartialsComponents`
```
and so on..

## Configuration

Current available options:

```ts
ViteAliases({
  /**
  * Relative path to the project directory
  */
  dir: 'src',

  /**
  * Prefix symbol for the aliases
  */
  prefix: '~',

  /**
  * Allow searching for subdirectories
  */
  deep: true,

  /**
  * Search depthlevel for subdirectories
  */
  depth: 1,

  /**
  * Creates a Logfile
  * use `logPath` to change the location
  */
  createLog: false,

  /**
  * Path for Logfile
  */
  logPath: 'src/logs',

  /**
  * Create global project directory alias
  */
  createGlobalAlias: true,

  /**
  * Turns duplicates into camelCased path aliases
  */
  adjustDuplicates: false,

  /**
  * Used paths in JS/TS configs will now be relative to baseUrl
  */
  useAbsolute: false,

  /**
  * Adds seperate index paths
  * approach created by @davidohlin
  */
  useIndexes: false,

  /**
  * Generates paths in IDE config file
  * works with JS or TS
  */
  useConfig: true,

  /**
  * Override config paths
  */
  ovrConfig: false,

  /**
  * Will generate Paths in tsconfig
  * used in combination with `useConfig`
  * Typescript will be auto detected
  */
  dts: false,

  /**
  * Disables any terminal output
  */
  silent: true,

  /**
  * Root path of Vite project
  */
  root: process.cwd()
});
```

## Thanks

Thanks to [@brattonross](https://github.com/brattonross) and [@antfu](https://github.com/antfu),
due to this tiny library beeing inspired by both projects:

[vite-plugin-voie](https://github.com/vamplate/vite-plugin-voie)

[unplugin-vue-components](https://github.com/antfu/unplugin-vue-components).

## License

MIT License © 2020-PRESENT [Leon Langer](https://github.com/subwaytime)


================================================
FILE: example/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Vite App</title>
</head>
<body>
  <div id="app"></div>
  <script type="module" src="./src/main.ts"></script>
</body>
</html>

================================================
FILE: example/package.json
================================================
{
	"name": "@vite-aliases/example",
	"description": "Example: Alias auto generation for Vite",
	"version": "0.1.0",
	"private": true,
	"license": "MIT",
	"author": "Subwaytime <leon.l@nophase.de>",
	"type": "module",
	"repository": {
		"type": "git",
		"url": "https://github.com/subwaytime/vite-aliases"
	},
	"homepage": "https://github.com/subwaytime/vite-aliases#readme",
	"bugs": "https://github.com/subwaytime/vite-aliases/issues",
	"scripts": {
		"update:packages": "npm update --save-dev && npm update --save",
		"dev": "vite",
		"build": "vite build"
	},
	"dependencies": {
		"@vitejs/plugin-vue": "^4.3.3",
		"@vue/compiler-sfc": "^3.3.4",
		"vite": "^4.4.9",
		"vitest": "^0.34.3",
		"vue": "^3.3.4"
	},
	"devDependencies": {
		"typescript": "^5.2.2"
	}
}


================================================
FILE: example/src/app.vue
================================================
<template>
	<div class="wrapper">
		<h1> Vite Aliases Example </h1>
		<home />
		<navigation />
		<div class="box">
			<p>
				Randomized Hexcode
				<br />
				<code> loaded from ~utils/random.js </code>
			</p>
			<div class="colored" :style="`background-color: ${color};`">
				{{ color }}
			</div>
		</div>
	</div>
</template>


<script setup lang="ts">
import { ref } from 'vue';
import home from '~pages/home.vue';
import navigation from '~components/navigation.vue';
import { random } from '~utils/random';

const color = ref(random());
</script>

<style lang="css">
	body {
		font-family: Avenir, Helvetica, Arial, sans-serif;
		-webkit-font-smoothing: antialiased;
		-moz-osx-font-smoothing: grayscale;
		align-items: center;
		background: #e9ecef;
		display: flex;
		height: 100vh;
		justify-content: center;
		margin: 0;
		padding: 0;
		text-align: center;
		width: 100%;
	}

	p {
		margin: 0.5rem 0;
	}

	.wrapper {
		align-items: center;
		background: #f8f9fa;
		border-radius: 1rem;
		box-shadow: 0 10px 15px -3px rgba(0, 0, 0, 0.1), 0 4px 6px -2px rgba(0, 0, 0, 0.05);
		display: flex;
		flex-flow: column wrap;
		height: 24rem;
		justify-content: center;
		margin: 0 auto;
		padding: 1.5rem;
		width: 24rem;
	}

	.colored {
		color: #151515;
		border-radius: 1rem;
		padding: 0.75em;
		margin-top: 0.5rem;
		text-align: center;
	}
</style>

================================================
FILE: example/src/components/navigation.vue
================================================
<template>
	<p> Navigation loaded from
		<br />
		<code> ~components/navigation.vue </code>
	</p>
</template>


================================================
FILE: example/src/logs/vite-aliases.json
================================================
[
    {
        "find": "@assets",
        "replacement": "D:/work/vite-aliases/example/src/assets"
    },
    {
        "find": "@components",
        "replacement": "D:/work/vite-aliases/example/src/components"
    },
    {
        "find": "@logs",
        "replacement": "D:/work/vite-aliases/example/src/logs"
    },
    {
        "find": "@pages",
        "replacement": "D:/work/vite-aliases/example/src/pages"
    },
    {
        "find": "@utils",
        "replacement": "D:/work/vite-aliases/example/src/utils"
    },
    {
        "find": "@",
        "replacement": "D:/work/vite-aliases/example/src"
    }
]

================================================
FILE: example/src/main.ts
================================================
import App from './app.vue'
import { createApp } from 'vue'

createApp(App).mount('#app');

================================================
FILE: example/src/pages/home.vue
================================================
<template>
	<p> Home loaded from
		<br />
		<code> ~pages/home.vue </code>
	</p>
</template>

================================================
FILE: example/src/utils/random.ts
================================================
/**
 * Return a Random Hexcode
 */

export function random() {
	let n = (Math.random() * 0xfffff * 1000000).toString(16);
	return '#' + n.slice(0, 6);
};

================================================
FILE: example/tsconfig.json
================================================
{
    "compilerOptions": {
        "baseUrl": ".",
        "paths": {
            "~components/*": [
                "src/components/*"
            ],
            "~logs/*": [
                "src/logs/*"
            ],
            "~pages/*": [
                "src/pages/*"
            ],
            "~utils/*": [
                "src/utils/*"
            ],
            "~/*": [
                "src/*"
            ]
        }
    }
}

================================================
FILE: example/vite-aliases.json
================================================
[
    {
        "find": "~components",
        "replacement": "/home/subway/work/vite-aliases/example/src/components"
    },
    {
        "find": "~logs",
        "replacement": "/home/subway/work/vite-aliases/example/src/logs"
    },
    {
        "find": "~pages",
        "replacement": "/home/subway/work/vite-aliases/example/src/pages"
    },
    {
        "find": "~utils",
        "replacement": "/home/subway/work/vite-aliases/example/src/utils"
    },
    {
        "find": "~",
        "replacement": "/home/subway/work/vite-aliases/example/src"
    }
]

================================================
FILE: example/vite.config.ts
================================================
import vue from '@vitejs/plugin-vue';
import { defineConfig } from 'vitest/config';
import { ViteAliases } from '../dist/index.js';


export default defineConfig({
	plugins: [
		vue(),
		ViteAliases({
			createLog: true,
			logPath: './',
			adjustDuplicates: true,
		}),
	],
	server: {
		port: 8080,
	},
	logLevel: 'silent',
});

================================================
FILE: package.json
================================================
{
  "name": "vite-aliases",
  "description": "Alias auto generation for Vite",
  "version": "0.11.8",
  "type": "module",
  "main": "./dist/index.js",
  "module": "./dist/index.js",
  "types": "./dist/index.d.ts",
  "exports": {
    ".": {
      "types": "./dist/index.d.ts",
      "module": "./dist/index.js",
      "import": "./dist/index.js"
    }
  },
  "private": false,
  "license": "MIT",
  "author": "Subwaytime <leon.l@nophase.de>",
  "repository": {
    "type": "git",
    "url": "https://github.com/subwaytime/vite-aliases"
  },
  "homepage": "https://github.com/subwaytime/vite-aliases#readme",
  "bugs": "https://github.com/subwaytime/vite-aliases/issues",
  "files": [
    "dist",
    "*.d.ts"
  ],
  "keywords": [
    "vite",
    "vue",
    "alias",
    "aliases",
    "auto",
    "generation"
  ],
  "scripts": {
    "build": "tsup",
    "dev": "npm run build -- --watch src",
    "release": "npx git-ensure -a && npx bumpp --commit --tag --push && npm publish",
    "prepublishOnly": "npm run build"
  },
  "devDependencies": {
    "@types/node": "^22.10.5",
    "terser": "^5.37.0",
    "tsup": "^8.3.5",
    "typescript": "^5.7.2"
  },
  "dependencies": {
    "chokidar": "^4.0.3",
    "comment-json": "^4.2.5",
    "consola": "^3.3.3",
    "fast-glob": "^3.3.3",
    "local-pkg": "^0.5.1"
  },
  "peerDependencies": {
    "vite": "6.x"
  },
  "packageManager": "pnpm@9.15.2",
  "engines": {
    "node": ">=22.x.x"
  }
}


================================================
FILE: src/constants.ts
================================================
import { isPackageExists } from 'local-pkg';
import type { Options } from './types';

export const MODULE_NAME = 'vite-aliases';

export const config: Required<Options> = {
	dir: 'src',

	prefix: '~',
	deep: true,
	depth: 1,

	createGlobalAlias: true,
	createLog: false,
	logPath: 'src/logs',
	adjustDuplicates: false,

	useAbsolute: false,
	useConfig: true,
	ovrConfig: false,
	useIndexes: false,

	dts: false,
	silent: true,
	root: process.cwd(),
};

export const IDEConfig = {
	compilerOptions: {
		baseUrl: '.',
		paths: {},
	},
};


================================================
FILE: src/fs/config.ts
================================================
import { abort, readJSON, interpretFileIndentation, writeJSON } from '../utils';

import { IDEConfig } from '../constants';
import type { Generator } from '../generator';
import type { Process } from '../types';
import type { Indentation } from '../utils';
import { normalizePath } from 'vite';
import { isEmpty } from '../utils';

/**
 * Creates a JS or TS Configfile
 */

export async function writeConfig(gen: Generator, process: Process = 'default') {
	const { root, dir, dts, useConfig, ovrConfig } = gen.options;

	if (!useConfig) {
		return;
	}

	const name = dts ? 'tsconfig' : 'jsconfig';
	const file = normalizePath(`${root}/${name}.json`);

	try {
		let [indentation, json]: [Indentation, any] = await Promise.all([
			interpretFileIndentation(file),
			readJSON(file),
		]);

		if (isEmpty(json) || isEmpty(json.compilerOptions)) {
			json = Object.assign({}, IDEConfig);
		}

		let paths = json.compilerOptions.paths || {};

		if (process === 'remove') {
			paths = Object.fromEntries(
				Object.entries(paths).filter((p: any) => {
					if (Object.values(gen.paths).flat().includes(p[1][0]) && p[1][0].includes(dir)) {
						return p;
					} else if (!p[1][0].includes(dir)) {
						return p;
					}
				}),
			);
		}

		json.compilerOptions.paths = ovrConfig ? gen.paths : { ...paths, ...gen.paths };
		await writeJSON(file, json, process, indentation);
	} catch (error) {
		abort(`Cannot write Config: ${file}.`);
	}
}


================================================
FILE: src/fs/glob.ts
================================================
import fg from 'fast-glob';
import type { Generator } from '../generator';
import { logger } from '../utils';

/**
 * Return all folders from the project directory
 * @param options
 */

export async function getDirectories(gen: Generator) {
	const { dir, root, deep, depth } = gen.options;

	const directories = await fg.sync(deep ? `${dir}/**/*` : `${dir}/*`, {
		ignore: ['node_modules'],
		onlyDirectories: true,
		cwd: root,
		deep: depth,
		absolute: true,
	});

	if (!directories.length) {
		logger.error(new Error('No Directories could be found!'));
	}

	gen.addAlias(directories);
}


================================================
FILE: src/fs/index.ts
================================================
export { writeConfig } from './config';
export { getDirectories } from './glob';
export { writeLog } from './log';


================================================
FILE: src/fs/log.ts
================================================
import { existsSync } from 'node:fs';
import { mkdir } from 'node:fs/promises';
import { normalizePath } from 'vite';

import { MODULE_NAME } from '../constants';
import type { Generator } from '../generator';
import type { Process } from '../types';
import { abort, writeJSON } from '../utils';



/**
 * Creates a Logfile
 * If needed it will also create a Logfolder
 */

export async function writeLog(gen: Generator, process: Process = 'normal') {
	const { createLog, logPath } = gen.options;

	if (!createLog) {
		return;
	}

	const folder = normalizePath(logPath);
	const file = normalizePath(`${folder}/${MODULE_NAME}.json`);
	const data = gen.aliases;

	try {
		if (!existsSync(folder)) {
			await mkdir(folder, { recursive: true });
		}
		await writeJSON(file, data, process);
	} catch (error) {
		abort(`Cannot create Logfolder ${folder}.`);
	}
}


================================================
FILE: src/generator.ts
================================================
import type { Alias, Options, Path } from './types';
import { normalizePath } from 'vite';
import { logger, split, toArray, toCamelCase, toRelative } from './utils';
import { writeLog, writeConfig } from './fs';

import chokidar from 'chokidar';
import { resolve } from 'path';
import { config } from "./constants";
import { getDirectories } from './fs';
import { isPackageExists } from 'local-pkg';

/**
 * Reads the Projectpath and returns Vite Aliases
 * @param options
 * @returns Record<string, string>
 */

export class Generator {
	readonly options: Options;
	readonly fullPath: string;

	public aliases: Alias[] = [];
	public directories = new Set<string>();
	public paths: Path = {};

	constructor(public readonly servermode: string, options?: Partial<Options>) {
		this.options = Object.assign({}, config, options);

		logger.level = this.options.silent ? -999 : 3;

		this.fullPath = normalizePath(resolve(this.options.root, this.options.dir)); // needed for absolute paths in watcher

		this.detectTypescript();

		// only watch on dev not on build
		if (servermode === 'serve') {
			this.observe();
		}
	}

	/**
	 * Add Alias
	 * @param path
	 */

	addAlias(path: string | string[]) {
		toArray(path).forEach((p) => {
			const correctedPath = normalizePath(p);
			const folders = split(correctedPath.replace(this.fullPath, this.options.dir), '/').filter(Boolean);
			const lastDir = folders.slice(-1)[0];
			let key = `${this.options.prefix}${lastDir}`;

			const uniqueFolders = [...new Set(folders)] as string[];
			this.checkForDuplicates(correctedPath, folders, uniqueFolders);

			if(this.aliases.some((a) => a.find === key)) {
				logger.warn(
					'There are duplicate Aliases generated, either fix the folderstructure or enable adjustDuplicates.',
				);

				if (this.options.adjustDuplicates && this.options.depth > 1) {
					const name = folders.filter((f) => !split(normalizePath(this.options.dir), '/').includes(f)).join('-');
					key = `${this.options.prefix}${toCamelCase(name)}`;
				}
			}

			if(lastDir === this.options.dir && this.options.createGlobalAlias) {
				key = `${this.options.prefix}`;
			}

			this.directories.add(p);
			this.aliases.push({
				find: `${key}`,
				replacement: `${p}`
			});

			const configPath = this.options.useAbsolute ? correctedPath : toRelative(correctedPath, this.options.dir);

			if(this.options.useIndexes) {
				this.paths[key] = [configPath];
			} else {
				this.paths[`${key}/*`] = [`${configPath}/*`];
			}
		});
	}

	/**
	 * Remove Alias
	 * @param path
	 */

	removeAlias(path: string | string[]) {
		toArray(path).forEach((p) => {
			const correctedPath = normalizePath(p);

			if(this.directories.has(correctedPath)) {
				this.directories.delete(correctedPath);
				this.aliases = this.aliases.filter((a) => a.replacement != correctedPath);
				this.paths = Object.fromEntries(
					Object.entries(this.paths).filter(
						(configPath) => configPath[1][0].slice(0, -2) != (
							this.options.useIndexes ? correctedPath : `${correctedPath}/*`
						)
					)
				)
			}
		});
	}

	/**
	 * Check for duplicates before adding them as aliases
	 * @param initialPath
	 * @param folders
	 * @param uniqueFolders
	 */

	checkForDuplicates(initialPath: string, folders: string[], uniqueFolders: string[]) {
		if (folders.length !== uniqueFolders.length) {
			const duplicateFolders = [...folders].sort().filter((f, i, self) => {
				if (self[i + 1] === self[i]) {
					return f;
				}
			});

			logger.warn(`Path: '${initialPath}' contains multiple folders with same name: ${duplicateFolders.toString()}.`);
		}
	}

	/**
	 *  Check if TypeScript is installed
	 */

	detectTypescript() {
		this.options.dts = this.options.dts || isPackageExists(`${this.options.root}/node_modules/typescript`) || isPackageExists('typescript');
		logger.info(this.options.dts ? 'TypeScript got detected.' : 'TypeScript is not installed, fallback to JS only.');
	}

	/**
	 * Glob directories
	 * writes Logfile
	 * writes IDE Config
	 */

	private searched: boolean = false;

	async init() {
		if (this.searched) {
			return;
		}

		await getDirectories(this);

		// add global alias if allowed
		if (this.options.createGlobalAlias) {
			this.addAlias(this.fullPath);
		}

		// start alias logger if allowed
		writeLog(this);

		// write js/ts config if allowed
		writeConfig(this);

		this.searched = true;
	}

	/**
	 * Watch for directory changes
	 */

	observe() {
		const watcher = chokidar.watch(this.fullPath, { ignoreInitial: true, depth: this.options.depth });

		watcher
			.on('addDir', (path) => {
				this.addAlias(path);
				writeLog(this, 'add');
				writeConfig(this, 'add');
				logger.info(`Watcher added new Path: ${path}`);
			})
			.on('unlinkDir', (path) => {
				this.removeAlias(path);
				writeLog(this, 'remove');
				writeConfig(this, 'remove');
				logger.info(`Watcher removed Path: ${path}`);
			});
	}
}


================================================
FILE: src/index.ts
================================================
import type { Plugin } from 'vite';
import { Generator } from './generator';
import type { Options } from './types';
import { toArray } from './utils';

export function ViteAliases(options: Partial<Options> = {}): Plugin {
	let gen: Generator;

	return {
		name: 'vite-aliases',
		enforce: 'pre',
		config(config, { command }) {
			gen = new Generator(command, options);
			gen.init();

			config.resolve = {
				alias: config.resolve?.alias ? [...toArray(config.resolve.alias as any), ...gen.aliases] : gen.aliases,
			};
		},
	};
};


================================================
FILE: src/types.ts
================================================
/**
 * Library options.
 */
export interface Options {
	/**
	 * Relative path to the project directory
	 * @default 'src'
	 */
	dir: string;

	/**
	 * Prefix symbol for the aliases
	 * @default '~'
	 */
	prefix: string;

	/**
	 * Allow searching for subdirectories
	 * @default true
	 */
	deep: boolean;

	/**
	 * Search depthlevel for subdirectories
	 * @default 1
	 */
	depth: number;

	/**
	 * Creates a Logfile
	 * use `logPath` to change the location
	 * @default false
	 */
	createLog: boolean;

	/**
	 * Path for Logfile
	 * @default 'src/logs'
	 */

	logPath: string;

	/**
	 * Create global project directory alias
	 * @default true
	 */
	createGlobalAlias: boolean;

	/**
	 * Turns duplicates into camelCased path aliases
	 * @default false
	 */
	adjustDuplicates: boolean;

	/**
	 * Used paths in JS/TS configs will now be relative to baseUrl
	 * @default false
	 */
	useAbsolute: boolean;

	/**
	 * Adds seperate index paths
	 * @default false
	 */
	useIndexes: boolean;

	/**
	 * Generates paths in IDE config file
	 * works with JS or TS
	 * @default true
	 */
	useConfig: boolean;

	/**
	 * Override config paths
	 * @default false
	 */
	ovrConfig: boolean

	/**
	 * Will generate Paths in tsconfig
	 * used in combination with `useConfig`
	 * Typescript will be auto detected
	 * @default false
	 */
	dts: boolean;

	/**
	 * Disables any terminal output
	 * @default true
	 */
	silent: boolean;

	/**
	 * Root path of Vite project
	 * @default 'process.cwd()'
	 */
	root: string;
}

export interface Alias {
	find: string;
	replacement: string;
}

export interface Path {
	[key: string]: string[];
}

export type Process = 'add' | 'remove' | 'default' | 'normal';


================================================
FILE: src/utils.ts
================================================
import { createConsola } from 'consola';
import fs from 'node:fs/promises';
import { normalizePath } from 'vite';
import { MODULE_NAME } from './constants';
import type { Process } from './types';
import { parse, stringify } from 'comment-json';

/**
 * Split String on Seperator into Array
 * @param string
 * @param seperator
 */

export function split(string: string, seperator: string): string[] {
	return string.split(seperator);
}

/**
 * Turns a Value into Array
 * @param string
 * @param seperator
 */

export function toArray<T>(value: T | T[]): T[] {
	if (Array.isArray(value)) {
		return value;
	} else {
		return [value];
	}
}

/**
 * Turns a absolute Path into an Relative Path
 * @param string
 * @param seperator
 */

export function toRelative(path: string, dir: string): string {
	let folders = split(normalizePath(path), '/');
	folders = folders.slice(
		folders.findIndex((f) => f === dir),
		folders.length,
	);
	return normalizePath(`./${folders.join('/')}`);
}

/**
 * Turns any String into Camelcased String
 * @param string
 */

export function toCamelCase(string: string): string {
	return string.trim().replace(/[-_\s]+(.)?/g, (_, c) => (c ? c.toUpperCase() : ''));
}

/**
 * Check if Value is Empty
 * supports: Array, Object, String
 * @param value
 */

export function isEmpty(value: any) {
	if (value === null || value === undefined || value === '{}' || value === '' || JSON.stringify(value) === '{}') {
		return true;
	}

	if ((Array.isArray(value) && Object.keys(value).length <= 0) || (Array.isArray(value) && value.length === 0)) {
		return true;
	}

	// if (Reflect.ownKeys(value).length === 0 && value.constructor === Object) {
	// 	return true;
	// }

	return false;
}

/**
 * Simple Info/Warn/Error Consola Instance
 */

export const logger = createConsola({ defaults: { message: `[${MODULE_NAME}] -` } });
export function abort(message: any) {
	throw logger.error(new Error(message));
}

/**
 * Reads a JSON File
 */

export async function readJSON(path: string) {
	try {
		const file = (await fs.readFile(path, 'utf-8')).toString();
		logger.success(`Config: ${path} successfully read!`);
		return parse(file);
	} catch (error) {
		logger.error(`File: ${path} was not found!`);
	}
}

/**
 * Writes a JSON File
 */

export const DEFAULT_INDENTATION: Indentation = 4; // default to 4 spaces before introducing the intepretation feature

export async function writeJSON(path: string, data: any, process: Process, indentation: Indentation = DEFAULT_INDENTATION) {
	const name = path.replace(/^.*[\\\/]/, '');
	const state = process === 'add' || process === 'default' ? 'created' : 'updated';

	try {
		await fs.writeFile(path, stringify(data, null, indentation));
		logger.success(`File: ${name} successfully ${state}`);
	} catch (error) {
		logger.error(`File: ${name} could not be ${state}.`);
		abort(error);
	}
}

/**
 * Interprets file indentations
 */

export type Indentation = number | '\t';

export async function interpretFileIndentation(path: string): Promise<Indentation> {
	const name = path.replace(/^.*[\\\/]/, '');

	try {
		const content = (await fs.readFile(path, 'utf-8')).toString();
		const lines = content.split('\n');
		const secondLine = lines[1];
		let indentation: Indentation;

		if (secondLine.startsWith('\t')) {
			indentation = '\t';
		} else {
			const firstNonSpaceCharacter = split(secondLine, '').findIndex(char => char !== ' ');

			if (firstNonSpaceCharacter === -1) {
				logger.error('Failed to interpret indentation from file. (No indentation found)');
			}

			indentation = firstNonSpaceCharacter;
		}

		logger.info(`File: Interpreted indentation as (${typeof indentation === 'number' ? `${indentation} spaces` : 'tabs'}) from file ${name} successfully`);

		return indentation;
	} catch (error) {
		logger.error(`File: Failed to interpret indentation from ${name}.`);
		return DEFAULT_INDENTATION;
	}
}


================================================
FILE: tsconfig.json
================================================
{
    "compilerOptions": {
        "module": "ESNext",
        "target": "ESNext",
        "lib": [
            "ESNext"
        ],
        "allowSyntheticDefaultImports": true,
        "esModuleInterop": false,
        "strict": true,
        "strictNullChecks": true,
        "moduleResolution": "node",
        "resolveJsonModule": true
    },
    "exclude": [
        "**/dist",
        "**/node_modules",
        "**/test"
    ]
}

================================================
FILE: tsup.config.ts
================================================
import type { Options } from 'tsup';

export const tsup: Options = {
	entry: ['./src/index.ts'],
	format: ['esm'],
	minify: 'terser',
	dts: true,
	splitting: true,
	clean: true,
	shims: true,
	treeshake: 'smallest'
};
Download .txt
gitextract_2w2y_h5y/

├── .gitattributes
├── .github/
│   └── FUNDING.yml
├── .gitignore
├── .prettierrc
├── LICENSE
├── README.md
├── example/
│   ├── index.html
│   ├── package.json
│   ├── src/
│   │   ├── app.vue
│   │   ├── components/
│   │   │   └── navigation.vue
│   │   ├── logs/
│   │   │   └── vite-aliases.json
│   │   ├── main.ts
│   │   ├── pages/
│   │   │   └── home.vue
│   │   └── utils/
│   │       └── random.ts
│   ├── tsconfig.json
│   ├── vite-aliases.json
│   └── vite.config.ts
├── package.json
├── src/
│   ├── constants.ts
│   ├── fs/
│   │   ├── config.ts
│   │   ├── glob.ts
│   │   ├── index.ts
│   │   └── log.ts
│   ├── generator.ts
│   ├── index.ts
│   ├── types.ts
│   └── utils.ts
├── tsconfig.json
└── tsup.config.ts
Download .txt
SYMBOL INDEX (29 symbols across 9 files)

FILE: example/src/utils/random.ts
  function random (line 5) | function random() {

FILE: src/constants.ts
  constant MODULE_NAME (line 4) | const MODULE_NAME = 'vite-aliases';

FILE: src/fs/config.ts
  function writeConfig (line 14) | async function writeConfig(gen: Generator, process: Process = 'default') {

FILE: src/fs/glob.ts
  function getDirectories (line 10) | async function getDirectories(gen: Generator) {

FILE: src/fs/log.ts
  function writeLog (line 17) | async function writeLog(gen: Generator, process: Process = 'normal') {

FILE: src/generator.ts
  class Generator (line 18) | class Generator {
    method constructor (line 26) | constructor(public readonly servermode: string, options?: Partial<Opti...
    method addAlias (line 46) | addAlias(path: string | string[]) {
    method removeAlias (line 92) | removeAlias(path: string | string[]) {
    method checkForDuplicates (line 117) | checkForDuplicates(initialPath: string, folders: string[], uniqueFolde...
    method detectTypescript (line 133) | detectTypescript() {
    method init (line 146) | async init() {
    method observe (line 171) | observe() {

FILE: src/index.ts
  function ViteAliases (line 6) | function ViteAliases(options: Partial<Options> = {}): Plugin {

FILE: src/types.ts
  type Options (line 4) | interface Options {
  type Alias (line 101) | interface Alias {
  type Path (line 106) | interface Path {
  type Process (line 110) | type Process = 'add' | 'remove' | 'default' | 'normal';

FILE: src/utils.ts
  function split (line 14) | function split(string: string, seperator: string): string[] {
  function toArray (line 24) | function toArray<T>(value: T | T[]): T[] {
  function toRelative (line 38) | function toRelative(path: string, dir: string): string {
  function toCamelCase (line 52) | function toCamelCase(string: string): string {
  function isEmpty (line 62) | function isEmpty(value: any) {
  function abort (line 83) | function abort(message: any) {
  function readJSON (line 91) | async function readJSON(path: string) {
  constant DEFAULT_INDENTATION (line 105) | const DEFAULT_INDENTATION: Indentation = 4;
  function writeJSON (line 107) | async function writeJSON(path: string, data: any, process: Process, inde...
  type Indentation (line 124) | type Indentation = number | '\t';
  function interpretFileIndentation (line 126) | async function interpretFileIndentation(path: string): Promise<Indentati...
Condensed preview — 29 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (31K chars).
[
  {
    "path": ".gitattributes",
    "chars": 66,
    "preview": "# Auto detect text files and perform LF normalization\n* text=auto\n"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 18,
    "preview": "github: subwaytime"
  },
  {
    "path": ".gitignore",
    "chars": 113,
    "preview": "node_modules\n.DS_Store\ndist\n.prettierignore\n.vscode\npackage-lock.json\nexample/jsconfig.json\nexmaple/tsconfig.json"
  },
  {
    "path": ".prettierrc",
    "chars": 224,
    "preview": "{\n  \"endOfLine\": \"auto\",\n  \"jsxBracketSameLine\": true,\n  \"jsxSingleQuote\": true,\n  \"printWidth\": 120,\n  \"singleQuote\": t"
  },
  {
    "path": "LICENSE",
    "chars": 1107,
    "preview": "MIT License\n\nCopyright (c) 2020-PRESENT Leon Langer<https://github.com/subwaytime>\n\nPermission is hereby granted, free o"
  },
  {
    "path": "README.md",
    "chars": 3776,
    "preview": "<h2 align=\"left\">vite-aliases</h2>\n\n<p align=\"left\">Alias auto generation for Vite 6</p>\n\n<p align=\"left\">\n<a href=\"http"
  },
  {
    "path": "example/index.html",
    "chars": 271,
    "preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"UTF-8\">\n  <meta name=\"viewport\" content=\"width=device-width, in"
  },
  {
    "path": "example/package.json",
    "chars": 766,
    "preview": "{\n\t\"name\": \"@vite-aliases/example\",\n\t\"description\": \"Example: Alias auto generation for Vite\",\n\t\"version\": \"0.1.0\",\n\t\"pr"
  },
  {
    "path": "example/src/app.vue",
    "chars": 1356,
    "preview": "<template>\n\t<div class=\"wrapper\">\n\t\t<h1> Vite Aliases Example </h1>\n\t\t<home />\n\t\t<navigation />\n\t\t<div class=\"box\">\n\t\t\t<"
  },
  {
    "path": "example/src/components/navigation.vue",
    "chars": 110,
    "preview": "<template>\n\t<p> Navigation loaded from\n\t\t<br />\n\t\t<code> ~components/navigation.vue </code>\n\t</p>\n</template>\n"
  },
  {
    "path": "example/src/logs/vite-aliases.json",
    "chars": 619,
    "preview": "[\n    {\n        \"find\": \"@assets\",\n        \"replacement\": \"D:/work/vite-aliases/example/src/assets\"\n    },\n    {\n       "
  },
  {
    "path": "example/src/main.ts",
    "chars": 90,
    "preview": "import App from './app.vue'\nimport { createApp } from 'vue'\n\ncreateApp(App).mount('#app');"
  },
  {
    "path": "example/src/pages/home.vue",
    "chars": 92,
    "preview": "<template>\n\t<p> Home loaded from\n\t\t<br />\n\t\t<code> ~pages/home.vue </code>\n\t</p>\n</template>"
  },
  {
    "path": "example/src/utils/random.ts",
    "chars": 153,
    "preview": "/**\n * Return a Random Hexcode\n */\n\nexport function random() {\n\tlet n = (Math.random() * 0xfffff * 1000000).toString(16)"
  },
  {
    "path": "example/tsconfig.json",
    "chars": 438,
    "preview": "{\n    \"compilerOptions\": {\n        \"baseUrl\": \".\",\n        \"paths\": {\n            \"~components/*\": [\n                \"sr"
  },
  {
    "path": "example/vite-aliases.json",
    "chars": 564,
    "preview": "[\n    {\n        \"find\": \"~components\",\n        \"replacement\": \"/home/subway/work/vite-aliases/example/src/components\"\n  "
  },
  {
    "path": "example/vite.config.ts",
    "chars": 329,
    "preview": "import vue from '@vitejs/plugin-vue';\nimport { defineConfig } from 'vitest/config';\nimport { ViteAliases } from '../dist"
  },
  {
    "path": "package.json",
    "chars": 1440,
    "preview": "{\n  \"name\": \"vite-aliases\",\n  \"description\": \"Alias auto generation for Vite\",\n  \"version\": \"0.11.8\",\n  \"type\": \"module\""
  },
  {
    "path": "src/constants.ts",
    "chars": 536,
    "preview": "import { isPackageExists } from 'local-pkg';\nimport type { Options } from './types';\n\nexport const MODULE_NAME = 'vite-a"
  },
  {
    "path": "src/fs/config.ts",
    "chars": 1435,
    "preview": "import { abort, readJSON, interpretFileIndentation, writeJSON } from '../utils';\n\nimport { IDEConfig } from '../constant"
  },
  {
    "path": "src/fs/glob.ts",
    "chars": 592,
    "preview": "import fg from 'fast-glob';\nimport type { Generator } from '../generator';\nimport { logger } from '../utils';\n\n/**\n * Re"
  },
  {
    "path": "src/fs/index.ts",
    "chars": 115,
    "preview": "export { writeConfig } from './config';\nexport { getDirectories } from './glob';\nexport { writeLog } from './log';\n"
  },
  {
    "path": "src/fs/log.ts",
    "chars": 857,
    "preview": "import { existsSync } from 'node:fs';\nimport { mkdir } from 'node:fs/promises';\nimport { normalizePath } from 'vite';\n\ni"
  },
  {
    "path": "src/generator.ts",
    "chars": 4893,
    "preview": "import type { Alias, Options, Path } from './types';\nimport { normalizePath } from 'vite';\nimport { logger, split, toArr"
  },
  {
    "path": "src/index.ts",
    "chars": 535,
    "preview": "import type { Plugin } from 'vite';\nimport { Generator } from './generator';\nimport type { Options } from './types';\nimp"
  },
  {
    "path": "src/types.ts",
    "chars": 1680,
    "preview": "/**\n * Library options.\n */\nexport interface Options {\n\t/**\n\t * Relative path to the project directory\n\t * @default 'src"
  },
  {
    "path": "src/utils.ts",
    "chars": 3884,
    "preview": "import { createConsola } from 'consola';\nimport fs from 'node:fs/promises';\nimport { normalizePath } from 'vite';\nimport"
  },
  {
    "path": "tsconfig.json",
    "chars": 435,
    "preview": "{\n    \"compilerOptions\": {\n        \"module\": \"ESNext\",\n        \"target\": \"ESNext\",\n        \"lib\": [\n            \"ESNext\""
  },
  {
    "path": "tsup.config.ts",
    "chars": 218,
    "preview": "import type { Options } from 'tsup';\n\nexport const tsup: Options = {\n\tentry: ['./src/index.ts'],\n\tformat: ['esm'],\n\tmini"
  }
]

About this extraction

This page contains the full source code of the Subwaytime/vite-aliases GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 29 files (26.1 KB), approximately 8.0k tokens, and a symbol index with 29 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!