├── .gitignore ├── .prettierrc ├── README.md ├── index.html ├── package.json ├── plugin-dev ├── index.ts ├── out │ └── index.js ├── package.json └── tsconfig.json ├── pnpm-lock.yaml ├── public └── vite.svg ├── src ├── App.css ├── App.tsx ├── LoadFileService.ts ├── ReadFileService.ts ├── assets │ └── react.svg ├── index.css ├── main.tsx └── vite-env.d.ts ├── tsconfig.json ├── tsconfig.node.json └── vite.config.ts /.gitignore: -------------------------------------------------------------------------------- 1 | # Logs 2 | logs 3 | *.log 4 | npm-debug.log* 5 | yarn-debug.log* 6 | yarn-error.log* 7 | pnpm-debug.log* 8 | lerna-debug.log* 9 | 10 | node_modules 11 | dist 12 | dist-ssr 13 | *.local 14 | .cache 15 | 16 | # Editor directories and files 17 | .vscode/* 18 | !.vscode/extensions.json 19 | .idea 20 | .DS_Store 21 | *.suo 22 | *.ntvs* 23 | *.njsproj 24 | *.sln 25 | *.sw? 26 | -------------------------------------------------------------------------------- /.prettierrc: -------------------------------------------------------------------------------- 1 | { 2 | "printWidth": 80, 3 | "singleQuote": false, 4 | "trailingComma": "all", 5 | "semi": true, 6 | "arrowParens": "always" 7 | } 8 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Effect Starter Vite (TSC) 2 | 3 | This project is a quick-start that uses the standard typescript compiler together with the `@effect/language-service` plugin to improve developer experience. 4 | 5 | ## Install & Run 6 | 7 | Run `pnpm install` and `pnpm run dev` to start the `src/App.tsx` program. 8 | -------------------------------------------------------------------------------- /index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | Vite + React + TS 8 | 9 | 10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "starter-vite-tsc", 3 | "private": true, 4 | "version": "0.0.1", 5 | "type": "module", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview", 10 | "clean": "rm -rf .cache && rm -rf node_modules/.vite", 11 | "build-plugin": "tsc -p plugin-dev/tsconfig.json && yarn clean && yarn upgrade @effect/plugin-vite-react" 12 | }, 13 | "dependencies": { 14 | "effect": "2.0.0-next.17", 15 | "react": "^18.2.0", 16 | "react-dom": "^18.2.0" 17 | }, 18 | "devDependencies": { 19 | "@babel/core": "^7.22.9", 20 | "@effect/language-service": "^0.0.19", 21 | "@effect/vite-plugin-react": "link:plugin-dev", 22 | "@rollup/pluginutils": "^5.0.2", 23 | "@types/babel__core": "^7.20.1", 24 | "@types/node": "^18.16.19", 25 | "@types/react": "^18.2.15", 26 | "@types/react-dom": "^18.2.7", 27 | "@vitejs/plugin-react": "^3.1.0", 28 | "babel-plugin-annotate-pure-calls": "^0.4.0", 29 | "typescript": "5.1.6", 30 | "vite": "^4.4.4" 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /plugin-dev/index.ts: -------------------------------------------------------------------------------- 1 | import { createFilter } from "@rollup/pluginutils"; 2 | import fs from "fs"; 3 | import * as nodePath from "path"; 4 | import ts from "typescript"; 5 | import type * as V from "vite"; 6 | import reactPlugin, { Options } from "@vitejs/plugin-react"; 7 | 8 | const configPath = ts.findConfigFile("./", ts.sys.fileExists, "tsconfig.json"); 9 | 10 | if (!configPath) { 11 | throw new Error('Could not find a valid "tsconfig.json".'); 12 | } 13 | 14 | const baseDir = nodePath.dirname(nodePath.resolve(configPath)); 15 | const cacheDir = nodePath.join(baseDir, ".cache/effect"); 16 | 17 | if (!fs.existsSync(cacheDir)) { 18 | fs.mkdirSync(cacheDir, { recursive: true }); 19 | } 20 | 21 | const registry = ts.createDocumentRegistry(); 22 | const files = new Set(); 23 | 24 | let services: ts.LanguageService; 25 | 26 | const getScriptVersion = (fileName: string): string => { 27 | const modified = ts.sys.getModifiedTime!(fileName); 28 | if (modified) { 29 | return ts.sys.createHash!(`${fileName}${modified.toISOString()}`); 30 | } else { 31 | files.delete(fileName); 32 | } 33 | return "none"; 34 | }; 35 | 36 | const init = () => { 37 | const { config } = ts.parseConfigFileTextToJson( 38 | configPath, 39 | ts.sys.readFile(configPath)! 40 | ); 41 | 42 | Object.assign(config.compilerOptions, { 43 | sourceMap: false, 44 | inlineSourceMap: true, 45 | inlineSources: true, 46 | noEmit: false, 47 | declaration: false, 48 | declarationMap: false, 49 | module: "ESNext", 50 | target: "ES2022", 51 | }); 52 | 53 | const tsconfig = ts.parseJsonConfigFileContent(config, ts.sys, baseDir!); 54 | 55 | if (!tsconfig.options) tsconfig.options = {}; 56 | 57 | tsconfig.fileNames.forEach((fileName) => { 58 | files.add(fileName); 59 | }); 60 | 61 | const servicesHost: ts.LanguageServiceHost = { 62 | realpath: (fileName) => ts.sys.realpath?.(fileName) ?? fileName, 63 | getScriptFileNames: () => Array.from(files), 64 | getScriptVersion: getScriptVersion, 65 | getScriptSnapshot: (fileName) => { 66 | if (!ts.sys.fileExists(fileName)) { 67 | return undefined; 68 | } 69 | return ts.ScriptSnapshot.fromString( 70 | ts.sys.readFile(fileName)!.toString() 71 | ); 72 | }, 73 | getCurrentDirectory: () => process.cwd(), 74 | getCompilationSettings: () => tsconfig.options, 75 | getDefaultLibFileName: (options) => ts.getDefaultLibFilePath(options), 76 | fileExists: (fileName) => ts.sys.fileExists(fileName), 77 | readFile: (fileName) => ts.sys.readFile(fileName), 78 | }; 79 | 80 | const services = ts.createLanguageService(servicesHost, registry); 81 | 82 | setTimeout(() => { 83 | services.getProgram(); 84 | }, 200); 85 | 86 | return services; 87 | }; 88 | 89 | const getEmit = (path: string) => { 90 | files.add(path); 91 | 92 | const program = services.getProgram()!; 93 | const source = program.getSourceFile(path); 94 | 95 | let text: string | undefined; 96 | 97 | program.emit( 98 | source, 99 | (file, content) => { 100 | if (file.endsWith(".js") || file.endsWith(".jsx")) { 101 | text = content; 102 | } 103 | }, 104 | void 0, 105 | void 0 106 | ); 107 | 108 | if (!text) { 109 | throw new Error(`Typescript failed emit for file: ${path}`); 110 | } 111 | 112 | return text; 113 | }; 114 | 115 | const cache = new Map(); 116 | 117 | export const fromCache = (fileName: string) => { 118 | const current = getScriptVersion(fileName); 119 | if (cache.has(fileName)) { 120 | const cached = cache.get(fileName)!; 121 | if (cached.hash === current) { 122 | return cached.content; 123 | } 124 | } 125 | const path = nodePath.join(cacheDir, `${ts.sys.createHash!(fileName)}.hash`); 126 | if (fs.existsSync(path)) { 127 | const hash = fs.readFileSync(path).toString("utf-8"); 128 | if (hash === current) { 129 | return fs 130 | .readFileSync( 131 | nodePath.join(cacheDir, `${ts.sys.createHash!(fileName)}.content`) 132 | ) 133 | .toString("utf-8"); 134 | } 135 | } 136 | }; 137 | 138 | export const toCache = (fileName: string, content: string) => { 139 | const current = getScriptVersion(fileName); 140 | const path = nodePath.join(cacheDir, `${ts.sys.createHash!(fileName)}.hash`); 141 | fs.writeFileSync(path, current); 142 | fs.writeFileSync( 143 | nodePath.join(cacheDir, `${ts.sys.createHash!(fileName)}.content`), 144 | content 145 | ); 146 | cache.set(fileName, { hash: current, content }); 147 | return content; 148 | }; 149 | 150 | export const getCompiled = (path: string) => { 151 | const cached = fromCache(path); 152 | if (cached) { 153 | return { 154 | code: cached, 155 | }; 156 | } 157 | 158 | const syntactic = services.getSyntacticDiagnostics(path); 159 | 160 | if (syntactic.length > 0) { 161 | throw new Error( 162 | syntactic 163 | .map((_) => ts.flattenDiagnosticMessageText(_.messageText, "\n")) 164 | .join("\n") 165 | ); 166 | } 167 | 168 | const semantic = services.getSemanticDiagnostics(path); 169 | services.cleanupSemanticCache(); 170 | 171 | if (semantic.length > 0) { 172 | throw new Error( 173 | semantic 174 | .map((_) => ts.flattenDiagnosticMessageText(_.messageText, "\n")) 175 | .join("\n") 176 | ); 177 | } 178 | 179 | const code = toCache(path, getEmit(path)); 180 | 181 | return { 182 | code, 183 | }; 184 | }; 185 | 186 | export function effectPlugin(options?: Options): V.PluginOption[] { 187 | const filter = createFilter(options?.include, options?.exclude); 188 | if (!services) { 189 | services = init(); 190 | } 191 | const plugin: V.PluginOption = { 192 | name: "vite:typescript-effect", 193 | enforce: "pre", 194 | configureServer(dev) { 195 | dev.watcher.on("all", (event, path) => { 196 | if (filter(path)) { 197 | if (/\.tsx?/.test(path)) { 198 | switch (event) { 199 | case "add": { 200 | files.add(path); 201 | break; 202 | } 203 | case "change": { 204 | files.add(path); 205 | break; 206 | } 207 | case "unlink": { 208 | files.delete(path); 209 | break; 210 | } 211 | } 212 | } 213 | } 214 | }); 215 | }, 216 | watchChange(path, change) { 217 | if (filter(path)) { 218 | if (/\.tsx?/.test(path)) { 219 | switch (change.event) { 220 | case "create": { 221 | files.add(path); 222 | break; 223 | } 224 | case "update": { 225 | files.add(path); 226 | break; 227 | } 228 | case "delete": { 229 | files.delete(path); 230 | break; 231 | } 232 | } 233 | } 234 | } 235 | }, 236 | transform(_, path) { 237 | if (/\.tsx?/.test(path) && filter(path)) { 238 | return getCompiled(path); 239 | } 240 | }, 241 | }; 242 | return [plugin, ...reactPlugin(options)]; 243 | } 244 | -------------------------------------------------------------------------------- /plugin-dev/out/index.js: -------------------------------------------------------------------------------- 1 | "use strict"; 2 | var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { 3 | if (k2 === undefined) k2 = k; 4 | var desc = Object.getOwnPropertyDescriptor(m, k); 5 | if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { 6 | desc = { enumerable: true, get: function() { return m[k]; } }; 7 | } 8 | Object.defineProperty(o, k2, desc); 9 | }) : (function(o, m, k, k2) { 10 | if (k2 === undefined) k2 = k; 11 | o[k2] = m[k]; 12 | })); 13 | var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { 14 | Object.defineProperty(o, "default", { enumerable: true, value: v }); 15 | }) : function(o, v) { 16 | o["default"] = v; 17 | }); 18 | var __importStar = (this && this.__importStar) || function (mod) { 19 | if (mod && mod.__esModule) return mod; 20 | var result = {}; 21 | if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); 22 | __setModuleDefault(result, mod); 23 | return result; 24 | }; 25 | var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) { 26 | if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) { 27 | if (ar || !(i in from)) { 28 | if (!ar) ar = Array.prototype.slice.call(from, 0, i); 29 | ar[i] = from[i]; 30 | } 31 | } 32 | return to.concat(ar || Array.prototype.slice.call(from)); 33 | }; 34 | var __importDefault = (this && this.__importDefault) || function (mod) { 35 | return (mod && mod.__esModule) ? mod : { "default": mod }; 36 | }; 37 | exports.__esModule = true; 38 | exports.effectPlugin = exports.getCompiled = exports.toCache = exports.fromCache = void 0; 39 | var pluginutils_1 = require("@rollup/pluginutils"); 40 | var fs_1 = __importDefault(require("fs")); 41 | var nodePath = __importStar(require("path")); 42 | var typescript_1 = __importDefault(require("typescript")); 43 | var plugin_react_1 = __importDefault(require("@vitejs/plugin-react")); 44 | var configPath = typescript_1["default"].findConfigFile("./", typescript_1["default"].sys.fileExists, "tsconfig.json"); 45 | if (!configPath) { 46 | throw new Error('Could not find a valid "tsconfig.json".'); 47 | } 48 | var baseDir = nodePath.dirname(nodePath.resolve(configPath)); 49 | var cacheDir = nodePath.join(baseDir, ".cache/effect"); 50 | if (!fs_1["default"].existsSync(cacheDir)) { 51 | fs_1["default"].mkdirSync(cacheDir, { recursive: true }); 52 | } 53 | var registry = typescript_1["default"].createDocumentRegistry(); 54 | var files = new Set(); 55 | var services; 56 | var getScriptVersion = function (fileName) { 57 | var modified = typescript_1["default"].sys.getModifiedTime(fileName); 58 | if (modified) { 59 | return typescript_1["default"].sys.createHash("".concat(fileName).concat(modified.toISOString())); 60 | } 61 | else { 62 | files["delete"](fileName); 63 | } 64 | return "none"; 65 | }; 66 | var init = function () { 67 | var config = typescript_1["default"].parseConfigFileTextToJson(configPath, typescript_1["default"].sys.readFile(configPath)).config; 68 | Object.assign(config.compilerOptions, { 69 | sourceMap: false, 70 | inlineSourceMap: true, 71 | inlineSources: true, 72 | noEmit: false, 73 | declaration: false, 74 | declarationMap: false, 75 | module: "ESNext", 76 | target: "ES2022" 77 | }); 78 | var tsconfig = typescript_1["default"].parseJsonConfigFileContent(config, typescript_1["default"].sys, baseDir); 79 | if (!tsconfig.options) 80 | tsconfig.options = {}; 81 | tsconfig.fileNames.forEach(function (fileName) { 82 | files.add(fileName); 83 | }); 84 | var servicesHost = { 85 | realpath: function (fileName) { var _a, _b, _c; return (_c = (_b = (_a = typescript_1["default"].sys).realpath) === null || _b === void 0 ? void 0 : _b.call(_a, fileName)) !== null && _c !== void 0 ? _c : fileName; }, 86 | getScriptFileNames: function () { return Array.from(files); }, 87 | getScriptVersion: getScriptVersion, 88 | getScriptSnapshot: function (fileName) { 89 | if (!typescript_1["default"].sys.fileExists(fileName)) { 90 | return undefined; 91 | } 92 | return typescript_1["default"].ScriptSnapshot.fromString(typescript_1["default"].sys.readFile(fileName).toString()); 93 | }, 94 | getCurrentDirectory: function () { return process.cwd(); }, 95 | getCompilationSettings: function () { return tsconfig.options; }, 96 | getDefaultLibFileName: function (options) { return typescript_1["default"].getDefaultLibFilePath(options); }, 97 | fileExists: function (fileName) { return typescript_1["default"].sys.fileExists(fileName); }, 98 | readFile: function (fileName) { return typescript_1["default"].sys.readFile(fileName); } 99 | }; 100 | var services = typescript_1["default"].createLanguageService(servicesHost, registry); 101 | setTimeout(function () { 102 | services.getProgram(); 103 | }, 200); 104 | return services; 105 | }; 106 | var getEmit = function (path) { 107 | files.add(path); 108 | var program = services.getProgram(); 109 | var source = program.getSourceFile(path); 110 | var text; 111 | program.emit(source, function (file, content) { 112 | if (file.endsWith(".js") || file.endsWith(".jsx")) { 113 | text = content; 114 | } 115 | }, void 0, void 0); 116 | if (!text) { 117 | throw new Error("Typescript failed emit for file: ".concat(path)); 118 | } 119 | return text; 120 | }; 121 | var cache = new Map(); 122 | var fromCache = function (fileName) { 123 | var current = getScriptVersion(fileName); 124 | if (cache.has(fileName)) { 125 | var cached = cache.get(fileName); 126 | if (cached.hash === current) { 127 | return cached.content; 128 | } 129 | } 130 | var path = nodePath.join(cacheDir, "".concat(typescript_1["default"].sys.createHash(fileName), ".hash")); 131 | if (fs_1["default"].existsSync(path)) { 132 | var hash = fs_1["default"].readFileSync(path).toString("utf-8"); 133 | if (hash === current) { 134 | return fs_1["default"] 135 | .readFileSync(nodePath.join(cacheDir, "".concat(typescript_1["default"].sys.createHash(fileName), ".content"))) 136 | .toString("utf-8"); 137 | } 138 | } 139 | }; 140 | exports.fromCache = fromCache; 141 | var toCache = function (fileName, content) { 142 | var current = getScriptVersion(fileName); 143 | var path = nodePath.join(cacheDir, "".concat(typescript_1["default"].sys.createHash(fileName), ".hash")); 144 | fs_1["default"].writeFileSync(path, current); 145 | fs_1["default"].writeFileSync(nodePath.join(cacheDir, "".concat(typescript_1["default"].sys.createHash(fileName), ".content")), content); 146 | cache.set(fileName, { hash: current, content: content }); 147 | return content; 148 | }; 149 | exports.toCache = toCache; 150 | var getCompiled = function (path) { 151 | var cached = (0, exports.fromCache)(path); 152 | if (cached) { 153 | return { 154 | code: cached 155 | }; 156 | } 157 | var syntactic = services.getSyntacticDiagnostics(path); 158 | if (syntactic.length > 0) { 159 | throw new Error(syntactic 160 | .map(function (_) { return typescript_1["default"].flattenDiagnosticMessageText(_.messageText, "\n"); }) 161 | .join("\n")); 162 | } 163 | var semantic = services.getSemanticDiagnostics(path); 164 | services.cleanupSemanticCache(); 165 | if (semantic.length > 0) { 166 | throw new Error(semantic 167 | .map(function (_) { return typescript_1["default"].flattenDiagnosticMessageText(_.messageText, "\n"); }) 168 | .join("\n")); 169 | } 170 | var code = (0, exports.toCache)(path, getEmit(path)); 171 | return { 172 | code: code 173 | }; 174 | }; 175 | exports.getCompiled = getCompiled; 176 | function effectPlugin(options) { 177 | var filter = (0, pluginutils_1.createFilter)(options === null || options === void 0 ? void 0 : options.include, options === null || options === void 0 ? void 0 : options.exclude); 178 | if (!services) { 179 | services = init(); 180 | } 181 | var plugin = { 182 | name: "vite:typescript-effect", 183 | enforce: "pre", 184 | configureServer: function (dev) { 185 | dev.watcher.on("all", function (event, path) { 186 | if (filter(path)) { 187 | if (/\.tsx?/.test(path)) { 188 | switch (event) { 189 | case "add": { 190 | files.add(path); 191 | break; 192 | } 193 | case "change": { 194 | files.add(path); 195 | break; 196 | } 197 | case "unlink": { 198 | files["delete"](path); 199 | break; 200 | } 201 | } 202 | } 203 | } 204 | }); 205 | }, 206 | watchChange: function (path, change) { 207 | if (filter(path)) { 208 | if (/\.tsx?/.test(path)) { 209 | switch (change.event) { 210 | case "create": { 211 | files.add(path); 212 | break; 213 | } 214 | case "update": { 215 | files.add(path); 216 | break; 217 | } 218 | case "delete": { 219 | files["delete"](path); 220 | break; 221 | } 222 | } 223 | } 224 | } 225 | }, 226 | transform: function (_, path) { 227 | if (/\.tsx?/.test(path) && filter(path)) { 228 | return (0, exports.getCompiled)(path); 229 | } 230 | } 231 | }; 232 | return __spreadArray([plugin], (0, plugin_react_1["default"])(options), true); 233 | } 234 | exports.effectPlugin = effectPlugin; 235 | -------------------------------------------------------------------------------- /plugin-dev/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "version": "0.0.0", 3 | "name": "@effect/vite-plugin-react", 4 | "main": "./out/index.js" 5 | } 6 | -------------------------------------------------------------------------------- /plugin-dev/tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "lib": ["ES2018"], 4 | "module": "CommonJS", 5 | "strict": true, 6 | "skipLibCheck": true, 7 | "esModuleInterop": true, 8 | "outDir": "out" 9 | }, 10 | "include": ["./*.ts"] 11 | } 12 | -------------------------------------------------------------------------------- /pnpm-lock.yaml: -------------------------------------------------------------------------------- 1 | lockfileVersion: '6.0' 2 | 3 | dependencies: 4 | effect: 5 | specifier: 2.0.0-next.17 6 | version: 2.0.0-next.17 7 | react: 8 | specifier: ^18.2.0 9 | version: 18.2.0 10 | react-dom: 11 | specifier: ^18.2.0 12 | version: 18.2.0(react@18.2.0) 13 | 14 | devDependencies: 15 | '@babel/core': 16 | specifier: ^7.22.9 17 | version: 7.22.9 18 | '@effect/language-service': 19 | specifier: ^0.0.19 20 | version: 0.0.19 21 | '@effect/vite-plugin-react': 22 | specifier: link:plugin-dev 23 | version: link:plugin-dev 24 | '@rollup/pluginutils': 25 | specifier: ^5.0.2 26 | version: 5.0.2 27 | '@types/babel__core': 28 | specifier: ^7.20.1 29 | version: 7.20.1 30 | '@types/node': 31 | specifier: ^18.16.19 32 | version: 18.16.19 33 | '@types/react': 34 | specifier: ^18.2.15 35 | version: 18.2.15 36 | '@types/react-dom': 37 | specifier: ^18.2.7 38 | version: 18.2.7 39 | '@vitejs/plugin-react': 40 | specifier: ^3.1.0 41 | version: 3.1.0(vite@4.4.4) 42 | babel-plugin-annotate-pure-calls: 43 | specifier: ^0.4.0 44 | version: 0.4.0(@babel/core@7.22.9) 45 | typescript: 46 | specifier: 5.1.6 47 | version: 5.1.6 48 | vite: 49 | specifier: ^4.4.4 50 | version: 4.4.4(@types/node@18.16.19) 51 | 52 | packages: 53 | 54 | /@ampproject/remapping@2.2.1: 55 | resolution: {integrity: sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==} 56 | engines: {node: '>=6.0.0'} 57 | dependencies: 58 | '@jridgewell/gen-mapping': 0.3.3 59 | '@jridgewell/trace-mapping': 0.3.18 60 | dev: true 61 | 62 | /@babel/code-frame@7.22.5: 63 | resolution: {integrity: sha512-Xmwn266vad+6DAqEB2A6V/CcZVp62BbwVmcOJc2RPuwih1kw02TjQvWVWlcKGbBPd+8/0V5DEkOcizRGYsspYQ==} 64 | engines: {node: '>=6.9.0'} 65 | dependencies: 66 | '@babel/highlight': 7.22.5 67 | dev: true 68 | 69 | /@babel/compat-data@7.22.9: 70 | resolution: {integrity: sha512-5UamI7xkUcJ3i9qVDS+KFDEK8/7oJ55/sJMB1Ge7IEapr7KfdfV/HErR+koZwOfd+SgtFKOKRhRakdg++DcJpQ==} 71 | engines: {node: '>=6.9.0'} 72 | dev: true 73 | 74 | /@babel/core@7.22.9: 75 | resolution: {integrity: sha512-G2EgeufBcYw27U4hhoIwFcgc1XU7TlXJ3mv04oOv1WCuo900U/anZSPzEqNjwdjgffkk2Gs0AN0dW1CKVLcG7w==} 76 | engines: {node: '>=6.9.0'} 77 | dependencies: 78 | '@ampproject/remapping': 2.2.1 79 | '@babel/code-frame': 7.22.5 80 | '@babel/generator': 7.22.9 81 | '@babel/helper-compilation-targets': 7.22.9(@babel/core@7.22.9) 82 | '@babel/helper-module-transforms': 7.22.9(@babel/core@7.22.9) 83 | '@babel/helpers': 7.22.6 84 | '@babel/parser': 7.22.7 85 | '@babel/template': 7.22.5 86 | '@babel/traverse': 7.22.8 87 | '@babel/types': 7.22.5 88 | convert-source-map: 1.9.0 89 | debug: 4.3.4 90 | gensync: 1.0.0-beta.2 91 | json5: 2.2.3 92 | semver: 6.3.1 93 | transitivePeerDependencies: 94 | - supports-color 95 | dev: true 96 | 97 | /@babel/generator@7.22.9: 98 | resolution: {integrity: sha512-KtLMbmicyuK2Ak/FTCJVbDnkN1SlT8/kceFTiuDiiRUUSMnHMidxSCdG4ndkTOHHpoomWe/4xkvHkEOncwjYIw==} 99 | engines: {node: '>=6.9.0'} 100 | dependencies: 101 | '@babel/types': 7.22.5 102 | '@jridgewell/gen-mapping': 0.3.3 103 | '@jridgewell/trace-mapping': 0.3.18 104 | jsesc: 2.5.2 105 | dev: true 106 | 107 | /@babel/helper-compilation-targets@7.22.9(@babel/core@7.22.9): 108 | resolution: {integrity: sha512-7qYrNM6HjpnPHJbopxmb8hSPoZ0gsX8IvUS32JGVoy+pU9e5N0nLr1VjJoR6kA4d9dmGLxNYOjeB8sUDal2WMw==} 109 | engines: {node: '>=6.9.0'} 110 | peerDependencies: 111 | '@babel/core': ^7.0.0 112 | dependencies: 113 | '@babel/compat-data': 7.22.9 114 | '@babel/core': 7.22.9 115 | '@babel/helper-validator-option': 7.22.5 116 | browserslist: 4.21.9 117 | lru-cache: 5.1.1 118 | semver: 6.3.1 119 | dev: true 120 | 121 | /@babel/helper-environment-visitor@7.22.5: 122 | resolution: {integrity: sha512-XGmhECfVA/5sAt+H+xpSg0mfrHq6FzNr9Oxh7PSEBBRUb/mL7Kz3NICXb194rCqAEdxkhPT1a88teizAFyvk8Q==} 123 | engines: {node: '>=6.9.0'} 124 | dev: true 125 | 126 | /@babel/helper-function-name@7.22.5: 127 | resolution: {integrity: sha512-wtHSq6jMRE3uF2otvfuD3DIvVhOsSNshQl0Qrd7qC9oQJzHvOL4qQXlQn2916+CXGywIjpGuIkoyZRRxHPiNQQ==} 128 | engines: {node: '>=6.9.0'} 129 | dependencies: 130 | '@babel/template': 7.22.5 131 | '@babel/types': 7.22.5 132 | dev: true 133 | 134 | /@babel/helper-hoist-variables@7.22.5: 135 | resolution: {integrity: sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==} 136 | engines: {node: '>=6.9.0'} 137 | dependencies: 138 | '@babel/types': 7.22.5 139 | dev: true 140 | 141 | /@babel/helper-module-imports@7.22.5: 142 | resolution: {integrity: sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==} 143 | engines: {node: '>=6.9.0'} 144 | dependencies: 145 | '@babel/types': 7.22.5 146 | dev: true 147 | 148 | /@babel/helper-module-transforms@7.22.9(@babel/core@7.22.9): 149 | resolution: {integrity: sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==} 150 | engines: {node: '>=6.9.0'} 151 | peerDependencies: 152 | '@babel/core': ^7.0.0 153 | dependencies: 154 | '@babel/core': 7.22.9 155 | '@babel/helper-environment-visitor': 7.22.5 156 | '@babel/helper-module-imports': 7.22.5 157 | '@babel/helper-simple-access': 7.22.5 158 | '@babel/helper-split-export-declaration': 7.22.6 159 | '@babel/helper-validator-identifier': 7.22.5 160 | dev: true 161 | 162 | /@babel/helper-plugin-utils@7.22.5: 163 | resolution: {integrity: sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==} 164 | engines: {node: '>=6.9.0'} 165 | dev: true 166 | 167 | /@babel/helper-simple-access@7.22.5: 168 | resolution: {integrity: sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==} 169 | engines: {node: '>=6.9.0'} 170 | dependencies: 171 | '@babel/types': 7.22.5 172 | dev: true 173 | 174 | /@babel/helper-split-export-declaration@7.22.6: 175 | resolution: {integrity: sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==} 176 | engines: {node: '>=6.9.0'} 177 | dependencies: 178 | '@babel/types': 7.22.5 179 | dev: true 180 | 181 | /@babel/helper-string-parser@7.22.5: 182 | resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} 183 | engines: {node: '>=6.9.0'} 184 | dev: true 185 | 186 | /@babel/helper-validator-identifier@7.22.5: 187 | resolution: {integrity: sha512-aJXu+6lErq8ltp+JhkJUfk1MTGyuA4v7f3pA+BJ5HLfNC6nAQ0Cpi9uOquUj8Hehg0aUiHzWQbOVJGao6ztBAQ==} 188 | engines: {node: '>=6.9.0'} 189 | dev: true 190 | 191 | /@babel/helper-validator-option@7.22.5: 192 | resolution: {integrity: sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==} 193 | engines: {node: '>=6.9.0'} 194 | dev: true 195 | 196 | /@babel/helpers@7.22.6: 197 | resolution: {integrity: sha512-YjDs6y/fVOYFV8hAf1rxd1QvR9wJe1pDBZ2AREKq/SDayfPzgk0PBnVuTCE5X1acEpMMNOVUqoe+OwiZGJ+OaA==} 198 | engines: {node: '>=6.9.0'} 199 | dependencies: 200 | '@babel/template': 7.22.5 201 | '@babel/traverse': 7.22.8 202 | '@babel/types': 7.22.5 203 | transitivePeerDependencies: 204 | - supports-color 205 | dev: true 206 | 207 | /@babel/highlight@7.22.5: 208 | resolution: {integrity: sha512-BSKlD1hgnedS5XRnGOljZawtag7H1yPfQp0tdNJCHoH6AZ+Pcm9VvkrK59/Yy593Ypg0zMxH2BxD1VPYUQ7UIw==} 209 | engines: {node: '>=6.9.0'} 210 | dependencies: 211 | '@babel/helper-validator-identifier': 7.22.5 212 | chalk: 2.4.2 213 | js-tokens: 4.0.0 214 | dev: true 215 | 216 | /@babel/parser@7.22.7: 217 | resolution: {integrity: sha512-7NF8pOkHP5o2vpmGgNGcfAeCvOYhGLyA3Z4eBQkT1RJlWu47n63bCs93QfJ2hIAFCil7L5P2IWhs1oToVgrL0Q==} 218 | engines: {node: '>=6.0.0'} 219 | hasBin: true 220 | dependencies: 221 | '@babel/types': 7.22.5 222 | dev: true 223 | 224 | /@babel/plugin-transform-react-jsx-self@7.22.5(@babel/core@7.22.9): 225 | resolution: {integrity: sha512-nTh2ogNUtxbiSbxaT4Ds6aXnXEipHweN9YRgOX/oNXdf0cCrGn/+2LozFa3lnPV5D90MkjhgckCPBrsoSc1a7g==} 226 | engines: {node: '>=6.9.0'} 227 | peerDependencies: 228 | '@babel/core': ^7.0.0-0 229 | dependencies: 230 | '@babel/core': 7.22.9 231 | '@babel/helper-plugin-utils': 7.22.5 232 | dev: true 233 | 234 | /@babel/plugin-transform-react-jsx-source@7.22.5(@babel/core@7.22.9): 235 | resolution: {integrity: sha512-yIiRO6yobeEIaI0RTbIr8iAK9FcBHLtZq0S89ZPjDLQXBA4xvghaKqI0etp/tF3htTM0sazJKKLz9oEiGRtu7w==} 236 | engines: {node: '>=6.9.0'} 237 | peerDependencies: 238 | '@babel/core': ^7.0.0-0 239 | dependencies: 240 | '@babel/core': 7.22.9 241 | '@babel/helper-plugin-utils': 7.22.5 242 | dev: true 243 | 244 | /@babel/template@7.22.5: 245 | resolution: {integrity: sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==} 246 | engines: {node: '>=6.9.0'} 247 | dependencies: 248 | '@babel/code-frame': 7.22.5 249 | '@babel/parser': 7.22.7 250 | '@babel/types': 7.22.5 251 | dev: true 252 | 253 | /@babel/traverse@7.22.8: 254 | resolution: {integrity: sha512-y6LPR+wpM2I3qJrsheCTwhIinzkETbplIgPBbwvqPKc+uljeA5gP+3nP8irdYt1mjQaDnlIcG+dw8OjAco4GXw==} 255 | engines: {node: '>=6.9.0'} 256 | dependencies: 257 | '@babel/code-frame': 7.22.5 258 | '@babel/generator': 7.22.9 259 | '@babel/helper-environment-visitor': 7.22.5 260 | '@babel/helper-function-name': 7.22.5 261 | '@babel/helper-hoist-variables': 7.22.5 262 | '@babel/helper-split-export-declaration': 7.22.6 263 | '@babel/parser': 7.22.7 264 | '@babel/types': 7.22.5 265 | debug: 4.3.4 266 | globals: 11.12.0 267 | transitivePeerDependencies: 268 | - supports-color 269 | dev: true 270 | 271 | /@babel/types@7.22.5: 272 | resolution: {integrity: sha512-zo3MIHGOkPOfoRXitsgHLjEXmlDaD/5KU1Uzuc9GNiZPhSqVxVRtxuPaSBZDsYZ9qV88AjtMtWW7ww98loJ9KA==} 273 | engines: {node: '>=6.9.0'} 274 | dependencies: 275 | '@babel/helper-string-parser': 7.22.5 276 | '@babel/helper-validator-identifier': 7.22.5 277 | to-fast-properties: 2.0.0 278 | dev: true 279 | 280 | /@effect/data@0.15.1: 281 | resolution: {integrity: sha512-dYe3GL2Lq8M56Q+QvEOPRtpRovhy1QprlBRGIjaCRPZ8DbwRFQZSdPPOL+ZX6e7y3DPF0RW+DFLHYRMA6qGOCw==} 282 | dev: false 283 | 284 | /@effect/io@0.33.0: 285 | resolution: {integrity: sha512-CwEiAKLZG368t2lNti7u3sX2wi0SS5c+Z0Xb3QVE0fA0WoRidNqlVwzvjMyUqYW6Rtwn0vCqyhAsfK3YVze5FQ==} 286 | dependencies: 287 | '@effect/data': 0.15.1 288 | dev: false 289 | 290 | /@effect/language-service@0.0.19: 291 | resolution: {integrity: sha512-sKNVo031dkwLfe1jHZzdTiF1UXgLq1lAYd2JG7q416dlmMoxRcMXrZWyw6a/SxIDM0hyIJAEmrz5iUkQPcPdBQ==} 292 | dependencies: 293 | '@fp-ts/core': 0.0.11 294 | '@fp-ts/data': 0.0.41 295 | dev: true 296 | 297 | /@esbuild/android-arm64@0.18.12: 298 | resolution: {integrity: sha512-BMAlczRqC/LUt2P97E4apTBbkvS9JTJnp2DKFbCwpZ8vBvXVbNdqmvzW/OsdtI/+mGr+apkkpqGM8WecLkPgrA==} 299 | engines: {node: '>=12'} 300 | cpu: [arm64] 301 | os: [android] 302 | requiresBuild: true 303 | dev: true 304 | optional: true 305 | 306 | /@esbuild/android-arm@0.18.12: 307 | resolution: {integrity: sha512-LIxaNIQfkFZbTLb4+cX7dozHlAbAshhFE5PKdro0l+FnCpx1GDJaQ2WMcqm+ToXKMt8p8Uojk/MFRuGyz3V5Sw==} 308 | engines: {node: '>=12'} 309 | cpu: [arm] 310 | os: [android] 311 | requiresBuild: true 312 | dev: true 313 | optional: true 314 | 315 | /@esbuild/android-x64@0.18.12: 316 | resolution: {integrity: sha512-zU5MyluNsykf5cOJ0LZZZjgAHbhPJ1cWfdH1ZXVMXxVMhEV0VZiZXQdwBBVvmvbF28EizeK7obG9fs+fpmS0eQ==} 317 | engines: {node: '>=12'} 318 | cpu: [x64] 319 | os: [android] 320 | requiresBuild: true 321 | dev: true 322 | optional: true 323 | 324 | /@esbuild/darwin-arm64@0.18.12: 325 | resolution: {integrity: sha512-zUZMep7YONnp6954QOOwEBwFX9svlKd3ov6PkxKd53LGTHsp/gy7vHaPGhhjBmEpqXEXShi6dddjIkmd+NgMsA==} 326 | engines: {node: '>=12'} 327 | cpu: [arm64] 328 | os: [darwin] 329 | requiresBuild: true 330 | dev: true 331 | optional: true 332 | 333 | /@esbuild/darwin-x64@0.18.12: 334 | resolution: {integrity: sha512-ohqLPc7i67yunArPj1+/FeeJ7AgwAjHqKZ512ADk3WsE3FHU9l+m5aa7NdxXr0HmN1bjDlUslBjWNbFlD9y12Q==} 335 | engines: {node: '>=12'} 336 | cpu: [x64] 337 | os: [darwin] 338 | requiresBuild: true 339 | dev: true 340 | optional: true 341 | 342 | /@esbuild/freebsd-arm64@0.18.12: 343 | resolution: {integrity: sha512-GIIHtQXqgeOOqdG16a/A9N28GpkvjJnjYMhOnXVbn3EDJcoItdR58v/pGN31CHjyXDc8uCcRnFWmqaJt24AYJg==} 344 | engines: {node: '>=12'} 345 | cpu: [arm64] 346 | os: [freebsd] 347 | requiresBuild: true 348 | dev: true 349 | optional: true 350 | 351 | /@esbuild/freebsd-x64@0.18.12: 352 | resolution: {integrity: sha512-zK0b9a1/0wZY+6FdOS3BpZcPc1kcx2G5yxxfEJtEUzVxI6n/FrC2Phsxj/YblPuBchhBZ/1wwn7AyEBUyNSa6g==} 353 | engines: {node: '>=12'} 354 | cpu: [x64] 355 | os: [freebsd] 356 | requiresBuild: true 357 | dev: true 358 | optional: true 359 | 360 | /@esbuild/linux-arm64@0.18.12: 361 | resolution: {integrity: sha512-JKgG8Q/LL/9sw/iHHxQyVMoQYu3rU3+a5Z87DxC+wAu3engz+EmctIrV+FGOgI6gWG1z1+5nDDbXiRMGQZXqiw==} 362 | engines: {node: '>=12'} 363 | cpu: [arm64] 364 | os: [linux] 365 | requiresBuild: true 366 | dev: true 367 | optional: true 368 | 369 | /@esbuild/linux-arm@0.18.12: 370 | resolution: {integrity: sha512-y75OijvrBE/1XRrXq1jtrJfG26eHeMoqLJ2dwQNwviwTuTtHGCojsDO6BJNF8gU+3jTn1KzJEMETytwsFSvc+Q==} 371 | engines: {node: '>=12'} 372 | cpu: [arm] 373 | os: [linux] 374 | requiresBuild: true 375 | dev: true 376 | optional: true 377 | 378 | /@esbuild/linux-ia32@0.18.12: 379 | resolution: {integrity: sha512-yoRIAqc0B4lDIAAEFEIu9ttTRFV84iuAl0KNCN6MhKLxNPfzwCBvEMgwco2f71GxmpBcTtn7KdErueZaM2rEvw==} 380 | engines: {node: '>=12'} 381 | cpu: [ia32] 382 | os: [linux] 383 | requiresBuild: true 384 | dev: true 385 | optional: true 386 | 387 | /@esbuild/linux-loong64@0.18.12: 388 | resolution: {integrity: sha512-qYgt3dHPVvf/MgbIBpJ4Sup/yb9DAopZ3a2JgMpNKIHUpOdnJ2eHBo/aQdnd8dJ21X/+sS58wxHtA9lEazYtXQ==} 389 | engines: {node: '>=12'} 390 | cpu: [loong64] 391 | os: [linux] 392 | requiresBuild: true 393 | dev: true 394 | optional: true 395 | 396 | /@esbuild/linux-mips64el@0.18.12: 397 | resolution: {integrity: sha512-wHphlMLK4ufNOONqukELfVIbnGQJrHJ/mxZMMrP2jYrPgCRZhOtf0kC4yAXBwnfmULimV1qt5UJJOw4Kh13Yfg==} 398 | engines: {node: '>=12'} 399 | cpu: [mips64el] 400 | os: [linux] 401 | requiresBuild: true 402 | dev: true 403 | optional: true 404 | 405 | /@esbuild/linux-ppc64@0.18.12: 406 | resolution: {integrity: sha512-TeN//1Ft20ZZW41+zDSdOI/Os1bEq5dbvBvYkberB7PHABbRcsteeoNVZFlI0YLpGdlBqohEpjrn06kv8heCJg==} 407 | engines: {node: '>=12'} 408 | cpu: [ppc64] 409 | os: [linux] 410 | requiresBuild: true 411 | dev: true 412 | optional: true 413 | 414 | /@esbuild/linux-riscv64@0.18.12: 415 | resolution: {integrity: sha512-AgUebVS4DoAblBgiB2ACQ/8l4eGE5aWBb8ZXtkXHiET9mbj7GuWt3OnsIW/zX+XHJt2RYJZctbQ2S/mDjbp0UA==} 416 | engines: {node: '>=12'} 417 | cpu: [riscv64] 418 | os: [linux] 419 | requiresBuild: true 420 | dev: true 421 | optional: true 422 | 423 | /@esbuild/linux-s390x@0.18.12: 424 | resolution: {integrity: sha512-dJ3Rb3Ei2u/ysSXd6pzleGtfDdc2MuzKt8qc6ls8vreP1G3B7HInX3i7gXS4BGeVd24pp0yqyS7bJ5NHaI9ing==} 425 | engines: {node: '>=12'} 426 | cpu: [s390x] 427 | os: [linux] 428 | requiresBuild: true 429 | dev: true 430 | optional: true 431 | 432 | /@esbuild/linux-x64@0.18.12: 433 | resolution: {integrity: sha512-OrNJMGQbPaVyHHcDF8ybNSwu7TDOfX8NGpXCbetwOSP6txOJiWlgQnRymfC9ocR1S0Y5PW0Wb1mV6pUddqmvmQ==} 434 | engines: {node: '>=12'} 435 | cpu: [x64] 436 | os: [linux] 437 | requiresBuild: true 438 | dev: true 439 | optional: true 440 | 441 | /@esbuild/netbsd-x64@0.18.12: 442 | resolution: {integrity: sha512-55FzVCAiwE9FK8wWeCRuvjazNRJ1QqLCYGZVB6E8RuQuTeStSwotpSW4xoRGwp3a1wUsaVCdYcj5LGCASVJmMg==} 443 | engines: {node: '>=12'} 444 | cpu: [x64] 445 | os: [netbsd] 446 | requiresBuild: true 447 | dev: true 448 | optional: true 449 | 450 | /@esbuild/openbsd-x64@0.18.12: 451 | resolution: {integrity: sha512-qnluf8rfb6Y5Lw2tirfK2quZOBbVqmwxut7GPCIJsM8lc4AEUj9L8y0YPdLaPK0TECt4IdyBdBD/KRFKorlK3g==} 452 | engines: {node: '>=12'} 453 | cpu: [x64] 454 | os: [openbsd] 455 | requiresBuild: true 456 | dev: true 457 | optional: true 458 | 459 | /@esbuild/sunos-x64@0.18.12: 460 | resolution: {integrity: sha512-+RkKpVQR7bICjTOPUpkTBTaJ4TFqQBX5Ywyd/HSdDkQGn65VPkTsR/pL4AMvuMWy+wnXgIl4EY6q4mVpJal8Kg==} 461 | engines: {node: '>=12'} 462 | cpu: [x64] 463 | os: [sunos] 464 | requiresBuild: true 465 | dev: true 466 | optional: true 467 | 468 | /@esbuild/win32-arm64@0.18.12: 469 | resolution: {integrity: sha512-GNHuciv0mFM7ouzsU0+AwY+7eV4Mgo5WnbhfDCQGtpvOtD1vbOiRjPYG6dhmMoFyBjj+pNqQu2X+7DKn0KQ/Gw==} 470 | engines: {node: '>=12'} 471 | cpu: [arm64] 472 | os: [win32] 473 | requiresBuild: true 474 | dev: true 475 | optional: true 476 | 477 | /@esbuild/win32-ia32@0.18.12: 478 | resolution: {integrity: sha512-kR8cezhYipbbypGkaqCTWIeu4zID17gamC8YTPXYtcN3E5BhhtTnwKBn9I0PJur/T6UVwIEGYzkffNL0lFvxEw==} 479 | engines: {node: '>=12'} 480 | cpu: [ia32] 481 | os: [win32] 482 | requiresBuild: true 483 | dev: true 484 | optional: true 485 | 486 | /@esbuild/win32-x64@0.18.12: 487 | resolution: {integrity: sha512-O0UYQVkvfM/jO8a4OwoV0mAKSJw+mjWTAd1MJd/1FCX6uiMdLmMRPK/w6e9OQ0ob2WGxzIm9va/KG0Ja4zIOgg==} 488 | engines: {node: '>=12'} 489 | cpu: [x64] 490 | os: [win32] 491 | requiresBuild: true 492 | dev: true 493 | optional: true 494 | 495 | /@fp-ts/core@0.0.11: 496 | resolution: {integrity: sha512-BCAJBYzghwoJpcUOARJ1tui50HoYJFlV2pJlVMlsEkDFhD8MTtq8xQVpZCRF66RmtkxtGBYINCQ+5H1lRaL35Q==} 497 | dev: true 498 | 499 | /@fp-ts/data@0.0.41: 500 | resolution: {integrity: sha512-0S93kOQ91D7wp60q/PSVWvMsJjSWJutjt4qX/BvVNV7+fymuC2hTfW2HlE2OcMK11xCNiI6Rq2AkvyzoMhOlpg==} 501 | dependencies: 502 | '@fp-ts/core': 0.0.11 503 | dev: true 504 | 505 | /@jridgewell/gen-mapping@0.3.3: 506 | resolution: {integrity: sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==} 507 | engines: {node: '>=6.0.0'} 508 | dependencies: 509 | '@jridgewell/set-array': 1.1.2 510 | '@jridgewell/sourcemap-codec': 1.4.15 511 | '@jridgewell/trace-mapping': 0.3.18 512 | dev: true 513 | 514 | /@jridgewell/resolve-uri@3.1.0: 515 | resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==} 516 | engines: {node: '>=6.0.0'} 517 | dev: true 518 | 519 | /@jridgewell/set-array@1.1.2: 520 | resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==} 521 | engines: {node: '>=6.0.0'} 522 | dev: true 523 | 524 | /@jridgewell/sourcemap-codec@1.4.14: 525 | resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==} 526 | dev: true 527 | 528 | /@jridgewell/sourcemap-codec@1.4.15: 529 | resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} 530 | dev: true 531 | 532 | /@jridgewell/trace-mapping@0.3.18: 533 | resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==} 534 | dependencies: 535 | '@jridgewell/resolve-uri': 3.1.0 536 | '@jridgewell/sourcemap-codec': 1.4.14 537 | dev: true 538 | 539 | /@rollup/pluginutils@5.0.2: 540 | resolution: {integrity: sha512-pTd9rIsP92h+B6wWwFbW8RkZv4hiR/xKsqre4SIuAOaOEQRxi0lqLke9k2/7WegC85GgUs9pjmOjCUi3In4vwA==} 541 | engines: {node: '>=14.0.0'} 542 | peerDependencies: 543 | rollup: ^1.20.0||^2.0.0||^3.0.0 544 | peerDependenciesMeta: 545 | rollup: 546 | optional: true 547 | dependencies: 548 | '@types/estree': 1.0.1 549 | estree-walker: 2.0.2 550 | picomatch: 2.3.1 551 | dev: true 552 | 553 | /@types/babel__core@7.20.1: 554 | resolution: {integrity: sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==} 555 | dependencies: 556 | '@babel/parser': 7.22.7 557 | '@babel/types': 7.22.5 558 | '@types/babel__generator': 7.6.4 559 | '@types/babel__template': 7.4.1 560 | '@types/babel__traverse': 7.20.1 561 | dev: true 562 | 563 | /@types/babel__generator@7.6.4: 564 | resolution: {integrity: sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==} 565 | dependencies: 566 | '@babel/types': 7.22.5 567 | dev: true 568 | 569 | /@types/babel__template@7.4.1: 570 | resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==} 571 | dependencies: 572 | '@babel/parser': 7.22.7 573 | '@babel/types': 7.22.5 574 | dev: true 575 | 576 | /@types/babel__traverse@7.20.1: 577 | resolution: {integrity: sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==} 578 | dependencies: 579 | '@babel/types': 7.22.5 580 | dev: true 581 | 582 | /@types/estree@1.0.1: 583 | resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==} 584 | dev: true 585 | 586 | /@types/node@18.16.19: 587 | resolution: {integrity: sha512-IXl7o+R9iti9eBW4Wg2hx1xQDig183jj7YLn8F7udNceyfkbn1ZxmzZXuak20gR40D7pIkIY1kYGx5VIGbaHKA==} 588 | dev: true 589 | 590 | /@types/prop-types@15.7.5: 591 | resolution: {integrity: sha512-JCB8C6SnDoQf0cNycqd/35A7MjcnK+ZTqE7judS6o7utxUCg6imJg3QK2qzHKszlTjcj2cn+NwMB2i96ubpj7w==} 592 | dev: true 593 | 594 | /@types/react-dom@18.2.7: 595 | resolution: {integrity: sha512-GRaAEriuT4zp9N4p1i8BDBYmEyfo+xQ3yHjJU4eiK5NDa1RmUZG+unZABUTK4/Ox/M+GaHwb6Ow8rUITrtjszA==} 596 | dependencies: 597 | '@types/react': 18.2.15 598 | dev: true 599 | 600 | /@types/react@18.2.15: 601 | resolution: {integrity: sha512-oEjE7TQt1fFTFSbf8kkNuc798ahTUzn3Le67/PWjE8MAfYAD/qB7O8hSTcromLFqHCt9bcdOg5GXMokzTjJ5SA==} 602 | dependencies: 603 | '@types/prop-types': 15.7.5 604 | '@types/scheduler': 0.16.3 605 | csstype: 3.1.2 606 | dev: true 607 | 608 | /@types/scheduler@0.16.3: 609 | resolution: {integrity: sha512-5cJ8CB4yAx7BH1oMvdU0Jh9lrEXyPkar6F9G/ERswkCuvP4KQZfZkSjcMbAICCpQTN4OuZn8tz0HiKv9TGZgrQ==} 610 | dev: true 611 | 612 | /@vitejs/plugin-react@3.1.0(vite@4.4.4): 613 | resolution: {integrity: sha512-AfgcRL8ZBhAlc3BFdigClmTUMISmmzHn7sB2h9U1odvc5U/MjWXsAaz18b/WoppUTDBzxOJwo2VdClfUcItu9g==} 614 | engines: {node: ^14.18.0 || >=16.0.0} 615 | peerDependencies: 616 | vite: ^4.1.0-beta.0 617 | dependencies: 618 | '@babel/core': 7.22.9 619 | '@babel/plugin-transform-react-jsx-self': 7.22.5(@babel/core@7.22.9) 620 | '@babel/plugin-transform-react-jsx-source': 7.22.5(@babel/core@7.22.9) 621 | magic-string: 0.27.0 622 | react-refresh: 0.14.0 623 | vite: 4.4.4(@types/node@18.16.19) 624 | transitivePeerDependencies: 625 | - supports-color 626 | dev: true 627 | 628 | /ansi-styles@3.2.1: 629 | resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} 630 | engines: {node: '>=4'} 631 | dependencies: 632 | color-convert: 1.9.3 633 | dev: true 634 | 635 | /babel-plugin-annotate-pure-calls@0.4.0(@babel/core@7.22.9): 636 | resolution: {integrity: sha512-oi4M/PWUJOU9ZyRGoPTfPMqdyMp06jbJAomd3RcyYuzUtBOddv98BqLm96Lucpi2QFoQHkdGQt0ACvw7VzVEQA==} 637 | peerDependencies: 638 | '@babel/core': ^6.0.0-0 || 7.x 639 | dependencies: 640 | '@babel/core': 7.22.9 641 | dev: true 642 | 643 | /browserslist@4.21.9: 644 | resolution: {integrity: sha512-M0MFoZzbUrRU4KNfCrDLnvyE7gub+peetoTid3TBIqtunaDJyXlwhakT+/VkvSXcfIzFfK/nkCs4nmyTmxdNSg==} 645 | engines: {node: ^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7} 646 | hasBin: true 647 | dependencies: 648 | caniuse-lite: 1.0.30001515 649 | electron-to-chromium: 1.4.461 650 | node-releases: 2.0.13 651 | update-browserslist-db: 1.0.11(browserslist@4.21.9) 652 | dev: true 653 | 654 | /caniuse-lite@1.0.30001515: 655 | resolution: {integrity: sha512-eEFDwUOZbE24sb+Ecsx3+OvNETqjWIdabMy52oOkIgcUtAsQifjUG9q4U9dgTHJM2mfk4uEPxc0+xuFdJ629QA==} 656 | dev: true 657 | 658 | /chalk@2.4.2: 659 | resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} 660 | engines: {node: '>=4'} 661 | dependencies: 662 | ansi-styles: 3.2.1 663 | escape-string-regexp: 1.0.5 664 | supports-color: 5.5.0 665 | dev: true 666 | 667 | /color-convert@1.9.3: 668 | resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} 669 | dependencies: 670 | color-name: 1.1.3 671 | dev: true 672 | 673 | /color-name@1.1.3: 674 | resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} 675 | dev: true 676 | 677 | /convert-source-map@1.9.0: 678 | resolution: {integrity: sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==} 679 | dev: true 680 | 681 | /csstype@3.1.2: 682 | resolution: {integrity: sha512-I7K1Uu0MBPzaFKg4nI5Q7Vs2t+3gWWW648spaF+Rg7pI9ds18Ugn+lvg4SHczUdKlHI5LWBXyqfS8+DufyBsgQ==} 683 | dev: true 684 | 685 | /debug@4.3.4: 686 | resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} 687 | engines: {node: '>=6.0'} 688 | peerDependencies: 689 | supports-color: '*' 690 | peerDependenciesMeta: 691 | supports-color: 692 | optional: true 693 | dependencies: 694 | ms: 2.1.2 695 | dev: true 696 | 697 | /effect@2.0.0-next.17: 698 | resolution: {integrity: sha512-OYYuZ497/zRlFSKThnyiTdi7ycyGIEWlWqJ9ILHW4P4BabIIL9MDif9V14UKFHJ8HuAVLDEI0Odk9HqnP//qRw==} 699 | dependencies: 700 | '@effect/data': 0.15.1 701 | '@effect/io': 0.33.0 702 | dev: false 703 | 704 | /electron-to-chromium@1.4.461: 705 | resolution: {integrity: sha512-1JkvV2sgEGTDXjdsaQCeSwYYuhLRphRpc+g6EHTFELJXEiznLt3/0pZ9JuAOQ5p2rI3YxKTbivtvajirIfhrEQ==} 706 | dev: true 707 | 708 | /esbuild@0.18.12: 709 | resolution: {integrity: sha512-XuOVLDdtsDslXStStduT41op21Ytmf4/BDS46aa3xPJ7X5h2eMWBF1oAe3QjUH3bDksocNXgzGUZ7XHIBya6Tg==} 710 | engines: {node: '>=12'} 711 | hasBin: true 712 | requiresBuild: true 713 | optionalDependencies: 714 | '@esbuild/android-arm': 0.18.12 715 | '@esbuild/android-arm64': 0.18.12 716 | '@esbuild/android-x64': 0.18.12 717 | '@esbuild/darwin-arm64': 0.18.12 718 | '@esbuild/darwin-x64': 0.18.12 719 | '@esbuild/freebsd-arm64': 0.18.12 720 | '@esbuild/freebsd-x64': 0.18.12 721 | '@esbuild/linux-arm': 0.18.12 722 | '@esbuild/linux-arm64': 0.18.12 723 | '@esbuild/linux-ia32': 0.18.12 724 | '@esbuild/linux-loong64': 0.18.12 725 | '@esbuild/linux-mips64el': 0.18.12 726 | '@esbuild/linux-ppc64': 0.18.12 727 | '@esbuild/linux-riscv64': 0.18.12 728 | '@esbuild/linux-s390x': 0.18.12 729 | '@esbuild/linux-x64': 0.18.12 730 | '@esbuild/netbsd-x64': 0.18.12 731 | '@esbuild/openbsd-x64': 0.18.12 732 | '@esbuild/sunos-x64': 0.18.12 733 | '@esbuild/win32-arm64': 0.18.12 734 | '@esbuild/win32-ia32': 0.18.12 735 | '@esbuild/win32-x64': 0.18.12 736 | dev: true 737 | 738 | /escalade@3.1.1: 739 | resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} 740 | engines: {node: '>=6'} 741 | dev: true 742 | 743 | /escape-string-regexp@1.0.5: 744 | resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} 745 | engines: {node: '>=0.8.0'} 746 | dev: true 747 | 748 | /estree-walker@2.0.2: 749 | resolution: {integrity: sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==} 750 | dev: true 751 | 752 | /fsevents@2.3.2: 753 | resolution: {integrity: sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==} 754 | engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} 755 | os: [darwin] 756 | requiresBuild: true 757 | dev: true 758 | optional: true 759 | 760 | /gensync@1.0.0-beta.2: 761 | resolution: {integrity: sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==} 762 | engines: {node: '>=6.9.0'} 763 | dev: true 764 | 765 | /globals@11.12.0: 766 | resolution: {integrity: sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==} 767 | engines: {node: '>=4'} 768 | dev: true 769 | 770 | /has-flag@3.0.0: 771 | resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} 772 | engines: {node: '>=4'} 773 | dev: true 774 | 775 | /js-tokens@4.0.0: 776 | resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} 777 | 778 | /jsesc@2.5.2: 779 | resolution: {integrity: sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==} 780 | engines: {node: '>=4'} 781 | hasBin: true 782 | dev: true 783 | 784 | /json5@2.2.3: 785 | resolution: {integrity: sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==} 786 | engines: {node: '>=6'} 787 | hasBin: true 788 | dev: true 789 | 790 | /loose-envify@1.4.0: 791 | resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} 792 | hasBin: true 793 | dependencies: 794 | js-tokens: 4.0.0 795 | dev: false 796 | 797 | /lru-cache@5.1.1: 798 | resolution: {integrity: sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==} 799 | dependencies: 800 | yallist: 3.1.1 801 | dev: true 802 | 803 | /magic-string@0.27.0: 804 | resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==} 805 | engines: {node: '>=12'} 806 | dependencies: 807 | '@jridgewell/sourcemap-codec': 1.4.15 808 | dev: true 809 | 810 | /ms@2.1.2: 811 | resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} 812 | dev: true 813 | 814 | /nanoid@3.3.6: 815 | resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} 816 | engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} 817 | hasBin: true 818 | dev: true 819 | 820 | /node-releases@2.0.13: 821 | resolution: {integrity: sha512-uYr7J37ae/ORWdZeQ1xxMJe3NtdmqMC/JZK+geofDrkLUApKRHPd18/TxtBOJ4A0/+uUIliorNrfYV6s1b02eQ==} 822 | dev: true 823 | 824 | /picocolors@1.0.0: 825 | resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==} 826 | dev: true 827 | 828 | /picomatch@2.3.1: 829 | resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} 830 | engines: {node: '>=8.6'} 831 | dev: true 832 | 833 | /postcss@8.4.26: 834 | resolution: {integrity: sha512-jrXHFF8iTloAenySjM/ob3gSj7pCu0Ji49hnjqzsgSRa50hkWCKD0HQ+gMNJkW38jBI68MpAAg7ZWwHwX8NMMw==} 835 | engines: {node: ^10 || ^12 || >=14} 836 | dependencies: 837 | nanoid: 3.3.6 838 | picocolors: 1.0.0 839 | source-map-js: 1.0.2 840 | dev: true 841 | 842 | /react-dom@18.2.0(react@18.2.0): 843 | resolution: {integrity: sha512-6IMTriUmvsjHUjNtEDudZfuDQUoWXVxKHhlEGSk81n4YFS+r/Kl99wXiwlVXtPBtJenozv2P+hxDsw9eA7Xo6g==} 844 | peerDependencies: 845 | react: ^18.2.0 846 | dependencies: 847 | loose-envify: 1.4.0 848 | react: 18.2.0 849 | scheduler: 0.23.0 850 | dev: false 851 | 852 | /react-refresh@0.14.0: 853 | resolution: {integrity: sha512-wViHqhAd8OHeLS/IRMJjTSDHF3U9eWi62F/MledQGPdJGDhodXJ9PBLNGr6WWL7qlH12Mt3TyTpbS+hGXMjCzQ==} 854 | engines: {node: '>=0.10.0'} 855 | dev: true 856 | 857 | /react@18.2.0: 858 | resolution: {integrity: sha512-/3IjMdb2L9QbBdWiW5e3P2/npwMBaU9mHCSCUzNln0ZCYbcfTsGbTJrU/kGemdH2IWmB2ioZ+zkxtmq6g09fGQ==} 859 | engines: {node: '>=0.10.0'} 860 | dependencies: 861 | loose-envify: 1.4.0 862 | dev: false 863 | 864 | /rollup@3.26.2: 865 | resolution: {integrity: sha512-6umBIGVz93er97pMgQO08LuH3m6PUb3jlDUUGFsNJB6VgTCUaDFpupf5JfU30529m/UKOgmiX+uY6Sx8cOYpLA==} 866 | engines: {node: '>=14.18.0', npm: '>=8.0.0'} 867 | hasBin: true 868 | optionalDependencies: 869 | fsevents: 2.3.2 870 | dev: true 871 | 872 | /scheduler@0.23.0: 873 | resolution: {integrity: sha512-CtuThmgHNg7zIZWAXi3AsyIzA3n4xx7aNyjwC2VJldO2LMVDhFK+63xGqq6CsJH4rTAt6/M+N4GhZiDYPx9eUw==} 874 | dependencies: 875 | loose-envify: 1.4.0 876 | dev: false 877 | 878 | /semver@6.3.1: 879 | resolution: {integrity: sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==} 880 | hasBin: true 881 | dev: true 882 | 883 | /source-map-js@1.0.2: 884 | resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==} 885 | engines: {node: '>=0.10.0'} 886 | dev: true 887 | 888 | /supports-color@5.5.0: 889 | resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} 890 | engines: {node: '>=4'} 891 | dependencies: 892 | has-flag: 3.0.0 893 | dev: true 894 | 895 | /to-fast-properties@2.0.0: 896 | resolution: {integrity: sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==} 897 | engines: {node: '>=4'} 898 | dev: true 899 | 900 | /typescript@5.1.6: 901 | resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==} 902 | engines: {node: '>=14.17'} 903 | hasBin: true 904 | dev: true 905 | 906 | /update-browserslist-db@1.0.11(browserslist@4.21.9): 907 | resolution: {integrity: sha512-dCwEFf0/oT85M1fHBg4F0jtLwJrutGoHSQXCh7u4o2t1drG+c0a9Flnqww6XUKSfQMPpJBRjU8d4RXB09qtvaA==} 908 | hasBin: true 909 | peerDependencies: 910 | browserslist: '>= 4.21.0' 911 | dependencies: 912 | browserslist: 4.21.9 913 | escalade: 3.1.1 914 | picocolors: 1.0.0 915 | dev: true 916 | 917 | /vite@4.4.4(@types/node@18.16.19): 918 | resolution: {integrity: sha512-4mvsTxjkveWrKDJI70QmelfVqTm+ihFAb6+xf4sjEU2TmUCTlVX87tmg/QooPEMQb/lM9qGHT99ebqPziEd3wg==} 919 | engines: {node: ^14.18.0 || >=16.0.0} 920 | hasBin: true 921 | peerDependencies: 922 | '@types/node': '>= 14' 923 | less: '*' 924 | lightningcss: ^1.21.0 925 | sass: '*' 926 | stylus: '*' 927 | sugarss: '*' 928 | terser: ^5.4.0 929 | peerDependenciesMeta: 930 | '@types/node': 931 | optional: true 932 | less: 933 | optional: true 934 | lightningcss: 935 | optional: true 936 | sass: 937 | optional: true 938 | stylus: 939 | optional: true 940 | sugarss: 941 | optional: true 942 | terser: 943 | optional: true 944 | dependencies: 945 | '@types/node': 18.16.19 946 | esbuild: 0.18.12 947 | postcss: 8.4.26 948 | rollup: 3.26.2 949 | optionalDependencies: 950 | fsevents: 2.3.2 951 | dev: true 952 | 953 | /yallist@3.1.1: 954 | resolution: {integrity: sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==} 955 | dev: true 956 | 957 | settings: 958 | autoInstallPeers: true 959 | excludeLinksFromLockfile: false 960 | -------------------------------------------------------------------------------- /public/vite.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/App.css: -------------------------------------------------------------------------------- 1 | #root { 2 | max-width: 1280px; 3 | margin: 0 auto; 4 | padding: 2rem; 5 | text-align: center; 6 | } 7 | 8 | .logo { 9 | height: 6em; 10 | padding: 1.5em; 11 | will-change: filter; 12 | } 13 | .logo:hover { 14 | filter: drop-shadow(0 0 2em #646cffaa); 15 | } 16 | .logo.react:hover { 17 | filter: drop-shadow(0 0 2em #61dafbaa); 18 | } 19 | 20 | @keyframes logo-spin { 21 | from { 22 | transform: rotate(0deg); 23 | } 24 | to { 25 | transform: rotate(360deg); 26 | } 27 | } 28 | 29 | @media (prefers-reduced-motion: no-preference) { 30 | a:nth-of-type(2) .logo { 31 | animation: logo-spin infinite 20s linear; 32 | } 33 | } 34 | 35 | .card { 36 | padding: 2em; 37 | } 38 | 39 | .read-the-docs { 40 | color: #888; 41 | } 42 | -------------------------------------------------------------------------------- /src/App.tsx: -------------------------------------------------------------------------------- 1 | import { useState } from "react"; 2 | import reactLogo from "./assets/react.svg"; 3 | import "./App.css"; 4 | import { Effect, Layer, pipe } from "effect"; 5 | import { ErrorOfReadingFile, ReadFileService } from "./ReadFileService"; 6 | import { ErrorOfLoadingImage, LoadImageService } from "./LoadFileService"; 7 | 8 | type ImageSize = { width: number; height: number }; 9 | type FileStatus = 10 | | { _tag: "NotSelected" } 11 | | { _tag: "NotImage" } 12 | | { _tag: "FileError" } 13 | | { _tag: "Selected"; size: ImageSize }; 14 | 15 | const ReadFileLive = Layer.succeed( 16 | ReadFileService, 17 | ReadFileService.of((file: File) => 18 | Effect.tryPromise({ 19 | try: () => { 20 | const reader = new FileReader(); 21 | return new Promise((resolve, reject) => { 22 | reader.onload = () => resolve(reader.result as string); 23 | reader.onerror = (e) => reject(e); 24 | reader.readAsDataURL(file); 25 | }); 26 | }, 27 | catch: (_) => new ErrorOfReadingFile(), 28 | }), 29 | ), 30 | ); 31 | 32 | const LoadImageLive = Layer.succeed( 33 | LoadImageService, 34 | LoadImageService.of((dataUrl: string) => 35 | Effect.tryPromise({ 36 | try: () => { 37 | const img = new Image(); 38 | return new Promise((resolve, reject) => { 39 | img.onload = () => resolve(img); 40 | img.onerror = (e) => reject(e); 41 | img.src = dataUrl; 42 | }); 43 | }, 44 | catch: (_) => new ErrorOfLoadingImage(), 45 | }), 46 | ), 47 | ); 48 | 49 | const getImageSize = ({ 50 | width, 51 | height, 52 | }: T): ImageSize => ({ width, height }); 53 | 54 | const programOfGetImageSize = (file: File) => 55 | pipe( 56 | Effect.all([ReadFileService, LoadImageService]), 57 | Effect.flatMap(([ReadFile, LoadImage]) => 58 | pipe( 59 | Effect.succeed(file), 60 | Effect.flatMap(ReadFile), 61 | Effect.flatMap(LoadImage), 62 | Effect.map(getImageSize), 63 | ), 64 | ), 65 | ); 66 | 67 | function App() { 68 | const [count, setCount] = useState(0); 69 | const [status, setStatus] = useState({ _tag: "NotSelected" }); 70 | 71 | const handleFileChange = async (e: React.ChangeEvent) => { 72 | const file = e.target.files?.[0]; 73 | if (file === undefined) { 74 | setStatus({ _tag: "NotSelected" }); 75 | return; 76 | } 77 | 78 | const program = programOfGetImageSize(file).pipe( 79 | // 이미지 변환 성공시 status로 인코딩 80 | Effect.map((size) => ({ _tag: "Selected", size } as const)), 81 | // 에러를 status로 인코딩 82 | Effect.catchTags({ 83 | ErrorOfReadingFile: () => 84 | Effect.succeed({ _tag: "FileError" } as const), 85 | ErrorOfLoadingImage: () => 86 | Effect.succeed({ _tag: "NotImage" } as const), 87 | }), 88 | ); 89 | 90 | const runnable: Effect.Effect = 91 | Effect.provideLayer(program, Layer.merge(ReadFileLive, LoadImageLive)); 92 | 93 | const result = await Effect.runPromise(runnable); 94 | 95 | setStatus(result); 96 | }; 97 | 98 | return ( 99 |
100 | 108 |

Vite + React

109 |
110 | 111 |
112 |
113 | {status._tag === "NotSelected" && "파일이 선택되지 않았습니다."} 114 | {status._tag === "NotImage" && "이미지 파일이 아닙니다."} 115 | {status._tag === "FileError" && "파일을 읽는 중에 에러가 발생했습니다."} 116 | {status._tag === "Selected" && 117 | `이미지 크기: ${status.size.width}x${status.size.height}`} 118 |
119 |
120 | 123 |

124 | Edit src/App.tsx and save to test HMR 125 |

126 |
127 |

128 | Click on the Vite and React logos to learn more 129 |

130 |
131 | ); 132 | } 133 | 134 | export default App; 135 | -------------------------------------------------------------------------------- /src/LoadFileService.ts: -------------------------------------------------------------------------------- 1 | import { Context, Effect } from "effect"; 2 | 3 | export class ErrorOfLoadingImage { 4 | readonly _tag = "ErrorOfLoadingImage"; 5 | } 6 | 7 | export type LoadImageService = ( 8 | dataUrl: string, 9 | ) => Effect.Effect; 10 | 11 | export const LoadImageService = Context.Tag(); 12 | -------------------------------------------------------------------------------- /src/ReadFileService.ts: -------------------------------------------------------------------------------- 1 | import { Context, Effect } from "effect"; 2 | 3 | export class ErrorOfReadingFile { 4 | readonly _tag = "ErrorOfReadingFile"; 5 | } 6 | 7 | export type ReadFileService = ( 8 | file: File, 9 | ) => Effect.Effect; 10 | 11 | export const ReadFileService = Context.Tag(); 12 | -------------------------------------------------------------------------------- /src/assets/react.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/index.css: -------------------------------------------------------------------------------- 1 | :root { 2 | font-family: Inter, Avenir, Helvetica, Arial, sans-serif; 3 | font-size: 16px; 4 | line-height: 24px; 5 | font-weight: 400; 6 | 7 | color-scheme: light dark; 8 | color: rgba(255, 255, 255, 0.87); 9 | background-color: #242424; 10 | 11 | font-synthesis: none; 12 | text-rendering: optimizeLegibility; 13 | -webkit-font-smoothing: antialiased; 14 | -moz-osx-font-smoothing: grayscale; 15 | -webkit-text-size-adjust: 100%; 16 | } 17 | 18 | a { 19 | font-weight: 500; 20 | color: #646cff; 21 | text-decoration: inherit; 22 | } 23 | a:hover { 24 | color: #535bf2; 25 | } 26 | 27 | body { 28 | margin: 0; 29 | display: flex; 30 | place-items: center; 31 | min-width: 320px; 32 | min-height: 100vh; 33 | } 34 | 35 | h1 { 36 | font-size: 3.2em; 37 | line-height: 1.1; 38 | } 39 | 40 | button { 41 | border-radius: 8px; 42 | border: 1px solid transparent; 43 | padding: 0.6em 1.2em; 44 | font-size: 1em; 45 | font-weight: 500; 46 | font-family: inherit; 47 | background-color: #1a1a1a; 48 | cursor: pointer; 49 | transition: border-color 0.25s; 50 | } 51 | button:hover { 52 | border-color: #646cff; 53 | } 54 | button:focus, 55 | button:focus-visible { 56 | outline: 4px auto -webkit-focus-ring-color; 57 | } 58 | 59 | @media (prefers-color-scheme: light) { 60 | :root { 61 | color: #213547; 62 | background-color: #ffffff; 63 | } 64 | a:hover { 65 | color: #747bff; 66 | } 67 | button { 68 | background-color: #f9f9f9; 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /src/main.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import App from "./App"; 4 | import "./index.css"; 5 | 6 | ReactDOM.createRoot(document.getElementById("root") as HTMLElement).render( 7 | 8 | 9 | , 10 | ); 11 | -------------------------------------------------------------------------------- /src/vite-env.d.ts: -------------------------------------------------------------------------------- 1 | /// 2 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ESNext", 4 | "useDefineForClassFields": true, 5 | "lib": ["DOM", "DOM.Iterable", "ESNext"], 6 | "allowJs": false, 7 | "skipLibCheck": true, 8 | "esModuleInterop": false, 9 | "allowSyntheticDefaultImports": true, 10 | "strict": true, 11 | "forceConsistentCasingInFileNames": true, 12 | "module": "ESNext", 13 | "moduleResolution": "Node", 14 | "resolveJsonModule": true, 15 | "isolatedModules": true, 16 | "noEmit": true, 17 | "jsx": "preserve" 18 | }, 19 | "include": ["src"], 20 | "references": [{ "path": "./tsconfig.node.json" }] 21 | } 22 | -------------------------------------------------------------------------------- /tsconfig.node.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "composite": true, 4 | "module": "ESNext", 5 | "moduleResolution": "Node", 6 | "allowSyntheticDefaultImports": true, 7 | "lib": ["ES2022"] 8 | }, 9 | "include": ["vite.config.ts"] 10 | } 11 | -------------------------------------------------------------------------------- /vite.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from "vite"; 2 | import { effectPlugin } from "@effect/vite-plugin-react"; 3 | 4 | export default defineConfig({ 5 | plugins: [ 6 | effectPlugin({ 7 | babel: { 8 | plugins: ["babel-plugin-annotate-pure-calls"], 9 | }, 10 | }), 11 | ], 12 | }); 13 | --------------------------------------------------------------------------------