diff options
Diffstat (limited to 'packages/config')
-rw-r--r-- | packages/config/.eslintrc.js | 4 | ||||
-rw-r--r-- | packages/config/app.tsconfig.json | 7 | ||||
-rw-r--r-- | packages/config/base.tsconfig.json | 22 | ||||
-rw-r--r-- | packages/config/eslint/base.js | 79 | ||||
-rw-r--r-- | packages/config/eslint/tailwind.js | 23 | ||||
-rw-r--r-- | packages/config/eslint/web.js | 22 | ||||
-rw-r--r-- | packages/config/index.js | 3 | ||||
-rw-r--r-- | packages/config/package.json | 29 | ||||
-rw-r--r-- | packages/config/vite/index.ts | 27 | ||||
-rw-r--r-- | packages/config/vite/relAlias.ts | 77 |
10 files changed, 293 insertions, 0 deletions
diff --git a/packages/config/.eslintrc.js b/packages/config/.eslintrc.js new file mode 100644 index 0000000..93a0c63 --- /dev/null +++ b/packages/config/.eslintrc.js @@ -0,0 +1,4 @@ +/** @type {import('eslint').ESLint.ConfigData} */ +module.exports = { + extends: [require.resolve('./eslint/base.js'), require.resolve('./eslint/tailwind.js')] +}; diff --git a/packages/config/app.tsconfig.json b/packages/config/app.tsconfig.json new file mode 100644 index 0000000..e17622d --- /dev/null +++ b/packages/config/app.tsconfig.json @@ -0,0 +1,7 @@ +{ + "extends": "./base.tsconfig.json", + "compilerOptions": { + "noEmit": true, + "emitDeclarationOnly": false + } +} diff --git a/packages/config/base.tsconfig.json b/packages/config/base.tsconfig.json new file mode 100644 index 0000000..2d27ce4 --- /dev/null +++ b/packages/config/base.tsconfig.json @@ -0,0 +1,22 @@ +{ + "$schema": "https://json.schemastore.org/tsconfig", + "display": "Default", + "compilerOptions": { + "strict": true, + "jsx": "react-jsx", + "esModuleInterop": true, + "skipLibCheck": true, + "preserveWatchOutput": true, + "forceConsistentCasingInFileNames": true, + "allowSyntheticDefaultImports": true, + "noUncheckedIndexedAccess": true, + "composite": true, + "declaration": true, + "emitDeclarationOnly": true, + "moduleResolution": "Node", + "resolveJsonModule": true, + "module": "ESNext", + "target": "ESNext", + "types": ["vite/client"] + } +} diff --git a/packages/config/eslint/base.js b/packages/config/eslint/base.js new file mode 100644 index 0000000..200f17d --- /dev/null +++ b/packages/config/eslint/base.js @@ -0,0 +1,79 @@ +const path = require('node:path'); + +/** @type {import('eslint').ESLint.ConfigData} */ +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + ecmaFeatures: { + jsx: true + }, + ecmaVersion: 12, + sourceType: 'module' + }, + extends: [ + 'eslint:recommended', + 'plugin:react/recommended', + 'plugin:react-hooks/recommended', + 'plugin:@typescript-eslint/recommended', + 'plugin:astro/recommended', + 'plugin:astro/jsx-a11y-recommended', + 'turbo', + 'prettier' + ], + plugins: ['react', 'jsx-a11y'], + rules: { + 'react/display-name': 'off', + 'react/prop-types': 'off', + 'react/no-unescaped-entities': 'off', + 'react/react-in-jsx-scope': 'off', + 'react-hooks/rules-of-hooks': 'warn', + 'react-hooks/exhaustive-deps': 'warn', + '@typescript-eslint/no-unused-vars': 'off', + '@typescript-eslint/ban-ts-comment': 'off', + '@typescript-eslint/no-explicit-any': 'off', + '@typescript-eslint/no-var-requires': 'off', + '@typescript-eslint/no-non-null-assertion': 'off', + '@typescript-eslint/explicit-module-boundary-types': 'off', + '@typescript-eslint/no-empty-interface': 'off', + '@typescript-eslint/no-empty-function': 'off', + '@typescript-eslint/ban-types': 'off', + 'no-control-regex': 'off', + 'no-mixed-spaces-and-tabs': ['warn', 'smart-tabs'], + 'turbo/no-undeclared-env-vars': [ + 'error', + { + cwd: path.resolve(path.join(__dirname, '..', '..', '..')) + } + ] + }, + ignorePatterns: ['dist', '**/*.js', '**/*.json', 'node_modules'], + settings: { + react: { + version: 'detect' + } + }, + overrides: [ + { + files: ['*.astro'], + parser: 'astro-eslint-parser', + parserOptions: { + parser: '@typescript-eslint/parser', + extraFileExtensions: ['.astro'] + }, + rules: { + 'astro/no-set-html-directive': 2, + 'indent': 'off' + } + }, + { + files: ['*.ts', '*.d.ts', '*.tsx', '*.js', '*.jsx', '*.mjs', '*.cjs'], + parser: '@typescript-eslint/parser', + parserOptions: { + parser: '@typescript-eslint/parser' + }, + rules: { + indent: 'off' + } + } + ] +}; diff --git a/packages/config/eslint/tailwind.js b/packages/config/eslint/tailwind.js new file mode 100644 index 0000000..9ac36ae --- /dev/null +++ b/packages/config/eslint/tailwind.js @@ -0,0 +1,23 @@ +const path = require('node:path'); + +/** @type {import('eslint').ESLint.ConfigData} */ +module.exports = { + extends: ['plugin:tailwindcss/recommended'], + rules: { + 'tailwindcss/no-custom-classname': 'off', + 'tailwindcss/classnames-order': [ + 'warn', + { + config: path.resolve( + path.join(__dirname, '../../..', 'packages/ui/tailwind.config.js') + ) + } + ] + }, + settings: { + tailwindcss: { + callees: ['classnames', 'clsx', 'ctl', 'cva', 'tw', 'twStyle'], + tags: ['tw', 'twStyle'] + } + } +}; diff --git a/packages/config/eslint/web.js b/packages/config/eslint/web.js new file mode 100644 index 0000000..dc010b3 --- /dev/null +++ b/packages/config/eslint/web.js @@ -0,0 +1,22 @@ +/** @type {import('eslint').ESLint.ConfigData} */ +module.exports = { + extends: [require.resolve('./base.js'), require.resolve('./tailwind.js')], + ignorePatterns: ['public', 'vite.config.ts'], + env: { + browser: true, + node: true + }, + rules: { + 'no-restricted-syntax': [ + 'error', + { + selector: "CallExpression[callee.name='useParams']", + message: 'useParams is illegal, use useZodRouteParams!' + }, + { + selector: "CallExpression[callee.name='useSearchParams']", + message: 'useSearchParams is illegal, use useZodSearchParams!' + } + ] + } +}; diff --git a/packages/config/index.js b/packages/config/index.js new file mode 100644 index 0000000..524af3b --- /dev/null +++ b/packages/config/index.js @@ -0,0 +1,3 @@ +module.exports = { + vite: require('./vite') +}; diff --git a/packages/config/package.json b/packages/config/package.json new file mode 100644 index 0000000..2a16d61 --- /dev/null +++ b/packages/config/package.json @@ -0,0 +1,29 @@ +{ + "name": "@polyfrost/config", + "version": "0.0.0", + "exports": { + "./*": "./*", + "./vite": "./vite", + "./vite/relAlias": "./vite/relAlias" + }, + "scripts": { + "lint": "eslint . --cache" + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "^6.7.5", + "@typescript-eslint/parser": "^6.7.5", + "eslint": "^8.51.0", + "eslint-config-turbo": "^1.10.15", + "eslint-config-prettier": "^9.0.0", + "eslint-plugin-prettier": "^5.0.1", + "eslint-plugin-react": "^7.33.2", + "eslint-plugin-react-hooks": "^4.6.0", + "eslint-plugin-tailwindcss": "^3.13.0", + "eslint-plugin-astro": "^0.29.1", + "eslint-plugin-jsx-a11y": "^6.7.1", + "eslint-utils": "^3.0.0", + "regexpp": "^3.2.0", + "vite-plugin-html": "^3.2.0", + "vite-plugin-svgr": "^4.1.0" + } +} diff --git a/packages/config/vite/index.ts b/packages/config/vite/index.ts new file mode 100644 index 0000000..a9306a6 --- /dev/null +++ b/packages/config/vite/index.ts @@ -0,0 +1,27 @@ +import react from '@vitejs/plugin-react'; +import { defineConfig } from 'vite'; +import { createHtmlPlugin } from 'vite-plugin-html'; +import svg from 'vite-plugin-svgr'; +import tsconfigPaths from 'vite-tsconfig-paths'; + +export default defineConfig({ + plugins: [ + tsconfigPaths(), + react(), + svg({ svgrOptions: { icon: true } }), + createHtmlPlugin({ + minify: true + }) + ], + css: { + modules: { + localsConvention: 'camelCaseOnly' + } + }, + root: 'src', + build: { + sourcemap: true, + outDir: '../dist', + assetsDir: '.' + } +}); diff --git a/packages/config/vite/relAlias.ts b/packages/config/vite/relAlias.ts new file mode 100644 index 0000000..1a502b5 --- /dev/null +++ b/packages/config/vite/relAlias.ts @@ -0,0 +1,77 @@ +import fs from 'fs/promises'; +import path from 'path'; +import { Alias } from 'vite'; + +const projectPath = path.resolve(__dirname, '../../../'); +const pkgJsonCache = new Map(); + +const SRC_DIR_PATH = `${path.sep}src${path.sep}`; + +const resolver: Alias = { + find: /^(~\/.+)/, + replacement: '$1', + async customResolver(source, importer) { + let root: null | string = null; + + if (importer) importer = path.normalize(importer); + + const [_, sourcePath] = source.split('~/'); + + const relativeImporter = importer?.replace(projectPath, ''); + if (relativeImporter && relativeImporter.includes(SRC_DIR_PATH)) { + const [pkg] = relativeImporter.split(SRC_DIR_PATH); + root = path.join(projectPath, pkg, 'src'); + } else if (importer) { + const pathObj = path.parse(importer); + + let parent = pathObj.dir; + while (parent !== pathObj.root) { + parent = path.dirname(parent); + + let hasPkgJson = pkgJsonCache.get(parent); + + if (hasPkgJson === undefined) + try { + await fs.stat(path.join(parent, 'package.json')); + pkgJsonCache.set(parent, (hasPkgJson = true)); + } catch { + pkgJsonCache.set(parent, (hasPkgJson = false)); + } + + if (hasPkgJson) { + root = parent; + break; + } + } + + if (root === null) + throw new Error(`Failed to resolve import path ${source} in file ${importer}`); + } else { + throw new Error(`Failed to resolve import path ${source} in file ${importer}`); + } + + const absolutePath = path.join(root, sourcePath); + + const folderItems = await fs.readdir(path.join(absolutePath, '..')); + + const item = folderItems.find((i) => i.startsWith(sourcePath.split('/').at(-1)!))!; + + const fullPath = absolutePath + path.extname(item); + + const stats = await fs.stat(fullPath); + + if (stats.isDirectory()) { + const directoryItems = await fs.readdir(absolutePath + path.extname(item)); + + const indexFile = directoryItems.find((i) => i.startsWith('index')); + if (!indexFile) + throw new Error(`Failed to resolve import path ${source} in file ${importer}`); + + return path.join(absolutePath, indexFile); + } else { + return fullPath; + } + } +}; + +export default resolver; |