diff --git a/language/.vscode/settings.json b/language/.vscode/settings.json index eb71540..cdd1b07 100644 --- a/language/.vscode/settings.json +++ b/language/.vscode/settings.json @@ -1,8 +1,9 @@ { - "editor.insertSpaces": false, + "editor.insertSpaces": true, "typescript.tsc.autoDetect": "off", "typescript.preferences.quoteStyle": "single", "editor.codeActionsOnSave": { "source.fixAll.eslint": "explicit" - } + }, + "editor.tabSize": 2, } \ No newline at end of file diff --git a/package.json b/package.json index 3965ace..2db9a68 100644 --- a/package.json +++ b/package.json @@ -11,6 +11,7 @@ "build:transformer": "yarn --cwd packages/idea-transformer build", "build:idea": "yarn --cwd packages/idea build", "build:example": "yarn --cwd example build", + "dev": "yarn --cwd packages/www dev", "report": "yarn report:env nyc yarn test && nyc report -r lcov", "report:env": "NODE_OPTIONS=\"--disable-warning=ExperimentalWarning --experimental-loader @istanbuljs/esm-loader-hook\"", "transform": "yarn --cwd example transform", diff --git a/packages/www/.gitignore b/packages/www/.gitignore new file mode 100644 index 0000000..185824a --- /dev/null +++ b/packages/www/.gitignore @@ -0,0 +1,137 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.development.local +.env.test.local +.env.production.local +.env.local + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* + +archives +.ink +.DS_Store +.build + +archives \ No newline at end of file diff --git a/packages/www/build.ts b/packages/www/build.ts new file mode 100644 index 0000000..9ec1611 --- /dev/null +++ b/packages/www/build.ts @@ -0,0 +1,93 @@ +//node +import fs from 'node:fs/promises'; +import path from 'node:path'; +//stackpress +import { Terminal } from 'stackpress/terminal'; +import * as scripts from 'stackpress/scripts'; +//plugins +import { docs } from './config/common.js'; +import bootstrap from './config/build.js'; + +async function build() { + const server = await bootstrap(); + const cli = new Terminal(['build'], server); + + cli.control.system('Copying public to docs...'); + await fsCopyFolder(path.join(cli.cwd, 'public'), docs); + + cli.control.system('Building pages, client and styles...'); + await scripts.build(server); + + cli.control.system('Generating markup in docs...'); + const ignore = Array.from(server.action.expressions.keys()); + const routes = Array.from(server.routes.entries()).filter( + ([event]) => !ignore.includes(event) + ); + + for (const [event, route] of routes) { + const request = server.request({ + url: new URL(`https://www.stackpress.io${route.path}`), + }); + const response = await server.resolve(event, request); + cli.control.system(`Generating ${request.url.href} ...`); + if (response.results) { + const routepath = route.path.replace(/^\//, ''); + const filepath = routepath === '' ? 'index.html' : `${routepath}.html`; + await fsWriteFile( + path.join(docs, filepath), + response.results as string + ) + } + } +}; + +async function fsWriteFile(file: string, data: string) { + const dirname = path.dirname(file); + if (!await fsExists(dirname)) { + await fs.mkdir(dirname, { recursive: true }); + } + await fs.writeFile(file, data, 'utf-8'); +} + +async function fsCopyFile(source: string, destination: string) { + if (await fsExists(source)) { + const dirname = path.dirname(destination); + if (!await fsExists(dirname)) { + await fs.mkdir(dirname, { recursive: true }); + } + await fs.copyFile(source, destination); + } +}; + +async function fsCopyFolder(source: string, destination: string) { + //find all the files from source + const files = await fs.readdir(source); + for (const file of files) { + //ignore . and .. + if (file === '.' || file === '..') continue; + //make an absolute source path + const absolute = path.join(source, file); + const stat = await fs.stat(absolute); + //if file is a directory, recurse + if (stat.isDirectory()) { + fsCopyFolder( + path.join(source, file), + path.join(destination, file) + ); + continue; + } + await fsCopyFile(absolute, path.join(destination, file)); + } +}; + +async function fsExists(path: string) { + return await fs.access(path).then(() => true).catch(() => false); +} + +build().then(() => { + console.log('Build completed successfully.'); + process.exit(0); +}).catch((error) => { + console.error('Build failed:', error); + process.exit(1); +}); \ No newline at end of file diff --git a/packages/www/config/build.ts b/packages/www/config/build.ts new file mode 100644 index 0000000..b894c8c --- /dev/null +++ b/packages/www/config/build.ts @@ -0,0 +1,60 @@ +//node +import path from 'node:path'; +//modules +import unocss from 'unocss/vite'; +//stackpress +import { server as http } from 'stackpress/http'; +//config +import type { Config } from './common.js'; +import * as common from './common.js'; + +export const config: Config = { + server: { + ...common.server, + mode: 'production' + }, + view: { + ...common.view, + //reactus specific settings + engine: { + //path where to save assets (css, images, etc) + assetPath: path.join(common.docs, 'assets'), + //path where to save the client scripts (js) + clientPath: path.join(common.docs, 'client'), + //path where to save the server scripts (js) + pagePath: path.join(common.build, 'pages'), + //filepath to a global css file + cssFiles: [ + 'frui/frui.css', + 'stackpress/stackpress.css', + 'virtual:uno.css' + ], + //vite plugins + plugins: [ unocss() ], + //original vite options (overrides other settings related to vite) + vite: undefined + } + }, + brand: common.brand, + cli: common.cli, + cookie: common.cookie, + language: common.language, + session: common.session +}; + +export default async function bootstrap() { + //make a server + const server = http(); + //set config + server.config.set(config); + //load the plugins + await server.bootstrap(); + //initialize the plugins + await server.resolve('config'); + //add events + await server.resolve('listen'); + //add routes + await server.resolve('route'); + //return the server + return server; +}; \ No newline at end of file diff --git a/packages/www/config/common.ts b/packages/www/config/common.ts new file mode 100644 index 0000000..a6157ad --- /dev/null +++ b/packages/www/config/common.ts @@ -0,0 +1,83 @@ +//node +import path from 'node:path'; + +export type { Config } from 'stackpress/types'; + +export const cwd = process.cwd(); +export const docs = path.join(cwd, 'docs'); +export const build = path.join(cwd, '.build'); +export const assets = path.join(cwd, 'public'); + +export const brand = { + name: 'Stackpress', + logo: '/logo.png', + icon: '/icon.png', + favicon: '/favicon.ico' +}; + +export const server = { + port: 3000, + cwd: cwd +}; + +export const view = { + //url flag (ie. ?json) used to disable template + //rendering and show the raw json data instead + noview: 'json', + //used by vite and in development mode + //to determine the root of the project + base: '/', + //frontend notification display settings + notify: { + position: 'bottom-center', + autoClose: 1000, + hideProgressBar: false, + closeOnClick: true, + pauseOnHover: true, + draggable: true, + theme: 'dark', + } +}; + +export const session = { + //name of the session cookie + key: 'session', + //used to generate the session id + seed: 'abc123', + access: { GUEST: [{ method: 'ALL', route: '/**' }] } +}; + +export const cookie = { + //see: https://github.com/jshttp/cookie?tab=readme-ov-file#options-1 + path: '/' +}; + +export const language = { + //url flag (ie. ?json) used to change the user's locale + //this is also the name of the cookie used to store the locale + key: 'locale', + //default locale + locale: 'en_US', + //languages and translations + languages: { + en_US: { + label: 'EN', + translations: { + 'Sign In': 'Signin', + 'Home Page': 'Home Page' + } + }, + th_TH: { + label: 'TH', + translations: { + 'Sign In': 'เข้าสู่ระบบ', + 'Home Page': 'หน้าหลัก' + } + } + } +}; + +export const cli = { + label: '[WWW]', + idea: path.join(cwd, 'schema.idea') +}; \ No newline at end of file diff --git a/packages/www/config/develop.ts b/packages/www/config/develop.ts new file mode 100644 index 0000000..ab1a1ac --- /dev/null +++ b/packages/www/config/develop.ts @@ -0,0 +1,57 @@ +//modules +import unocss from 'unocss/vite'; +//stackpress +import { server as http } from 'stackpress/http'; +//config +import type { Config } from './common.js'; +import * as common from './common.js'; + +export const config: Config = { + server: { + ...common.server, + mode: 'development' + }, + view: { + ...common.view, + //reactus specific settings + engine: { + //base path (used in vite) + basePath: '/', + //client script route prefix used in the document markup + //ie. /client/[id][extname] + // + // + clientRoute: '/client', + //filepath to a global css file + cssFiles: [ + 'frui/frui.css', + 'stackpress/stackpress.css', + 'virtual:uno.css' + ], + //vite plugins + plugins: [ unocss() ] + } + }, + brand: common.brand, + cli: common.cli, + cookie: common.cookie, + language: common.language, + session: common.session +}; + +export default async function bootstrap() { + //make a server + const server = http(); + //set config + server.config.set(config); + //load the plugins + await server.bootstrap(); + //initialize the plugins + await server.resolve('config'); + //add events + await server.resolve('listen'); + //add routes + await server.resolve('route'); + //return the server + return server; +}; \ No newline at end of file diff --git a/packages/www/config/preview.ts b/packages/www/config/preview.ts new file mode 100644 index 0000000..32769f7 --- /dev/null +++ b/packages/www/config/preview.ts @@ -0,0 +1,59 @@ +//node +import path from 'node:path'; +//stackpress +import type { Server } from 'stackpress/server'; +import { server as http } from 'stackpress/http'; +//plugin +import assets from '../plugins/assets/plugin.js'; +//config +import type { Config } from './common.js'; +import * as common from './common.js'; + +export const config: Config = { + assets: common.assets, + server: { + ...common.server, + mode: 'production' + }, + view: { + ...common.view, + //reactus specific settings + engine: { + //client script route prefix used in the document markup + //ie. /client/[id][extname] + // + // + clientRoute: '/client', + //style route prefix used in the document markup + //ie. /assets/[id][extname] + // + // + cssRoute: '/assets', + //path where to save and load (live) the server script (js) + pagePath: path.join(common.cwd, '.build/views') + } + }, + brand: common.brand, + cli: common.cli, + cookie: common.cookie, + language: common.language +}; + +export default async function bootstrap() { + //make a server + const server = http(); + //set config + server.config.set(config); + //load the plugins + await server.bootstrap(); + //add the assets plugin + assets(server as Server); + //initialize the plugins + await server.resolve('config'); + //add events + await server.resolve('listen'); + //add routes + await server.resolve('route'); + //return the server + return server; +}; \ No newline at end of file diff --git a/packages/www/package.json b/packages/www/package.json new file mode 100644 index 0000000..2a2cdae --- /dev/null +++ b/packages/www/package.json @@ -0,0 +1,55 @@ +{ + "type": "module", + "name": "stackpress-with-unocss", + "version": "1.0.0", + "private": true, + "plugins": [ + "./plugins/app/plugin", + "./plugins/docs/plugin", + "stackpress" + ], + "scripts": { + "build": "yarn build:purge && yarn build:tsx", + "build:purge": "rm -rf docs", + "build:tsx": "npx tsx build.ts", + "dev": "stackpress serve -v --b config/develop", + "emit": "stackpress emit -v --b config/develop", + "preview": "stackpress serve -v --b config/preview" + }, + "dependencies": { + "@tailwindcss/vite": "^4.1.12", + "clsx": "^2.1.1", + "frui": "0.1.8", + "fuse.js": "^7.1.0", + "react": "19.1.0", + "react-dom": "19.1.0", + "react-syntax-highlighter": "15.6.1", + "react-toastify": "^11.0.5", + "stackpress": "0.6.1", + "tailwindcss": "^4.1.12", + "vanta-react": "^0.4.3" + }, + "devDependencies": { + "@stackpress/idea-transformer": "0.6.1", + "@types/chai": "5.2.1", + "@types/mocha": "10.0.10", + "@types/node": "22.14.1", + "@types/react": "19.1.2", + "@types/react-dom": "19.1.2", + "@types/react-syntax-highlighter": "15.5.13", + "@vitejs/plugin-react": "4.4.1", + "chai": "5.2.0", + "dotenv-cli": "8.0.0", + "fast-glob": "3.3.3", + "mocha": "11.2.2", + "nyc": "17.1.0", + "prettier": "3.5.3", + "ts-mocha": "11.1.0", + "ts-morph": "25.0.1", + "ts-node": "10.9.2", + "tsx": "4.19.3", + "typescript": "5.8.3", + "unocss": "66.0.0", + "vite": "6.3.2" + } +} diff --git a/packages/www/plugins/app/Layout.tsx b/packages/www/plugins/app/Layout.tsx new file mode 100644 index 0000000..eebce8e --- /dev/null +++ b/packages/www/plugins/app/Layout.tsx @@ -0,0 +1,209 @@ +//modules +import { useState, useEffect } from 'react'; +import clsx from 'clsx'; +//views +import type { + PanelAppProps, + LayoutHeadProps, + LayoutPanelProps +} from 'stackpress/view/client'; +import { + unload, + useTheme, + useLanguage, + NotifyContainer, + LayoutMain, + LayoutProvider +} from 'stackpress/view/client'; +//styles +import './styles/page.css'; + +//components +import SearchField from './components/Search.js'; + +//styles +//---------------------------------------------------------------------- + +const headerStyles = clsx( + 'absolute', + 'border-b', + 'duration-200', + 'px-h-60', + 'px-l-0', + 'px-r-0', + 'px-t-0', + 'theme-bc-bd0', + 'theme-bg-bg1' +); + +const headerContainerStyles = clsx( + 'align-middle', + 'flex', + 'items-center', + 'justify-between', + 'px-h-100-0', + 'px-px-20' +); + +const docsAnchorTagStyles = clsx( + 'flex', + 'hover:text-yellow-500', + 'items-center', + 'mt-1', + 'no-underline', + 'theme-tx1', + 'uppercase' +); + +const npmAnchorTagStyles = clsx( + 'flex', + 'hex-bg-CB3837', + 'items-center', + 'justify-center', + 'px-h-26', + 'px-mr-10', + 'px-w-26', + 'rounded-full' +); + +//---------------------------------------------------------------------- + +export function Head(props: LayoutHeadProps) { + const { theme, toggleTheme } = props; + const { _ } = useLanguage(); + const themeColor = theme === 'dark' ? 'bg-gray-600' : 'bg-orange-600'; + const themeIcon = theme === 'dark' ? 'fa-moon' : 'fa-sun'; + return ( +
+
+
+ + idea-logo + idea + + +
+
+ +
+
+
+ ); +} + +export function App(props: PanelAppProps) { + const { children } = props; + const { theme, toggle: toggleTheme } = useTheme(); + return ( +
+ + {children} +
+ ); +} + +export default function Layout(props: LayoutPanelProps) { + const { + data, + session, + response, + children + } = props; + const [request, setRequest] = useState>({ + ...(props.request || {}), + session: { + ...(props.request?.session || {}), + theme: props.request?.session?.theme || 'dark' + } + }); + //unload flash message + useEffect(() => { + const light = document.cookie.includes('theme=light'); + if (!request.session?.theme) { + setRequest({ + ...request, + session: { theme: light ? 'light' : 'dark' } + }); + } + unload(); + }, []); + if (!request?.session?.theme) { + return null; + } + + return ( + + {children} + + + ); +} \ No newline at end of file diff --git a/packages/www/plugins/app/components/Search.tsx b/packages/www/plugins/app/components/Search.tsx new file mode 100644 index 0000000..a687f1a --- /dev/null +++ b/packages/www/plugins/app/components/Search.tsx @@ -0,0 +1,143 @@ +//modules +import { useState, useEffect } from "react" +import Fuse from "fuse.js" +import clsx from "clsx"; + +//search types +type SearchItem = { + title: string; + url: string; + description: string; +}; + +//styles +//--------------------------------------------------------------------// + +const searchFieldStyle = clsx( + "border", + "border-gray-500", + "lg:w-120", + "mx-10", + "p-2", + "placeholder:text-gray-600", + "theme-bg-bg1", + "z-10" +); + +const searchResultsStyle = clsx( + "absolute", + "border", + "border-gray-500", + "lg:w-120", + "mb-2", + "md:w-96", + "mt-3", + "right-10", + "sm:w-100", + "top-full", + "w-85", + "z-200" +); + +const noResultsStyle = clsx( + "absolute", + "border", + "border-gray-500", + "lg:w-120", + "mb-2", + "md:w-96", + "mt-3", + "right-10", + "sm:w-100", + "top-full", + "w-85", + "z-200" +); + +//--------------------------------------------------------------------// + +export default function Search() { + //hooks + const [query, setQuery] = useState(""); + const [results, setResults] = useState([]); + const [fuse, setFuse] = useState>(); + + //load search index function + async function loadIndex() { + //fetch search index file from public directory + const result = await fetch("/search-list.json"); + //await response and parse json + const data: SearchItem[] = await result.json(); + + //create fuse instance with options + const fuseInstance = new Fuse(data, { + keys: ["title", "description"], + threshold: 0.6, + findAllMatches: false, + minMatchCharLength: 2 + }); + + //set fuse instance to state + setFuse(fuseInstance); + } + + //effect to load index and perform search + useEffect(() => { + //initial load + loadIndex() + + //check if fuse is ready and query is not empty + if (!fuse || !query) { + setResults([]) + return + } + + //perform search + const searchResults = fuse.search(query).map(result => result.item) + setResults(searchResults) + }, [query, fuse]) + + return ( + <> + {/* Search Field Component */} +
+ setQuery(e.target.value)} + className={searchFieldStyle} + /> + {results.length > 0 ? ( + //results found +
+ +
+ ) : query ? ( + //if no results found +
+
    +
  • + No results found. +
  • +
+
+ ) : null} +
+ + ) +} \ No newline at end of file diff --git a/packages/www/plugins/app/components/landing-page/AIDevelopmentWorkflowSection.tsx b/packages/www/plugins/app/components/landing-page/AIDevelopmentWorkflowSection.tsx new file mode 100644 index 0000000..a02e2ce --- /dev/null +++ b/packages/www/plugins/app/components/landing-page/AIDevelopmentWorkflowSection.tsx @@ -0,0 +1,210 @@ +//modules +import { Translate, useLanguage } from 'r22n'; +import clsx from 'clsx'; + +//styles +//--------------------------------------------------------------------// + +const headlineBarStyle = clsx( + 'bg-yellow-100', + 'border', + 'gap-2', + 'inline-flex', + 'items-center', + 'mb-4', + 'px-3', + 'py-1', + 'rounded-full', + 'text-sm' +); + +const stepOneStyle = clsx( + 'bg-pink-100', + 'flex', + 'h-8', + 'items-center', + 'justify-center', + 'rounded-full', + 'text-pink-600', + 'w-8' +); + +const stepTwoStyle = clsx( + 'bg-purple-100', + 'flex', + 'h-8', + 'items-center', + 'justify-center', + 'rounded-full', + 'text-purple-600', + 'w-8' +); + +const stepThreeStyle = clsx( + 'bg-yellow-100', + 'flex', + 'h-8', + 'items-center', + 'justify-center', + 'rounded-full', + 'text-yellow-600', + 'w-8' +); + +const stepFourStyle = clsx( + 'bg-green-100', + 'flex', + 'h-8', + 'items-center', + 'justify-center', + 'rounded-full', + 'text-green-600', + 'w-8' +); + +const stepFiveStyle = clsx( + 'bg-blue-100', + 'flex', + 'h-8', + 'items-center', + 'justify-center', + 'rounded-full', + 'text-blue-600', + 'w-8' +); + +//--------------------------------------------------------------------// + +export default function AIDevelopmentWorkflowSection() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* AI Development Workflow Section Content */} +
+
+
+ + + + + {_('AI‑Powered Development Workflow')} + +
+ +

+ {_('Build faster with AI + .idea')} +

+ +

+ + The .idea format is perfect for AI‑driven development. + +

+
+ + {/* AI Development Workflow Steps */} +
+ {/* Step 1 */} +
+
+ + + +

+ {_('Step 1')} +

+
+

+ + Describe your application to an AI assistant + +

+
+ + {/* Step 2 */} +
+
+ + + +

+ {_('Step 2')} +

+
+

+ + Generate a .idea schema from the description + +

+
+ + {/* Step 3 */} +
+
+ + + +

+ {_('Step 3')} +

+
+

+ + Configure plugins for your target technologies + +

+
+ + {/* Step 4 */} +
+
+ + + +

+ {_('Step 4')} +

+
+

+ + Execute the transformation to generate full‑stack code + +

+
+ + {/* Step 5 */} +
+
+ + + +

+ {_('Step 5')} +

+
+

+ + Iterate by updating the schema and regenerating + +

+
+
+ + {/* Text to describe the workflow */} +
+

+ + This workflow enables rapid prototyping and development + and goes from idea to working application in minutes rather + than days. + +

+
+
+ + ) +} + + diff --git a/packages/www/plugins/app/components/landing-page/AboutSection.tsx b/packages/www/plugins/app/components/landing-page/AboutSection.tsx new file mode 100644 index 0000000..0ade07d --- /dev/null +++ b/packages/www/plugins/app/components/landing-page/AboutSection.tsx @@ -0,0 +1,30 @@ +//modules +import { Translate, useLanguage } from 'r22n'; + +export default function AboutSection() { + //hooks + const { _ } = useLanguage(); + return ( + <> + {/* About .idea Section Content */} +
+
+

+ {_('.idea')} +

+
+

+ + The .idea file format is a declarative schema definition + language designed to simplify application development by + providing a single source of truth for data structures, + relationships, and code generation. + +

+
+
+ + ) +} \ No newline at end of file diff --git a/packages/www/plugins/app/components/landing-page/AudienceSection.tsx b/packages/www/plugins/app/components/landing-page/AudienceSection.tsx new file mode 100644 index 0000000..3558038 --- /dev/null +++ b/packages/www/plugins/app/components/landing-page/AudienceSection.tsx @@ -0,0 +1,103 @@ +//modules +import { Translate, useLanguage } from 'r22n'; + +export default function AudienceSection() { + //hooks + const { _ } = useLanguage(); + return ( + <> + {/* Audience Section Content */} +
+

+ {_('Who Should Use This?')} +

+ +
+
+
+ + + +

+ {_('Junior Developers')} +

+
+
    +
  • + + Easy-to-understand syntax with examples + +
  • +
  • + + Rapid prototyping without deep framework knowledge + +
  • +
+
+ +
+
+ + + +

+ {_('Senior Developers')} +

+
+
    +
  • + + Powerful features for complex apps + +
  • +
  • + + Extensible plugin system + +
  • +
  • + + Cross-platform code generation + +
  • +
+
+ +
+
+ + + +

+ {_('CTOs & Leaders')} +

+
+
    +
  • + + Reduce dev time by 60–80% + +
  • +
  • + + Improve code consistency across teams + +
  • +
  • + + Lower maintenance costs + +
  • +
  • + + Accelerate time-to-market + +
  • +
+
+
+
+ + ) +} \ No newline at end of file diff --git a/packages/www/plugins/app/components/landing-page/BenefitsSection.tsx b/packages/www/plugins/app/components/landing-page/BenefitsSection.tsx new file mode 100644 index 0000000..a7a0f0e --- /dev/null +++ b/packages/www/plugins/app/components/landing-page/BenefitsSection.tsx @@ -0,0 +1,97 @@ +//modules +import { Translate, useLanguage } from 'r22n'; +import clsx from 'clsx'; + +//benefit cards data +//--------------------------------------------------------------------// + +const benefitCards = [ + { + title: 'Single Source of Truth', + desc: 'One schema powers DB, types, APIs, docs, and forms.', + icon: 'fa-bullseye', + color: 'text-green-400' + }, + { + title: 'Type Safety Everywhere', + desc: 'Consistent, type‑safe code across languages and frameworks.', + icon: 'fa-shield-halved', + color: 'text-blue-400' + }, + { + title: 'Rapid Development', + desc: 'Generate boilerplate, forms, and docs in seconds.', + icon: 'fa-bolt', + color: 'text-purple-400' + }, + { + title: 'Perfect Consistency', + desc: 'Update the schema once—everything stays in sync.', + icon: 'fa-arrows-rotate', + color: 'text-yellow-400' + }, + { + title: 'Extensible by Plugins', + desc: 'Target any framework or language with custom generators.', + icon: 'fa-plug', + color: 'text-pink-400' + }, + { + title: 'AI‑to‑Code Bridge', + desc: 'Describe your model, generate production‑ready code.', + icon: 'fa-robot', + color: 'text-teal-400' + } +]; + +//--------------------------------------------------------------------// + +export default function BenefitsSection() { + //hooks + const { _ } = useLanguage(); + return ( + <> + {/* Benefits Section Content */} +
+

+ {_('Key Benefits')} +

+ + {/* Benefit Cards Grid */} +
+ {benefitCards.map((card, index) => ( +
+
+ + + +
+
+ {_(card.title)} +
+

+ + {card.desc} + +

+
+
+
+ ))} +
+
+ + ) +} diff --git a/packages/www/plugins/app/components/landing-page/FutureSection.tsx b/packages/www/plugins/app/components/landing-page/FutureSection.tsx new file mode 100644 index 0000000..b8d36c9 --- /dev/null +++ b/packages/www/plugins/app/components/landing-page/FutureSection.tsx @@ -0,0 +1,215 @@ +//modules +import Button from 'frui/form/Button'; +import { Translate, useLanguage } from 'r22n'; +import clsx from 'clsx'; + +//styles +//--------------------------------------------------------------------// + +const headlineBarStyle = clsx( + 'bg-green-800', + 'border', + 'gap-2', + 'inline-flex', + 'items-center', + 'mb-4', + 'px-3', + 'py-1', + 'rounded-full', + 'text-sm', + 'text-green-200' +); + +const getStartedButtonStyle = clsx( + 'bg-yellow-500', + 'hover:bg-yellow-600', + 'px-6', + 'py-3', + 'rounded-lg', + 'font-bold', + 'hover:scale-105', + 'transition' +); + +const readTheSpecButtonStyle = clsx( + 'px-6', + 'py-3', + 'border', + 'border-gray-600', + 'rounded-lg', + 'bg-gray-800', + 'hover:bg-gray-700', + 'text-white', + 'hover:scale-105', + 'transition' +); + +//--------------------------------------------------------------------// + +export default function FutureSection() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Future Section Content */} +
+
+
+
+ + {_('The Future')} +
+ +

+ {_('Declarative')}. + {_(' Type‑Safe. Automated.')} +

+ +

+ + Define intent once. Generate apps, APIs, and docs in + seconds. + +

+ + +
+ + {/* Features, Benefits, Resources, Philosophy sections */} +
+ {/* Features */} +
+

+ {_('Features')} +

+
+
+

+ {_('Automated')} +

+

+ + Less boilerplate. More building. + +

+
+
+

+ {_('Unified')} +

+

+ + One spec, many outputs. + +

+
+
+
+ + {/* Benefits */} +
+

+ {_('Benefits')} +

+
+
+

+ {_('Proactive')} +

+

+ + Types catch issues early. + +

+
+
+

+ {_('Instant')} +

+

+ + Generate full layers fast. + +

+
+
+
+ + {/* Resources */} + + + {/* Philosophy */} +
+

+ {_('Philosophy')} +

+
+ + "The fastest, safest line of code is the one you never + write." + +
+
+ {_('— Steve Jobs')} +
+
+
+ + {/* Copyright section */} +
+

+ + © 2025 .idea. Building the future of declarative development. + +

+
+
+
+ + ) +} diff --git a/packages/www/plugins/app/components/landing-page/HeroSection.tsx b/packages/www/plugins/app/components/landing-page/HeroSection.tsx new file mode 100644 index 0000000..2ec3e78 --- /dev/null +++ b/packages/www/plugins/app/components/landing-page/HeroSection.tsx @@ -0,0 +1,278 @@ +//modules +import { Translate, useLanguage } from 'r22n'; +import Button from 'frui/form/Button'; +import clsx from 'clsx'; +//local +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const installCommand = `npm i -D @stackpress/idea` + +//--------------------------------------------------------------------// + +const schemaExample = +`model User { + id String @id @default("nanoid()") + name String @required + email String @unique @required + created Date @default("now()") +} + +plugin "./plugins/typescript-generator.js" { + output "./generated/types.ts" +}` + +//--------------------------------------------------------------------// + +const transformCommand = `npx idea transform --input schema.idea` + +//--------------------------------------------------------------------// + +//styles +//--------------------------------------------------------------------// + +const headlineStyle = clsx( + 'font-bold', + 'lg:text-8xl', + 'mb-6', + 'md:text-5xl', + 'sm:text-6xl', + 'text-5xl', + 'text-white', + 'theme-tx1', + 'xs:text-4xl' +); + +const subheadlineStyle = clsx( + 'max-w-3xl', + 'mb-6', + 'mx-auto', + 'text-lg', + 'theme-tx1', + 'theme-color-text-muted' +); + +const ctaButtonStyle = clsx( + 'bg-yellow-500', + 'font-bold', + 'hover:bg-yellow-600', + 'hover:scale-105', + 'px-8', + 'py-4', + 'rounded-lg', + 'text-lg', + 'transition' +); + +//--------------------------------------------------------------------// + +export default function HeroSection() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Hero Content */} +
+
+
+
+ logo +
+
+ + {/* Headline */} +

+ + From Idea to Code + +

+ + {/* Subheadline */} +

+ + A meta language to express and transform your ideas to + reality. + +

+ +

+ + Generate TypeScript, GraphQL, REST APIs, and more from a + single schema + +

+ + {/* Call to Action Button */} +
+ +
+ +
+
+
+ +
+
+ {_('Fast')} +
+
+
+
+ +
+
+ {_('Safe')} +
+
+
+
+ +
+
+ {_('Flexible')} +
+
+
+
+
+ + {/* Steps Section */} +
+
+

+ + Turn Your Ideas Into Reality + +

+

+ + Simple steps to transform your schema into production-ready + code + +

+
+ +
+ {/* Install the Package */} +
+
+
+ +
+

+ {_('1. Install the Package')} +

+
+ + {installCommand} + +
+ + {/* Create Your Schema */} +
+
+
+ +
+

+ {_('2. Create Your Schema')} +

+
+

+ + Define your data models in a simple .idea file: + +

+ + {schemaExample} + +
+ + {/* Generate Code */} +
+
+
+ +
+

+ {_('3. Generate Code')} +

+
+

+ + Run the transformer to generate your code: + +

+ + {transformCommand} + +
+ + {/* Your Idea is Now Code! */} +
+
+
+ +
+

+ {_('4. Your Idea is Now Code!')} +

+
+
+

+ Generated files include: +

+
    +
  • + TypeScript interfaces & types +
  • +
  • + GraphQL schema definitions +
  • +
  • + REST API client libraries +
  • +
  • + Validation schemas (Zod) +
  • +
  • + Database migrations +
  • +
  • + API documentation +
  • +
+
+
+
+
+ + ) +} \ No newline at end of file diff --git a/packages/www/plugins/app/components/landing-page/PluginEcosystemSection.tsx b/packages/www/plugins/app/components/landing-page/PluginEcosystemSection.tsx new file mode 100644 index 0000000..e24b5cc --- /dev/null +++ b/packages/www/plugins/app/components/landing-page/PluginEcosystemSection.tsx @@ -0,0 +1,67 @@ +//modules +import { Translate, useLanguage } from 'r22n'; + +//data samples +//--------------------------------------------------------------------// + +const iconData = [ + { + icon: 'fa-earth-asia fa-solid hover:animate-spin', + color: 'text-blue-400', + title: 'Multi‑Language Support' + }, + { + icon: 'fa-brands fa-react hover:animate-spin', + color: 'text-blue-400', + title: 'Framework Integration' + }, + { + icon: 'fa-solid fa-database hover:animate-bounce', + color: 'text-green-400', + title: 'Database Support' + }, + { + icon: 'fa-solid fa-book-open hover:animate-bounce', + color: 'text-purple-400', + title: 'Documentation & Tools' + } +]; + +//--------------------------------------------------------------------// + +export default function PluginEcosystemSection() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Plugin Ecosystem Section Content */} +
+

+ {_('The Plugin Ecosystem')} +

+ +

+ + The true power of .idea + lies in its plugin system — a bridge from simple schema + definitions to full‑stack applications. + +

+ +
+ {iconData.map((item) => ( +
+ + + +

+ {_(item.title)} +

+
+ ))} +
+
+ + ) +} \ No newline at end of file diff --git a/packages/www/plugins/app/components/landing-page/RealWorldExampleSection.tsx b/packages/www/plugins/app/components/landing-page/RealWorldExampleSection.tsx new file mode 100644 index 0000000..19b127c --- /dev/null +++ b/packages/www/plugins/app/components/landing-page/RealWorldExampleSection.tsx @@ -0,0 +1,170 @@ +//modules +import { Translate, useLanguage } from 'r22n'; +//local +import Code from '../../../docs/components/Code.js'; + +//code example +//--------------------------------------------------------------------// + +const exampleSchema = +`// schema.idea +enum UserRole { + ADMIN "Administrator" + CUSTOMER "Customer" + VENDOR "Vendor" +} + +type Address { + street String @required + city String @required + country String @default("US") +} + +model User { + id String @id @default("nanoid()") + email String @unique @required @field.input(Email) + name String @required @field.input(Text) + role UserRole @default("CUSTOMER") + address Address? + orders Order[] @relation(Order.userId) + created Date @default("now()") +} + +model Product { + id String @id @default("nanoid()") + name String @required @field.input(Text) + price Number @required @field.input(Currency) + description String @field.textarea + category String @field.select + inStock Boolean @default(true) +} + +model Order { + id String @id @default("nanoid()") + userId String @relation(User.id) + user User @relation(User, userId) + items OrderItem[] @relation(OrderItem.orderId) + total Number @required + status OrderStatus @default("PENDING") + created Date @default("now()") +} + +// Plugin configurations +plugin "./plugins/typescript-generator.js" { + output "./src/types/schema.ts" +} + +plugin "./plugins/database-generator.js" { + output "./database/schema.sql" + dialect "postgresql" +} + +plugin "./plugins/react-forms.js" { + output "./src/components/forms/" + framework "react" + styling "tailwind" +} + +plugin "./plugins/api-generator.js" { + output "./src/api/" + framework "express" + includeValidation true +}`; + +//--------------------------------------------------------------------// + +export default function RealWorldExampleSection() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Real-World Example Section Content */} +
+
+
+

+ {_('Real-World Example')} +

+ +

+ + See how a simple e‑commerce schema can generate a + full-stack application: + +

+ + + {exampleSchema} + +
+ +
+
+

+ {_('From this single schema, generate:')} +

+ +
    +
  • + + + TypeScript interfaces and types + +
  • +
  • + + + PostgreSQL database schema + +
  • +
  • + + + React form components with Tailwind CSS + +
  • +
  • + + + Express.js API routes with validation + +
  • +
  • + + + OpenAPI documentation + +
  • +
  • + + + Test data and fixtures + +
  • +
  • + + + Database migration files + +
  • +
  • + + + Validation schemas (Zod, Joi, etc.) + +
  • +
+
+
+
+
+ + ) +} diff --git a/packages/www/plugins/app/components/landing-page/index.tsx b/packages/www/plugins/app/components/landing-page/index.tsx new file mode 100644 index 0000000..d7cda1b --- /dev/null +++ b/packages/www/plugins/app/components/landing-page/index.tsx @@ -0,0 +1,9 @@ +//exporting all landing page sections from a single file for easier imports +export { default as AboutSection } from './AboutSection.js'; +export { default as AIDevelopmentWorkflowSection } from './AIDevelopmentWorkflowSection.js'; +export { default as AudienceSection } from './AudienceSection.js'; +export { default as BenefitsSection } from './BenefitsSection.js'; +export { default as FutureSection } from './FutureSection.js'; +export { default as HeroSection } from './HeroSection.js'; +export { default as PluginEcosystemSection } from './PluginEcosystemSection.js'; +export { default as RealWorldExampleSection } from './RealWorldExampleSection.js'; \ No newline at end of file diff --git a/packages/www/plugins/app/pages/error.ts b/packages/www/plugins/app/pages/error.ts new file mode 100644 index 0000000..2b68665 --- /dev/null +++ b/packages/www/plugins/app/pages/error.ts @@ -0,0 +1,58 @@ +//node +import fs from 'node:fs'; +import path from 'node:path'; +//stackpress +import { action } from 'stackpress/server'; + +export default action(async function ErrorPage(req, res, ctx) { + //if there is already a body + if (res.body) return; + //set data for template layer + res.data.set('server', { + mode: ctx.config.path('server.mode', 'production'), + }); + //general settings + const response = res.toStatusResponse(); + const { stack = [] } = response; + //add snippets to stack + stack.forEach((trace, i) => { + //skip the first trace + if (i === 0 + || !trace.file.startsWith(path.sep) + || !fs.existsSync(trace.file) + ) return; + const { file, line, char } = trace; + const source = fs.readFileSync(file, 'utf8') + const lines = source.split('\n'); + const snippet: Record = { + before: lines[line - 2] || undefined, + main: lines[line - 1] || undefined, + after: lines[line] || undefined, + }; + //if location doesnt match main line + if (snippet.main && snippet.main.length >= char) { + snippet.location = ' '.repeat(Math.max(char - 1, 0)) + '^'; + } + //@ts-ignore - snippet does not exist in type Trace + stack[i] = { ...trace, snippet }; + }); + if (req.url.pathname.endsWith('.js')) { + delete response.stack; + res.setBody( + 'application/javascript', + `console.log(${JSON.stringify(response)});`, + res.code, + res.status + ); + return; + } else if (req.url.pathname.endsWith('.css')) { + delete response.stack; + res.setBody( + 'text/css', + `/* ${JSON.stringify(response)} */`, + res.code, + res.status + ); + return; + } +}); \ No newline at end of file diff --git a/packages/www/plugins/app/plugin.ts b/packages/www/plugins/app/plugin.ts new file mode 100644 index 0000000..3a3f1f0 --- /dev/null +++ b/packages/www/plugins/app/plugin.ts @@ -0,0 +1,20 @@ +//stackpress +import type { Server } from 'stackpress/server'; + +export default function plugin(server: Server) { + server.on('listen', async _ => { + //on error, show error page + server.on('error', () => import('./pages/error.js')); + server.on('error', '@/plugins/app/views/error', -100); + //on response, check for errors + server.on('response', async (req, res, ctx) => { + if (res.error) { + await ctx.emit('error', req, res); + } + }); + }); + server.on('route', async _ => { + server.get('/', '@/plugins/app/views/home', -100); + server.get('/future', '@/plugins/app/views/future', -100); + }); +}; \ No newline at end of file diff --git a/packages/www/plugins/app/styles/page.css b/packages/www/plugins/app/styles/page.css new file mode 100644 index 0000000..2faf739 --- /dev/null +++ b/packages/www/plugins/app/styles/page.css @@ -0,0 +1,5 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap'); + +:root { display: initial; } + +* { font-family: 'Poppins', sans-serif; } \ No newline at end of file diff --git a/packages/www/plugins/app/views/error.tsx b/packages/www/plugins/app/views/error.tsx new file mode 100644 index 0000000..4a73cf5 --- /dev/null +++ b/packages/www/plugins/app/views/error.tsx @@ -0,0 +1,108 @@ +import '../styles/page.css'; +import type { Trace, ServerPageProps } from 'stackpress/view/client'; +import Layout from '../Layout.js'; + +//placeholder for translation +const _ = (text: string) => text; + +export type Config = { + server: { mode: string } +} + +export default function ErrorPage(props: ServerPageProps) { + const { + data = { server: { mode: 'production' } }, + request, + response + } = props; + + const theme = request.session.theme as string | undefined; + const mode = data.server?.mode || 'production'; + const production = mode === 'production'; + const notfound = response.code === 404; + const title = notfound ? _('Not Found') : _('Oops...'); + const description = notfound + ? _('The requested resource was not found.') + : _(response.error || 'There was an error.'); + const stack = (response.stack || []) as (Trace & { + snippet: Record + })[]; + const red = theme === 'dark' ? 'bg-red-900' : 'bg-red-100'; + return ( + +
+

+ {title} +

+

+ + {description} +

+ {!production && !notfound && stack.length > 0 && ( +
+ {stack.map((trace, index) => ( +
+

+ #{stack.length - Number(index)} {trace.method} +

+
+ {trace.file}:{trace.line}:{trace.char} +
+ {trace.snippet && ( +
+ {trace.snippet.before && ( +
{trace.line - 1} | {trace.snippet.before}
+ )} + {trace.snippet.main && ( +
{trace.line} | {trace.snippet.main}
+ )} + {trace.snippet.location && ( +
{' '.repeat(String(trace.line).length + 3)}{trace.snippet.location}
+ )} + {trace.snippet.after && ( +
{trace.line + 1} | {trace.snippet.after}
+ )} +
+ )} +
+ ))} +
+ )} +
+
+ ) +} + +export function Head(props: ServerPageProps) { + const { + request, + response, + styles = [] + } = props; + + const notfound = response.code === 404; + const url = request.url?.pathname || '/'; + const title = notfound ? _('Not Found') : _('Oops...'); + const description = notfound + ? _('The requested resource was not found.') + : _('There was an error.'); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} \ No newline at end of file diff --git a/packages/www/plugins/app/views/home.tsx b/packages/www/plugins/app/views/home.tsx new file mode 100644 index 0000000..c2b2947 --- /dev/null +++ b/packages/www/plugins/app/views/home.tsx @@ -0,0 +1,145 @@ +//modules +import { useEffect } from 'react'; +import clsx from 'clsx'; +import { ToastContainer } from 'react-toastify'; +//local +import '../styles/page.css'; +//stackpress +import type { ServerPageProps } from 'stackpress/view/client'; +import { useTheme } from 'stackpress/view/client'; +import Layout from '../Layout.js'; +//multiple section components +import { + AboutSection, + AIDevelopmentWorkflowSection, + AudienceSection, + BenefitsSection, + FutureSection, + HeroSection, + PluginEcosystemSection, + RealWorldExampleSection +} from '../components/landing-page/index.js'; + +//styles +//---------------------------------------------------------------------- + +const mainStyle = clsx( + 'overflow-auto', + 'px-h-100-0', + 'px-w-100-0', + 'relative', + 'theme-bg-bg0', + 'theme-tx1', +); + +//---------------------------------------------------------------------- + +export function Head(props: ServerPageProps) { + const { styles = [] } = props; + + return ( + <> + Idea + + + + + {/* Vanta.js Dependencies */} + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +function HomeContent() { + //hooks + const { theme } = useTheme(); + + useEffect(() => { + //check if Vanta is available in the window object + if (typeof window !== 'undefined' && (window as any).VANTA && theme) { + //define colors based on theme from useTheme hook + const backgroundColor = theme === 'dark' ? '#121212' : '#EFEFEF'; + const pointColor = theme === 'dark' ? '#FFC107' : '#FF9800'; + + //vanta configuration + const effect = (window as any).VANTA.NET({ + backgroundColor: backgroundColor, + color: pointColor, + el: '#vanta-bg', + maxDistance: 15.00, + minHeight: 500.00, + minWidth: 500.00, + mouseControls: true, + opacity: theme === 'dark' ? 0.5 : 0.3, + points: 10.00, + scale: 1.00, + scaleMobile: 1.00, + showDots: false, + spacing: 15.00, + touchControls: true + }); + + //destroy the effect when the component unmounts or theme changes + return () => { + if (effect) effect.destroy(); + }; + } + }, [theme]); + + return ( +
+ {/* Hero Section */} + + + {/* About Section */} + + + {/* Benefits Section */} + + + {/* Audience Section */} +
+ +
+ + {/* Plugin Ecosystem Section */} + + + {/* Real World Example Section */} +
+ +
+ + {/* AI Development Workflow Section */} + + + {/* Future Section */} +
+ +
+ + {/* Toast Container for notifications */} + +
+ ); +} + +export default function HomePage(props: ServerPageProps) { + //props + const { session, request, response } = props; + + return ( + + + + ) +} \ No newline at end of file diff --git a/packages/www/plugins/assets/plugin.ts b/packages/www/plugins/assets/plugin.ts new file mode 100644 index 0000000..d73cdfb --- /dev/null +++ b/packages/www/plugins/assets/plugin.ts @@ -0,0 +1,39 @@ +//node +import fs from 'node:fs'; +import path from 'node:path'; +//stackpress +import type { Server } from 'stackpress/server'; + +const mime: Record = { + '.html': 'text/html', + '.css': 'text/css', + '.js': 'text/javascript', + '.json': 'application/json', + '.png': 'image/png', + '.jpg': 'image/jpg', + '.jpeg': 'image/jpeg', + '.gif': 'image/gif', + '.svg': 'image/svg+xml', + '.ico': 'image/x-icon' +}; + +export default function plugin(server: Server) { + server.on('route', async _ => { + //static assets + server.on('request', async (req, res) => { + //if there is a body or a code that is not 404, skip + if (res.body || (res.code && res.code !== 404)) return; + //get the resource pathname + const resource = req.url.pathname.substring(1).replace(/\/\//, '/'); + //if no pathname, skip + if (resource.length === 0) return; + const assets = server.config.get('assets'); + const file = path.resolve(assets, resource); + if (fs.existsSync(file)) { + const ext = path.extname(file); + const type = mime[ext] || 'application/octet-stream'; + res.setBody(type, fs.createReadStream(file)); + } + }); + }); +}; \ No newline at end of file diff --git a/packages/www/plugins/docs/components/Code.tsx b/packages/www/plugins/docs/components/Code.tsx new file mode 100644 index 0000000..d9241dc --- /dev/null +++ b/packages/www/plugins/docs/components/Code.tsx @@ -0,0 +1,93 @@ +import type { CSSProperties } from 'react'; +import { useEffect, useState } from 'react'; +import SyntaxHighlighter from 'react-syntax-highlighter'; +import { atomOneDark } from 'react-syntax-highlighter/dist/cjs/styles/hljs'; +import { toast, Bounce } from 'react-toastify'; + +// copy should reveal the copy button, but onCopy should be defined to modify its behavior +// meanwhile, the presence of onCopy should be enough to show the copy button + +export default function Code(props: { + copy?: boolean; + className?: string; + value?: string; + language?: string; + numbers?: boolean; + onCopy?: () => void; + children: string; + style?: CSSProperties; +}) { + const [mounted, setMounted] = useState(false); + const { + children, + className, + copy, + onCopy, + language = 'javascript', + numbers, + style = { + background: 'transparent', + color: 'inherit', + padding: '0 10px 10px', + width: '100%' + } + } = props; + + const body = children + .split('\n') + .map((line) => (language === 'bash' ? `$ ${line}` : line)) + .join('\n'); + + //extends the default copy function if an extension is provided + const handleCopy = () => { + if (onCopy) { + onCopy(); + } + navigator.clipboard.writeText(children.toString()); + + toast.success('Code copied to clipboard!', { + position: "bottom-center", + autoClose: 3000, + hideProgressBar: false, + closeOnClick: false, + pauseOnHover: true, + draggable: true, + progress: undefined, + theme: "dark", + transition: Bounce, + }); + }; + + //only add highlighting when mounted + //necessary because of problems with SSR + useEffect(() => { + setMounted(true); + }, []); + + return ( +
+ {copy && ( +
+ Copy +
+ )} + {mounted && ( + //@ts-ignore + + {body} + + )} +
+ ); +} diff --git a/packages/www/plugins/docs/components/Editor.tsx b/packages/www/plugins/docs/components/Editor.tsx new file mode 100644 index 0000000..d99cbce --- /dev/null +++ b/packages/www/plugins/docs/components/Editor.tsx @@ -0,0 +1,139 @@ +import { useState } from 'react'; +import { notify } from 'stackpress/view/client'; +import Code from './Code.js'; + +export type File = { + type: 'file', + id: string, + name: string, + level: number, + content: string +}; +export type Folder = { + type: 'folder', + name: string, + level: number +}; +export type EditorTabsProps = { + active: string, + files: (File|Folder)[], + open: (file: string) => void +}; +export type EditorFilesProps = { + active: string, + files: (File|Folder)[], + className?: string +}; +export type EditorExplorerProps = { + active: string, + files: (File|Folder)[], + open: (file: string) => void +}; +export type EditorProps = { + files: (File|Folder)[], + value: string, + className?: string, + leftClassName?: string, + topClassName?: string, + mainClassName?: string, + title?: string +}; + +export function EditorExplorer(props: EditorExplorerProps) { + const { active, files, open } = props; + return ( +
+ {files.map((item, index) => { + const left = 5 + (item.level * 15); + if (item.type === 'folder') { + return ( +
+ + {item.name} +
+ ); + } + const icon = item.name.endsWith('.tsx') ? 'fab fa-react' : 'fas fa-file'; + return ( +
open(item.id)} + > + + {item.name} +
+ ); + })} +
+ ); +}; + +export function EditorTabs(props: EditorTabsProps) { + const { active, files, open } = props; + return ( +
+ {files.filter(item => item.type === 'file').map((item, index) => { + const icon = item.name.endsWith('.tsx') ? 'fab fa-react' : 'fas fa-file'; + return ( +
open(item.id)} + > + + {item.name} +
+ ); + })} +
+ ); +}; + +export function EditorFiles(props: EditorFilesProps) { + const { active, className = '', files } = props; + return ( + <> + {files.filter(item => item.type === 'file').map((item, index) => { + return ( + notify('success', 'Copied to clipboard')} + className={`${active !== item.id ? 'hidden': ''} rsm-px-l-0 bg-black text-white overflow-auto !absolute px-r-0 px-b-0 px-t-34 ${className}`} + >{item.content} + ); + })} + + ); +}; + +export default function Editor(props: EditorProps) { + const { + title = 'PROJECT', + files = [], + value, + className = '', + leftClassName = '', + topClassName = '', + mainClassName = '' + } = props; + const [ file, open ] = useState(value); + return ( +
+
+
{title}
+ +
+
+ +
+ +
+ ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/Layout.tsx b/packages/www/plugins/docs/components/Layout.tsx new file mode 100644 index 0000000..7ed65ee --- /dev/null +++ b/packages/www/plugins/docs/components/Layout.tsx @@ -0,0 +1,612 @@ +//modules +import type { ReactNode } from 'react'; +import { useState, useEffect } from 'react'; +import { useLanguage } from 'r22n'; +import clsx from 'clsx'; +//stackpress +import type { + LayoutProviderProps, + PanelAppProps, +} from 'stackpress/view/client'; +import { + LayoutProvider, + NotifyContainer, + unload, + useTheme, + useRequest, + useToggle +} from 'stackpress/view/client'; +//styles +import '../styles/styles.css'; +//components +import Search from '../../app/components/Search.js'; + +//styles +//--------------------------------------------------------------------// + +const menuAnchorTagStyles = clsx( + 'flex', + 'font-semibold', + 'items-center', + 'px-fs-16', + 'px-mb-0', + 'px-mt-0', + 'px-px-20', + 'px-py-12', + 'theme-bc-bd1', + 'theme-bg-bg2', + 'theme-tx1', + 'uppercase' +); + +const rightNavStyles = clsx( + 'absolute', + 'duration-200', + 'px-b-0', + 'px-r-0', + 'px-t-0', + 'px-t-60', + 'px-w-220', + 'px-z-100', + 'rlg-hidden' +); + +//--------------------------------------------------------------------// + +export function LayoutHead(props: { + open?: boolean, + theme: string, + base?: string, + logo?: string, + brand?: string, + toggleLeft?: () => void, + toggleTheme?: () => void +}) { + const { + open, + theme, + base, + logo, + brand, + toggleLeft, + toggleTheme + } = props; + const left = open ? 'rmd-px-l-220' : 'rmd-px-l-0'; + const full = typeof open === 'undefined' ? 'px-l-0' : 'px-l-220'; + const themeColor = theme === 'dark' ? 'bg-gray-600' : 'bg-orange-600'; + const themeIcon = theme === 'dark' ? 'fa-moon' : 'fa-sun'; + return ( +
+
+ {toggleLeft && ( + + )} +
+ {base ? ( + + {logo && {brand}} + {brand && {brand}} + + ) : brand || logo ? ( + + {logo && {brand}} + {brand && {brand}} + + ) : undefined} +
+ + {/* Search Component */} + + + {toggleTheme && ( + + )} +
+
+ ); +} + +export function LayoutLeft(props: { + pathname?: string, + open: boolean, + toggle: () => void +}) { + const { pathname = '/', open, toggle } = props; + const left = open ? 'rmd-px-l-0' : 'rmd-px-l--220'; + const { _ } = useLanguage(); + const menu = [ + { + label: '', + search: '', + children: [ + { + label: 'Introduction', + search: '/docs/introduction', + href: '/docs/introduction' + }, + { + label: 'Getting Started', + search: '/docs/getting-started', + href: '/docs/getting-started' + } + ] + }, + { + label: 'Specifications', + search: '/docs/specifications', + children: [ + { + label: 'Syntax Overview', + search: '/docs/specifications/syntax-overview', + href: '/docs/specifications/syntax-overview' + }, + { + label: 'Data Types', + search: '/docs/specifications/data-types', + href: '/docs/specifications/data-types' + }, + { + label: 'Schema Elements', + search: '/docs/specifications/schema-elements', + href: '/docs/specifications/schema-elements' + }, + { + label: 'Schema Structure', + search: '/docs/specifications/schema-structure', + href: '/docs/specifications/schema-structure' + }, + { + label: 'Schema Directives', + search: '/docs/specifications/schema-directives', + href: '/docs/specifications/schema-directives' + }, + { + label: 'Processing Flow', + search: '/docs/specifications/processing-flow', + href: '/docs/specifications/processing-flow' + }, + { + label: 'Plugin System', + search: '/docs/specifications/plugin-system', + href: '/docs/specifications/plugin-system' + }, + { + label: 'Complete Example', + search: '/docs/specifications/complete-examples', + href: '/docs/specifications/complete-examples' + }, + { + label: 'Best Practices', + search: '/docs/specifications/best-practices', + href: '/docs/specifications/best-practices' + }, + { + label: 'Error Handling', + search: '/docs/specifications/error-handling', + href: '/docs/specifications/error-handling' + } + ] + }, + { + label: 'Parser', + search: '/docs/parser', + children: [ + { + label: 'Installation', + search: '/docs/parser/installation', + href: '/docs/parser/installation' + }, + { + label: 'Core Concepts', + search: '/docs/parser/core-concepts', + href: '/docs/parser/core-concepts' + }, + { + label: 'API Reference', + search: '/docs/parser/api-reference', + href: '/docs/parser/api-reference' + }, + { + label: 'Examples', + search: '/docs/parser/examples', + href: '/docs/parser/examples' + }, + { + label: 'Best Practices', + search: '/docs/parser/best-practices', + href: '/docs/parser/best-practices' + } + ] + }, + { + label: 'Transformers', + search: '/docs/transformers', + children: [ + { + label: 'Introduction', + search: '/docs/transformers/introduction', + href: '/docs/transformers/introduction' + }, + { + label: 'API Reference', + search: '/docs/transformers/api-reference', + href: '/docs/transformers/api-reference' + }, + { + label: 'Architecture', + search: '/docs/transformers/architecture', + href: '/docs/transformers/architecture' + }, + { + label: 'Usage Patterns', + search: '/docs/transformers/usage-patterns', + href: '/docs/transformers/usage-patterns' + }, + { + label: 'Common Use Cases', + search: '/docs/transformers/common-use-cases', + href: '/docs/transformers/common-use-cases' + }, + { + label: 'Examples', + search: '/docs/transformers/examples', + href: '/docs/transformers/examples' + }, + { + label: 'Error Handling', + search: '/docs/transformers/error-handling', + href: '/docs/transformers/error-handling' + }, + { + label: 'Best Practices', + search: '/docs/transformers/best-practices', + href: '/docs/transformers/best-practices' + } + + ] + }, + { + label: 'Plugin', + search: '/docs/plugin-development', + children: [ + { + label: 'Plugin Development Guide', + search: '/docs/plugin-development/plugin-development-guide', + href: '/docs/plugin-development/plugin-development-guide' + }, + { + label: 'Plugin Examples', + search: '/docs/plugin-development/plugin-examples', + href: '/docs/plugin-development/plugin-examples' + }, + { + label: 'Plugin Configuration', + search: '/docs/plugin-development/plugin-configuration', + href: '/docs/plugin-development/plugin-configuration' + }, + { + label: 'Error Handling', + search: '/docs/plugin-development/error-handling', + href: '/docs/plugin-development/error-handling' + }, + { + label: 'Best Practices', + search: '/docs/plugin-development/best-practices', + href: '/docs/plugin-development/best-practices' + }, + { + label: 'Available Tutorials', + search: '/docs/plugin-development/available-tutorials', + href: '/docs/plugin-development/available-tutorials' + }, + { + label: 'Advanced Tutorials', + search: '/docs/plugin-development/advanced-tutorials', + href: '/docs/plugin-development/advanced-tutorials' + }, + { + label: 'Getting Started', + search: '/docs/plugin-development/getting-started', + href: '/docs/plugin-development/getting-started' + } + ] + }, + { + label: 'Tutorials', + search: '/docs/tutorials', + children: [ + { + label: 'TSMorph Plugin Guide', + search: '/docs/tutorials/tsmorph-plugin-guide', + href: '/docs/tutorials/tsmorph-plugin-guide' + }, + { + label: 'MySQL Tables Plugin', + search: '/docs/tutorials/mysql-table-plugin', + href: '/docs/tutorials/mysql-table-plugin' + }, + { + label: 'HTML Form Plugin', + search: '/docs/tutorials/html-form-plugin', + href: '/docs/tutorials/html-form-plugin' + }, + { + label: 'Markdown Documentation Plugin', + search: '/docs/tutorials/markdown-documentation-plugin', + href: '/docs/tutorials/markdown-documentation-plugin' + }, + { + label: 'GraphQL Schema Plugin', + search: '/docs/tutorials/graphql-schema-plugin', + href: '/docs/tutorials/graphql-schema-plugin' + }, + { + label: 'TypeScript Interface Plugin', + search: '/docs/tutorials/typescript-interface-plugin', + href: '/docs/tutorials/typescript-interface-plugin' + }, + { + label: 'API Client Plugin', + search: '/docs/tutorials/api-client-plugin', + href: '/docs/tutorials/api-client-plugin' + }, + { + label: 'Validation Plugin', + search: '/docs/tutorials/validation-plugin', + href: '/docs/tutorials/validation-plugin' + }, + { + label: 'Test Data Plugin', + search: '/docs/tutorials/test-data-plugin', + href: '/docs/tutorials/test-data-plugin' + }, + { + label: 'OpenAPI Specification Plugin', + search: '/docs/tutorials/openapi-specification-plugin', + href: '/docs/tutorials/openapi-specification-plugin' + } + + ] + } + + ]; + return ( + + ); +} + +export function LayoutMain(props: { + open?: boolean, + right?: boolean, + children: ReactNode +}) { + const { open, children } = props; + const left = open ? 'rmd-px-l-220' : 'rmd-px-l-0'; + const right = props.right ? 'px-r-220 rlg-px-r-0' : 'px-r-0'; + const full = typeof open === 'undefined' ? 'px-l-0' : 'px-l-220'; + return ( +
+ {children} +
+ ); +} + +export function LayoutRight({ children }: { + children: ReactNode +}) { + return ( + + ); +} + +export function LayoutApp(props: { + right?: ReactNode, + children: ReactNode +}) { + const { children } = props; + const request = useRequest(); + const [left, toggleLeft] = useToggle(); + const { theme, toggle: toggleTheme } = useTheme(); + const pathname = request?.url?.pathname || '/'; + return ( +
+ + + {props.right ? ({props.right}) : null} + {children} +
+ ); +} + +export default function Layout(props: LayoutProviderProps & PanelAppProps) { + const { + data, + session, + response, + right, + children + } = props; + const [request, setRequest] = useState>({ + ...(props.request || {}), + session: { + ...(props.request?.session || {}), + theme: props.request?.session?.theme || 'dark' + } + }); + //unload flash message + useEffect(() => { + const light = document.cookie.includes('theme=light'); + if (!request.session?.theme) { + setRequest({ + ...request, + session: { theme: light ? 'light' : 'dark' } + }); + } + unload(); + }, []); + + return ( + + + {children} + + + + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/api-client-plugin/AdvancedFeatures.tsx b/packages/www/plugins/docs/components/api-client-plugin/AdvancedFeatures.tsx new file mode 100644 index 0000000..86e853d --- /dev/null +++ b/packages/www/plugins/docs/components/api-client-plugin/AdvancedFeatures.tsx @@ -0,0 +1,151 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const authenticationStrategies = +`// Bearer token authentication +authentication: { + type: "bearer", + headerName: "Authorization" +} + +// API key authentication +authentication: { + type: "apikey", + headerName: "X-API-Key" +} + +// Basic authentication +authentication: { + type: "basic", + headerName: "Authorization" +} + +// Custom authentication +authentication: { + type: "custom", + headerName: "X-Custom-Auth" +}`; + +//--------------------------------------------------------------------// + +const errorHandlingStrategies = +`// Return errors in response (default) +errorHandling: "return" +const response = await client.user.getById('123'); +if (!response.success) { + console.error(response.error); +} + +// Throw errors as exceptions +errorHandling: "throw" +try { + const user = await client.user.getById('123'); +} catch (error) { + console.error(error.message); +} + +// Use callback for error handling +errorHandling: "callback" +const response = await client.user.getById('123', { + onError: (error) => console.error(error) +});`; + +//--------------------------------------------------------------------// + +const requestCancellation = +`// Using AbortController for request cancellation +const controller = new AbortController(); + +const response = await client.user.getAll({}, { + signal: controller.signal +}); + +controller.abort();`; + +//--------------------------------------------------------------------// + +const customHeaders = +`// Add custom headers to requests +const response = await client.user.getById('123', { + headers: { + 'X-Custom-Header': 'value', + 'Accept-Language': 'en-US' + } +});`; + +//--------------------------------------------------------------------// + +export default function AdvancedFeatures() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Advanced Features Section Content */} +
+

{_('7. Advanced Features')}

+

+ + Advanced features extend the basic API client functionality with + sophisticated authentication, error handling, request management, + and customization options. These features enable production-ready + API clients that can handle complex scenarios and enterprise + requirements. + +

+ +

{_('7.1. Authentication Strategies')}

+ + {authenticationStrategies} + + +

{_('7.2. Error Handling Strategies')}

+

+ + Error handling strategies determine how the API client responds + to and manages different types of errors. The plugin supports + multiple approaches including returning errors in responses, + throwing exceptions, and using callback functions for flexible + error management. + +

+ + {errorHandlingStrategies} + + +

{_('7.3. Request Cancellation')}

+

+ + Request cancellation allows you to abort ongoing API requests + when they are no longer needed. This is essential for preventing + unnecessary network traffic and improving application performance, + especially in scenarios with user navigation or component + unmounting. + +

+ + {requestCancellation} + + +

{_('7.4. Custom Headers')}

+

+ + Custom headers allow you to add additional metadata to requests, + such as localization preferences, custom authentication tokens, or + API versioning information. The generated client supports flexible + header management for each request. + +

+ + {customHeaders} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/api-client-plugin/BestPractices.tsx b/packages/www/plugins/docs/components/api-client-plugin/BestPractices.tsx new file mode 100644 index 0000000..6823ed1 --- /dev/null +++ b/packages/www/plugins/docs/components/api-client-plugin/BestPractices.tsx @@ -0,0 +1,170 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const typeSafety = +`// Always use generated types +interface UserWithPosts extends User { + posts: Post[]; +} + +// Type-safe error handling +function handleUserResponse(response: APIResponse) { + if (response.success) { + // TypeScript knows response.data is User + console.log(response.data.email); + } else { + // TypeScript knows response.error exists + console.error(response.error); + } +}`; + +//--------------------------------------------------------------------// + +const errorHandlingPattern = +`// Centralized error handling +class APIErrorHandler { + static handle(response: APIResponse) { + if (!response.success) { + if (response.errors) { + // Handle validation errors + Object.entries(response.errors).forEach(([field, messages]) => { + console.error(\`\${field}: \${messages.join(', ')}\`); + }); + } else { + // Handle general errors + console.error(response.error); + } + } + } +} + +// Usage +const response = await client.user.create(userData); +APIErrorHandler.handle(response);`; + +//--------------------------------------------------------------------// + +const clientExtension = +`// Extend base client for custom behavior +class CustomAPIClient extends APIClient { + constructor(baseUrl?: string) { + super(baseUrl); + this.setupInterceptors(); + } + + private setupInterceptors() { + // Add request logging + const originalRequest = this.request; + this.request = async (method, url, data, options) => { + console.log(\`\${method} \${url}\`, data); + return originalRequest.call(this, method, url, data, options); + }; + } +}`; + +//--------------------------------------------------------------------// + +const cachingPattern = +`// Simple in-memory cache +class CachedAPIClient extends APIClient { + private cache = new Map(); + private cacheTimeout = 5 * 60 * 1000; // 5 minutes + + async getCached(key: string, fetcher: () => Promise>): Promise> { + const cached = this.cache.get(key); + + if (cached && Date.now() - cached.timestamp < this.cacheTimeout) { + return { success: true, data: cached.data }; + } + + const response = await fetcher(); + + if (response.success) { + this.cache.set(key, { + data: response.data, + timestamp: Date.now() + }); + } + + return response; + } +}`; + +//--------------------------------------------------------------------// + +export default function BestPractices() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Best Practices Section Content */} +
+

{_('8. Best Practices')}

+

+ + Following best practices ensures your API client is maintainable, + performant, and robust. These patterns have been proven in + production environments and help avoid common pitfalls when + working with generated API clients. + +

+ +

{_('8.1. Type Safety')}

+

+ + Leverage TypeScript's type system to catch errors at compile time + and improve developer experience. Always use the generated types + and interfaces to maintain type safety throughout your application. + +

+ + {typeSafety} + + +

{_('8.2. Error Handling')}

+

+ + Implement consistent error handling patterns across your + application. Create centralized error handling utilities to avoid + code duplication and ensure consistent error presentation to users. + +

+ + {errorHandlingPattern} + + +

{_('8.3. Client Extension')}

+

+ + Extend the generated client for custom functionality while + maintaining the generated code's integrity. Use inheritance and + composition patterns to add logging, metrics, or custom behavior. + +

+ + {clientExtension} + + +

{_('8.4. Caching Strategies')}

+

+ + Implement appropriate caching strategies to improve performance + and reduce server load. Consider using in-memory caches for + frequently accessed data and implement cache invalidation + strategies. + +

+ + {cachingPattern} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/api-client-plugin/Implementation.tsx b/packages/www/plugins/docs/components/api-client-plugin/Implementation.tsx new file mode 100644 index 0000000..248f47d --- /dev/null +++ b/packages/www/plugins/docs/components/api-client-plugin/Implementation.tsx @@ -0,0 +1,312 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const corePluginFunction = +`export default async function generateAPIClient( + props: PluginProps<{ config: APIClientConfig }> +) { + const { config, schema, transformer } = props; + + try { + // Validate configuration + validateConfig(config); + + // Generate client content + let content = ''; + + // Add file header and imports + content += generateFileHeader(config); + content += generateImports(config); + + // Generate types if requested + if (config.generateTypes) { + content += generateTypes(schema, config); + } + + // Generate base client class + content += generateBaseClient(config); + + // Generate model-specific clients + if (schema.model) { + if (config.clientType === 'rest' || config.clientType === 'both') { + content += generateRESTClients(schema.model, config); + } + + if (config.clientType === 'graphql' || config.clientType === 'both') { + content += generateGraphQLClients(schema.model, config); + } + } + + // Generate main client export + content += generateMainClient(schema, config); + + // Write to output file + const outputPath = await transformer.loader.absolute(config.output); + await fs.mkdir(path.dirname(outputPath), { recursive: true }); + await fs.writeFile(outputPath, content, 'utf8'); + + console.log(\`✅ API client generated: \${outputPath}\`); + + } catch (error) { + console.error('❌ API client generation failed:', error.message); + throw error; + } +}`; + +//--------------------------------------------------------------------// + +const headerAndImports = +`function generateFileHeader(config: APIClientConfig): string { + const timestamp = new Date().toISOString(); + return \`/** + * Generated API Client + * Generated at: \${timestamp} + * Client Type: \${config.clientType} + * HTTP Library: \${config.httpLibrary || 'fetch'} + * + * This file is auto-generated. Do not edit manually. + */ + +\`; +} + +function generateImports(config: APIClientConfig): string { + let imports = ''; + + if (config.httpLibrary === 'axios') { + imports += \`import axios, { AxiosInstance, AxiosResponse, AxiosError } from 'axios';\\n\`; + } + + if (config.clientType === 'graphql' || config.clientType === 'both') { + imports += \`import { ApolloClient, InMemoryCache, gql, DocumentNode } from '@apollo/client';\\n\`; + } + + imports += \` +// Base types +interface APIResponse { + success: boolean; + data?: T; + error?: string; + errors?: Record; +} + +interface PaginatedResponse extends APIResponse { + total: number; + page: number; + limit: number; +} + +interface RequestOptions { + headers?: Record; + signal?: AbortSignal; +} + +\`; + + return imports; +}`; + +//--------------------------------------------------------------------// + +const typeGeneration = +`function generateTypes(schema: any, config: APIClientConfig): string { + let content = '// Generated Types\\n'; + + // Generate enums + if (schema.enum) { + for (const [enumName, enumDef] of Object.entries(schema.enum)) { + content += \`export enum \${enumName} {\\n\`; + for (const [key, value] of Object.entries(enumDef)) { + content += \` \${key} = "\${value}",\\n\`; + } + content += '}\\n\\n'; + } + } + + // Generate interfaces + if (schema.model) { + for (const [modelName, model] of Object.entries(schema.model)) { + content += \`export interface \${modelName} {\\n\`; + for (const column of model.columns || []) { + const optional = !column.required ? '?' : ''; + const type = mapTypeToTypeScript(column.type); + content += \` \${column.name}\${optional}: \${type};\\n\`; + } + content += '}\\n\\n'; + + // Generate input types + const autoFields = model.columns + ?.filter((col: any) => col.attributes?.id || col.attributes?.default) + .map((col: any) => \`'\${col.name}'\`) + .join(' | '); + + if (autoFields) { + content += \`export type Create\${modelName}Input = Omit<\${modelName}, \${autoFields}>;\\n\`; + } else { + content += \`export type Create\${modelName}Input = \${modelName};\\n\`; + } + + content += \`export type Update\${modelName}Input = Partial<\${modelName}>;\\n\\n\`; + } + } + + return content; +}`; + +//--------------------------------------------------------------------// + +const baseClientGeneration = +`function generateBaseClient(config: APIClientConfig): string { + const authType = config.authentication?.type || 'bearer'; + const headerName = config.authentication?.headerName || 'Authorization'; + + return \` +// Base Client Class +export class BaseAPIClient { + private baseUrl: string; + private authToken?: string; + \${config.httpLibrary === 'axios' ? 'private axiosInstance: AxiosInstance;' : ''} + + constructor(baseUrl: string = '\${config.baseUrl || '/api'}') { + this.baseUrl = baseUrl.replace(/\\/$/, ''); + \${config.httpLibrary === 'axios' ? generateAxiosSetup() : ''} + } + + setAuthToken(token: string): void { + this.authToken = token; + } + + private getAuthHeaders(): Record { + if (!this.authToken) return {}; + + \${generateAuthHeaders(authType, headerName)} + } + + \${config.httpLibrary === 'axios' ? generateAxiosMethods() : generateFetchMethods()} +} + +\`; +}`; + +//--------------------------------------------------------------------// + +const restClientGeneration = +`function generateRESTClients(models: Record, config: APIClientConfig): string { + let content = '// REST API Clients\\n'; + + for (const [modelName, model] of Object.entries(models)) { + const lowerName = modelName.toLowerCase(); + const pluralName = \`\${lowerName}s\`; + + content += \` +export class \${modelName}Client extends BaseAPIClient { + // Get all \${pluralName} + async getAll(params?: { + page?: number; + limit?: number; + search?: string; + sort?: string; + }, options?: RequestOptions): Promise> { + const queryParams = new URLSearchParams(); + if (params?.page) queryParams.set('page', params.page.toString()); + if (params?.limit) queryParams.set('limit', params.limit.toString()); + if (params?.search) queryParams.set('search', params.search); + if (params?.sort) queryParams.set('sort', params.sort); + + const query = queryParams.toString(); + const url = \\\`/\${pluralName}\\\${query ? \\\`?\\\${query}\\\` : ''}\\\`; + + return this.get<\${modelName}[]>(url, options) as Promise>; + } + + // Get single \${lowerName} by ID + async getById(id: string, options?: RequestOptions): Promise> { + return this.get<\${modelName}>(\\\`/\${pluralName}/\\\${id}\\\`, options); + } + + // Create new \${lowerName} + async create(data: Create\${modelName}Input, options?: RequestOptions): Promise> { + return this.post<\${modelName}>(\\\`/\${pluralName}\\\`, data, options); + } + + // Update existing \${lowerName} + async update(id: string, data: Update\${modelName}Input, options?: RequestOptions): Promise> { + return this.put<\${modelName}>(\\\`/\${pluralName}/\\\${id}\\\`, data, options); + } + + // Delete \${lowerName} + async delete(id: string, options?: RequestOptions): Promise> { + return this.delete(\\\`/\${pluralName}/\\\${id}\\\`, options); + } +} +\`; + } + + return content; +}`; + +//--------------------------------------------------------------------// + +export default function Implementation() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Implementation Section Content */} +
+

{_('4. Implementation')}

+

+ + The implementation section covers the core plugin function and + supporting utilities that handle API client generation. This + includes configuration validation, content generation, file + writing, and error handling throughout the generation process. + +

+ +

{_('4.1. Core Plugin Function')}

+

+ + The core plugin function serves as the main entry point for API + client generation. It orchestrates the entire process from + configuration validation through content generation to file + output, ensuring proper error handling and logging throughout. + +

+ + {corePluginFunction} + + +

{_('4.2. Generation Functions')}

+

+ + The generation functions handle the creation of specific parts of + the API client code. These utility functions generate file headers, + imports, type definitions, base client classes, and model-specific + client methods, ensuring consistent code structure and proper + TypeScript typing. + +

+ + {headerAndImports} + + + {typeGeneration} + + + {baseClientGeneration} + + + {restClientGeneration} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/api-client-plugin/Introduction.tsx b/packages/www/plugins/docs/components/api-client-plugin/Introduction.tsx new file mode 100644 index 0000000..8aa70a8 --- /dev/null +++ b/packages/www/plugins/docs/components/api-client-plugin/Introduction.tsx @@ -0,0 +1,26 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C } from '../../../docs/components/index.js'; + +export default function Introduction() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* API Client Generator Plugin Tutorial */} +
+

{_('API Client Generator Plugin Tutorial')}

+

+ + This tutorial demonstrates how to create a plugin that + generates REST and GraphQL API clients from .idea + schema files. The plugin will transform your schema models + into type-safe API client libraries with full CRUD operations. + +

+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/api-client-plugin/Overview.tsx b/packages/www/plugins/docs/components/api-client-plugin/Overview.tsx new file mode 100644 index 0000000..43b5cb4 --- /dev/null +++ b/packages/www/plugins/docs/components/api-client-plugin/Overview.tsx @@ -0,0 +1,45 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; + +export default function Overview() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Overview Section Content */} +
+

{_('1. Overview')}

+

+ + API clients provide a convenient interface for interacting with + backend services. This plugin generates type-safe API clients + from your schema, including: + +

+
    +
  • + Type-safe REST and GraphQL client generation +
  • +
  • + Full CRUD operations for all models +
  • +
  • + Configurable authentication strategies +
  • +
  • + Error handling and validation +
  • +
  • + Support for multiple HTTP libraries +
  • +
  • + Request cancellation and custom headers +
  • +
+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/api-client-plugin/PluginStructure.tsx b/packages/www/plugins/docs/components/api-client-plugin/PluginStructure.tsx new file mode 100644 index 0000000..c6d3a21 --- /dev/null +++ b/packages/www/plugins/docs/components/api-client-plugin/PluginStructure.tsx @@ -0,0 +1,62 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const pluginStructureExample = +`import type { PluginProps } from '@stackpress/idea-transformer/types'; +import fs from 'fs/promises'; +import path from 'path'; + +interface APIClientConfig { + output: string; + clientType: 'rest' | 'graphql' | 'both'; + httpLibrary?: 'fetch' | 'axios'; + baseUrl?: string; + authentication?: { + type: 'bearer' | 'apikey' | 'basic' | 'custom'; + headerName?: string; + }; + generateTypes?: boolean; + includeValidation?: boolean; + errorHandling?: 'throw' | 'return' | 'callback'; +} + +export default async function generateAPIClient( + props: PluginProps<{ config: APIClientConfig }> +) { + const { config, schema, transformer } = props; + + // Implementation here... +}`; + +//--------------------------------------------------------------------// + +export default function PluginStructure() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Plugin Structure Section Content */} +
+

{_('3. Plugin Structure')}

+

+ + The plugin structure defines the core architecture and + configuration interface for the API client generator. This + includes the main plugin function, configuration types, and + the overall organization of the generated client code. + +

+ + {pluginStructureExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/api-client-plugin/Prerequisites.tsx b/packages/www/plugins/docs/components/api-client-plugin/Prerequisites.tsx new file mode 100644 index 0000000..cd67ba7 --- /dev/null +++ b/packages/www/plugins/docs/components/api-client-plugin/Prerequisites.tsx @@ -0,0 +1,43 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; + +export default function Prerequisites() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Prerequisites Section Content */} +
+

{_('2. Prerequisites')}

+

+ + Before implementing the API client generator plugin, ensure you + have the necessary development environment and dependencies. This + section covers the essential requirements and setup needed to + successfully create and use the plugin. + +

+
    +
  • + Node.js and npm/yarn package manager +
  • +
  • + Basic understanding of TypeScript and API design +
  • +
  • + Familiarity with REST and/or GraphQL concepts +
  • +
  • + Knowledge of .idea schema structure +
  • +
  • + Understanding of plugin development patterns +
  • +
+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/api-client-plugin/SchemaConfiguration.tsx b/packages/www/plugins/docs/components/api-client-plugin/SchemaConfiguration.tsx new file mode 100644 index 0000000..b88b565 --- /dev/null +++ b/packages/www/plugins/docs/components/api-client-plugin/SchemaConfiguration.tsx @@ -0,0 +1,123 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +import { Table, Thead, Trow, Tcol } from 'frui/element/Table'; +//local +import { H1, H2, P, C, SS } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const schemaConfigExample = +`plugin "./plugins/api-client.js" { + output "./generated/api-client.ts" + clientType "rest" + httpLibrary "fetch" + baseUrl "/api/v1" + authentication { + type "bearer" + headerName "Authorization" + } + generateTypes true + includeValidation false + errorHandling "return" +}` + +//--------------------------------------------------------------------// + +export default function SchemaConfiguration() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Schema Configuration Section Content */} +
+

{_('5. Schema Configuration')}

+

+ + Add the API Client plugin to your .idea schema file: + +

+ + {schemaConfigExample} + + +

{_('Configuration Options')}

+ + + + Option + Type + Default + Description + + + output + string + Required + + Output file path for the API client + + + + clientType + 'rest'|'graphql'|'both' + Required + + Type of client to generate + + + + httpLibrary + 'fetch'|'axios' + 'fetch' + + HTTP library to use + + + + baseUrl + string + '/api' + + Base URL for API requests + + + + authentication + object + undefined + + Authentication configuration + + + + generateTypes + boolean + true + + Generate TypeScript types + + + + includeValidation + boolean + false + + Include request validation + + + + errorHandling + 'throw'|'return'|'callback' + 'return' + + Error handling strategy + + +
+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/api-client-plugin/Troubleshooting.tsx b/packages/www/plugins/docs/components/api-client-plugin/Troubleshooting.tsx new file mode 100644 index 0000000..5018b97 --- /dev/null +++ b/packages/www/plugins/docs/components/api-client-plugin/Troubleshooting.tsx @@ -0,0 +1,163 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const corsIssues = +`// Ensure your API server allows CORS +// Add appropriate headers in your API configuration + +// For development, you might need to proxy requests +const client = new APIClient('/api/proxy');`; + +//--------------------------------------------------------------------// + +const authenticationIssues = +`// Check token format and expiration +function isTokenValid(token: string): boolean { + try { + const payload = JSON.parse(atob(token.split('.')[1])); + return payload.exp * 1000 > Date.now(); + } catch { + return false; + } +} + +// Refresh token automatically +client.setAuthToken(await refreshToken());`; + +//--------------------------------------------------------------------// + +const networkIssues = +`// Implement retry logic +async function withRetry( + operation: () => Promise>, + maxRetries: number = 3 +): Promise> { + for (let i = 0; i < maxRetries; i++) { + try { + const result = await operation(); + if (result.success) return result; + + if (i === maxRetries - 1) return result; + await new Promise(resolve => setTimeout(resolve, 1000 * (i + 1))); + } catch (error) { + if (i === maxRetries - 1) throw error; + } + } + + throw new Error('Max retries exceeded'); +}`; + +//--------------------------------------------------------------------// + +const debuggingTips = +`// Add to base client +private logRequest(method: string, url: string, data?: any) { + if (process.env.NODE_ENV === 'development') { + console.group(\`API \${method} \${url}\`); + if (data) console.log('Data:', data); + console.groupEnd(); + } +}`; + +//--------------------------------------------------------------------// + +const responseValidation = +`// Validate response structure +function validateResponse(response: any): response is APIResponse { + return ( + typeof response === 'object' && + typeof response.success === 'boolean' && + (response.success ? 'data' in response : 'error' in response) + ); +}`; + +//--------------------------------------------------------------------// + +export default function Troubleshooting() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Troubleshooting Section Content */} +
+

{_('9. Troubleshooting')}

+

+ + This section covers common issues you might encounter when + using the generated API client and provides solutions and + debugging strategies to resolve them quickly. + +

+ +

{_('9.1. CORS Issues')}

+

+ + Cross-Origin Resource Sharing (CORS) issues are common + when making API requests from web applications. Ensure + your server is properly configured to handle CORS or use + appropriate proxy settings during development. + +

+ + {corsIssues} + + +

{_('9.2. Authentication Problems')}

+

+ + Authentication issues often stem from expired tokens, incorrect + formats, or missing headers. Implement proper token validation + and refresh mechanisms to handle these scenarios gracefully. + +

+ + {authenticationIssues} + + +

{_('9.3. Network Issues')}

+

+ + Network connectivity problems require robust retry logic + and proper error handling. Implement exponential backoff + strategies for transient failures and provide meaningful + feedback to users. + +

+ + {networkIssues} + + +

{_('9.4. Debugging Tips')}

+

+ + Enable comprehensive logging during development to track request + flows and identify issues. Use browser developer tools and server + logs to diagnose problems effectively. + +

+ + {debuggingTips} + + +

{_('9.5. Response Validation')}

+

+ + Validate API responses to ensure they match expected formats. + This helps catch schema mismatches and API changes that could + break your application. + +

+ + {responseValidation} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/api-client-plugin/UsageExamples.tsx b/packages/www/plugins/docs/components/api-client-plugin/UsageExamples.tsx new file mode 100644 index 0000000..d11c5ed --- /dev/null +++ b/packages/www/plugins/docs/components/api-client-plugin/UsageExamples.tsx @@ -0,0 +1,143 @@ +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; +//modules +import { useLanguage, Translate } from 'r22n'; + +//code examples +//--------------------------------------------------------------------// + +const basicSchemaExample = +`enum UserRole { + ADMIN "admin" + USER "user" + GUEST "guest" +} + +model User { + id String @id @default("nanoid()") + email String @unique @required + name String @required + role UserRole @default("USER") + active Boolean @default(true) + createdAt Date @default("now()") +} + +model Post { + id String @id @default("nanoid()") + title String @required + content String @required + authorId String @required + published Boolean @default(false) + createdAt Date @default("now()") +} + +plugin "./plugins/api-client.js" { + output "./api-client.ts" + clientType "rest" + httpLibrary "fetch" + baseUrl "/api/v1" + generateTypes true +}` + +//--------------------------------------------------------------------// + +const generatedClientUsageExample = +`import APIClient from './api-client'; + +// Initialize client +const client = new APIClient('https://api.example.com'); + +// Set authentication token +client.setAuthToken('your-jwt-token'); + +// Use the client +async function example() { + // Get all users with pagination + const usersResponse = await client.user.getAll({ + page: 1, + limit: 10, + search: 'john' + }); + + if (usersResponse.success) { + console.log('Users:', usersResponse.data); + console.log('Total:', usersResponse.total); + } + + // Get user by ID + const userResponse = await client.user.getById('user-123'); + + if (userResponse.success) { + console.log('User:', userResponse.data); + } + + // Create new user + const newUserResponse = await client.user.create({ + email: 'john@example.com', + name: 'John Doe', + role: UserRole.USER + }); + + if (newUserResponse.success) { + console.log('Created user:', newUserResponse.data); + } + + // Update user + const updateResponse = await client.user.update('user-123', { + name: 'John Smith' + }); + + // Delete user + const deleteResponse = await client.user.delete('user-123'); +}` + +//--------------------------------------------------------------------// + +export default function UsageExamples() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Usage Examples Section Content */} +
+

{_('6. Usage Examples')}

+

+ + This section demonstrates practical usage of the API client + generator plugin with real-world examples. The examples show how to + configure the plugin in schema files and how to use the generated + client code in applications. + +

+ +

{_('6.1. Basic Schema')}

+

+ + A basic schema example shows the fundamental structure needed to + generate API clients. This includes model definitions with proper + attributes, enum declarations, and plugin configuration that + produces a functional REST API client. + +

+ + {basicSchemaExample} + + +

{_('6.2. Generated Client Usage')}

+

+ + The generated client provides a type-safe interface for interacting + with your API endpoints. This example demonstrates how to initialize + the client, set authentication, and perform common CRUD operations + with proper error handling and TypeScript support. + +

+ + {generatedClientUsageExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/api-client-plugin/index.tsx b/packages/www/plugins/docs/components/api-client-plugin/index.tsx new file mode 100644 index 0000000..fa590ad --- /dev/null +++ b/packages/www/plugins/docs/components/api-client-plugin/index.tsx @@ -0,0 +1,11 @@ +//exporting all components to have multiple imports from a single file +export { default as AdvancedFeatures } from './AdvancedFeatures.js'; +export { default as BestPractices } from './BestPractices.js'; +export { default as Implementation } from './Implementation.js'; +export { default as Introduction } from './Introduction.js'; +export { default as Overview } from './Overview.js'; +export { default as PluginStructure } from './PluginStructure.js'; +export { default as Prerequisites } from './Prerequisites.js'; +export { default as SchemaConfiguration } from './SchemaConfiguration.js'; +export { default as Troubleshooting } from './Troubleshooting.js'; +export { default as UsageExamples } from './UsageExamples.js'; \ No newline at end of file diff --git a/packages/www/plugins/docs/components/graphql-schema-plugin/AdvancedFeatures.tsx b/packages/www/plugins/docs/components/graphql-schema-plugin/AdvancedFeatures.tsx new file mode 100644 index 0000000..65e6fd3 --- /dev/null +++ b/packages/www/plugins/docs/components/graphql-schema-plugin/AdvancedFeatures.tsx @@ -0,0 +1,120 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, Code, H2 } from '../../../docs/components/index.js'; + +//code examples +//--------------------------------------------------------------------// + +const customScalarTypesExample = +`// In your plugin configuration +customScalars: { + Email: "String", + URL: "String", + PhoneNumber: "String", + BigInt: "String" +}`; + +//--------------------------------------------------------------------// + +const relationshipHandlingExample = +`function handleRelationships(column: any, models: Record): string { + // Check if the column type is another model + if (models[column.type]) { + let type = column.type; + + if (column.multiple) { + type = \`[\${type}]\`; + } + + if (column.required) { + type += '!'; + } + + return type; + } + + return formatFieldType(column); +}` + +//--------------------------------------------------------------------// + +const directiveSupportExample = +`function generateDirectives(column: any): string { + const directives: string[] = []; + + if (column.attributes?.unique) { + directives.push('@unique'); + } + + if (column.attributes?.deprecated) { + directives.push('@deprecated(reason: "Use alternative field")'); + } + + return directives.length > 0 ? \` \${directives.join(' ')}\` : ''; +}`; + +//--------------------------------------------------------------------// + +export default function AdvancedFeatures() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Advanced Features Section Content */} +
+

{_('7. Advanced Features')}

+

+ + Advanced features extend the basic GraphQL schema generation + with sophisticated type handling, relationship management, + directive support, and custom scalar types. These features + enable production-ready GraphQL schemas that handle complex + requirements. + +

+ +

{_('Custom Scalar Types')}

+

+ + Custom scalar types allow you to define specialized data + types that map to specific validation or formatting requirements. + This feature enables the creation of domain-specific types + that enhance type safety and API clarity. + +

+ + {customScalarTypesExample} + + +

{_('Relationship Handling')}

+

+ + Relationship handling manages references between different + types and models in your schema. This ensures that type + relationships are properly represented in the generated + GraphQL schema with correct type references and nullability + handling. + +

+ + {relationshipHandlingExample} + + +

{_('Directive Support')}

+

+ + Directive support enables the addition of GraphQL directives + to fields and types, providing metadata and behavior hints + for GraphQL servers and tools. This feature enhances schema + expressiveness and enables advanced GraphQL features. + +

+ + {directiveSupportExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/graphql-schema-plugin/BestPractices.tsx b/packages/www/plugins/docs/components/graphql-schema-plugin/BestPractices.tsx new file mode 100644 index 0000000..d1aab82 --- /dev/null +++ b/packages/www/plugins/docs/components/graphql-schema-plugin/BestPractices.tsx @@ -0,0 +1,154 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, Code } from '../../../docs/components/index.js'; + +//code examples +//--------------------------------------------------------------------// + +const typeSafetyExample = +`interface GraphQLColumn { + name: string; + type: string; + required: boolean; + multiple: boolean; + attributes?: Record; +} + +function validateColumn(column: any): column is GraphQLColumn { + return ( + typeof column.name === 'string' && + typeof column.type === 'string' && + typeof column.required === 'boolean' + ); +}`; + +//--------------------------------------------------------------------// + +const errorHandlingExample = +`function generateTypes(models: Record): string { + try { + let content = '# Types\\n'; + + for (const [modelName, model] of Object.entries(models)) { + if (!model.columns || !Array.isArray(model.columns)) { + console.warn(\`⚠️ Model \${modelName} has no valid columns\`); + continue; + } + + content += generateSingleType(modelName, model); + } + + return content; + } catch (error) { + throw new Error(\`Failed to generate GraphQL types: \${error.message}\`); + } +}`; + +//--------------------------------------------------------------------// + +const configurationValidationExample = +`function validateConfig(config: any): asserts config is GraphQLConfig { + if (!config.output || typeof config.output !== 'string') { + throw new Error('GraphQL plugin requires "output" configuration as string'); + } + + if (config.customScalars && typeof config.customScalars !== 'object') { + throw new Error('customScalars must be an object'); + } +}`; + +//--------------------------------------------------------------------// + +const performanceOptimizationExample = +`// Cache type mappings +const typeCache = new Map(); + +function getCachedType(schemaType: string, customScalars: Record): string { + const cacheKey = \`\${schemaType}:\${JSON.stringify(customScalars)}\`; + + if (typeCache.has(cacheKey)) { + return typeCache.get(cacheKey)!; + } + + const mappedType = mapSchemaTypeToGraphQL(schemaType, customScalars); + typeCache.set(cacheKey, mappedType); + + return mappedType; +}`; + +//--------------------------------------------------------------------// + +export default function BestPractices() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Best Practices Section Content */} +
+

{_('8. Best Practices')}

+

+ + Best practices ensure your generated GraphQL schemas are + maintainable, performant, and follow GraphQL conventions. + These guidelines cover type safety, error handling, configuration + validation, and performance optimization. + +

+ +

{_('Type Safety')}

+

+ + Type safety is crucial for preventing runtime errors and + ensuring reliable GraphQL schema generation. Always validate + input data and use proper TypeScript types throughout the + plugin implementation to ensure consistent output. + +

+ + {typeSafetyExample} + + +

{_('Error Handling')}

+

+ + Proper error handling ensures that schema generation failures + provide clear, actionable feedback to developers. Implement + comprehensive error handling patterns and meaningful error + messages to improve the debugging experience. + +

+ + {errorHandlingExample} + + +

{_('Configuration Validation')}

+

+ + Configuration validation ensures that plugin settings are + correct and complete before schema generation begins. This + prevents runtime errors and provides early feedback about + configuration issues. + +

+ + {configurationValidationExample} + + +

{_('Performance Optimization')}

+

+ + Performance optimization techniques help maintain reasonable + generation times when working with large schemas. Implement + caching strategies and efficient algorithms to ensure the + plugin scales well with complex type hierarchies. + +

+ + {performanceOptimizationExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/graphql-schema-plugin/Conclusion.tsx b/packages/www/plugins/docs/components/graphql-schema-plugin/Conclusion.tsx new file mode 100644 index 0000000..39184dc --- /dev/null +++ b/packages/www/plugins/docs/components/graphql-schema-plugin/Conclusion.tsx @@ -0,0 +1,27 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C } from '../../../docs/components/index.js'; + +export default function Conclusion() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Conclusion Section Content */} +
+

{_('10. Conclusion')}

+

+ + This tutorial provides a comprehensive foundation for + creating GraphQL schema generators from .idea + files. The generated schemas can be used with any GraphQL + server implementation like Apollo Server, GraphQL Yoga, + or others. + +

+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/graphql-schema-plugin/Implementation.tsx b/packages/www/plugins/docs/components/graphql-schema-plugin/Implementation.tsx new file mode 100644 index 0000000..1c48023 --- /dev/null +++ b/packages/www/plugins/docs/components/graphql-schema-plugin/Implementation.tsx @@ -0,0 +1,296 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, C, Code } from '../../../docs/components/index.js'; + +//code examples +//--------------------------------------------------------------------// + +const corePluginFunctionExample = +`export default async function generateGraphQLSchema( + props: PluginProps<{ config: GraphQLConfig }> +) { + const { config, schema, transformer } = props; + + try { + // Validate configuration + if (!config.output) { + throw new Error('GraphQL plugin requires "output" configuration'); + } + + // Generate GraphQL schema + let schemaContent = ''; + + // Add custom scalars + schemaContent += generateCustomScalars(config.customScalars || {}); + + // Generate enums + if (schema.enum) { + schemaContent += generateEnums(schema.enum); + } + + // Generate types + if (schema.model) { + schemaContent += generateTypes(schema.model); + + if (config.generateInputTypes) { + schemaContent += generateInputTypes(schema.model); + } + } + + // Generate custom types + if (schema.type) { + schemaContent += generateCustomTypes(schema.type); + } + + // Generate root types + if (config.includeQueries) { + schemaContent += generateQueries(schema.model || {}); + } + + if (config.includeMutations) { + schemaContent += generateMutations(schema.model || {}); + } + + if (config.includeSubscriptions) { + schemaContent += generateSubscriptions(schema.model || {}); + } + + // Write to output file + const outputPath = await transformer.loader.absolute(config.output); + await fs.mkdir(path.dirname(outputPath), { recursive: true }); + await fs.writeFile(outputPath, schemaContent, 'utf8'); + + console.log(\`✅ GraphQL schema generated: \${outputPath}\`); + + } catch (error) { + console.error('❌ GraphQL schema generation failed:', error.message); + throw error; + } +}`; + +//--------------------------------------------------------------------// + +const typeMappingFunctionsExample = +`function mapSchemaTypeToGraphQL(schemaType: string, customScalars: Record = {}): string { + // Check for custom scalar mappings first + if (customScalars[schemaType]) { + return customScalars[schemaType]; + } + + // Standard type mappings + const typeMap: Record = { + 'String': 'String', + 'Number': 'Float', + 'Integer': 'Int', + 'Boolean': 'Boolean', + 'Date': 'DateTime', + 'JSON': 'JSON', + 'ID': 'ID' + }; + + return typeMap[schemaType] || schemaType; +} + +function formatFieldType(column: any, customScalars: Record = {}): string { + let type = mapSchemaTypeToGraphQL(column.type, customScalars); + + // Handle arrays + if (column.multiple) { + type = \`[\${type}]\`; + } + + // Handle required fields + if (column.required) { + type += '!'; + } + + return type; +}`; + +//--------------------------------------------------------------------// + +const customScalarsExample = +`function generateCustomScalars(customScalars: Record): string { + if (Object.keys(customScalars).length === 0) { + return \`# Custom Scalars +scalar DateTime +scalar JSON + +\`; + } + + let content = '# Custom Scalars\\n'; + content += 'scalar DateTime\\n'; + content += 'scalar JSON\\n'; + + for (const [name, description] of Object.entries(customScalars)) { + content += \`scalar \${name}\\n\`; + } + + return content + '\\n'; +}`; + +//--------------------------------------------------------------------// + +const enumsAndTypesExample = +`function generateEnums(enums: Record): string { + let content = '# Enums\\n'; + + for (const [enumName, enumDef] of Object.entries(enums)) { + content += \`enum \${enumName} {\\n\`; + + for (const [key, value] of Object.entries(enumDef)) { + content += \` \${key}\\n\`; + } + + content += '}\\n\\n'; + } + + return content; +} + +function generateTypes(models: Record): string { + let content = '# Types\\n'; + + for (const [modelName, model] of Object.entries(models)) { + content += \`type \${modelName} {\\n\`; + + for (const column of model.columns || []) { + const fieldType = formatFieldType(column); + content += \` \${column.name}: \${fieldType}\\n\`; + } + + content += '}\\n\\n'; + } + + return content; +}`; + +//--------------------------------------------------------------------// + +const inputTypesAndQueriesExample = +`function generateInputTypes(models: Record): string { + let content = '# Input Types\\n'; + + for (const [modelName, model] of Object.entries(models)) { + // Create input type + content += \`input \${modelName}Input {\\n\`; + + for (const column of model.columns || []) { + // Skip auto-generated fields like ID for input types + if (column.attributes?.id) continue; + + let fieldType = formatFieldType(column); + // Remove required constraint for input types (make them optional) + fieldType = fieldType.replace('!', ''); + + content += \` \${column.name}: \${fieldType}\\n\`; + } + + content += '}\\n\\n'; + + // Create update input type + content += \`input \${modelName}UpdateInput {\\n\`; + + for (const column of model.columns || []) { + let fieldType = formatFieldType(column); + // All fields are optional in update input + fieldType = fieldType.replace('!', ''); + + content += \` \${column.name}: \${fieldType}\\n\`; + } + + content += '}\\n\\n'; + } + + return content; +} + +function generateQueries(models: Record): string { + let content = '# Queries\\ntype Query {\\n'; + + for (const [modelName, model] of Object.entries(models)) { + const lowerName = modelName.toLowerCase(); + + // Get single item + content += \` \${lowerName}(id: ID!): \${modelName}\\n\`; + + // Get multiple items + content += \` \${lowerName}s(limit: Int, offset: Int): [\${modelName}]\\n\`; + } + + content += '}\\n\\n'; + return content; +}`; + +//--------------------------------------------------------------------// + +export default function Implementation() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Implementation Section Content */} +
+

{_('4. Implementation')}

+

+ + The implementation section covers the core plugin function + and supporting utilities that handle GraphQL schema generation. + This includes configuration validation, content generation, + file writing, and error handling throughout the generation + process. + +

+ +

{_('Core Plugin Function')}

+

+ + The core plugin function serves as the main entry point for + GraphQL schema generation. It orchestrates the entire process + from configuration validation through content generation to + file output, ensuring proper error handling and logging + throughout. + +

+ + {corePluginFunctionExample} + + +

{_('Type Mapping Functions')}

+

+ + Type mapping functions handle the conversion of .idea + schema types to their GraphQL equivalents. These functions + ensure proper type safety and handle complex scenarios like + arrays, required fields, and custom scalar types. + +

+ + {typeMappingFunctionsExample} + + +

{_('Schema Generation Functions')}

+

+ + Schema generation functions create specific parts of the + GraphQL schema including custom scalars, enums, types, input + types, and root operation types. These functions handle proper + GraphQL syntax construction and type relationships. + +

+ + {customScalarsExample} + + + {enumsAndTypesExample} + + + {inputTypesAndQueriesExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/graphql-schema-plugin/Introduction.tsx b/packages/www/plugins/docs/components/graphql-schema-plugin/Introduction.tsx new file mode 100644 index 0000000..18958f4 --- /dev/null +++ b/packages/www/plugins/docs/components/graphql-schema-plugin/Introduction.tsx @@ -0,0 +1,24 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C } from '../../../docs/components/index.js'; + +export default function Introduction() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* GraphQL Schema Generator Plugin Tutorial */} +

{_('GraphQL Schema Generator Plugin Tutorial')}

+

+ + This tutorial demonstrates how to create a plugin that + generates GraphQL type definitions from .idea schema + files. The plugin will transform your schema models, types, + and enums into proper GraphQL schema definitions. + +

+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/graphql-schema-plugin/Overview.tsx b/packages/www/plugins/docs/components/graphql-schema-plugin/Overview.tsx new file mode 100644 index 0000000..4e15477 --- /dev/null +++ b/packages/www/plugins/docs/components/graphql-schema-plugin/Overview.tsx @@ -0,0 +1,60 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C, SS } from '../../../docs/components/index.js'; + +export default function Overview() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Overview Section Content */} +
+

{_('1. Overview')}

+

+ + GraphQL is a query language and runtime for APIs that provides a + complete and understandable description of the data in your API. + This plugin transforms your .idea schema definitions into + comprehensive GraphQL type definitions that enable type-safe API + development with excellent tooling support. + +

+

+ + This plugin generates GraphQL type definitions from your + .idea schema, including: + +

+
    +
  • + + Types: GraphQL object types from schema models + +
  • +
  • + + Inputs: GraphQL input types for mutations + +
  • +
  • + + Enums: GraphQL enum types from schema enums + +
  • +
  • + + Scalars: Custom scalar types when needed + +
  • +
  • + + Queries and Mutations: Basic CRUD operations + +
  • +
+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/graphql-schema-plugin/PluginStructure.tsx b/packages/www/plugins/docs/components/graphql-schema-plugin/PluginStructure.tsx new file mode 100644 index 0000000..b807906 --- /dev/null +++ b/packages/www/plugins/docs/components/graphql-schema-plugin/PluginStructure.tsx @@ -0,0 +1,57 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, Code } from '../../../docs/components/index.js'; + +//code examples +//--------------------------------------------------------------------// + +const pluginStructureExample = +`import type { PluginProps } from '@stackpress/idea-transformer/types'; +import fs from 'fs/promises'; +import path from 'path'; + +interface GraphQLConfig { + output: string; + includeQueries?: boolean; + includeMutations?: boolean; + includeSubscriptions?: boolean; + customScalars?: Record; + generateInputTypes?: boolean; +} + +export default async function generateGraphQLSchema( + props: PluginProps<{ config: GraphQLConfig }> +) { + const { config, schema, transformer } = props; + + // Implementation here... +}`; + +//--------------------------------------------------------------------// + +export default function PluginStructure() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Plugin Structure Section Content */} +
+

{_('3. Plugin Structure')}

+

+ + The plugin structure defines the core architecture and + configuration interface for the GraphQL schema generator. + This includes the main plugin function, configuration types, + and the overall organization of the generated GraphQL schema + definitions. + +

+ + {pluginStructureExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/graphql-schema-plugin/Prerequisites.tsx b/packages/www/plugins/docs/components/graphql-schema-plugin/Prerequisites.tsx new file mode 100644 index 0000000..f07ed6b --- /dev/null +++ b/packages/www/plugins/docs/components/graphql-schema-plugin/Prerequisites.tsx @@ -0,0 +1,49 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C } from '../../../docs/components/index.js'; + +export default function Prerequisites() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Prerequisites Section Content */} +
+

{_('2. Prerequisites')}

+

+ + Before implementing the GraphQL schema generator plugin, + ensure you have the necessary development environment and + knowledge. This section covers the essential requirements + for successful plugin creation and GraphQL integration. + +

+
    +
  • + + Node.js 16+ and npm/yarn + +
  • +
  • + + Basic understanding of GraphQL + +
  • +
  • + + Familiarity with the @stackpress/idea-transformer + library + +
  • +
  • + + Understanding of .idea schema format + +
  • +
+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/graphql-schema-plugin/SchemaConfiguration.tsx b/packages/www/plugins/docs/components/graphql-schema-plugin/SchemaConfiguration.tsx new file mode 100644 index 0000000..395665c --- /dev/null +++ b/packages/www/plugins/docs/components/graphql-schema-plugin/SchemaConfiguration.tsx @@ -0,0 +1,132 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, C, SS, Code } from '../../../docs/components/index.js'; +import { Table, Thead, Trow, Tcol } from 'frui/element/Table'; + +//code examples +//--------------------------------------------------------------------// + +const schemaConfigurationExample = +`plugin "./plugins/graphql-schema.js" { + output "./generated/schema.graphql" + includeQueries true + includeMutations true + includeSubscriptions false + generateInputTypes true + customScalars { + Email "String" + URL "String" + PhoneNumber "String" + } +}`; + +//--------------------------------------------------------------------// + +export default function SchemaConfiguration() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Schema Configuration Section Content */} +
+

{_('5. Schema Configuration')}

+

+ + Schema configuration demonstrates how to integrate the + GraphQL schema generator into your .idea schema + files. This section covers plugin configuration options + and their effects on the generated GraphQL schema definitions. + +

+

+ + Add the GraphQL plugin to your .idea schema file: + +

+ + {schemaConfigurationExample} + + +

{_('Configuration Options')}

+

+ + Configuration options control how GraphQL schema definitions + are generated, including operation types, input generation, + and custom scalar handling. Understanding these options helps + you customize the plugin to meet your specific GraphQL + requirements. + +

+ + + {_('Option')} + {_('Type')} + {_('Default')} + {_('Description')} + + output + string + {_('Required')} + + + Output file path for the GraphQL schema + + + + + includeQueries + boolean + false + + + Generate Query type with CRUD operations + + + + + includeMutations + boolean + false + + + Generate Mutation type with CRUD operations + + + + + includeSubscriptions + boolean + false + + + Generate Subscription type for real-time updates + + + + + generateInputTypes + boolean + true + + + Generate input types for mutations + + + + + customScalars + object + {} + + + Custom scalar type mappings. + + + +
+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/graphql-schema-plugin/Troubleshooting.tsx b/packages/www/plugins/docs/components/graphql-schema-plugin/Troubleshooting.tsx new file mode 100644 index 0000000..fcb82eb --- /dev/null +++ b/packages/www/plugins/docs/components/graphql-schema-plugin/Troubleshooting.tsx @@ -0,0 +1,169 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, Code } from '../../../docs/components/index.js'; + +//code examples +//--------------------------------------------------------------------// + +const invalidGraphQLNamesExample = +`function sanitizeGraphQLName(name: string): string { + // GraphQL names must match /^[_A-Za-z][_0-9A-Za-z]*$/ + return name.replace(/[^_A-Za-z0-9]/g, '_').replace(/^[0-9]/, '_$&'); +}`; + +//--------------------------------------------------------------------// + +const circularDependenciesExample = +`function detectCircularDependencies(models: Record): string[] { + const visited = new Set(); + const recursionStack = new Set(); + const cycles: string[] = []; + + // Implementation for cycle detection... + + return cycles; +}`; + +//--------------------------------------------------------------------// + +const missingRequiredFieldsExample = +`function validateRequiredFields(model: any): void { + if (!model.columns || model.columns.length === 0) { + throw new Error(\`Model must have at least one column\`); + } +}`; + +//--------------------------------------------------------------------// + +const verboseLoggingExample = +`const DEBUG = process.env.DEBUG === 'true'; + +function debugLog(message: string, data?: any) { + if (DEBUG) { + console.log(\`[GraphQL Plugin] \${message}\`, data || ''); + } +}`; + +//--------------------------------------------------------------------// + +const validateGeneratedSchemaExample = +`import { buildSchema } from 'graphql'; + +function validateGeneratedSchema(schemaContent: string): void { + try { + buildSchema(schemaContent); + console.log('✅ Generated GraphQL schema is valid'); + } catch (error) { + throw new Error(\`Invalid GraphQL schema: \${error.message}\`); + } +}`; + +//--------------------------------------------------------------------// + +export default function Troubleshooting() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Troubleshooting Section Content */} +
+

{_('9. Troubleshooting')}

+

+ + This section addresses common issues encountered when + generating GraphQL schemas and provides solutions for + debugging and resolving problems. Understanding these + troubleshooting techniques helps ensure reliable schema + generation. + +

+ +

{_('Common Issues')}

+

+ + Common issues include invalid GraphQL identifiers, circular + dependencies, and missing required fields. These problems + typically arise from schema complexity or naming conflicts + that can be resolved with proper validation and sanitization. + +

+ +

{_('Invalid GraphQL Names')}

+

+ + Invalid GraphQL names occur when schema identifiers contain + characters that are not valid in GraphQL. The plugin should + validate and sanitize names to ensure they conform to GraphQL + naming conventions. + +

+ + {invalidGraphQLNamesExample} + + +

{_('Circular Dependencies')}

+

+ + Circular dependencies can cause infinite loops during + generation or invalid GraphQL schemas. Detecting and + handling these scenarios is essential for robust schema + generation, especially with complex type relationships. + +

+ + {circularDependenciesExample} + + +

{_('Missing Required Fields')}

+

+ + Missing required fields can result in invalid GraphQL + types that fail validation. Ensure all models have proper + field definitions and handle edge cases where schema + definitions might be incomplete. + +

+ + {missingRequiredFieldsExample} + + +

{_('Debugging Tips')}

+

+ + Debugging tips help identify and resolve issues during + GraphQL schema generation. These techniques provide visibility + into the generation process and help diagnose problems with + schema logic or output formatting. + +

+ +

{_('Enable Verbose Logging')}

+

+ + Verbose logging provides detailed information about the + schema generation process, helping identify where issues + occur and what data is being processed at each step. + +

+ + {verboseLoggingExample} + + +

{_('Validate Generated Schema')}

+

+ + Validating the generated GraphQL schema ensures that the + output is syntactically correct and will work with GraphQL + servers and tools. This validation step catches generation + errors before deployment. + +

+ + {validateGeneratedSchemaExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/graphql-schema-plugin/UsageExamples.tsx b/packages/www/plugins/docs/components/graphql-schema-plugin/UsageExamples.tsx new file mode 100644 index 0000000..625c277 --- /dev/null +++ b/packages/www/plugins/docs/components/graphql-schema-plugin/UsageExamples.tsx @@ -0,0 +1,135 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, Code } from '../../../docs/components/index.js'; + +//code examples +//--------------------------------------------------------------------// + +const basicSchemaExample = + `enum UserRole { + ADMIN "admin" + USER "user" + GUEST "guest" +} + +model User { + id String @id @default("nanoid()") + email String @unique @required + name String @required + role UserRole @default("USER") + active Boolean @default(true) + createdAt Date @default("now()") +} + +plugin "./plugins/graphql-schema.js" { + output "./schema.graphql" + includeQueries true + includeMutations true +}`; + +//--------------------------------------------------------------------// + +const generatedOutputExample = + `# Custom Scalars +scalar DateTime +scalar JSON + +# Enums +enum UserRole { + ADMIN + USER + GUEST +} + +# Types +type User { + id: ID! + email: String! + name: String! + role: UserRole! + active: Boolean! + createdAt: DateTime! +} + +# Input Types +input UserInput { + email: String + name: String + role: UserRole + active: Boolean +} + +input UserUpdateInput { + email: String + name: String + role: UserRole + active: Boolean + createdAt: DateTime +} + +# Queries +type Query { + user(id: ID!): User + users(limit: Int, offset: Int): [User] +} + +# Mutations +type Mutation { + createUser(input: UserInput!): User + updateUser(id: ID!, input: UserUpdateInput!): User + deleteUser(id: ID!): Boolean +}`; + +//--------------------------------------------------------------------// + +export default function UsageExamples() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Usage Examples Section Content */} +
+

{_('6. Usage Examples')}

+

+ + Usage examples demonstrate practical applications of the + GraphQL schema generator with real-world scenarios. These + examples show how to configure the plugin for different + use cases and how the generated GraphQL schemas integrate + into development workflows. + +

+ +

{_('Basic Schema')}

+

+ + A basic schema example shows the fundamental structure + needed to generate GraphQL type definitions. This includes + model definitions with proper attributes, enum declarations, + and plugin configuration that produces comprehensive GraphQL + schemas. + +

+ + {basicSchemaExample} + + +

{_('Generated Output')}

+

+ + The generated output demonstrates the GraphQL schema + produced by the plugin from the basic schema example. + This shows how schema definitions are transformed into + proper GraphQL type definitions with full type safety and + operation support. + +

+ + {generatedOutputExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/graphql-schema-plugin/index.tsx b/packages/www/plugins/docs/components/graphql-schema-plugin/index.tsx new file mode 100644 index 0000000..b52a632 --- /dev/null +++ b/packages/www/plugins/docs/components/graphql-schema-plugin/index.tsx @@ -0,0 +1,12 @@ +//exporting all components to have multiple imports from a single file +export { default as AdvancedFeatures } from './AdvancedFeatures.js'; +export { default as BestPractices } from './BestPractices.js'; +export { default as Conclusion } from './Conclusion.js'; +export { default as Implementation } from './Implementation.js'; +export { default as Introduction } from './Introduction.js'; +export { default as Overview } from './Overview.js'; +export { default as PluginStructure } from './PluginStructure.js'; +export { default as Prerequisites } from './Prerequisites.js'; +export { default as SchemaConfiguration } from './SchemaConfiguration.js'; +export { default as Troubleshooting } from './Troubleshooting.js'; +export { default as UsageExamples } from './UsageExamples.js'; \ No newline at end of file diff --git a/packages/www/plugins/docs/components/html-form-plugin/CreatePluginStructure.tsx b/packages/www/plugins/docs/components/html-form-plugin/CreatePluginStructure.tsx new file mode 100644 index 0000000..c6ca1c4 --- /dev/null +++ b/packages/www/plugins/docs/components/html-form-plugin/CreatePluginStructure.tsx @@ -0,0 +1,89 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const pluginStructureExample = + `import type { PluginProps } from '@stackpress/idea-transformer/types'; +import fs from 'fs/promises'; +import path from 'path'; + +interface HTMLFormConfig { + output: string; + title?: string; + theme?: 'bootstrap' | 'tailwind' | 'custom'; + layout?: 'vertical' | 'horizontal' | 'inline'; + includeCSS?: boolean; + includeJS?: boolean; + submitUrl?: string; + method?: 'GET' | 'POST'; +} + +export default async function htmlFormPlugin( + props: PluginProps<{ config: HTMLFormConfig }> +) { + const { config, schema, transformer, cwd } = props; + + // Validate configuration + if (!config.output) { + throw new Error('HTML Form Plugin requires "output" configuration'); + } + + // Set defaults + const options = { + title: config.title || 'Generated Form', + theme: config.theme || 'bootstrap', + layout: config.layout || 'vertical', + includeCSS: config.includeCSS !== false, + includeJS: config.includeJS !== false, + submitUrl: config.submitUrl || '#', + method: config.method || 'POST', + ...config + }; + + // Generate HTML content + const htmlContent = generateHTML(schema, options); + + // Write to output file + const outputPath = await transformer.loader.absolute(config.output); + await fs.mkdir(path.dirname(outputPath), { recursive: true }); + await fs.writeFile(outputPath, htmlContent, 'utf8'); + + console.log(\`✅ HTML form generated: \${outputPath}\`); +}`; + +//--------------------------------------------------------------------// + +export default function CreatePluginStructure() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Create the Plugin Structure Section Content */} +
+

{_('4. Create the Plugin Structure')}

+

+ + The plugin structure provides the foundation for the HTML + form generator. This section covers the main plugin function, + configuration interface, and the basic workflow for + processing schemas and generating HTML output. + +

+

+ + Create a new file + html-form-plugin.js: +

+ + {pluginStructureExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/html-form-plugin/ErrorHandlingAndBestPractices.tsx b/packages/www/plugins/docs/components/html-form-plugin/ErrorHandlingAndBestPractices.tsx new file mode 100644 index 0000000..0d9b9cf --- /dev/null +++ b/packages/www/plugins/docs/components/html-form-plugin/ErrorHandlingAndBestPractices.tsx @@ -0,0 +1,91 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const errorHandlingExample = + `export default async function htmlFormPlugin(props: PluginProps<{}>) { + const { config, schema, transformer, cwd } = props; + + try { + // Validate configuration + validateConfig(config); + + // Validate schema has models + if (!schema.model || Object.keys(schema.model).length === 0) { + console.warn('⚠️ No models found in schema. Skipping HTML form generation.'); + return; + } + + // Generate HTML + const htmlContent = generateHTML(schema, config); + + // Ensure output directory exists + const outputPath = await transformer.loader.absolute(config.output); + await fs.mkdir(path.dirname(outputPath), { recursive: true }); + + // Write file + await fs.writeFile(outputPath, htmlContent, 'utf8'); + + console.log(\`✅ HTML form generated: \${outputPath}\`); + console.log(\`📊 Generated forms for \${Object.keys(schema.model).length} model(s)\`); + + } catch (error) { + console.error(\`❌ HTML Form Plugin failed: \${error.message}\`); + throw error; + } +} + +function validateConfig(config: any): void { + if (!config.output) { + throw new Error('HTML Form Plugin requires "output" configuration'); + } + + if (config.theme && !['bootstrap', 'tailwind', 'custom'].includes(config.theme)) { + throw new Error(\`Unsupported theme: \${config.theme}\`); + } + + if (config.layout && !['vertical', 'horizontal', 'inline'].includes(config.layout)) { + throw new Error(\`Unsupported layout: \${config.layout}\`); + } + + if (config.method && !['GET', 'POST'].includes(config.method)) { + throw new Error(\`Unsupported HTTP method: \${config.method}\`); + } +}`; + +//--------------------------------------------------------------------// + +export default function ErrorHandlingAndBestPractices() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Error Handling and Best Practices Section Content */} +
+

{_('10. Error Handling and Best Practices')}

+

+ + Proper error handling and following best practices ensure + that your plugin is robust and reliable. This section covers + validation techniques, error reporting, and recommended + patterns for plugin development. + +

+

+ + Add proper error handling and validation: + +

+ + {errorHandlingExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/html-form-plugin/GenerateCompleteHtmlDocument.tsx b/packages/www/plugins/docs/components/html-form-plugin/GenerateCompleteHtmlDocument.tsx new file mode 100644 index 0000000..357b678 --- /dev/null +++ b/packages/www/plugins/docs/components/html-form-plugin/GenerateCompleteHtmlDocument.tsx @@ -0,0 +1,178 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const htmlGenerationExample = + `function generateHTML(schema: any, options: any): string { + let html = generateHTMLHeader(options); + + // Generate forms for each model + if (schema.model) { + for (const [modelName, model] of Object.entries(schema.model)) { + html += generateFormHTML(modelName, model, schema, options); + html += '\\n'; + } + } + + html += generateHTMLFooter(options); + + return html; +} + +function generateHTMLHeader(options: any): string { + let html = '\\n'; + html += '\\n'; + html += '\\n'; + html += ' \\n'; + html += ' \\n'; + html += \` \${escapeHtml(options.title)}\\n\`; + + // Include CSS + if (options.includeCSS) { + html += generateCSS(options); + } + + html += '\\n'; + html += '\\n'; + html += '
\\n'; + html += \`

\${escapeHtml(options.title)}

\\n\`; + + return html; +} + +function generateFormHTML(modelName: string, model: any, schema: any, options: any): string { + let html = \`
\\n\`; + html += \`

\${escapeHtml(modelName)} Form

\\n\`; + html += \`
\\n\`; + + // Generate form fields + for (const column of model.columns || []) { + // Skip hidden fields or system fields + if (column.attributes?.list?.hide || column.attributes?.view?.hide) { + continue; + } + + html += generateFormElement(column, schema, options); + } + + // Add submit button + html += generateSubmitButton(options); + + html += '
\\n'; + html += '
\\n'; + + return html; +} + +function generateSubmitButton(options: any): string { + let button = '
\\n'; + button += ' \\n'; + button += ' \\n'; + break; + case 'tailwind': + button += 'mt-6">\\n'; + button += ' \\n'; + button += ' \\n'; + break; + default: + button += 'form-actions">\\n'; + button += ' \\n'; + button += ' \\n'; + } + + button += '
\\n'; + + return button; +} + +function generateHTMLFooter(options: any): string { + let html = '
\\n'; + + // Include JavaScript + if (options.includeJS) { + html += generateJavaScript(options); + } + + html += '\\n'; + html += '\\n'; + + return html; +} + +function generateCSS(options: any): string { + let css = ''; + + switch (options.theme) { + case 'bootstrap': + css += ' \\n'; + break; + case 'tailwind': + css += ' \\n'; + break; + default: + css += ' \\n'; + } + + return css; +} + +function generateJavaScript(options: any): string { + let js = ''; + + switch (options.theme) { + case 'bootstrap': + js += ' \\n'; + break; + } + + // Add form validation JavaScript + js += ' \\n'; + + return js; +}`; + +//--------------------------------------------------------------------// + +export default function GenerateCompleteHtmlDocument() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Generate Complete HTML Document Section Content */} +
+

{_('7. Generate Complete HTML Document')}

+

+ + Generating a complete HTML document involves combining all + form elements into a properly structured HTML page. This + section shows how to create the HTML structure, include + necessary CSS and JavaScript files, and generate forms for + multiple models within a single document. + +

+

+ + Implement the main HTML generation function: + +

+ + {htmlGenerationExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/html-form-plugin/GeneratedOutput.tsx b/packages/www/plugins/docs/components/html-form-plugin/GeneratedOutput.tsx new file mode 100644 index 0000000..869c312 --- /dev/null +++ b/packages/www/plugins/docs/components/html-form-plugin/GeneratedOutput.tsx @@ -0,0 +1,157 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const generatedOutputExample = + ` + + + + + User Registration Form + + + +
+

User Registration Form

+
+

User Form

+
+
+ + +
Minimum 2 characters. Maximum 50 characters
+
+ +
+ + +
+ +
+ + +
Minimum value: 18. Maximum value: 100
+
+ +
+ + +
+ +
+ + +
Maximum 500 characters
+
+ +
+ + +
+ +
+ + +
+
+
+
+ + + + +`; + +//--------------------------------------------------------------------// + +export default function GeneratedOutput() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Generated Output Section Content */} +
+

{_('9. Generated Output')}

+

+ + The generated output section shows examples of the HTML code + that the plugin produces. This helps you understand what to + expect from the plugin and how the various configuration + options affect the final output. + +

+

+ + The plugin will generate HTML like this: + +

+ + {generatedOutputExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/html-form-plugin/ImplementFormElementGeneration.tsx b/packages/www/plugins/docs/components/html-form-plugin/ImplementFormElementGeneration.tsx new file mode 100644 index 0000000..8de609f --- /dev/null +++ b/packages/www/plugins/docs/components/html-form-plugin/ImplementFormElementGeneration.tsx @@ -0,0 +1,238 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const formElementExample = + `function generateFormElement(column: any, schema: any, options: any): string { + const { name, type, required, attributes = {} } = column; + const fieldConfig = attributes.field || {}; + const label = attributes.label || name; + const validation = attributes.is || {}; + + // Determine form element type + let element = ''; + + if (fieldConfig.input) { + element = generateInputElement(column, fieldConfig.input, options); + } else if (fieldConfig.textarea) { + element = generateTextareaElement(column, fieldConfig.textarea, options); + } else if (fieldConfig.select) { + element = generateSelectElement(column, schema, fieldConfig.select, options); + } else if (fieldConfig.checkbox) { + element = generateCheckboxElement(column, fieldConfig.checkbox, options); + } else if (fieldConfig.radio) { + element = generateRadioElement(column, schema, fieldConfig.radio, options); + } else if (fieldConfig.file) { + element = generateFileElement(column, fieldConfig.file, options); + } else { + // Auto-detect based on type and attributes + element = autoGenerateElement(column, schema, options); + } + + // Wrap in form group + return wrapFormGroup(element, label, name, required, validation, options); +} + +function generateInputElement(column: any, inputConfig: any, options: any): string { + const { name, required, attributes = {} } = column; + const validation = attributes.is || {}; + + const inputType = inputConfig.type || 'text'; + const placeholder = inputConfig.placeholder || ''; + const defaultValue = attributes.default || ''; + + let input = \`\${escapeHtml(defaultValue)}\`; + + return textarea; +} + +function generateSelectElement(column: any, schema: any, selectConfig: any, options: any): string { + const { name, type, required, attributes = {} } = column; + const defaultValue = attributes.default || ''; + + let select = \`'; + + return select; +} + +function autoGenerateElement(column: any, schema: any, options: any): string { + const { type, attributes = {} } = column; + + // Auto-detect based on type + switch (type) { + case 'String': + if (attributes.email) { + return generateInputElement(column, { type: 'email' }, options); + } + if (attributes.password) { + return generateInputElement(column, { type: 'password' }, options); + } + if (attributes.url) { + return generateInputElement(column, { type: 'url' }, options); + } + if (attributes.text || attributes.textarea) { + return generateTextareaElement(column, {}, options); + } + return generateInputElement(column, { type: 'text' }, options); + + case 'Number': + return generateInputElement(column, { type: 'number' }, options); + + case 'Boolean': + return generateCheckboxElement(column, {}, options); + + case 'Date': + if (attributes.time) { + return generateInputElement(column, { type: 'datetime-local' }, options); + } + return generateInputElement(column, { type: 'date' }, options); + + default: + // Check if it's an enum type + if (schema.enum && schema.enum[type]) { + return generateSelectElement(column, schema, {}, options); + } + + // Default to text input + return generateInputElement(column, { type: 'text' }, options); + } +}`; + +//--------------------------------------------------------------------// + +export default function ImplementFormElementGeneration() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Implement Form Element Generation Section Content */} +
+

{_('5. Implement Form Element Generation')}

+

+ + Form element generation is the core functionality of the + plugin. This section demonstrates how to create functions + that generate different types of HTML form elements based + on schema column definitions, including inputs, textareas, + selects, checkboxes, radio buttons, and file inputs. + +

+

+ + Create functions to generate different form elements: + +

+ + {formElementExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/html-form-plugin/ImplementFormLayoutAndStyling.tsx b/packages/www/plugins/docs/components/html-form-plugin/ImplementFormLayoutAndStyling.tsx new file mode 100644 index 0000000..caaaf18 --- /dev/null +++ b/packages/www/plugins/docs/components/html-form-plugin/ImplementFormLayoutAndStyling.tsx @@ -0,0 +1,143 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const formLayoutExample = + `function wrapFormGroup(element: string, label: string, name: string, required: boolean, validation: any, options: any): string { + const requiredMark = required ? ' *' : ''; + const helpText = generateHelpText(validation); + + switch (options.theme) { + case 'bootstrap': + return wrapBootstrapFormGroup(element, label, name, requiredMark, helpText, options); + case 'tailwind': + return wrapTailwindFormGroup(element, label, name, requiredMark, helpText, options); + default: + return wrapCustomFormGroup(element, label, name, requiredMark, helpText, options); + } +} + +function wrapBootstrapFormGroup(element: string, label: string, name: string, requiredMark: string, helpText: string, options: any): string { + let group = ''; + + if (options.layout === 'horizontal') { + group += '
\\n'; + group += \` \\n\`; + group += '
\\n'; + group += \` \${element}\\n\`; + if (helpText) { + group += \`
\${helpText}
\\n\`; + } + group += '
\\n'; + group += '
\\n'; + } else { + group += '
\\n'; + group += \` \\n\`; + group += \` \${element}\\n\`; + if (helpText) { + group += \`
\${helpText}
\\n\`; + } + group += '
\\n'; + } + + return group; +} + +function wrapTailwindFormGroup(element: string, label: string, name: string, requiredMark: string, helpText: string, options: any): string { + let group = ''; + + if (options.layout === 'horizontal') { + group += '
\\n'; + group += \` \\n\`; + group += '
\\n'; + group += \` \${element}\\n\`; + if (helpText) { + group += \`

\${helpText}

\\n\`; + } + group += '
\\n'; + group += '
\\n'; + } else { + group += '
\\n'; + group += \` \\n\`; + group += \` \${element}\\n\`; + if (helpText) { + group += \`

\${helpText}

\\n\`; + } + group += '
\\n'; + } + + return group; +} + +// CSS class generators for different themes +function getInputClasses(theme: string): string { + switch (theme) { + case 'bootstrap': + return 'form-control'; + case 'tailwind': + return 'block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500'; + default: + return 'form-input'; + } +} + +function getSelectClasses(theme: string): string { + switch (theme) { + case 'bootstrap': + return 'form-select'; + case 'tailwind': + return 'block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500'; + default: + return 'form-select'; + } +} + +function getTextareaClasses(theme: string): string { + switch (theme) { + case 'bootstrap': + return 'form-control'; + case 'tailwind': + return 'block w-full px-3 py-2 border border-gray-300 rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500'; + default: + return 'form-textarea'; + } +}`; + +//--------------------------------------------------------------------// + +export default function ImplementFormLayoutAndStyling() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Implement Form Layout and Styling Section Content */} +
+

{_('6. Implement Form Layout and Styling')}

+

+ + Form layout and styling ensure that generated forms are + visually appealing and work well with different CSS + frameworks. This section covers how to implement support + for Bootstrap, Tailwind CSS, and custom styling, along with + different layout options like vertical, horizontal, and + inline forms. + +

+

+ + Create functions for different themes and layouts: + +

+ + {formLayoutExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/html-form-plugin/Introduction.tsx b/packages/www/plugins/docs/components/html-form-plugin/Introduction.tsx new file mode 100644 index 0000000..a1c8bc9 --- /dev/null +++ b/packages/www/plugins/docs/components/html-form-plugin/Introduction.tsx @@ -0,0 +1,27 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C } from '../../../docs/components/index.js'; + +export default function Introduction() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Creating an HTML Form Plugin */} +
+

{_('Creating an HTML Form Plugin')}

+

+ + This tutorial will guide you through creating a plugin that + generates HTML forms from a processed .idea schema. + You'll learn how to parse schema models, generate appropriate + form elements, handle validation, and create responsive forms + with multiple CSS framework support. + +

+
+ + ) +} diff --git a/packages/www/plugins/docs/components/html-form-plugin/Overview.tsx b/packages/www/plugins/docs/components/html-form-plugin/Overview.tsx new file mode 100644 index 0000000..30b1b80 --- /dev/null +++ b/packages/www/plugins/docs/components/html-form-plugin/Overview.tsx @@ -0,0 +1,60 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; + +export default function Overview() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Overview Section Content */} +
+

{_('1. Overview')}

+

+ + This section provides an overview of what the HTML Form + Plugin accomplishes and its key features. The plugin + transforms schema definitions into fully functional HTML + forms with proper validation, styling, and accessibility + features. + +

+

+ + The HTML Form Plugin will: + +

+
    +
  • + + Parse schema models and their columns + +
  • +
  • + + Generate HTML form elements based on field types and + attributes + +
  • +
  • + + Include validation attributes and constraints + +
  • +
  • + + Create responsive, accessible forms with proper styling + +
  • +
  • + + Support different form layouts and themes + +
  • +
+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/html-form-plugin/Prerequisites.tsx b/packages/www/plugins/docs/components/html-form-plugin/Prerequisites.tsx new file mode 100644 index 0000000..a830c6b --- /dev/null +++ b/packages/www/plugins/docs/components/html-form-plugin/Prerequisites.tsx @@ -0,0 +1,45 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, SS, C } from '../../../docs/components/index.js'; + +export default function Prerequisites() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Prerequisites Section Content */} +
+

{_('2. Prerequisites')}

+

+ + Before starting this tutorial, ensure you have the necessary + knowledge and tools to successfully implement the HTML Form + Plugin. These prerequisites will help you understand the + concepts and follow along with the implementation. + +

+
    +
  • + + Basic understanding of + TypeScript/JavaScript +
  • +
  • + + Familiarity with HTML forms and CSS + +
  • +
  • + + Understanding of the + idea-transformer + plugin system + +
  • +
+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/html-form-plugin/UnderstandingSchemaStructure.tsx b/packages/www/plugins/docs/components/html-form-plugin/UnderstandingSchemaStructure.tsx new file mode 100644 index 0000000..cbf7fd6 --- /dev/null +++ b/packages/www/plugins/docs/components/html-form-plugin/UnderstandingSchemaStructure.tsx @@ -0,0 +1,104 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const schemaExample = + `// Example processed schema +{ + model: { + User: { + mutable: false, + columns: [ + { + name: 'name', + type: 'String', + required: true, + multiple: false, + attributes: { + field: { input: { type: 'text', placeholder: 'Enter your name' } }, + label: 'Full Name', + is: { required: true, minLength: 2, maxLength: 50 } + } + }, + { + name: 'email', + type: 'String', + required: true, + multiple: false, + attributes: { + field: { input: { type: 'email' } }, + label: 'Email Address', + is: { required: true, email: true } + } + }, + { + name: 'age', + type: 'Number', + required: false, + multiple: false, + attributes: { + field: { number: { min: 18, max: 100 } }, + label: 'Age', + is: { min: 18, max: 100 } + } + }, + { + name: 'role', + type: 'UserRole', + required: true, + multiple: false, + attributes: { + field: { select: true }, + label: 'User Role', + default: 'USER' + } + } + ] + } + }, + enum: { + UserRole: { + ADMIN: 'Administrator', + USER: 'Regular User', + GUEST: 'Guest User' + } + } +}`; + +//--------------------------------------------------------------------// + +export default function UnderstandingSchemaStructure() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Understanding the Schema Structure Section Content */} +
+

{_('3. Understanding the Schema Structure')}

+

+ + Understanding how schema attributes map to form elements is + crucial for creating effective form generation. This section + explains the processed schema structure and how different + field types and attributes translate into HTML form elements. + +

+

+ + Before creating the plugin, let's understand how schema + attributes map to form elements: + +

+ + {schemaExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/html-form-plugin/UsageInSchema.tsx b/packages/www/plugins/docs/components/html-form-plugin/UsageInSchema.tsx new file mode 100644 index 0000000..6bf39b5 --- /dev/null +++ b/packages/www/plugins/docs/components/html-form-plugin/UsageInSchema.tsx @@ -0,0 +1,71 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const usageExample = + `// schema.idea +plugin "./plugins/html-form-plugin.js" { + output "./forms/user-form.html" + title "User Registration Form" + theme "bootstrap" + layout "vertical" + includeCSS true + includeJS true + submitUrl "/api/users" + method "POST" +} + +model User { + name String @label("Full Name") @field.input(Text) @is.required @is.minLength(2) @is.maxLength(50) + email String @label("Email Address") @field.input(Email) @is.required @is.email + age Number @label("Age") @field.number @is.min(18) @is.max(100) + role UserRole @label("User Role") @field.select @default("USER") + bio String @label("Biography") @field.textarea @is.maxLength(500) + active Boolean @label("Active Account") @field.checkbox @default(true) + created Date @label("Registration Date") @field.date @default("now()") +} + +enum UserRole { + ADMIN "Administrator" + USER "Regular User" + GUEST "Guest User" +}`; + +//--------------------------------------------------------------------// + +export default function UsageInSchema() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Usage in Schema Section Content */} +
+

{_('8. Usage in Schema')}

+

+ + This section demonstrates how to configure and use the HTML + Form Plugin within your + .idea + schema files. You'll learn about the available configuration + options and how to set up your schema to generate the desired + form output. + +

+

+ + To use this plugin in your schema file: + +

+ + {usageExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/html-form-plugin/index.tsx b/packages/www/plugins/docs/components/html-form-plugin/index.tsx new file mode 100644 index 0000000..b203a2e --- /dev/null +++ b/packages/www/plugins/docs/components/html-form-plugin/index.tsx @@ -0,0 +1,12 @@ +//exporting all components to have multiple imports from a single file +export { default as CreatePluginStructure } from './CreatePluginStructure.js'; +export { default as ErrorHandlingAndBestPractices } from './ErrorHandlingAndBestPractices.js'; +export { default as GenerateCompleteHtmlDocument } from './GenerateCompleteHtmlDocument.js'; +export { default as GeneratedOutput } from './GeneratedOutput.js'; +export { default as ImplementFormElementGeneration } from './ImplementFormElementGeneration.js'; +export { default as ImplementFormLayoutAndStyling } from './ImplementFormLayoutAndStyling.js'; +export { default as Introduction } from './Introduction.js'; +export { default as Overview } from './Overview.js'; +export { default as Prerequisites } from './Prerequisites.js'; +export { default as UnderstandingSchemaStructure } from './UnderstandingSchemaStructure.js'; +export { default as UsageInSchema } from './UsageInSchema.js'; \ No newline at end of file diff --git a/packages/www/plugins/docs/components/index.tsx b/packages/www/plugins/docs/components/index.tsx new file mode 100644 index 0000000..f56aef1 --- /dev/null +++ b/packages/www/plugins/docs/components/index.tsx @@ -0,0 +1,220 @@ +import type { ReactNode } from 'react'; +import { useEffect, useState } from 'react'; +import SyntaxHighlighter from 'react-syntax-highlighter'; +import { atomOneDark } from 'react-syntax-highlighter/dist/cjs/styles/hljs'; +import { notify, useLanguage, Translate } from 'stackpress/view/client'; +import Alert from 'frui/element/Alert'; +import CodeView from './Code.js'; +import Editor from './Editor.js'; +import Layout from './Layout.js'; + +export type { File, Folder } from './Editor.js'; + +export { Editor, Layout }; + +export function Header1({ children }: { children: string }) { + const { _ } = useLanguage(); + return ( +

+ {_(children)} +

+ ); +} + +export function Header2({ children }: { children: string }) { + const { _ } = useLanguage(); + return ( +

+ {_(children)} +

+ ); +} + +export function Header3({ children }: { children: string }) { + const { _ } = useLanguage(); + return ( +

+ {_(children)} +

+ ); +} + +export function Header4({ children }: { children: string }) { + const { _ } = useLanguage(); + return ( +

+ {_(children)} +

+ ); +} + +export function Paragraph({ children }: { children: ReactNode }) { + return ( +
+ {children} +
+ ); +} + +export function Highlight({ children }: { children: ReactNode }) { + return ( + + + {children} + + + ); +} + +export function InlineCode({ lang = 'typescript', children }: { + lang?: string, + children: string +}) { + const [mounted, setMounted] = useState(false); + //only add highlighting when mounted + //necessary because of problems with SSR + useEffect(() => { + setMounted(true); + }, []); + if (mounted) { + return ( + + + + {children} + + + + ); + } + return null; +} + +export function Bash({ children }: { children: string }) { + return ( + {children} + ); +} + +export function Code(props: { lang?: string, children: string }) { + const { lang = 'typescript', children } = props; + return ( + notify('success', 'Copied to clipboard')} + >{children} + ); +} + +export function Link(props: { + className?: string, + blank?: boolean, + href?: string, + children: ReactNode +}) { + const { className = '', blank, children, ...attributes } = props; + return ( + {children} + ); +} + +export function Strong({ children }: { children: ReactNode }) { + return ( + + {children} + + ); +} + +export function Semibold({ children }: { children: ReactNode }) { + return ( + + {children} + + ); +} + +export function Emphasis({ children }: { children: ReactNode }) { + return ( + + {children} + + ); +} + +export function Note({ children }: { children: ReactNode }) { + return ( + + + NOTE: {children} + + ); +} + +export function Congrats({ children }: { children: ReactNode }) { + return ( + + + CONGRATS: {children} + + ); +} + +export function Warn({ children }: { children: ReactNode }) { + return ( + + + WARNING: {children} + + ); +} + +export function Nav({ next, prev }: { + next?: { text: string, href: string }, + prev?: { text: string, href: string } +}) { + const { _ } = useLanguage(); + return ( + + ); +} + +export const H1 = Header1; +export const H2 = Header2; +export const H3 = Header3; +export const H4 = Header4; +export const A = Link; +export const H = Highlight; +export const S = Semibold; +export const SS = Strong; +export const E = Emphasis; +export const P = Paragraph; +export const C = InlineCode; +export const B = Bash; diff --git a/packages/www/plugins/docs/components/markdown-documentation-plugin/AdvancedFeatures.tsx b/packages/www/plugins/docs/components/markdown-documentation-plugin/AdvancedFeatures.tsx new file mode 100644 index 0000000..5b86a48 --- /dev/null +++ b/packages/www/plugins/docs/components/markdown-documentation-plugin/AdvancedFeatures.tsx @@ -0,0 +1,50 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; + +export default function AdvancedFeatures() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Advanced Features Section Content */} +
+

{_('12. Advanced Features')}

+

+ + The plugin can be extended with additional features: + +

+
    +
  • + + Custom templates and themes + +
  • +
  • + + Diagram generation (Mermaid, PlantUML) + +
  • +
  • + + Integration with documentation sites (GitBook, Docusaurus) + +
  • +
  • + + API documentation formats (OpenAPI, GraphQL) + +
  • +
  • + + Multi-language documentation generation + +
  • +
+
+ + ) +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/markdown-documentation-plugin/Conclusion.tsx b/packages/www/plugins/docs/components/markdown-documentation-plugin/Conclusion.tsx new file mode 100644 index 0000000..ba5d154 --- /dev/null +++ b/packages/www/plugins/docs/components/markdown-documentation-plugin/Conclusion.tsx @@ -0,0 +1,60 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; + +export default function Conclusion() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Conclusion Section Content */} +
+

{_('13. Conclusion')}

+

+ + This Markdown Documentation Plugin demonstrates how to: + +

+
    +
  • + + Parse all schema elements (models, types, enums, props) + +
  • +
  • + + Generate comprehensive, structured documentation + +
  • +
  • + + Support multiple output formats (single file vs. + multiple files) + +
  • +
  • + + Include examples, cross-references, and detailed + attribute information + +
  • +
  • + + Provide flexible configuration options for different + documentation needs + +
  • +
+

+ + The plugin is highly customizable and can be extended to + support additional features like custom templates, diagram + generation, and integration with documentation platforms. + +

+
+ + ) +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/markdown-documentation-plugin/CreatePluginStructure.tsx b/packages/www/plugins/docs/components/markdown-documentation-plugin/CreatePluginStructure.tsx new file mode 100644 index 0000000..9f2d657 --- /dev/null +++ b/packages/www/plugins/docs/components/markdown-documentation-plugin/CreatePluginStructure.tsx @@ -0,0 +1,80 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const pluginStructureExample = + `import type { PluginProps } from '@stackpress/idea-transformer/types'; +import fs from 'fs/promises'; +import path from 'path'; + +interface MarkdownDocsConfig { + output: string; + title?: string; + format?: 'single' | 'multiple'; + includeIndex?: boolean; + includeExamples?: boolean; + includeAttributes?: boolean; + sections?: string[]; + template?: 'default' | 'api' | 'guide'; +} + +export default async function markdownDocsPlugin( + props: PluginProps<{ config: MarkdownDocsConfig }> +) { + const { config, schema, transformer, cwd } = props; + + // Validate configuration + if (!config.output) { + throw new Error('Markdown Documentation Plugin requires "output" configuration'); + } + + // Set defaults + const options = { + title: config.title || 'Schema Documentation', + format: config.format || 'single', + includeIndex: config.includeIndex !== false, + includeExamples: config.includeExamples !== false, + includeAttributes: config.includeAttributes !== false, + sections: config.sections || ['models', 'types', 'enums', 'props'], + template: config.template || 'default', + ...config + }; + + // Generate documentation + if (options.format === 'single') { + await generateSingleFile(schema, options, transformer); + } else { + await generateMultipleFiles(schema, options, transformer); + } + + console.log(\`✅ Markdown documentation generated: \${options.output}\`); +}`; + +//--------------------------------------------------------------------// + +export default function CreatePluginStructure() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Create the Plugin Structure Section Content */} +
+

{_('4. Create the Plugin Structure')}

+

+ + Create a new file markdown-docs-plugin.js: + +

+ + {pluginStructureExample} + +
+ + ) +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/markdown-documentation-plugin/ErrorHandlingAndBestPractices.tsx b/packages/www/plugins/docs/components/markdown-documentation-plugin/ErrorHandlingAndBestPractices.tsx new file mode 100644 index 0000000..32fa3ce --- /dev/null +++ b/packages/www/plugins/docs/components/markdown-documentation-plugin/ErrorHandlingAndBestPractices.tsx @@ -0,0 +1,53 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const errorHandlingExample = + `function validateConfig(config: any): void { + if (!config.output) { + throw new Error('Markdown Documentation Plugin requires "output" configuration'); + } + + if (config.format && !['single', 'multiple'].includes(config.format)) { + throw new Error(\`Unsupported format: \${config.format}\`); + } + + if (config.template && !['default', 'api', 'guide'].includes(config.template)) { + throw new Error(\`Unsupported template: \${config.template}\`); + } +}`; + +//--------------------------------------------------------------------// + +export default function ErrorHandlingAndBestPractices() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Error Handling and Best Practices Section Content */} +
+

{_('11. Error Handling and Best Practices')}

+

+ + Add proper error handling and validation: + +

+ + {errorHandlingExample} + +

+ + Always validate configuration parameters and provide meaningful + error messages to help users troubleshoot issues. + +

+
+ + ) +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/markdown-documentation-plugin/GenerateModelsDocumentation.tsx b/packages/www/plugins/docs/components/markdown-documentation-plugin/GenerateModelsDocumentation.tsx new file mode 100644 index 0000000..c62d702 --- /dev/null +++ b/packages/www/plugins/docs/components/markdown-documentation-plugin/GenerateModelsDocumentation.tsx @@ -0,0 +1,44 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const modelsGenerationExample = + `function generateModelsSection(models: any, schema: any, options: any): string { + let content = '## Models\\n\\n'; + content += 'Models represent the main data structures in your application.\\n\\n'; + + for (const [modelName, model] of Object.entries(models)) { + content += generateModelDocumentation(modelName, model, schema, options); + } + + return content; +}`; + +//--------------------------------------------------------------------// + +export default function GenerateModelsDocumentation() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Generate Models Documentation Section Content */} +
+

{_('6. Generate Models Documentation')}

+

+ + Implement model documentation generation: + +

+ + {modelsGenerationExample} + +
+ + ) +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/markdown-documentation-plugin/GenerateTypesEnumsProps.tsx b/packages/www/plugins/docs/components/markdown-documentation-plugin/GenerateTypesEnumsProps.tsx new file mode 100644 index 0000000..b0a5f24 --- /dev/null +++ b/packages/www/plugins/docs/components/markdown-documentation-plugin/GenerateTypesEnumsProps.tsx @@ -0,0 +1,32 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; + +export default function GenerateTypesEnumsProps() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Generate Types, Enums, and Props Section Content */} +
+

{_('7. Generate Types, Enums, and Props')}

+

+ + Similar to models, you can implement generation functions for + types, enums, and props. Each follows the same pattern of + creating markdown sections with tables and descriptions. + +

+

+ + Types define reusable data structures, enums define sets of + named constants, and props define reusable property + configurations for form fields and validation. + +

+
+ + ) +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/markdown-documentation-plugin/GeneratedOutput.tsx b/packages/www/plugins/docs/components/markdown-documentation-plugin/GeneratedOutput.tsx new file mode 100644 index 0000000..d50f2a5 --- /dev/null +++ b/packages/www/plugins/docs/components/markdown-documentation-plugin/GeneratedOutput.tsx @@ -0,0 +1,86 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const generatedOutputExample = + `# My Application Schema + +API Reference documentation for the schema definitions. + +## Overview + +This document provides comprehensive API documentation for all schema +elements including models, types, enums, and properties. + +Generated on: 2024-01-15T10:30:00.000Z + +## Table of Contents + +- [Models](#models) + - [User](#user) +- [Enums](#enums) + - [UserRole](#userrole) + +## Models + +Models represent the main data structures in your application. + +### User + +**Mutability:** Immutable + +#### Columns + +| Name | Type | Required | Multiple | Description | +|------|------|----------|----------|-------------| +| id | \`String\` | ✓ | ✗ | Unique identifier for the user | +| email | \`String\` | ✓ | ✗ | User email address for authentication | +| name | \`String\` | ✓ | ✗ | Full name of the user | +| role | [UserRole](#userrole) | ✓ | ✗ | User's role in the system | + +## Enums + +Enums define sets of named constants with associated values. + +### UserRole + +#### Values + +| Key | Value | Description | +|-----|-------|-----------| +| ADMIN | Administrator | - | +| USER | Regular User | - | +| GUEST | Guest User | - | + +--- + +*Documentation generated on 1/15/2024, 10:30:00 AM*`; + +//--------------------------------------------------------------------// + +export default function GeneratedOutput() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Generated Output Section Content */} +
+

{_('10. Generated Output')}

+

+ + The plugin will generate markdown documentation like this: + +

+ + {generatedOutputExample} + +
+ + ) +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/markdown-documentation-plugin/ImplementDocumentationGeneration.tsx b/packages/www/plugins/docs/components/markdown-documentation-plugin/ImplementDocumentationGeneration.tsx new file mode 100644 index 0000000..95bdb29 --- /dev/null +++ b/packages/www/plugins/docs/components/markdown-documentation-plugin/ImplementDocumentationGeneration.tsx @@ -0,0 +1,76 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const documentationGenerationExample = + `async function generateSingleFile(schema: any, options: any, transformer: any): Promise { + let content = generateHeader(options); + + // Generate table of contents + if (options.includeIndex) { + content += generateTableOfContents(schema, options); + } + + // Generate sections + for (const section of options.sections) { + switch (section) { + case 'models': + if (schema.model) { + content += generateModelsSection(schema.model, schema, options); + } + break; + case 'types': + if (schema.type) { + content += generateTypesSection(schema.type, schema, options); + } + break; + case 'enums': + if (schema.enum) { + content += generateEnumsSection(schema.enum, options); + } + break; + case 'props': + if (schema.prop) { + content += generatePropsSection(schema.prop, options); + } + break; + } + } + + // Add footer + content += generateFooter(options); + + // Write to file + const outputPath = await transformer.loader.absolute(options.output); + await fs.mkdir(path.dirname(outputPath), { recursive: true }); + await fs.writeFile(outputPath, content, 'utf8'); +}`; + +//--------------------------------------------------------------------// + +export default function ImplementDocumentationGeneration() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Implement Documentation Generation Section Content */} +
+

{_('5. Implement Documentation Generation')}

+

+ + Create functions to generate different sections of documentation: + +

+ + {documentationGenerationExample} + +
+ + ) +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/markdown-documentation-plugin/Introduction.tsx b/packages/www/plugins/docs/components/markdown-documentation-plugin/Introduction.tsx new file mode 100644 index 0000000..10fb7d7 --- /dev/null +++ b/packages/www/plugins/docs/components/markdown-documentation-plugin/Introduction.tsx @@ -0,0 +1,27 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C } from '../../../docs/components/index.js'; + +export default function Introduction() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Creating a Markdown Documentation Plugin */} +
+

{_('Creating a Markdown Documentation Plugin')}

+

+ + This tutorial will guide you through creating a plugin that + generates comprehensive markdown documentation from a processed + .idea schema. You'll learn how to parse schema models, + types, enums, and props to create structured documentation with + examples and cross-references. + +

+
+ + ) +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/markdown-documentation-plugin/Overview.tsx b/packages/www/plugins/docs/components/markdown-documentation-plugin/Overview.tsx new file mode 100644 index 0000000..6df5410 --- /dev/null +++ b/packages/www/plugins/docs/components/markdown-documentation-plugin/Overview.tsx @@ -0,0 +1,50 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; + +export default function Overview() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Overview Section Content */} +
+

{_('1. Overview')}

+

+ + The Markdown Documentation Plugin will: + +

+
    +
  • + + Parse schema models, types, enums, and props + +
  • +
  • + + Generate structured markdown documentation + +
  • +
  • + + Include examples and usage notes + +
  • +
  • + + Create navigation and cross-references + +
  • +
  • + + Support different documentation formats and styles + +
  • +
+
+ + ) +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/markdown-documentation-plugin/Prerequisites.tsx b/packages/www/plugins/docs/components/markdown-documentation-plugin/Prerequisites.tsx new file mode 100644 index 0000000..ba1f786 --- /dev/null +++ b/packages/www/plugins/docs/components/markdown-documentation-plugin/Prerequisites.tsx @@ -0,0 +1,35 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, C } from '../../../docs/components/index.js'; + +export default function Prerequisites() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Prerequisites Section Content */} +
+

{_('2. Prerequisites')}

+
    +
  • + + Basic understanding of TypeScript/JavaScript + +
  • +
  • + + Familiarity with Markdown syntax + +
  • +
  • + + Understanding of the idea-transformer plugin system + +
  • +
+
+ + ) +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/markdown-documentation-plugin/UnderstandingSchemaStructure.tsx b/packages/www/plugins/docs/components/markdown-documentation-plugin/UnderstandingSchemaStructure.tsx new file mode 100644 index 0000000..f4f823f --- /dev/null +++ b/packages/www/plugins/docs/components/markdown-documentation-plugin/UnderstandingSchemaStructure.tsx @@ -0,0 +1,99 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const exampleProcessedSchema = + `// Example processed schema +{ + model: { + User: { + mutable: false, + columns: [ + { + name: 'id', + type: 'String', + required: true, + multiple: false, + attributes: { + id: true, + label: 'User ID', + default: 'nanoid()', + description: 'Unique identifier for the user' + } + }, + { + name: 'email', + type: 'String', + required: true, + multiple: false, + attributes: { + unique: true, + label: 'Email Address', + field: { input: { type: 'email' } }, + description: 'User email address for authentication' + } + } + ] + } + }, + enum: { + UserRole: { + ADMIN: 'Administrator', + USER: 'Regular User', + GUEST: 'Guest User' + } + }, + type: { + Address: { + mutable: true, + columns: [ + { + name: 'street', + type: 'String', + required: true, + multiple: false, + attributes: { + label: 'Street Address' + } + } + ] + } + }, + prop: { + Text: { + type: 'text', + placeholder: 'Enter text', + maxLength: 255 + } + } +}`; + +//--------------------------------------------------------------------// + +export default function UnderstandingSchemaStructure() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Understanding the Schema Structure Section Content */} +
+

{_('3. Understanding the Schema Structure')}

+

+ + Before creating the plugin, let's understand what documentation + we can generate from a schema: + +

+ + {exampleProcessedSchema} + +
+ + ) +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/markdown-documentation-plugin/UsageInSchema.tsx b/packages/www/plugins/docs/components/markdown-documentation-plugin/UsageInSchema.tsx new file mode 100644 index 0000000..53b2a2b --- /dev/null +++ b/packages/www/plugins/docs/components/markdown-documentation-plugin/UsageInSchema.tsx @@ -0,0 +1,60 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const schemaUsageExample = + `// schema.idea +plugin "./plugins/markdown-docs-plugin.js" { + output "./docs/schema.md" + title "My Application Schema" + format "single" + includeIndex true + includeExamples true + includeAttributes true + sections ["models", "types", "enums", "props"] + template "api" +} + +model User! { + id String @id @default("nanoid()") @description("User ID") + email String @unique @field.input(Email) @description("Email") + name String @field.input(Text) @description("Full name") + role UserRole @default("USER") @description("User's role") + active Boolean @default(true) @description("Active status") + created Date @default("now()") @description("Creation date") +} + +enum UserRole { + ADMIN "Administrator" + USER "Regular User" + GUEST "Guest User" +}`; + +//--------------------------------------------------------------------// + +export default function UsageInSchema() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Usage in Schema Section Content */} +
+

{_('9. Usage in Schema')}

+

+ + To use this plugin in your schema file: + +

+ + {schemaUsageExample} + +
+ + ) +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/markdown-documentation-plugin/UtilityFunctions.tsx b/packages/www/plugins/docs/components/markdown-documentation-plugin/UtilityFunctions.tsx new file mode 100644 index 0000000..104256f --- /dev/null +++ b/packages/www/plugins/docs/components/markdown-documentation-plugin/UtilityFunctions.tsx @@ -0,0 +1,53 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const utilityFunctionsExample = + `function formatType(type: string, multiple: boolean = false): string { + let formattedType = type; + + // Add array notation if multiple + if (multiple) { + formattedType += '[]'; + } + + // Add markdown formatting for built-in types + const builtInTypes = ['String', 'Number', 'Boolean', 'Date', 'JSON']; + if (builtInTypes.includes(type)) { + formattedType = \`\\\`\${formattedType}\\\`\`; + } else { + // Link to other types/enums + formattedType = \`[\${formattedType}](#\${type.toLowerCase()})\`; + } + + return formattedType; +}`; + +//--------------------------------------------------------------------// + +export default function UtilityFunctions() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Utility Functions Section Content */} +
+

{_('8. Utility Functions')}

+

+ + Create helper functions for formatting and processing: + +

+ + {utilityFunctionsExample} + +
+ + ) +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/markdown-documentation-plugin/index.tsx b/packages/www/plugins/docs/components/markdown-documentation-plugin/index.tsx new file mode 100644 index 0000000..5cc0849 --- /dev/null +++ b/packages/www/plugins/docs/components/markdown-documentation-plugin/index.tsx @@ -0,0 +1,15 @@ +//exporting all components to have multiple imports from a single file +export { default as AdvancedFeatures } from './AdvancedFeatures.js'; +export { default as Conclusion } from './Conclusion.js'; +export { default as CreatePluginStructure } from './CreatePluginStructure.js'; +export { default as ErrorHandlingAndBestPractices } from './ErrorHandlingAndBestPractices.js'; +export { default as GeneratedOutput } from './GeneratedOutput.js'; +export { default as GenerateModelsDocumentation } from './GenerateModelsDocumentation.js'; +export { default as GenerateTypesEnumsProps } from './GenerateTypesEnumsProps.js'; +export { default as ImplementDocumentationGeneration } from './ImplementDocumentationGeneration.js'; +export { default as Introduction } from './Introduction.js'; +export { default as Overview } from './Overview.js'; +export { default as Prerequisites } from './Prerequisites.js'; +export { default as UnderstandingSchemaStructure } from './UnderstandingSchemaStructure.js'; +export { default as UsageInSchema } from './UsageInSchema.js'; +export { default as UtilityFunctions } from './UtilityFunctions.js'; \ No newline at end of file diff --git a/packages/www/plugins/docs/components/mysql-table-plugin/BestPractices.tsx b/packages/www/plugins/docs/components/mysql-table-plugin/BestPractices.tsx new file mode 100644 index 0000000..64f3205 --- /dev/null +++ b/packages/www/plugins/docs/components/mysql-table-plugin/BestPractices.tsx @@ -0,0 +1,93 @@ +//module +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const enhancedErrorHandling = + `export default async function mysqlTablesPlugin(props: PluginProps<{}>) { + const { config, schema, transformer, cwd } = props; + + try { + // Validate configuration + validateConfig(config); + + // Validate schema has models + if (!schema.model || Object.keys(schema.model).length === 0) { + console.warn('⚠️ No models found in schema. Skipping MySQL table generation.'); + return; + } + + // Generate SQL + const sqlContent = generateSQL(schema, config); + + // Ensure output directory exists + const outputPath = await transformer.loader.absolute(config.output); + await fs.mkdir(path.dirname(outputPath), { recursive: true }); + + // Write file + await fs.writeFile(outputPath, sqlContent, 'utf8'); + + console.log(\`✅ MySQL tables generated: \${outputPath}\`); + console.log(\`📊 Generated \${Object.keys(schema.model).length} table(s)\`); + + } catch (error) { + console.error(\`❌ MySQL Tables Plugin failed: \${error.message}\`); + throw error; + } +}`; + +//--------------------------------------------------------------------// + +const configValidation = + `function validateConfig(config: any): void { + if (!config.output) { + throw new Error('MySQL Tables Plugin requires "output" configuration'); + } + + if (config.engine && !['InnoDB', 'MyISAM', 'Memory'].includes(config.engine)) { + throw new Error(\`Unsupported MySQL engine: \${config.engine}\`); + } +}`; + +//--------------------------------------------------------------------// + +export default function BestPractices() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Best Practices Section Content */} +
+

{_('9. Error Handling and Best Practices')}

+

+ + Add proper error handling and validation to make your + plugin robust and user-friendly. + +

+ +

{_('9.1. Enhanced Error Handling')}

+ {enhancedErrorHandling} + + +

{_('9.2. Configuration Validation')}

+ + {configValidation} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/mysql-table-plugin/Conclusion.tsx b/packages/www/plugins/docs/components/mysql-table-plugin/Conclusion.tsx new file mode 100644 index 0000000..e35da8d --- /dev/null +++ b/packages/www/plugins/docs/components/mysql-table-plugin/Conclusion.tsx @@ -0,0 +1,57 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; + +export default function Conclusion() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Conclusion Section Content */} +
+

{_('10. Conclusion')}

+

+ + This MySQL Tables Plugin demonstrates how to: + +

+
    +
  • + + Parse schema models and columns + +
  • +
  • + + Map schema types to database-specific types + +
  • +
  • + + Generate SQL DDL statements + +
  • +
  • + + Handle constraints, indexes, and foreign keys + +
  • +
  • + + Provide proper error handling and validation + +
  • +
+

+ + The plugin is flexible and can be extended to support + additional MySQL features like partitioning, triggers, + or stored procedures. + +

+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/mysql-table-plugin/CreatePluginStructure.tsx b/packages/www/plugins/docs/components/mysql-table-plugin/CreatePluginStructure.tsx new file mode 100644 index 0000000..c60726e --- /dev/null +++ b/packages/www/plugins/docs/components/mysql-table-plugin/CreatePluginStructure.tsx @@ -0,0 +1,81 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const basicPluginStructure = + `import type { PluginProps } from '@stackpress/idea-transformer/types'; +import fs from 'fs/promises'; +import path from 'path'; + +interface MySQLPluginConfig { + output: string; + database?: string; + engine?: string; + charset?: string; + collation?: string; +} + +export default async function mysqlTablesPlugin( + props: PluginProps<{ config: MySQLPluginConfig }> +) { + const { config, schema, transformer, cwd } = props; + + // Validate configuration + if (!config.output) { + throw new Error('MySQL Tables Plugin requires "output" configuration'); + } + + // Set defaults + const options = { + database: config.database || 'app_database', + engine: config.engine || 'InnoDB', + charset: config.charset || 'utf8mb4', + collation: config.collation || 'utf8mb4_unicode_ci', + ...config + }; + + // Generate SQL content + const sqlContent = generateSQL(schema, options); + + // Write to output file + const outputPath = await transformer.loader.absolute(config.output); + await fs.mkdir(path.dirname(outputPath), { recursive: true }); + await fs.writeFile(outputPath, sqlContent, 'utf8'); + + console.log(\`✅ MySQL tables generated: \${outputPath}\`); +}`; + +//--------------------------------------------------------------------// + +export default function CreatePluginStructure() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Create the Plugin Structure Section Content */} +
+

{_('4. Create the Plugin Structure')}

+

+ + Create a new file mysql-tables-plugin.js. This will be + the main entry point for our plugin that handles configuration + validation and orchestrates the SQL generation process. + +

+

{_('Basic Plugin Structure')}

+ {basicPluginStructure} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/mysql-table-plugin/GenerateSqlStatements.tsx b/packages/www/plugins/docs/components/mysql-table-plugin/GenerateSqlStatements.tsx new file mode 100644 index 0000000..7a476f9 --- /dev/null +++ b/packages/www/plugins/docs/components/mysql-table-plugin/GenerateSqlStatements.tsx @@ -0,0 +1,219 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const mainSQLGeneration = + `function generateSQL(schema: any, options: any): string { + let sql = ''; + + // Add header comment + sql += \`-- Generated MySQL Tables\\n\`; + sql += \`-- Database: \${options.database}\\n\`; + sql += \`-- Generated at: \${new Date().toISOString()}\\n\\n\`; + + // Create database if specified + if (options.database) { + sql += \`CREATE DATABASE IF NOT EXISTS \\\`\${options.database}\\\`;\\n\`; + sql += \`USE \\\`\${options.database}\\\`;\\n\\n\`; + } + + // Generate tables for each model + if (schema.model) { + for (const [modelName, model] of Object.entries(schema.model)) { + sql += generateTableSQL(modelName, model, options); + sql += '\\n'; + } + } + + return sql; +}`; + +//--------------------------------------------------------------------// + +const tableSQLGeneration = + `function generateTableSQL(tableName: string, model: any, options: any): string { + const columns: string[] = []; + const indexes: string[] = []; + const foreignKeys: string[] = []; + let primaryKey = ''; + + // Process each column + for (const column of model.columns || []) { + const columnDef = generateColumnDefinition(column, options); + columns.push(columnDef.definition); + + // Handle constraints + if (columnDef.isPrimary) { + primaryKey = column.name; + } + if (columnDef.isUnique) { + indexes.push(\`UNIQUE KEY \\\`uk_\${tableName}_\${column.name}\\\` (\\\`\${column.name}\\\`)\`); + } + if (columnDef.isIndex) { + indexes.push(\`KEY \\\`idx_\${tableName}_\${column.name}\\\` (\\\`\${column.name}\\\`)\`); + } + if (columnDef.foreignKey) { + foreignKeys.push(columnDef.foreignKey); + } + } + + // Build CREATE TABLE statement + let sql = \`CREATE TABLE \\\`\${tableName}\\\` (\\n\`; + + // Add columns + sql += columns.map(col => \` \${col}\`).join(',\\n'); + + // Add primary key + if (primaryKey) { + sql += \`,\\n PRIMARY KEY (\\\`\${primaryKey}\\\`)\`; + } + + // Add indexes + if (indexes.length > 0) { + sql += ',\\n ' + indexes.join(',\\n '); + } + + // Add foreign keys + if (foreignKeys.length > 0) { + sql += ',\\n ' + foreignKeys.join(',\\n '); + } + + sql += \`\\n) ENGINE=\${options.engine} DEFAULT CHARSET=\${options.charset} COLLATE=\${options.collation};\\n\`; + + return sql; +}`; + +//--------------------------------------------------------------------// + +const columnDefinitionGeneration = + `function generateColumnDefinition(column: any, options: any): any { + const { name, required, attributes = {} } = column; + const mysqlType = mapSchemaTypeToMySQL(column); + + let definition = \`\\\`\${name}\\\` \${mysqlType}\`; + + // Handle NULL/NOT NULL + if (required || attributes.id) { + definition += ' NOT NULL'; + } else { + definition += ' NULL'; + } + + // Handle AUTO_INCREMENT + if (attributes.id && attributes.autoIncrement !== false) { + if (mysqlType.includes('INT')) { + definition += ' AUTO_INCREMENT'; + } + } + + // Handle DEFAULT values + if (attributes.default !== undefined) { + const defaultValue = attributes.default; + if (defaultValue === 'now()' || defaultValue === 'CURRENT_TIMESTAMP') { + definition += ' DEFAULT CURRENT_TIMESTAMP'; + } else if (defaultValue === 'updated()') { + definition += ' DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP'; + } else if (typeof defaultValue === 'string') { + definition += \` DEFAULT '\${defaultValue}'\`; + } else { + definition += \` DEFAULT \${defaultValue}\`; + } + } + + // Handle COMMENT + if (attributes.label) { + const comment = Array.isArray(attributes.label) + ? attributes.label[0] + : attributes.label; + definition += \` COMMENT '\${comment.replace(/'/g, "''")}'\`; + } + + return { + definition, + isPrimary: !!attributes.id, + isUnique: !!attributes.unique, + isIndex: !!attributes.index || !!attributes.searchable || !!attributes.filterable, + foreignKey: generateForeignKey(column, options) + }; +}`; + +//--------------------------------------------------------------------// + +const foreignKeyGeneration = + `function generateForeignKey(column: any, options: any): string | null { + const { name, type, attributes = {} } = column; + + // Check if this column references another model + if (schema.model && schema.model[type]) { + const referencedTable = type; + const referencedColumn = 'id'; // Assuming 'id' is the primary key + + return \`CONSTRAINT \\\`fk_\${name}\\\` FOREIGN KEY (\\\`\${name}\\\`) REFERENCES \\\`\${referencedTable}\\\` (\\\`\${referencedColumn}\\\`) ON DELETE \${attributes.onDelete || 'CASCADE'} ON UPDATE \${attributes.onUpdate || 'CASCADE'}\`; + } + + return null; +}`; + +//--------------------------------------------------------------------// + +export default function GenerateSqlStatements() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Generate SQL Statements Section Content */} +
+

{_('6. Generate SQL Statements')}

+

+ + Implement the main SQL generation function. This section + contains the core logic for creating MySQL CREATE TABLE + statements from the processed schema. + +

+ +

{_('6.1. Main SQL Generation')}

+ + {mainSQLGeneration} + + +

{_('6.2. Table SQL Generation')}

+ + {tableSQLGeneration} + + +

{_('6.3. Column Definition Generation')}

+ + {columnDefinitionGeneration} + + +

{_('6.4. Foreign Key Generation')}

+ + {foreignKeyGeneration} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/mysql-table-plugin/GeneratedOutput.tsx b/packages/www/plugins/docs/components/mysql-table-plugin/GeneratedOutput.tsx new file mode 100644 index 0000000..4db034c --- /dev/null +++ b/packages/www/plugins/docs/components/mysql-table-plugin/GeneratedOutput.tsx @@ -0,0 +1,61 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const generatedOutputExample = + `-- Generated MySQL Tables +-- Database: my_app +-- Generated at: 2024-01-15T10:30:00.000Z + +CREATE DATABASE IF NOT EXISTS \`my_app\`; +USE \`my_app\`; + +CREATE TABLE \`User\` ( + \`id\` VARCHAR(255) NOT NULL COMMENT 'ID', + \`email\` VARCHAR(255) NOT NULL COMMENT 'Email', + \`name\` VARCHAR(255) NOT NULL COMMENT 'Name', + \`age\` TINYINT UNSIGNED NULL COMMENT 'Age', + \`role\` ENUM('admin', 'user') NOT NULL DEFAULT 'user' COMMENT 'Role', + \`active\` BOOLEAN NOT NULL DEFAULT true COMMENT 'Active', + \`created\` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 'Created', + \`updated\` DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'Updated', + PRIMARY KEY (\`id\`), + UNIQUE KEY \`uk_User_email\` (\`email\`), + KEY \`idx_User_age\` (\`age\`) +) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;`; + +//--------------------------------------------------------------------// + +export default function GeneratedOutput() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Generated Output Section Content */} +
+

{_('8. Generated Output')}

+

+ + The plugin will generate SQL like this. The output includes + proper MySQL syntax with constraints, indexes, and foreign + keys. + +

+

{_('Example Generated SQL')}

+ + {generatedOutputExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/mysql-table-plugin/ImplementTypeMapping.tsx b/packages/www/plugins/docs/components/mysql-table-plugin/ImplementTypeMapping.tsx new file mode 100644 index 0000000..c265e5c --- /dev/null +++ b/packages/www/plugins/docs/components/mysql-table-plugin/ImplementTypeMapping.tsx @@ -0,0 +1,113 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const typeMappingFunction = + `function mapSchemaTypeToMySQL(column: any): string { + const { type, attributes = {} } = column; + + switch (type) { + case 'String': + // Check for specific string constraints + if (attributes.id) { + return 'VARCHAR(255)'; // Primary key strings + } + if (attributes.email || attributes.url) { + return 'VARCHAR(255)'; + } + if (attributes.text || attributes.textarea) { + return 'TEXT'; + } + if (attributes.maxLength) { + return \`VARCHAR(\${attributes.maxLength})\`; + } + return 'VARCHAR(255)'; // Default string length + + case 'Number': + if (attributes.unsigned) { + if (attributes.max && attributes.max <= 255) { + return 'TINYINT UNSIGNED'; + } + if (attributes.max && attributes.max <= 65535) { + return 'SMALLINT UNSIGNED'; + } + if (attributes.max && attributes.max <= 16777215) { + return 'MEDIUMINT UNSIGNED'; + } + return 'INT UNSIGNED'; + } + if (attributes.float || attributes.decimal) { + const precision = attributes.precision || 10; + const scale = attributes.scale || 2; + return \`DECIMAL(\${precision},\${scale})\`; + } + return 'INT'; + + case 'Boolean': + return 'BOOLEAN'; + + case 'Date': + if (attributes.time) { + return 'DATETIME'; + } + if (attributes.timestamp) { + return 'TIMESTAMP'; + } + return 'DATE'; + + case 'JSON': + return 'JSON'; + + default: + // Check if it's an enum type + if (schema.enum && schema.enum[type]) { + const enumValues = Object.values(schema.enum[type]) + .map(value => \`'\${value}'\`) + .join(', '); + return \`ENUM(\${enumValues})\`; + } + + // Check if it's a foreign key (another model) + if (schema.model && schema.model[type]) { + return 'VARCHAR(255)'; // Assuming string-based foreign keys + } + + return 'VARCHAR(255)'; // Default fallback + } +}`; + +//--------------------------------------------------------------------// + +export default function ImplementTypeMapping() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Implement Type Mapping */} +
+

{_('5. Implement Type Mapping')}

+

+ + Create a function to map schema types to MySQL types. This + function handles the conversion between idea schema types and + their corresponding MySQL data types. + +

+

{_('Type Mapping Function')}

+ + {typeMappingFunction} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/mysql-table-plugin/Introduction.tsx b/packages/www/plugins/docs/components/mysql-table-plugin/Introduction.tsx new file mode 100644 index 0000000..c8baca9 --- /dev/null +++ b/packages/www/plugins/docs/components/mysql-table-plugin/Introduction.tsx @@ -0,0 +1,25 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; + +export default function Introduction() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Creating a MySQL Tables Plugin */} +
+

{_('Creating a MySQL Tables Plugin')}

+

+ + This tutorial will guide you through creating a plugin + that generates MySQL CREATE TABLE statements from a + processed .idea schema. + +

+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/mysql-table-plugin/Overview.tsx b/packages/www/plugins/docs/components/mysql-table-plugin/Overview.tsx new file mode 100644 index 0000000..509a428 --- /dev/null +++ b/packages/www/plugins/docs/components/mysql-table-plugin/Overview.tsx @@ -0,0 +1,52 @@ + +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; + +export default function Overview() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Overview Section Content */} +
+

{_('1. Overview')}

+

+ + The MySQL Tables Plugin will: + +

+
    +
  • + + Parse schema models and their columns + +
  • +
  • + + Map schema types to MySQL data types + +
  • +
  • + + Generate SQL CREATE TABLE statements + +
  • +
  • + + Handle primary keys, foreign keys, and indexes + +
  • +
  • + + Output SQL files that can be executed to create + database tables + +
  • +
+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/mysql-table-plugin/Prerequisites.tsx b/packages/www/plugins/docs/components/mysql-table-plugin/Prerequisites.tsx new file mode 100644 index 0000000..d307e72 --- /dev/null +++ b/packages/www/plugins/docs/components/mysql-table-plugin/Prerequisites.tsx @@ -0,0 +1,41 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; + +export default function Prerequisites() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Prerequisites Section Content */} +
+

{_('2. Prerequisites')}

+

+ + Before creating this plugin, you should have the following + knowledge and tools: + +

+
    +
  • + + Basic understanding of TypeScript/JavaScript + +
  • +
  • + + Familiarity with MySQL and SQL syntax + +
  • +
  • + + Understanding of the idea-transformer plugin system + +
  • +
+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/mysql-table-plugin/UnderstandingSchemaStructure.tsx b/packages/www/plugins/docs/components/mysql-table-plugin/UnderstandingSchemaStructure.tsx new file mode 100644 index 0000000..c493c96 --- /dev/null +++ b/packages/www/plugins/docs/components/mysql-table-plugin/UnderstandingSchemaStructure.tsx @@ -0,0 +1,88 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const schemaStructureExample = + `// Example processed schema +{ + model: { + User: { + mutable: false, + columns: [ + { + name: 'id', + type: 'String', + required: true, + multiple: false, + attributes: { + id: true, + default: 'nanoid()' + } + }, + { + name: 'email', + type: 'String', + required: true, + multiple: false, + attributes: { + unique: true, + field: { input: { type: 'email' } } + } + }, + { + name: 'age', + type: 'Number', + required: false, + multiple: false, + attributes: { + unsigned: true, + min: 0, + max: 150 + } + } + ] + } + }, + enum: { + UserRole: { + ADMIN: 'admin', + USER: 'user' + } + } +}`; + +//--------------------------------------------------------------------// + +export default function UnderstandingSchemaStructure() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Understanding Schema Structure Section Content */} +
+

{_('3. Understanding the Schema Structure')}

+

+ + Before creating the plugin, let's understand what a processed + schema looks like. The schema structure contains models, enums, + and other configuration data that our plugin will process. + +

+

{_('Example Schema Structure')}

+ + {schemaStructureExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/mysql-table-plugin/UsageInSchema.tsx b/packages/www/plugins/docs/components/mysql-table-plugin/UsageInSchema.tsx new file mode 100644 index 0000000..192b531 --- /dev/null +++ b/packages/www/plugins/docs/components/mysql-table-plugin/UsageInSchema.tsx @@ -0,0 +1,64 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const schemaUsageExample = + `// schema.idea +plugin "./plugins/mysql-tables-plugin.js" { + output "./database/tables.sql" + database "my_app" + engine "InnoDB" + charset "utf8mb4" + collation "utf8mb4_unicode_ci" +} + +model User { + id String @id @default("nanoid()") + email String @unique @field.input(Email) + name String @field.input(Text) + age Number @unsigned @min(0) @max(150) + role UserRole @default("USER") + active Boolean @default(true) + created Date @default("now()") + updated Date @default("updated()") +} + +enum UserRole { + ADMIN "admin" + USER "user" +}`; + +//--------------------------------------------------------------------// + +export default function UsageInSchema() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Usage In Schema Section Content */} +
+

{_('7. Usage in Schema')}

+

+ + To use this plugin in your schema file, add the plugin + declaration with appropriate configuration options. + +

+

{_('Schema Configuration')}

+ + {schemaUsageExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/mysql-table-plugin/index.tsx b/packages/www/plugins/docs/components/mysql-table-plugin/index.tsx new file mode 100644 index 0000000..7ae20ca --- /dev/null +++ b/packages/www/plugins/docs/components/mysql-table-plugin/index.tsx @@ -0,0 +1,12 @@ +//exporting all components to have multiple imports from a single file +export { default as BestPractices } from './BestPractices.js'; +export { default as Conclusion } from './Conclusion.js'; +export { default as CreatePluginStructure } from './CreatePluginStructure.js'; +export { default as GeneratedOutput } from './GeneratedOutput.js'; +export { default as GenerateSqlStatements } from './GenerateSqlStatements.js'; +export { default as ImplementTypeMapping } from './ImplementTypeMapping.js'; +export { default as Introduction } from './Introduction.js'; +export { default as Overview } from './Overview.js'; +export { default as Prerequisites } from './Prerequisites.js'; +export { default as UnderstandingSchemaStructure } from './UnderstandingSchemaStructure.js'; +export { default as UsageInSchema } from './UsageInSchema.js'; \ No newline at end of file diff --git a/packages/www/plugins/docs/components/openapi-specification-plugin/AdvancedFeatures.tsx b/packages/www/plugins/docs/components/openapi-specification-plugin/AdvancedFeatures.tsx new file mode 100644 index 0000000..238ec9b --- /dev/null +++ b/packages/www/plugins/docs/components/openapi-specification-plugin/AdvancedFeatures.tsx @@ -0,0 +1,305 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const advancedConfigExample = + `interface AdvancedOpenAPIConfig extends OpenAPIConfig { + formats?: ('json' | 'yaml' | 'html')[]; + validation?: { + strict?: boolean; + examples?: boolean; + }; + documentation?: { + includeExamples?: boolean; + includeSchemas?: boolean; + customTemplates?: string; + }; +} + +export default async function generateAdvancedOpenAPISpec( + props: PluginProps<{ config: AdvancedOpenAPIConfig }> +) { + const { config, schema, transformer } = props; + + const spec = generateSpecification(schema, config); + + // Add validation and examples + if (config.validation?.examples) { + addExamples(spec, schema); + } + + if (config.validation?.strict) { + validateSpecification(spec); + } + + // Generate multiple formats + const formats = config.formats || ['json']; + const outputBase = config.output.replace(/\\.[^.]+$/, ''); + + for (const format of formats) { + await generateFormat(spec, format, outputBase, transformer); + } +}`; + +//--------------------------------------------------------------------// + +const formatGenerationExample = + `async function generateFormat( + spec: any, + format: string, + outputBase: string, + transformer: any +): Promise { + let content: string; + let extension: string; + + switch (format) { + case 'json': + content = JSON.stringify(spec, null, 2); + extension = '.json'; + break; + case 'yaml': + const yaml = await import('yaml'); + content = yaml.stringify(spec); + extension = '.yaml'; + break; + case 'html': + content = generateHTMLDocumentation(spec); + extension = '.html'; + break; + default: + throw new Error(\`Unsupported format: \${format}\`); + } + + const outputPath = await transformer.loader.absolute(\`\${outputBase}\${extension}\`); + await fs.writeFile(outputPath, content, 'utf8'); + console.log(\`✅ Generated \${format.toUpperCase()} specification: \${outputPath}\`); +}`; + +//--------------------------------------------------------------------// + +const exampleGenerationExample = + `function addExamples(spec: any, schema: any): void { + // Add examples to schemas + for (const [name, schemaObj] of Object.entries(spec.components.schemas)) { + if (schemaObj.type === 'object') { + schemaObj.example = generateExample(schemaObj, schema); + } + } + + // Add examples to endpoints + for (const [path, pathObj] of Object.entries(spec.paths)) { + for (const [method, operation] of Object.entries(pathObj)) { + if (operation.requestBody?.content?.['application/json']?.schema) { + const schema = operation.requestBody.content['application/json'].schema; + if (!schema.example) { + schema.example = generateExample(schema, schema); + } + } + } + } +} + +function generateExample(schemaObj: any, fullSchema: any): any { + if (schemaObj.$ref) { + const refName = schemaObj.$ref.split('/').pop(); + return generateExample(fullSchema.components?.schemas?.[refName] || {}, fullSchema); + } + + if (schemaObj.type === 'object') { + const example: any = {}; + for (const [propName, propSchema] of Object.entries(schemaObj.properties || {})) { + example[propName] = generatePropertyExample(propSchema); + } + return example; + } + + if (schemaObj.type === 'array') { + return [generateExample(schemaObj.items, fullSchema)]; + } + + return generatePropertyExample(schemaObj); +} + +function generatePropertyExample(propSchema: any): any { + if (propSchema.example !== undefined) { + return propSchema.example; + } + + if (propSchema.enum) { + return propSchema.enum[0]; + } + + switch (propSchema.type) { + case 'string': + if (propSchema.format === 'email') return 'user@example.com'; + if (propSchema.format === 'date-time') return new Date().toISOString(); + if (propSchema.format === 'date') return new Date().toISOString().split('T')[0]; + return 'string'; + case 'number': + return 42.5; + case 'integer': + return 42; + case 'boolean': + return true; + case 'array': + return [generatePropertyExample(propSchema.items)]; + case 'object': + return {}; + default: + return null; + } +}`; + +//--------------------------------------------------------------------// + +const validationExample = + `function validateSpecification(spec: any): void { + // Basic validation + if (!spec.openapi) { + throw new Error('OpenAPI version is required'); + } + + if (!spec.info?.title) { + throw new Error('API title is required'); + } + + if (!spec.info?.version) { + throw new Error('API version is required'); + } + + // Validate paths + for (const [path, pathObj] of Object.entries(spec.paths)) { + if (!path.startsWith('/')) { + throw new Error(\`Path must start with '/': \${path}\`); + } + + for (const [method, operation] of Object.entries(pathObj)) { + if (!operation.responses) { + throw new Error(\`Operation \${method.toUpperCase()} \${path} must have responses\`); + } + } + } + + console.log('✅ OpenAPI specification validation passed'); +}`; + +//--------------------------------------------------------------------// + +const htmlGenerationExample = + `function generateHTMLDocumentation(spec: any): string { + return \` + + + + + + \${spec.info.title} - API Documentation + + + + +
+ + + + +\`; +}`; + +//--------------------------------------------------------------------// + +export default function AdvancedFeatures() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Advanced Features Section Content */} +
+

{_('5. Advanced Features')}

+ +

{_('5.1. Multiple Output Formats')}

+

+ + Multiple output formats allow you to generate OpenAPI + specifications in JSON, YAML, and HTML formats. This + flexibility ensures compatibility with different tools + and enables both machine-readable specifications and + human-friendly documentation. + +

+ + {advancedConfigExample} + + + {formatGenerationExample} + + + {exampleGenerationExample} + + + {validationExample} + + + {htmlGenerationExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/openapi-specification-plugin/BasicImplementation.tsx b/packages/www/plugins/docs/components/openapi-specification-plugin/BasicImplementation.tsx new file mode 100644 index 0000000..bfbf049 --- /dev/null +++ b/packages/www/plugins/docs/components/openapi-specification-plugin/BasicImplementation.tsx @@ -0,0 +1,332 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, C } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const basicPluginExample = + `// plugins/openapi-spec.ts +import type { PluginProps } from '@stackpress/idea-transformer/types'; +import fs from 'fs/promises'; +import path from 'path'; + +interface OpenAPIConfig { + output: string; + info?: { + title?: string; + version?: string; + description?: string; + contact?: { + name?: string; + email?: string; + url?: string; + }; + license?: { + name?: string; + url?: string; + }; + }; + servers?: Array<{ + url: string; + description?: string; + }>; + security?: { + apiKey?: boolean; + bearer?: boolean; + oauth2?: boolean; + }; + endpoints?: { + crud?: boolean; + custom?: Record; + }; +} + +export default async function generateOpenAPISpec( + props: PluginProps<{ config: OpenAPIConfig }> +) { + const { config, schema, transformer } = props; + + // Validate configuration + if (!config.output) { + throw new Error('OpenAPI plugin requires "output" configuration'); + } + + // Generate OpenAPI specification + const spec = generateSpecification(schema, config); + + // Write to output file + const outputPath = await transformer.loader.absolute(config.output); + await fs.mkdir(path.dirname(outputPath), { recursive: true }); + await fs.writeFile(outputPath, JSON.stringify(spec, null, 2), 'utf8'); + + console.log(\`✅ Generated OpenAPI specification: \${outputPath}\`); +}`; + +//--------------------------------------------------------------------// + +const schemaGenerationExample = +`function generateSpecification(schema: any, config: OpenAPIConfig) { + const spec: any = { + openapi: '3.0.3', + info: { + title: config.info?.title || 'API Documentation', + version: config.info?.version || '1.0.0', + description: config.info?.description || 'Generated API documentation', + ...config.info?.contact && { contact: config.info.contact }, + ...config.info?.license && { license: config.info.license } + }, + servers: config.servers || [ + { url: 'http://localhost:3000', description: 'Development server' } + ], + paths: {}, + components: { + schemas: {}, + securitySchemes: {} + } + }; + + // Generate schemas from models and types + if (schema.model) { + for (const [name, model] of Object.entries(schema.model)) { + spec.components.schemas[name] = generateModelSchema(model); + } + } + + if (schema.type) { + for (const [name, type] of Object.entries(schema.type)) { + spec.components.schemas[name] = generateTypeSchema(type); + } + } + + if (schema.enum) { + for (const [name, enumDef] of Object.entries(schema.enum)) { + spec.components.schemas[name] = generateEnumSchema(enumDef); + } + } + + // Generate security schemes + if (config.security) { + generateSecuritySchemes(spec, config.security); + } + + // Generate CRUD endpoints + if (config.endpoints?.crud && schema.model) { + for (const [name, model] of Object.entries(schema.model)) { + generateCRUDEndpoints(spec, name, model); + } + } + + // Add custom endpoints + if (config.endpoints?.custom) { + for (const [path, operation] of Object.entries(config.endpoints.custom)) { + spec.paths[path] = operation; + } + } + + return spec; +}`; + +//--------------------------------------------------------------------// + +const modelSchemaExample = +`function generateModelSchema(model: any): any { + const schema: any = { + type: 'object', + properties: {}, + required: [] + }; + + if (model.columns) { + for (const column of model.columns) { + const property = generatePropertySchema(column); + schema.properties[column.name] = property; + + if (column.required) { + schema.required.push(column.name); + } + } + } + + return schema; +} + +function generateTypeSchema(type: any): any { + const schema: any = { + type: 'object', + properties: {}, + required: [] + }; + + if (type.columns) { + for (const column of type.columns) { + const property = generatePropertySchema(column); + schema.properties[column.name] = property; + + if (column.required) { + schema.required.push(column.name); + } + } + } + + return schema; +} + +function generateEnumSchema(enumDef: any): any { + const values = Object.values(enumDef); + return { + type: 'string', + enum: values, + example: values[0] + }; +}`; + +//--------------------------------------------------------------------// + +const propertySchemaExample = +`function generatePropertySchema(column: any): any { + const property: any = {}; + + // Map idea types to OpenAPI types + switch (column.type) { + case 'String': + property.type = 'string'; + break; + case 'Number': + property.type = 'number'; + break; + case 'Integer': + property.type = 'integer'; + break; + case 'Boolean': + property.type = 'boolean'; + break; + case 'Date': + property.type = 'string'; + property.format = 'date-time'; + break; + case 'JSON': + property.type = 'object'; + break; + default: + // Reference to another schema + property.$ref = \`#/components/schemas/\${column.type}\`; + } + + // Handle arrays + if (column.multiple) { + property = { + type: 'array', + items: property + }; + } + + // Add validation from attributes + if (column.attributes) { + addValidationRules(property, column.attributes); + } + + return property; +} + +function addValidationRules(property: any, attributes: any): void { + // String validations + if (attributes.minLength) { + property.minLength = attributes.minLength; + } + if (attributes.maxLength) { + property.maxLength = attributes.maxLength; + } + if (attributes.pattern) { + property.pattern = attributes.pattern; + } + + // Number validations + if (attributes.minimum) { + property.minimum = attributes.minimum; + } + if (attributes.maximum) { + property.maximum = attributes.maximum; + } + + // Examples and descriptions + if (attributes.example) { + property.example = attributes.example; + } + if (attributes.description) { + property.description = attributes.description; + } + + // Format validations + if (attributes.format) { + property.format = attributes.format; + } +}`; + +//--------------------------------------------------------------------// + +export default function BasicImplementation() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Basic Implementation Section Content */} +
+

{_('2. Basic Implementation')}

+

+ + The basic implementation provides the foundation for + generating OpenAPI specifications from .idea + schema files. This section covers the core plugin + structure, configuration interface, and essential + generation functions needed to create functional API + documentation. + +

+

+ + Let's start with a basic OpenAPI specification generator: + +

+ +

{_('2.1. Plugin Structure')}

+

+ + The plugin structure defines the main entry point and + configuration interface for the OpenAPI generator. This + includes type definitions for configuration options, the + primary plugin function, and the core specification + generation logic. + +

+ + {basicPluginExample} + + + {schemaGenerationExample} + + +

{_('2.2. Schema Generation')}

+

+ + Schema generation transforms + .idea + model and type definitions into OpenAPI-compliant schema + objects. This process includes mapping data types, handling + validation rules, and creating proper JSON Schema structures + that integrate with OpenAPI tooling. + +

+ + {modelSchemaExample} + + + {propertySchemaExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/openapi-specification-plugin/BestPractices.tsx b/packages/www/plugins/docs/components/openapi-specification-plugin/BestPractices.tsx new file mode 100644 index 0000000..9710dec --- /dev/null +++ b/packages/www/plugins/docs/components/openapi-specification-plugin/BestPractices.tsx @@ -0,0 +1,303 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const documentationBestPracticesExample = + `// Always include detailed descriptions +function generateModelSchema(model: any): any { + const schema: any = { + type: 'object', + description: model.description || \`\${model.name} entity\`, + properties: {}, + required: [] + }; + + // Add property descriptions + if (model.columns) { + for (const column of model.columns) { + const property = generatePropertySchema(column); + + // Add description from attributes or generate one + if (column.attributes?.description) { + property.description = column.attributes.description; + } else { + property.description = generatePropertyDescription(column); + } + + schema.properties[column.name] = property; + } + } + + return schema; +} + +function generatePropertyDescription(column: any): string { + const descriptions: Record = { + id: 'Unique identifier', + email: 'Email address', + name: 'Full name', + created: 'Creation timestamp', + updated: 'Last update timestamp', + active: 'Active status flag' + }; + + return descriptions[column.name] || \`\${column.name} field\`; +}`; + +//--------------------------------------------------------------------// + +const errorResponsesExample = `function generateErrorResponses(): any { + return { + '400': { + description: 'Bad Request', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + error: { type: 'string', description: 'Error message' }, + code: { type: 'string', description: 'Error code' }, + errors: { + type: 'object', + additionalProperties: { type: 'string' }, + description: 'Field-specific errors' + } + }, + required: ['error'] + } + } + } + }, + '401': { + description: 'Unauthorized', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + error: { type: 'string', example: 'Authentication required' } + } + } + } + } + }, + '403': { + description: 'Forbidden', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + error: { type: 'string', example: 'Insufficient permissions' } + } + } + } + } + }, + '404': { + description: 'Not Found', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + error: { type: 'string', example: 'Resource not found' } + } + } + } + } + }, + '500': { + description: 'Internal Server Error', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + error: { type: 'string', example: 'Internal server error' } + } + } + } + } + } + }; +}`; + +//--------------------------------------------------------------------// + +const securityBestPracticesExample = `function addSecurityToEndpoints(spec: any): void { + // Add security requirements to all endpoints + for (const [path, pathObj] of Object.entries(spec.paths)) { + for (const [method, operation] of Object.entries(pathObj)) { + // Skip public endpoints + if (isPublicEndpoint(path, method)) { + continue; + } + + // Add appropriate security scheme + if (!operation.security) { + operation.security = [{ BearerAuth: [] }]; + } + } + } +} + +function isPublicEndpoint(path: string, method: string): boolean { + const publicEndpoints = [ + { path: '/auth/login', method: 'post' }, + { path: '/auth/register', method: 'post' }, + { path: '/health', method: 'get' } + ]; + + return publicEndpoints.some(endpoint => + endpoint.path === path && endpoint.method === method.toLowerCase() + ); +}`; + +//--------------------------------------------------------------------// + +const validationExamplesExample = `function addValidationExamples(spec: any): void { + // Add validation examples to request bodies + for (const [path, pathObj] of Object.entries(spec.paths)) { + for (const [method, operation] of Object.entries(pathObj)) { + if (operation.requestBody?.content?.['application/json']?.schema) { + const schema = operation.requestBody.content['application/json'].schema; + + // Add valid example + if (!schema.example) { + schema.example = generateValidExample(schema); + } + + // Add examples for validation errors + if (!schema.examples) { + schema.examples = { + valid: { + summary: 'Valid request', + value: generateValidExample(schema) + }, + invalid: { + summary: 'Invalid request (validation errors)', + value: generateInvalidExample(schema) + } + }; + } + } + } + } +} + +function generateValidExample(schema: any): any { + // Generate a valid example based on schema + if (schema.$ref) { + return { id: '123', name: 'Example' }; + } + + const example: any = {}; + for (const [propName, propSchema] of Object.entries(schema.properties || {})) { + example[propName] = generatePropertyExample(propSchema); + } + + return example; +} + +function generateInvalidExample(schema: any): any { + // Generate an invalid example to show validation errors + const example: any = {}; + for (const [propName, propSchema] of Object.entries(schema.properties || {})) { + // Intentionally create invalid values + if (propSchema.type === 'string' && propSchema.format === 'email') { + example[propName] = 'invalid-email'; + } else if (propSchema.type === 'string' && propSchema.minLength) { + example[propName] = 'x'; // Too short + } else if (propSchema.type === 'number' && propSchema.minimum) { + example[propName] = propSchema.minimum - 1; // Below minimum + } else { + example[propName] = null; // Invalid type + } + } + + return example; +}` + +//--------------------------------------------------------------------// + +export default function BestPractices() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Best Practices Section Content */} +
+

{_('7. Best Practices')}

+

+ + Best practices ensure your generated OpenAPI specifications + are comprehensive, maintainable, and follow industry + standards. These guidelines cover documentation quality, + error handling, security implementation, and validation + strategies. + +

+ +

{_('7.1. Comprehensive Documentation')}

+

+ + Comprehensive documentation practices ensure your API + specifications provide clear, detailed information for both + human readers and automated tools. This includes proper + descriptions, examples, and consistent formatting throughout + the specification. + +

+ + {documentationBestPracticesExample} + + +

{_('7.2. Consistent Error Responses')}

+

+ + Consistent error responses provide standardized error + handling across your API endpoints. This approach ensures + predictable error formats that client applications can + handle reliably, improving the overall developer experience. + +

+ + {errorResponsesExample} + + +

{_('7.3. Security Best Practices')}

+

+ + Security best practices ensure your API documentation + properly represents authentication and authorization + requirements. This includes applying appropriate security + schemes to endpoints and documenting access control patterns. + +

+ + {securityBestPracticesExample} + + +

{_('7.4. Validation and Testing')}

+

+ + Validation and testing practices ensure your generated + OpenAPI specifications are accurate and functional. This + includes adding validation examples, testing request/response + formats, and verifying specification compliance. + +

+ + {validationExamplesExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/openapi-specification-plugin/Conclusion.tsx b/packages/www/plugins/docs/components/openapi-specification-plugin/Conclusion.tsx new file mode 100644 index 0000000..9b83a13 --- /dev/null +++ b/packages/www/plugins/docs/components/openapi-specification-plugin/Conclusion.tsx @@ -0,0 +1,114 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, C, SS } from '../../../docs/components/index.js'; + +export default function Conclusion() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Conclusion Section Content */} +
+

{_('Conclusion')}

+

+ + This OpenAPI Specification Generator plugin provides a + comprehensive solution for generating API documentation from + .idea schema files. Key features include: + +

+
    +
  • + Complete OpenAPI 3.0 Support: + + Generates fully compliant specifications + +
  • +
  • + Automatic CRUD Endpoints: + + Creates standard REST endpoints for models + +
  • +
  • + Security Integration: + + Supports multiple authentication schemes + +
  • +
  • + Multiple Output Formats: + + JSON, YAML, and HTML documentation + +
  • +
  • + Validation and Examples: + + Includes request/response examples and validation + +
  • +
  • + Extensible Configuration: + + Highly customizable for different use cases + +
  • +
+ +

+ + The plugin follows TypeScript best practices and provides + comprehensive error handling, making it suitable for + production use in API development workflows. + +

+ +

{_('Next Steps')}

+
    +
  • + Extend Schema Mapping: + + Add support for more complex schema relationships + +
  • +
  • + Custom Templates: + + Implement custom documentation templates + +
  • +
  • + Integration Testing: + + Add automated testing for generated specifications + +
  • +
  • + Performance Optimization: + + Implement caching and incremental generation + +
  • +
  • + Plugin Ecosystem: + + Create complementary plugins for API testing and + client generation + +
  • +
+ +

+ + This tutorial provides a solid foundation for generating + professional API documentation that can be used with tools + like Swagger UI, Postman, and various code generators. + +

+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/openapi-specification-plugin/ConfigurationOptions.tsx b/packages/www/plugins/docs/components/openapi-specification-plugin/ConfigurationOptions.tsx new file mode 100644 index 0000000..75c7ef5 --- /dev/null +++ b/packages/www/plugins/docs/components/openapi-specification-plugin/ConfigurationOptions.tsx @@ -0,0 +1,129 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const configurationExample = + `// schema.idea +plugin "./plugins/openapi-spec.js" { + output "./docs/api-spec.json" + info { + title "User Management API" + version "2.0.0" + description "Comprehensive user management system API" + contact { + name "API Support" + email "support@example.com" + url "https://example.com/support" + } + license { + name "MIT" + url "https://opensource.org/licenses/MIT" + } + } + servers [ + { + url "https://api.example.com/v2" + description "Production server" + } + { + url "https://staging-api.example.com/v2" + description "Staging server" + } + { + url "http://localhost:3000" + description "Development server" + } + ] + security { + apiKey true + bearer true + oauth2 false + } + endpoints { + crud true + custom { + "/auth/login" { + post { + summary "User login" + requestBody { + required true + content { + "application/json" { + schema { + type "object" + properties { + email { + type "string" + format "email" + } + password { + type "string" + minLength 8 + } + } + required ["email" "password"] + } + } + } + } + responses { + "200" { + description "Login successful" + content { + "application/json" { + schema { + type "object" + properties { + token { + type "string" + } + user { + "$ref" "#/components/schemas/User" + } + } + } + } + } + } + "401" { + description "Invalid credentials" + } + } + } + } + } + } +}`; + +//--------------------------------------------------------------------// + +export default function ConfigurationOptions() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Configuration Options Section Content */} +
+

{_('3. Configuration Options')}

+

+ + Configuration options control how the OpenAPI specification + is generated, including output formats, API metadata, server + definitions, and security schemes. Proper configuration + ensures the generated documentation meets your specific + requirements and integrates with your development workflow. + +

+ + {configurationExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/openapi-specification-plugin/Introduction.tsx b/packages/www/plugins/docs/components/openapi-specification-plugin/Introduction.tsx new file mode 100644 index 0000000..cb8b353 --- /dev/null +++ b/packages/www/plugins/docs/components/openapi-specification-plugin/Introduction.tsx @@ -0,0 +1,27 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C } from '../../../docs/components/index.js'; + +export default function Introduction() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Creating an OpenAPI Specification Generator Plugin */} +
+

{_('OpenAPI Specification Generator Plugin Tutorial')}

+

+ + This tutorial demonstrates how to create a plugin for + @stackpress/idea-transformer that generates OpenAPI + 3.0 specifications from .idea schema files. The + plugin will create comprehensive API documentation with + endpoints, schemas, and validation rules. + +

+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/openapi-specification-plugin/Overview.tsx b/packages/www/plugins/docs/components/openapi-specification-plugin/Overview.tsx new file mode 100644 index 0000000..2503334 --- /dev/null +++ b/packages/www/plugins/docs/components/openapi-specification-plugin/Overview.tsx @@ -0,0 +1,102 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, C } from '../../../docs/components/index.js'; + +export default function Overview() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Overview Section Content */} +
+

{_('1. Overview')}

+

+ + OpenAPI (formerly Swagger) specifications provide a + standard way to document REST APIs. This plugin transforms + your .idea schema definitions into comprehensive + API documentation that follows industry standards and + integrates seamlessly with existing API development + workflows. + +

+

+ + This plugin will: + +

+
    +
  • + + Generate OpenAPI 3.0 compliant specifications + +
  • +
  • + + Create schemas from idea models and types + +
  • +
  • + + Generate CRUD endpoints for models + +
  • +
  • + + Include validation rules and examples + +
  • +
  • + + Support custom endpoints and operations + +
  • +
  • + + Generate security schemes and authentication + +
  • +
+ +

{_('What You\'ll Learn')}

+

+ + This section outlines the key concepts and skills you'll + acquire through this tutorial. Understanding these fundamentals + will enable you to create robust API documentation that serves + both developers and automated tooling. + +

+
    +
  • + + Processing idea schemas for API documentation + +
  • +
  • + + OpenAPI 3.0 specification structure + +
  • +
  • + + Schema generation and validation + +
  • +
  • + + Endpoint documentation patterns + +
  • +
  • + + Security and authentication schemes + +
  • +
+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/openapi-specification-plugin/SchemaProcessing.tsx b/packages/www/plugins/docs/components/openapi-specification-plugin/SchemaProcessing.tsx new file mode 100644 index 0000000..ac0514b --- /dev/null +++ b/packages/www/plugins/docs/components/openapi-specification-plugin/SchemaProcessing.tsx @@ -0,0 +1,273 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const securitySchemesExample = + `function generateSecuritySchemes(spec: any, security: any): void { + if (security.apiKey) { + spec.components.securitySchemes.ApiKeyAuth = { + type: 'apiKey', + in: 'header', + name: 'X-API-Key' + }; + } + + if (security.bearer) { + spec.components.securitySchemes.BearerAuth = { + type: 'http', + scheme: 'bearer', + bearerFormat: 'JWT' + }; + } + + if (security.oauth2) { + spec.components.securitySchemes.OAuth2 = { + type: 'oauth2', + flows: { + authorizationCode: { + authorizationUrl: 'https://example.com/oauth/authorize', + tokenUrl: 'https://example.com/oauth/token', + scopes: { + read: 'Read access', + write: 'Write access', + admin: 'Admin access' + } + } + } + }; + } +}`; + +//--------------------------------------------------------------------// + +const crudEndpointsExample = +`function generateCRUDEndpoints(spec: any, modelName: string, model: any): void { + const resourcePath = \`/\${modelName.toLowerCase()}s\`; + const itemPath = \`\${resourcePath}/{id}\`; + + // GET /resources - List all + spec.paths[resourcePath] = { + get: { + summary: \`List all \${modelName}s\`, + tags: [modelName], + parameters: [ + { + name: 'page', + in: 'query', + schema: { type: 'integer', minimum: 1, default: 1 }, + description: 'Page number' + }, + { + name: 'limit', + in: 'query', + schema: { type: 'integer', minimum: 1, maximum: 100, default: 10 }, + description: 'Items per page' + }, + { + name: 'sort', + in: 'query', + schema: { type: 'string' }, + description: 'Sort field' + }, + { + name: 'order', + in: 'query', + schema: { type: 'string', enum: ['asc', 'desc'], default: 'asc' }, + description: 'Sort order' + } + ], + responses: { + '200': { + description: \`List of \${modelName}s\`, + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + data: { + type: 'array', + items: { $ref: \`#/components/schemas/\${modelName}\` } + }, + pagination: { + type: 'object', + properties: { + page: { type: 'integer' }, + limit: { type: 'integer' }, + total: { type: 'integer' }, + pages: { type: 'integer' } + } + } + } + } + } + } + } + }, + security: [{ BearerAuth: [] }] + }, + post: { + summary: \`Create a new \${modelName}\`, + tags: [modelName], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { $ref: \`#/components/schemas/\${modelName}\` } + } + } + }, + responses: { + '201': { + description: \`\${modelName} created successfully\`, + content: { + 'application/json': { + schema: { $ref: \`#/components/schemas/\${modelName}\` } + } + } + }, + '400': { + description: 'Validation error', + content: { + 'application/json': { + schema: { + type: 'object', + properties: { + error: { type: 'string' }, + errors: { + type: 'object', + additionalProperties: { type: 'string' } + } + } + } + } + } + } + }, + security: [{ BearerAuth: [] }] + } + }; + + // GET /resources/{id} - Get by ID + spec.paths[itemPath] = { + get: { + summary: \`Get \${modelName} by ID\`, + tags: [modelName], + parameters: [ + { + name: 'id', + in: 'path', + required: true, + schema: { type: 'string' }, + description: \`\${modelName} ID\` + } + ], + responses: { + '200': { + description: \`\${modelName} details\`, + content: { + 'application/json': { + schema: { $ref: \`#/components/schemas/\${modelName}\` } + } + } + }, + '404': { + description: \`\${modelName} not found\` + } + }, + security: [{ BearerAuth: [] }] + }, + put: { + summary: \`Update \${modelName}\`, + tags: [modelName], + parameters: [ + { + name: 'id', + in: 'path', + required: true, + schema: { type: 'string' }, + description: \`\${modelName} ID\` + } + ], + requestBody: { + required: true, + content: { + 'application/json': { + schema: { $ref: \`#/components/schemas/\${modelName}\` } + } + } + }, + responses: { + '200': { + description: \`\${modelName} updated successfully\`, + content: { + 'application/json': { + schema: { $ref: \`#/components/schemas/\${modelName}\` } + } + } + }, + '404': { + description: \`\${modelName} not found\` + } + }, + security: [{ BearerAuth: [] }] + }, + delete: { + summary: \`Delete \${modelName}\`, + tags: [modelName], + parameters: [ + { + name: 'id', + in: 'path', + required: true, + schema: { type: 'string' }, + description: \`\${modelName} ID\` + } + ], + responses: { + '204': { + description: \`\${modelName} deleted successfully\` + }, + '404': { + description: \`\${modelName} not found\` + } + }, + security: [{ BearerAuth: [] }] + } + }; +}`; + +//--------------------------------------------------------------------// + +export default function SchemaProcessing() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Schema Processing Section Content */} +
+

{_('4. Schema Processing')}

+

+ + Schema processing handles the transformation of .idea + definitions into OpenAPI components and endpoints. This + includes generating security schemes, creating CRUD endpoints + for models, and handling complex schema relationships and + validations. + +

+ + {securitySchemesExample} + + + {crudEndpointsExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/openapi-specification-plugin/Troubleshooting.tsx b/packages/www/plugins/docs/components/openapi-specification-plugin/Troubleshooting.tsx new file mode 100644 index 0000000..c4d676c --- /dev/null +++ b/packages/www/plugins/docs/components/openapi-specification-plugin/Troubleshooting.tsx @@ -0,0 +1,310 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const circularReferencesExample = + `// Problem: Circular references in schemas +// Solution: Use allOf or oneOf patterns + +function handleCircularReferences(spec: any): void { + // Detect and resolve circular references + const visited = new Set(); + + function checkSchema(schema: any, path: string): void { + if (visited.has(path)) { + // Circular reference detected + console.warn(\`Circular reference detected: \${path}\`); + return; + } + + visited.add(path); + + if (schema.$ref) { + const refPath = schema.$ref.replace('#/components/schemas/', ''); + checkSchema(spec.components.schemas[refPath], refPath); + } + + if (schema.properties) { + for (const [propName, propSchema] of Object.entries(schema.properties)) { + checkSchema(propSchema, \`\${path}.\${propName}\`); + } + } + + visited.delete(path); + } + + for (const [name, schema] of Object.entries(spec.components.schemas)) { + checkSchema(schema, name); + } +}`; + +//--------------------------------------------------------------------// + +const validationErrorsExample = + `// Problem: Generated spec doesn't validate +// Solution: Add comprehensive validation + +function validateOpenAPISpec(spec: any): void { + const errors: string[] = []; + + // Check required fields + if (!spec.openapi) errors.push('Missing openapi version'); + if (!spec.info) errors.push('Missing info object'); + if (!spec.paths) errors.push('Missing paths object'); + + // Validate info object + if (spec.info) { + if (!spec.info.title) errors.push('Missing info.title'); + if (!spec.info.version) errors.push('Missing info.version'); + } + + // Validate paths + if (spec.paths) { + for (const [path, pathObj] of Object.entries(spec.paths)) { + if (!path.startsWith('/')) { + errors.push(\`Path must start with '/': \${path}\`); + } + + for (const [method, operation] of Object.entries(pathObj)) { + if (!operation.responses) { + errors.push(\`Missing responses for \${method.toUpperCase()} \${path}\`); + } + } + } + } + + // Validate components + if (spec.components?.schemas) { + for (const [name, schema] of Object.entries(spec.components.schemas)) { + if (!schema.type && !schema.$ref && !schema.allOf && !schema.oneOf) { + errors.push(\`Schema \${name} missing type definition\`); + } + } + } + + if (errors.length > 0) { + throw new Error(\`OpenAPI validation failed:\\n\${errors.join('\\n')}\`); + } + + console.log('✅ OpenAPI specification validation passed'); +}`; + +//--------------------------------------------------------------------// + +const dependenciesExample = + `# Install required dependencies +npm install --save-dev yaml swagger-ui-dist + +# For validation +npm install --save-dev swagger-parser + +# For code generation +npm install --save-dev @openapitools/openapi-generator-cli` + +//--------------------------------------------------------------------// + +const performanceOptimizationExample = + `// Problem: Large schemas cause performance issues +// Solution: Implement schema optimization + +function optimizeSchema(spec: any): any { + // Remove unused schemas + const usedSchemas = new Set(); + + // Find all schema references + function findReferences(obj: any): void { + if (typeof obj === 'object' && obj !== null) { + if (obj.$ref && obj.$ref.startsWith('#/components/schemas/')) { + const schemaName = obj.$ref.replace('#/components/schemas/', ''); + usedSchemas.add(schemaName); + } + + for (const value of Object.values(obj)) { + findReferences(value); + } + } + } + + findReferences(spec.paths); + + // Remove unused schemas + const optimizedSchemas: any = {}; + for (const schemaName of usedSchemas) { + if (spec.components.schemas[schemaName]) { + optimizedSchemas[schemaName] = spec.components.schemas[schemaName]; + } + } + + return { + ...spec, + components: { + ...spec.components, + schemas: optimizedSchemas + } + }; +}\n`; + +//--------------------------------------------------------------------// + +const debugModeExample = + `interface DebugOpenAPIConfig extends AdvancedOpenAPIConfig { + debug?: boolean; + logLevel?: 'info' | 'warn' | 'error'; +} + +export default async function generateOpenAPISpecWithDebug( + props: PluginProps<{ config: DebugOpenAPIConfig }> +) { + const { config, schema, transformer } = props; + + if (config.debug) { + console.log('🔍 Debug mode enabled'); + console.log('Schema models:', Object.keys(schema.model || {})); + console.log('Schema types:', Object.keys(schema.type || {})); + console.log('Schema enums:', Object.keys(schema.enum || {})); + } + + try { + const spec = await generateOpenAPISpecification(schema, config); + + if (config.debug) { + console.log('Generated schemas:', Object.keys(spec.components.schemas)); + console.log('Generated paths:', Object.keys(spec.paths)); + } + + // Validate before writing + if (config.validation?.strict) { + await validateOpenAPISpecification(spec); + } + + // Optimize if needed + const optimizedSpec = config.debug ? + await optimizeOpenAPISchema(spec) : spec; + + // Generate outputs + const formats = config.formats || ['json']; + const outputBase = config.output.replace(/\\.[^.]+$/, ''); + + for (const format of formats) { + await generateOpenAPIFormat(optimizedSpec, format, outputBase, transformer); + } + + if (config.debug) { + console.log('✅ OpenAPI generation completed successfully'); + } + + } catch (error) { + console.error('❌ OpenAPI generation failed:', error.message); + if (config.debug) { + console.error('Stack trace:', error.stack); + } + throw error; + } +}\n`; + +//--------------------------------------------------------------------// + +export default function Troubleshooting() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Troubleshooting Section Content */} +
+

{_('8. Troubleshooting')}

+

+ + This section addresses common issues encountered when + generating OpenAPI specifications and provides solutions + for debugging and resolving problems. Understanding these + troubleshooting techniques helps ensure reliable + specification generation. + +

+ +

{_('8.1. Common Issues')}

+

+ + Common issues include schema reference errors, validation + failures, and performance problems with large specifications. + These problems typically arise from circular references, + invalid configurations, or missing dependencies. + +

+ +

{_('8.1.1. Schema Reference Errors')}

+

+ + Schema reference errors occur when the generator encounters + circular dependencies or invalid references between schema + components. These issues can break the specification + generation process and require careful handling of schema + relationships. + +

+ + {circularReferencesExample} + + +

{_('8.1.2. Invalid OpenAPI Format')}

+

+ + Invalid OpenAPI format errors occur when the generated + specification doesn't conform to OpenAPI standards. These + validation failures can prevent the specification from + working with OpenAPI tools and require comprehensive + validation during generation. + +

+ + {validationErrorsExample} + + +

{_('8.1.3. Missing Dependencies')}

+

+ + Missing dependencies can cause the plugin to fail during + execution or limit available features. Ensuring all required + packages are installed and properly configured is essential + for reliable operation. + +

+ + {dependenciesExample} + + +

{_('8.1.4. Performance Issues')}

+

+ + Performance issues can occur when generating specifications + for large schemas with many models and complex relationships. + Optimization techniques help maintain reasonable generation + times and manageable output file sizes. + +

+ + {performanceOptimizationExample} + + +

{_('8.2. Debug Mode')}

+

+ + Debug mode provides detailed logging and diagnostic + information during specification generation. This feature + helps identify issues, understand the generation process, + and optimize plugin configuration for better results. + +

+ + {debugModeExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/openapi-specification-plugin/UsageExamples.tsx b/packages/www/plugins/docs/components/openapi-specification-plugin/UsageExamples.tsx new file mode 100644 index 0000000..7d7f6e7 --- /dev/null +++ b/packages/www/plugins/docs/components/openapi-specification-plugin/UsageExamples.tsx @@ -0,0 +1,261 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, C } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const basicUsageExample = + `// schema.idea +enum UserRole { + ADMIN "admin" + USER "user" + GUEST "guest" +} + +model User { + id String @id @default("nanoid()") + email String @unique @format("email") + name String @minLength(2) @maxLength(100) + role UserRole @default("USER") + active Boolean @default(true) + created Date @default("now()") + updated Date @default("updated()") +} + +plugin "./plugins/openapi-spec.js" { + output "./docs/api-spec.json" + info { + title "User API" + version "1.0.0" + description "User management API" + } + endpoints { + crud true + } + security { + bearer true + } +}`; + +//--------------------------------------------------------------------// + +const advancedUsageExample = +`// schema.idea +plugin "./plugins/openapi-spec.js" { + output "./docs/api-spec" + formats ["json" "yaml" "html"] + info { + title "E-commerce API" + version "2.1.0" + description "Comprehensive e-commerce platform API" + contact { + name "API Team" + email "api@ecommerce.com" + url "https://ecommerce.com/api-support" + } + license { + name "Apache 2.0" + url "https://www.apache.org/licenses/LICENSE-2.0.html" + } + } + servers [ + { + url "https://api.ecommerce.com/v2" + description "Production server" + } + { + url "https://staging-api.ecommerce.com/v2" + description "Staging server" + } + ] + security { + apiKey true + bearer true + oauth2 true + } + endpoints { + crud true + custom { + "/auth/login" { + post { + summary "Authenticate user" + tags ["Authentication"] + requestBody { + required true + content { + "application/json" { + schema { + type "object" + properties { + email { type "string" format "email" } + password { type "string" minLength 8 } + remember { type "boolean" default false } + } + required ["email" "password"] + } + } + } + } + responses { + "200" { + description "Login successful" + content { + "application/json" { + schema { + type "object" + properties { + token { type "string" } + refreshToken { type "string" } + expiresIn { type "integer" } + user { "$ref" "#/components/schemas/User" } + } + } + } + } + } + "401" { + description "Invalid credentials" + content { + "application/json" { + schema { + type "object" + properties { + error { type "string" } + code { type "string" } + } + } + } + } + } + } + } + } + "/auth/refresh" { + post { + summary "Refresh access token" + tags ["Authentication"] + requestBody { + required true + content { + "application/json" { + schema { + type "object" + properties { + refreshToken { type "string" } + } + required ["refreshToken"] + } + } + } + } + responses { + "200" { + description "Token refreshed" + content { + "application/json" { + schema { + type "object" + properties { + token { type "string" } + expiresIn { type "integer" } + } + } + } + } + } + } + } + } + } + } + validation { + strict true + examples true + } +}`; + +//--------------------------------------------------------------------// + +const cliIntegrationExample = +`# Generate OpenAPI specification +npm run transform + +# Serve documentation locally +npx swagger-ui-serve docs/api-spec.json + +# Validate specification +npx swagger-codegen validate -i docs/api-spec.json + +# Generate client SDKs +npx swagger-codegen generate -i docs/api-spec.json -l typescript-fetch -o ./sdk/typescript +npx swagger-codegen generate -i docs/api-spec.json -l python -o ./sdk/python`; + +//--------------------------------------------------------------------// + +export default function UsageExamples() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Usage Examples Section Content */} +
+

{_('6. Usage Examples')}

+

+ + Usage examples demonstrate practical applications of the + OpenAPI generator plugin with real-world scenarios. These + examples show how to configure the plugin for different + use cases and integrate the generated documentation into + your development workflow. + +

+ +

{_('6.1. Basic Usage')}

+

+ + Basic usage examples show the fundamental configuration + needed to generate OpenAPI specifications from simple + .idea + schemas. This includes model definitions, plugin + configuration, and the resulting API documentation structure. + +

+ + {basicUsageExample} + + +

{_('6.2. Advanced Configuration')}

+

+ + Advanced configuration demonstrates comprehensive plugin + setup with multiple output formats, detailed API metadata, + custom endpoints, and security schemes. This example shows + how to create production-ready API documentation with full + feature coverage. + +

+ + {advancedUsageExample} + + +

{_('6.3. CLI Integration')}

+

+ + CLI integration shows how to incorporate the OpenAPI + generator into your development workflow using command-line + tools. This includes generating specifications, serving + documentation locally, and integrating with API development + tools. + +

+ + {cliIntegrationExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/openapi-specification-plugin/index.tsx b/packages/www/plugins/docs/components/openapi-specification-plugin/index.tsx new file mode 100644 index 0000000..5f7ebb2 --- /dev/null +++ b/packages/www/plugins/docs/components/openapi-specification-plugin/index.tsx @@ -0,0 +1,11 @@ +//exporting all components to have multiple imports from a single file +export { default as AdvancedFeatures } from './AdvancedFeatures.js'; +export { default as BasicImplementation } from './BasicImplementation.js'; +export { default as BestPractices } from './BestPractices.js'; +export { default as Conclusion } from './Conclusion.js'; +export { default as ConfigurationOptions } from './ConfigurationOptions.js'; +export { default as Introduction } from './Introduction.js'; +export { default as Overview } from './Overview.js'; +export { default as SchemaProcessing } from './SchemaProcessing.js'; +export { default as Troubleshooting } from './Troubleshooting.js'; +export { default as UsageExamples } from './UsageExamples.js'; \ No newline at end of file diff --git a/packages/www/plugins/docs/components/specifications/data-types/Enums.tsx b/packages/www/plugins/docs/components/specifications/data-types/Enums.tsx new file mode 100644 index 0000000..e20ac34 --- /dev/null +++ b/packages/www/plugins/docs/components/specifications/data-types/Enums.tsx @@ -0,0 +1,152 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, SS } from '../../../../docs/components/index.js'; +import Code from '../../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const enumsExamples = [ + `enum EnumName { + KEY1 "Display Value 1" + KEY2 "Display Value 2" + KEY3 "Display Value 3" +}`, + + //------------------------------------------------------------------// + + `enum UserRole { + ADMIN "Administrator" + MODERATOR "Moderator" + USER "Regular User" + GUEST "Guest User" +} + +enum OrderStatus { + PENDING "Pending Payment" + PAID "Payment Confirmed" + SHIPPED "Order Shipped" + DELIVERED "Order Delivered" + CANCELLED "Order Cancelled" +} + +enum Priority { + LOW "Low Priority" + MEDIUM "Medium Priority" + HIGH "High Priority" + URGENT "Urgent" +}`, + + //------------------------------------------------------------------// + + `export enum UserRole { + ADMIN = "Administrator", + MODERATOR = "Moderator", + USER = "Regular User", + GUEST = "Guest User" +}`, + + //------------------------------------------------------------------// + + `{ + "enum": { + "UserRole": { + "ADMIN": "Administrator", + "MODERATOR": "Moderator", + "USER": "Regular User", + "GUEST": "Guest User" + } + } +}` +]; + +//--------------------------------------------------------------------// + +export default function Enums() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Enums Section Content */} +
+

{_('Enums')}

+ +

+ + Enums define a set of named constants with associated values, + perfect for representing fixed sets of options like user roles, + status values, or categories. + +

+ +

{_('Syntax')}

+ + + {enumsExamples[0]} + + +

{_('Structure')}

+
    +
  • + {_('EnumName: ')} + + The identifier used to reference this enum + +
  • +
  • + {_('KEY: ')} + + The constant name (typically uppercase) + +
  • +
  • + {_('"Display Value": ')} + + Human-readable label for the constant + +
  • +
+ +

{_('Example')}

+ + + {enumsExamples[1]} + + +

{_('Generate Output')}

+ +

+ + When processed, enums generate language-specific constants: + +

+ +

{_('TypeScript:')}

+ + + {enumsExamples[2]} + + +

{_('JSON:')}

+ + + {enumsExamples[3]} + +
+ + ) +} diff --git a/packages/www/plugins/docs/components/specifications/data-types/Models.tsx b/packages/www/plugins/docs/components/specifications/data-types/Models.tsx new file mode 100644 index 0000000..e5d940f --- /dev/null +++ b/packages/www/plugins/docs/components/specifications/data-types/Models.tsx @@ -0,0 +1,189 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, SS, C } from '../../../../docs/components/index.js'; +import Code from '../../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const modelsExamples = [ + `model ModelName { + columnName DataType @attribute1 @attribute2 + relationColumn RelatedModel @relation +} + +model ModelName! { // Mutable model + // columns... +}`, + + //------------------------------------------------------------------// + + `// base-schema.idea +model User { + id String @id + name String @required +} + +// extended-schema.idea +use "./base-schema.idea" + +// This will merge with the imported User model +model User { + email String @required + created Date @default("now()") +} + +// This will NOT merge - it completely replaces the imported User +model User! { + id String @id + username String @required + password String @required +}`, + + //------------------------------------------------------------------// + + `model User! { + id String @id @default("nanoid()") + email String @unique @required @field.input(Email) + username String @unique @required @field.input(Text) + password String @required @field.input(Password) + profile UserProfile? + role UserRole @default("USER") + active Boolean @default(true) + lastLogin Date? + created Date @default("now()") + updated Date @default("updated()") +} + +model UserProfile { + id String @id @default("nanoid()") + userId String @relation(User.id) + firstName String @required @field.input(Text) + lastName String @required @field.input(Text) + bio String @field.textarea + avatar String @field.upload + address Address + contact ContactInfo + preferences { + theme String @default("light") + language String @default("en") + notifications Boolean @default(true) + } +} + +model Post { + id String @id @default("nanoid()") + title String @required @field.input(Text) + slug String @unique @generated + content String @required @field.richtext + excerpt String @field.textarea + authorId String @relation(User.id) + author User @relation(User, authorId) + status PostStatus @default("DRAFT") + tags String[] @field.tags + publishedAt Date? + created Date @default("now()") + updated Date @default("updated()") +} + +enum PostStatus { + DRAFT "Draft" + PUBLISHED "Published" + ARCHIVED "Archived" +}` +]; + +//--------------------------------------------------------------------// + +export default function Models() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Models Section Content */} +
+

{_('Models')}

+ +

+ + Models represent the core entities in your application, + typically corresponding to database tables or API + resources. They define the structure, relationships, and + behavior of your data. + +

+ +
+

{_('Syntax')}

+ + {modelsExamples[0]} + + +

{_('Structure')}

+
    +
  • + {_('ModelName: ')} + The identifier for this model +
  • +
  • + !: + + Optional non-mergeable indicator prevents automatic + merging when using use directives + +
  • +
  • + {_('columnName: ')} + The field name within the model +
  • +
  • + {_('DataType: ')} + + Built-in types (String, Number, Boolean, Date) or custom + types/enums + +
  • +
  • + {_('@attribute: ')} + + Attributes for validation, relationships, UI, etc. + +
  • +
+ +

{_('Merging Behavior')}

+ +

+ + By default, when importing schemas with use directives, + models with the same name are automatically merged. The ! + suffix prevents this behavior: + +

+ + {modelsExamples[1]} + + +

{_('Example')}

+ + {modelsExamples[2]} + +
+
+ + ) +} diff --git a/packages/www/plugins/docs/components/specifications/data-types/Props.tsx b/packages/www/plugins/docs/components/specifications/data-types/Props.tsx new file mode 100644 index 0000000..3aa6150 --- /dev/null +++ b/packages/www/plugins/docs/components/specifications/data-types/Props.tsx @@ -0,0 +1,142 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//locals +import { H1, H2, P, SS, C } from '../../../../docs/components/index.js'; +import Code from '../../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const propsExamples = [ + `prop PropName { + property "value" + nested { + property "value" + } +}`, + + //------------------------------------------------------------------// + + `prop Email { + type "email" + format "email" + validation { + required true + pattern "^[^\s@]+@[^\s@]+\.[^\s@]+$" + } + ui { + component "EmailInput" + placeholder "Enter your email address" + icon "envelope" + } +} + +prop Password { + type "password" + validation { + required true + minLength 8 + pattern "^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])[A-Za-z\d@$!%*?&]" + } + ui { + component "PasswordInput" + placeholder "Enter a secure password" + showStrength true + } +} + +prop Currency { + type "number" + format "currency" + validation { + min 0 + precision 2 + } + ui { + component "CurrencyInput" + symbol "$" + locale "en-US" + } +}`, + + //------------------------------------------------------------------// + + `model User { + email String @field.input(Email) + password String @field.input(Password) +}` +]; + +//--------------------------------------------------------------------// + +export default function Props() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Props Section Content */} +
+

{_('Props')}

+ +

+ + Props are reusable property configurations that define common + field behaviors, validation rules, and UI components. They + promote consistency and reduce duplication across your schema. + +

+ +

{_('Syntax')}

+ + {propsExamples[0]} + + +

{_('Structure')}

+ +
    +
  • + {_('PropName:')} + + The identifier used to reference this prop + +
  • +
  • + {_('property:')} + Configuration key-value pairs +
  • +
  • + {_('nested:')} + A nested prop +
  • +
+ +

{_('Example')}

+ + {propsExamples[1]} + + + {_('Usage in Models')} +

+ Props are referenced using the + {_('@field')} {_('attribute:')} +

+ + {propsExamples[2]} + +
+ + ) +} diff --git a/packages/www/plugins/docs/components/specifications/data-types/Type.tsx b/packages/www/plugins/docs/components/specifications/data-types/Type.tsx new file mode 100644 index 0000000..0784487 --- /dev/null +++ b/packages/www/plugins/docs/components/specifications/data-types/Type.tsx @@ -0,0 +1,134 @@ +//moudles +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, SS } from '../../../../docs/components/index.js'; +import Code from '../../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const typeExamples = [ + `type TypeName { + columnName DataType @attribute1 @attribute2 + anotherColumn DataType @attribute +}`, + +//--------------------------------------------------------------------// + +`type Address { + street String @required @field.input(Text) + city String @required @field.input(Text) + state String @field.select + postalCode String @field.input(Text) + country String @default("US") @field.select + coordinates { + latitude Number @field.input(Number) + longitude Number @field.input(Number) + } +} + +type ContactInfo { + email String @required @field.input(Email) + phone String @field.input(Phone) + website String @field.input(URL) + socialMedia { + twitter String @field.input(Text) + linkedin String @field.input(Text) + github String @field.input(Text) + } +} + +type Money { + amount Number @required @field.input(Currency) + currency String @default("USD") @field.select + exchangeRate Number @field.input(Number) +}`, + +//--------------------------------------------------------------------// + +`model Company { + name String @required + address Address @required + contact ContactInfo + revenue Money +}` +] + +export default function Type() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Type Section Content */} +
+

{_('Type')}

+ +

+ + Types define custom data structures with multiple columns, + similar to objects or structs in programming languages. They + are perfect for representing complex data that doesn't warrant + a full model. + +

+ +

{_('Syntax')}

+ + {typeExamples[0]} + + +

{_('Structure')}

+ +
    +
  • + {_('TypeName: ')} + + The identifier used to reference this type + +
  • +
  • + {_('columnName: ')} + The field name within the type +
  • +
  • + {_('DataType: ')} + + The data type (String, Number, Boolean, Date, etc.) + +
  • +
  • + {_('attribute: ')} + + Optional attributes for validation, UI, or behavior + +
  • +
+ +

{_('Example')}

+ + + {typeExamples[1]} + + +

{_('Usage in Models')}

+

+ Types are used as column data types: +

+ + {typeExamples[2]} + +
+ + ) +} diff --git a/packages/www/plugins/docs/components/specifications/data-types/index.tsx b/packages/www/plugins/docs/components/specifications/data-types/index.tsx new file mode 100644 index 0000000..2e8915a --- /dev/null +++ b/packages/www/plugins/docs/components/specifications/data-types/index.tsx @@ -0,0 +1,5 @@ +//exporting all components to have multiple imports from a single file +export { default as Enums } from './Enums.js'; +export { default as Models } from './Models.js'; +export { default as Props } from './Props.js'; +export { default as Type } from './Type.js'; \ No newline at end of file diff --git a/packages/www/plugins/docs/components/specifications/schema-directives/Plugin.tsx b/packages/www/plugins/docs/components/specifications/schema-directives/Plugin.tsx new file mode 100644 index 0000000..33c0e7e --- /dev/null +++ b/packages/www/plugins/docs/components/specifications/schema-directives/Plugin.tsx @@ -0,0 +1,309 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, SS, C } from '../../../../docs/components/index.js'; +import Code from '../../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const pluginExamples = [ + `plugin "path/to/plugin.js" { + configKey "configValue" + nestedConfig { + option "value" + flag true + } +}`, + + //------------------------------------------------------------------// + + `// TypeScript interface generation +plugin "./plugins/typescript-generator.js" { + output "./src/types/schema.ts" + namespace "Schema" + exportType "named" + includeComments true + formatting { + indent 2 + semicolons true + trailingCommas true + } +} + +// Database schema generation +plugin "./plugins/database-generator.js" { + output "./database/schema.sql" + dialect "postgresql" + includeIndexes true + includeForeignKeys true + tablePrefix "app_" + options { + dropExisting false + addTimestamps true + charset "utf8mb4" + } +} + +// API documentation generation +plugin "./plugins/openapi-generator.js" { + output "./docs/api.yaml" + version "1.0.0" + title "My API Documentation" + description "Comprehensive API documentation generated from schema" + servers [ + { + url "https://api.example.com/v1" + description "Production server" + } + { + url "https://staging-api.example.com/v1" + description "Staging server" + } + ] + security { + type "bearer" + scheme "JWT" + } +} + +// Form generation +plugin "./plugins/form-generator.js" { + output "./src/components/forms/" + framework "react" + styling "tailwind" + validation "zod" + features { + typescript true + storybook true + tests true + } + components { + inputWrapper "FormField" + submitButton "SubmitButton" + errorMessage "ErrorText" + } +}`, + + //------------------------------------------------------------------// + + `plugin "./plugins/my-plugin.js" { + // Output configuration + output "./generated/output.ts" + outputDir "./generated/" + + // Format and style options + format "typescript" // or "javascript", "json", "yaml" + style "camelCase" // or "snake_case", "kebab-case" + + // Feature flags + includeComments true + generateTests false + addValidation true + + // Framework-specific options + framework "react" // or "vue", "angular", "svelte" + styling "tailwind" // or "bootstrap", "material", "custom" + + // Advanced configuration + templates { + model "./templates/model.hbs" + enum "./templates/enum.hbs" + } + + // Custom options (plugin-specific) + customOptions { + apiVersion "v1" + includeMetadata true + compressionLevel 9 + } +}`, + + //------------------------------------------------------------------// + + `// Generate TypeScript types +plugin "./plugins/typescript.js" { + output "./src/types/index.ts" +} + +// Generate database schema +plugin "./plugins/database.js" { + output "./database/schema.sql" + dialect "postgresql" +} + +// Generate API documentation +plugin "./plugins/docs.js" { + output "./docs/api.md" + format "markdown" +} + +// Generate form components +plugin "./plugins/forms.js" { + output "./src/forms/" + framework "react" +} + +// Generate validation schemas +plugin "./plugins/validation.js" { + output "./src/validation/index.ts" + library "zod" +}`, + + //------------------------------------------------------------------// + + `// Example plugin structure +import type { PluginProps } from '@stackpress/idea-transformer/types'; + +interface MyPluginConfig { + output: string; + format?: 'typescript' | 'javascript'; + includeComments?: boolean; +} + +export default async function myPlugin( + props: PluginProps<{ config: MyPluginConfig }> +) { + const { config, schema, transformer, cwd } = props; + + // Validate configuration + if (!config.output) { + throw new Error('Output path is required'); + } + + // Process schema + const content = generateContent(schema, config); + + // Write output + const outputPath = await transformer.loader.absolute(config.output); + await writeFile(outputPath, content); + + console.log(\`✅ Generated: \${outputPath}\`); +}` +]; + +//--------------------------------------------------------------------// + +export default function Plugin() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Plugin Section Content */} +
+

{_('Plugin')}

+

+ + The plugin directive configures code generation + plugins that process your schema and generate various + outputs like TypeScript interfaces, database schemas, API + documentation, and more. + +

+ + {/* Syntax Section Content */} +
+

{_('Syntax')}

+ + {pluginExamples[0]} + +
+ + {/* Structure Section Content */} +
+

{_('Structure')}

+
    +
  • + {_('Path:')}{' '} + + Relative or absolute path to the plugin file + +
  • +
  • + {_('Configuration Block:')}{' '} + + Key-value pairs that configure the plugin behavior + +
  • +
  • + {_('Nested Configuration:')}{' '} + + Support for complex configuration structures + +
  • +
+
+ + {/* Example Section Content */} +
+

{_('Example')}

+ + {pluginExamples[1]} + +
+ + {/* Plugin Configuration Options Section Content */} +
+

{_('Plugin Configuration Options')}

+

+ + Common configuration patterns across different plugin types: + +

+ + {pluginExamples[2]} + +
+ + {/* Multiple Plugins Execution Section Content */} +
+

{_('Multiple Plugins Execution')}

+

+ + You can configure multiple plugins to generate different + outputs from the same schema: + +

+ + {pluginExamples[3]} + +
+ + {/* Plugin Development Section Content */} +
+

{_('Plugin Development')}

+

+ + Plugins are JavaScript/TypeScript modules that export a + default function: + +

+ + {pluginExamples[4]} + +
+
+ + ); +} diff --git a/packages/www/plugins/docs/components/specifications/schema-directives/Use.tsx b/packages/www/plugins/docs/components/specifications/schema-directives/Use.tsx new file mode 100644 index 0000000..3609c94 --- /dev/null +++ b/packages/www/plugins/docs/components/specifications/schema-directives/Use.tsx @@ -0,0 +1,252 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, SS, C } from '../../../../docs/components/index.js'; +import Code from '../../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const useExamples = [ + `use "package/to/schema.idea" +use "./relative/path/schema.idea" +use "../parent/directory/schema.idea"`, + + //------------------------------------------------------------------// + + `// Common types used across multiple schemas +type Address { + street String @required + city String @required + country String @default("US") +} + +enum Status { + ACTIVE "Active" + INACTIVE "Inactive" +} + +prop Email { + type "email" + validation { + required true + format "email" + } +}`, + + //------------------------------------------------------------------// + + `// Import common definitions +use "../shared/common.idea" + +// Extend the Status enum (will merge with imported one) +enum Status { + PENDING "Pending Approval" + SUSPENDED "Temporarily Suspended" +} + +// Use imported types and props +model User { + id String @id @default("nanoid()") + email String @field.input(Email) + address Address + status Status @default("PENDING") +}`, + + //------------------------------------------------------------------// + + `// The Status enum now contains all values +enum Status { + ACTIVE "Active" // From common.idea + INACTIVE "Inactive" // From common.idea + PENDING "Pending Approval" // From user-schema.idea + SUSPENDED "Temporarily Suspended" // From user-schema.idea +}`, + + //------------------------------------------------------------------// + + `enum UserRole { + USER "Regular User" + ADMIN "Administrator" +}`, + + //------------------------------------------------------------------// + + `use "./base-schema.idea" + +// This will NOT merge with the imported UserRole +// Instead, it will override it completely +enum UserRole! { + GUEST "Guest User" + MEMBER "Member" + MODERATOR "Moderator" + ADMIN "Administrator" +}`, + + //------------------------------------------------------------------// + + `// ✅ Good - organize by domain +use "./shared/common-types.idea" +use "./auth/user-types.idea" +use "./commerce/product-types.idea" + +// ✅ Good - clear file naming +use "./enums/status-enums.idea" +use "./types/address-types.idea" +use "./props/form-props.idea" + +// ❌ Avoid - unclear imports +use "./stuff.idea" +use "./misc.idea"` +]; + +//--------------------------------------------------------------------// + +export default function Use() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Use Section Content */} +
+

{_('Use')}

+

+ + The use directive imports definitions from other{' '} + .idea files, enabling modular schema organization and{' '} + reusability. When importing, data types with the same name are{' '} + automatically merged unless the ! (non-mergeable){' '} + indicator is used. + +

+ + {/* Syntax Section Content */} +
+

{_('Syntax')}

+ + {useExamples[0]} + +
+ + {/* Structure Section Content */} +
+

{_('Structure')}

+
    +
  • + {_('Path:')} {_('Relative or absolute path to the')}{' '} + .idea {_('file to import')} +
  • +
  • + {_('Automatic Merging:')}{' '} + {_('Data types with matching names are merged by default')} +
  • +
  • + {_('Merge Prevention:')} {_('Use')} !{' '} + {_('suffix to prevent merging')} +
  • +
+
+ + {/* Example Section Content */} +
+

{_('Example')}

+

shared/common.idea

+ + {useExamples[1]} + + +

user/user-schema.idea:

+ + {useExamples[2]} + + +

{_('Result after merging:')}

+ + {useExamples[3]} + +
+ + {/* Prevent Merging with ! Section Content */} +
+ {_('Prevent merging with')} ! +

+ + When you want to prevent automatic merging and keep definitions{' '} + separate, use the ! suffix: + +

+ + {_('base-schema.idea:')} + + {useExamples[4]} + + + {_('extended-schema.idea:')} + + {useExamples[5]} + +
+ + {/* Use Cases Content */} +
+

{_('Use Cases')}

+
    +
  • + {_('Shared Types:')}{' '} + {_('Define common types once and reuse across multiple schemas')} +
  • +
  • + {_('Modular Organization:')}{' '} + {_('Split large schemas into manageable, focused files')} +
  • +
  • + {_('Team Collaboration:')}{' '} + {_('Different teams can work on separate schema files')} +
  • +
  • + {_('Environment-Specific:')}{' '} + {_('Override certain definitions for different environments')} +
  • +
+
+ + {/* Best Practices Section Content */} +
+

{_('Best Practices')}

+ + {useExamples[6]} + +
+
+ + ); +} diff --git a/packages/www/plugins/docs/components/specifications/schema-directives/index.tsx b/packages/www/plugins/docs/components/specifications/schema-directives/index.tsx new file mode 100644 index 0000000..78056b1 --- /dev/null +++ b/packages/www/plugins/docs/components/specifications/schema-directives/index.tsx @@ -0,0 +1,3 @@ +//exporting all components to have multiple imports from a single file +export { default as Plugin } from './Plugin.js'; +export { default as Use } from './Use.js'; \ No newline at end of file diff --git a/packages/www/plugins/docs/components/test-data-plugin/Conclusion.tsx b/packages/www/plugins/docs/components/test-data-plugin/Conclusion.tsx new file mode 100644 index 0000000..12b336e --- /dev/null +++ b/packages/www/plugins/docs/components/test-data-plugin/Conclusion.tsx @@ -0,0 +1,26 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; + +export default function Conclusion() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Conclusion Section Content */} +
+

{_('Conclusion')}

+

+ + This tutorial provides a comprehensive foundation for + creating test data generation plugins that can handle + complex schemas and generate realistic, useful test data + for development and testing workflows. + +

+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/test-data-plugin/CorePluginFunction.tsx b/packages/www/plugins/docs/components/test-data-plugin/CorePluginFunction.tsx new file mode 100644 index 0000000..b6f2fed --- /dev/null +++ b/packages/www/plugins/docs/components/test-data-plugin/CorePluginFunction.tsx @@ -0,0 +1,142 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const corePluginExample = +`export default async function generateTestData( + props: PluginProps<{ config: TestDataConfig }> +) { + const { config, schema, transformer } = props; + + try { + // Validate configuration + validateConfig(config); + + // Generate test data content + let content = ''; + + // Add file header and imports + content += generateFileHeader(config); + content += generateImports(config); + + // Generate data factories if requested + if (config.generateFactories) { + content += generateFactories(schema, config); + } + + // Generate mock data + if (schema.model) { + content += generateMockData(schema.model, config); + } + + // Generate fixtures if requested + if (config.generateFixtures) { + content += generateFixtures(schema, config); + } + + // Generate main export + content += generateMainExport(schema, config); + + // Write to output file + const outputPath = await transformer.loader.absolute(config.output); + await fs.mkdir(path.dirname(outputPath), { recursive: true }); + await fs.writeFile(outputPath, content, 'utf8'); + + console.log(\`✅ Test data generated: \${outputPath}\`); + + } catch (error) { + console.error('❌ Test data generation failed:', error.message); + throw error; + } +}`; + +//--------------------------------------------------------------------// + +const headerAndImportsExample = +`function generateFileHeader(config: TestDataConfig): string { + const timestamp = new Date().toISOString(); + return \`/** + * Generated Test Data and Fixtures + * Generated at: \${timestamp} + * Format: \${config.format} + * Count: \${config.count || 10} + * Seed: \${config.seed || 'random'} + * + * This file is auto-generated. Do not edit manually. + */ + +\`; +} + +function generateImports(config: TestDataConfig): string { + let imports = ''; + + if (config.format === 'typescript' || config.format === 'javascript') { + imports += \`import { faker } from '@faker-js/faker';\\n\\n\`; + + if (config.seed) { + imports += \`// Set seed for reproducible data\\nfaker.seed(\${config.seed});\\n\\n\`; + } + + if (config.locale && config.locale !== 'en') { + imports += \`// Set locale\\nfaker.setLocale('\${config.locale}');\\n\\n\`; + } + } + + return imports; +}`; + +//--------------------------------------------------------------------// + +export default function CorePluginFunction() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Implementation Section Content */} +
+

{_('4. Implementation')}

+

+ + The implementation section covers the core plugin function + and supporting utilities that handle test data generation. + This includes the main plugin entry point, data generation + functions, and configuration validation. + +

+ +

{_('4.1. Core Plugin Function')}

+

+ + The core plugin function serves as the main entry point for + test data generation. It orchestrates the entire process from + configuration validation to file output, handling different + formats and generation options. + +

+ + {corePluginExample} + + +

{_('4.2. Generation Functions')}

+

+ + The generation functions provide the core logic for creating + different types of test data content. These utility functions + handle file headers, imports, data factories, and various data + generation patterns based on schema definitions. + +

+ + {headerAndImportsExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/test-data-plugin/GenerationFunctions.tsx b/packages/www/plugins/docs/components/test-data-plugin/GenerationFunctions.tsx new file mode 100644 index 0000000..0becec7 --- /dev/null +++ b/packages/www/plugins/docs/components/test-data-plugin/GenerationFunctions.tsx @@ -0,0 +1,520 @@ +//local +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const factoriesExample = + `function generateFactories(schema: any, config: TestDataConfig): string { + let content = '// Data Factories\\n'; + + // Generate enum factories + if (schema.enum) { + for (const [enumName, enumDef] of Object.entries(schema.enum)) { + content += generateEnumFactory(enumName, enumDef, config); + } + } + + // Generate model factories + if (schema.model) { + for (const [modelName, model] of Object.entries(schema.model)) { + content += generateModelFactory(modelName, model, config); + } + } + + return content + '\\n'; +} + +function generateEnumFactory(enumName: string, enumDef: any, config: TestDataConfig): string { + const values = Object.values(enumDef); + const valuesArray = values.map(v => \`"\${v}"\`).join(', '); + + return \`export function generate\${enumName}(): string { + return faker.helpers.arrayElement([\${valuesArray}]); +} + +\`; +} + +function generateModelFactory(modelName: string, model: any, config: TestDataConfig): string { + let content = \`export function generate\${modelName}(overrides: Partial<\${modelName}> = {}): \${modelName} { + return { +\`; + + for (const column of model.columns || []) { + const generator = generateFieldGenerator(column, config); + content += \` \${column.name}: \${generator},\\n\`; + } + + content += \` ...overrides, + }; +} + +export function generate\${modelName}Array(count: number = \${config.count || 10}): \${modelName}[] { + return Array.from({ length: count }, () => generate\${modelName}()); +} + +\`; + + return content; +}`; + +//--------------------------------------------------------------------// + +const fieldGeneratorExample = + `function generateFieldGenerator(column: any, config: TestDataConfig): string { + // Check for custom generators first + if (config.customGenerators && config.customGenerators[column.type]) { + return config.customGenerators[column.type]; + } + + // Handle arrays + if (column.multiple) { + const baseGenerator = getBaseGenerator(column, config); + const arraySize = column.attributes?.minLength || 1; + const maxSize = column.attributes?.maxLength || 5; + return \`faker.helpers.multiple(() => \${baseGenerator}, { count: { min: \${arraySize}, max: \${maxSize} } })\`; + } + + return getBaseGenerator(column, config); +} + +function getBaseGenerator(column: any, config: TestDataConfig): string { + const { type, attributes = {} } = column; + + // Handle custom field types based on attributes + if (attributes.email) { + return 'faker.internet.email()'; + } + + if (attributes.url) { + return 'faker.internet.url()'; + } + + if (attributes.uuid) { + return 'faker.string.uuid()'; + } + + if (attributes.phone) { + return 'faker.phone.number()'; + } + + if (attributes.color) { + return 'faker.internet.color()'; + } + + // Handle based on field name patterns + const fieldName = column.name.toLowerCase(); + + if (fieldName.includes('email')) { + return 'faker.internet.email()'; + } + + if (fieldName.includes('name')) { + if (fieldName.includes('first')) return 'faker.person.firstName()'; + if (fieldName.includes('last')) return 'faker.person.lastName()'; + if (fieldName.includes('full')) return 'faker.person.fullName()'; + return 'faker.person.fullName()'; + } + + if (fieldName.includes('address')) { + return 'faker.location.streetAddress()'; + } + + if (fieldName.includes('city')) { + return 'faker.location.city()'; + } + + if (fieldName.includes('country')) { + return 'faker.location.country()'; + } + + if (fieldName.includes('phone')) { + return 'faker.phone.number()'; + } + + if (fieldName.includes('company')) { + return 'faker.company.name()'; + } + + if (fieldName.includes('title')) { + return 'faker.lorem.sentence()'; + } + + if (fieldName.includes('description') || fieldName.includes('content')) { + return 'faker.lorem.paragraphs()'; + } + + if (fieldName.includes('image') || fieldName.includes('avatar')) { + return 'faker.image.url()'; + } + + if (fieldName.includes('price') || fieldName.includes('amount')) { + return 'faker.commerce.price()'; + } + + // Handle based on schema type + switch (type) { + case 'String': + if (attributes.min && attributes.max) { + return \`faker.lorem.words({ min: \${attributes.min}, max: \${attributes.max} })\`; + } + return 'faker.lorem.words()'; + + case 'Number': + case 'Integer': + const min = attributes.min || 1; + const max = attributes.max || 1000; + return \`faker.number.int({ min: \${min}, max: \${max} })\`; + + case 'Boolean': + return 'faker.datatype.boolean()'; + + case 'Date': + if (fieldName.includes('birth')) { + return 'faker.date.birthdate()'; + } + if (fieldName.includes('future')) { + return 'faker.date.future()'; + } + if (fieldName.includes('past')) { + return 'faker.date.past()'; + } + return 'faker.date.recent()'; + + case 'JSON': + return 'faker.datatype.json()'; + + case 'ID': + return 'faker.string.uuid()'; + + default: + // Check if it's an enum or custom type + if (type.endsWith('Role') || type.endsWith('Status') || type.endsWith('Type')) { + return \`generate\${type}()\`; + } + return 'faker.lorem.word()'; + } +}`; + +//--------------------------------------------------------------------// + +const mockDataExample = + `function generateMockData(models: Record, config: TestDataConfig): string { + if (config.format === 'json') { + return generateJSONMockData(models, config); + } + + let content = '// Mock Data\\n'; + + for (const [modelName, model] of Object.entries(models)) { + content += \`export const mock\${modelName}Data = generate\${modelName}Array(\${config.count || 10});\\n\`; + } + + return content + '\\n'; +} + +function generateJSONMockData(models: Record, config: TestDataConfig): string { + let content = ''; + const mockData: Record = {}; + + for (const [modelName, model] of Object.entries(models)) { + const data = []; + for (let i = 0; i < (config.count || 10); i++) { + const item: Record = {}; + + for (const column of model.columns || []) { + item[column.name] = generateMockValue(column, config); + } + + data.push(item); + } + + mockData[modelName.toLowerCase()] = data; + } + + return JSON.stringify(mockData, null, 2); +} + +function generateMockValue(column: any, config: TestDataConfig): any { + const { type, attributes = {} } = column; + + // Simple mock value generation for JSON format + switch (type) { + case 'String': + if (attributes.email) return 'user@example.com'; + if (attributes.url) return 'https://example.com'; + if (column.name.toLowerCase().includes('name')) return 'John Doe'; + return 'Sample Text'; + + case 'Number': + case 'Integer': + return Math.floor(Math.random() * 1000) + 1; + + case 'Boolean': + return Math.random() > 0.5; + + case 'Date': + return new Date().toISOString(); + + case 'ID': + return \`id_\${Math.random().toString(36).substr(2, 9)}\`; + + default: + return 'mock_value'; + } +}`; + +//--------------------------------------------------------------------// + +const fixturesExample = + `function generateFixtures(schema: any, config: TestDataConfig): string { + let content = '// Test Fixtures\\n'; + + if (schema.model) { + for (const [modelName, model] of Object.entries(schema.model)) { + content += generateModelFixtures(modelName, model, config); + } + } + + return content; +} + +function generateModelFixtures(modelName: string, model: any, config: TestDataConfig): string { + const lowerName = modelName.toLowerCase(); + + return \`export const \${lowerName}Fixtures = { + valid: generate\${modelName}({ + // Override with specific test values + }), + + minimal: generate\${modelName}({ + // Minimal required fields only + \${generateMinimalFields(model)} + }), + + invalid: { + // Invalid data for negative testing + \${generateInvalidFields(model)} + }, + + edge: generate\${modelName}({ + // Edge case values + \${generateEdgeCaseFields(model)} + }), +}; + +\`; +}`; + +//--------------------------------------------------------------------// + +const fixtureUtilsExample = + `function generateMinimalFields(model: any): string { + const requiredFields = model.columns?.filter((col: any) => + col.required && !col.attributes?.id && !col.attributes?.default + ) || []; + + return requiredFields.map((col: any) => { + const value = getMinimalValue(col); + return \`\${col.name}: \${value}\`; + }).join(',\\n '); +} + +function generateInvalidFields(model: any): string { + const fields = model.columns?.slice(0, 3) || []; // First 3 fields for example + + return fields.map((col: any) => { + const invalidValue = getInvalidValue(col); + return \`\${col.name}: \${invalidValue}\`; + }).join(',\\n '); +} + +function generateEdgeCaseFields(model: any): string { + const fields = model.columns?.slice(0, 3) || []; // First 3 fields for example + + return fields.map((col: any) => { + const edgeValue = getEdgeCaseValue(col); + return \`\${col.name}: \${edgeValue}\`; + }).join(',\\n '); +}`; + +//--------------------------------------------------------------------// + +const valueGeneratorsExample = + `function getMinimalValue(column: any): string { + switch (column.type) { + case 'String': + return '"a"'; + case 'Number': + case 'Integer': + return column.attributes?.min || '1'; + case 'Boolean': + return 'true'; + case 'Date': + return 'new Date()'; + default: + return '""'; + } +} + +function getInvalidValue(column: any): string { + switch (column.type) { + case 'String': + if (column.attributes?.email) return '"invalid-email"'; + if (column.attributes?.min) return '""'; // Too short + return 'null'; + case 'Number': + case 'Integer': + return '"not-a-number"'; + case 'Boolean': + return '"not-boolean"'; + case 'Date': + return '"invalid-date"'; + default: + return 'null'; + } +} + +function getEdgeCaseValue(column: any): string { + switch (column.type) { + case 'String': + if (column.attributes?.max) { + return \`"\${'a'.repeat(column.attributes.max)}"\`; + } + return '"very long string that might cause issues with processing or display"'; + case 'Number': + case 'Integer': + return column.attributes?.max || '999999'; + case 'Boolean': + return 'false'; + case 'Date': + return 'new Date("1900-01-01")'; + default: + return '""'; + } +}`; + +//--------------------------------------------------------------------// + +const mainExportExample = + `function generateMainExport(schema: any, config: TestDataConfig): string { + if (config.format === 'json') { + return ''; // JSON format doesn't need exports + } + + let content = '// Main Export\\nexport const testData = {\\n'; + + // Export factories + if (config.generateFactories && schema.model) { + content += ' factories: {\\n'; + for (const modelName of Object.keys(schema.model)) { + content += \` \${modelName}: generate\${modelName},\\n\`; + content += \` \${modelName}Array: generate\${modelName}Array,\\n\`; + } + content += ' },\\n'; + } + + // Export mock data + if (schema.model) { + content += ' mockData: {\\n'; + for (const modelName of Object.keys(schema.model)) { + content += \` \${modelName.toLowerCase()}: mock\${modelName}Data,\\n\`; + } + content += ' },\\n'; + } + + // Export fixtures + if (config.generateFixtures && schema.model) { + content += ' fixtures: {\\n'; + for (const modelName of Object.keys(schema.model)) { + content += \` \${modelName.toLowerCase()}: \${modelName.toLowerCase()}Fixtures,\\n\`; + } + content += ' },\\n'; + } + + content += '};\\n\\nexport default testData;\\n'; + + return content; +} + +function validateConfig(config: any): asserts config is TestDataConfig { + if (!config.output || typeof config.output !== 'string') { + throw new Error('Test Data plugin requires "output" configuration as string'); + } + + if (!config.format || !['json', 'typescript', 'javascript'].includes(config.format)) { + throw new Error('format must be one of: json, typescript, javascript'); + } + + if (config.count && (typeof config.count !== 'number' || config.count < 1)) { + throw new Error('count must be a positive number'); + } +}`; + +//--------------------------------------------------------------------// + +export default function GenerationFunctions() { + return ( + <> + {/* Generation Functions Section Content */} +
+ + {factoriesExample} + + + + {fieldGeneratorExample} + + + + {mockDataExample} + + + + {fixturesExample} + + + + {fixtureUtilsExample} + + + + {valueGeneratorsExample} + + + + {mainExportExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/test-data-plugin/Overview.tsx b/packages/www/plugins/docs/components/test-data-plugin/Overview.tsx new file mode 100644 index 0000000..c8a84ac --- /dev/null +++ b/packages/www/plugins/docs/components/test-data-plugin/Overview.tsx @@ -0,0 +1,65 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, SS } from '../../../docs/components/index.js'; + +export default function Overview() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Creating a Test Data Generator Plugin */} +
+

{_('Test Data Generator Plugin Tutorial')}

+

+ + This tutorial demonstrates how to create a plugin that + generates mock data and test fixtures from .idea schema + files. The plugin will transform your schema models into + realistic test data for development, testing, and prototyping. + +

+
+ + {/* Overview Section Content */} +
+

{_('1. Overview')}

+

+ + Test data generation is crucial for development and testing + workflows. This plugin generates realistic mock data from your + .idea schema, including: + +

+
    +
  • + Mock Data: + Realistic test data based on schema types + +
  • +
  • + Fixtures: + Predefined test datasets for consistent testing + +
  • +
  • + Factories: + Data generation functions for dynamic testing + +
  • +
  • + Relationships: + Proper handling of model relationships + +
  • +
  • + Customization: + Custom data generators and constraints + +
  • +
+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/test-data-plugin/PluginStructure.tsx b/packages/www/plugins/docs/components/test-data-plugin/PluginStructure.tsx new file mode 100644 index 0000000..296dfba --- /dev/null +++ b/packages/www/plugins/docs/components/test-data-plugin/PluginStructure.tsx @@ -0,0 +1,62 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const pluginStructureExample = + `import type { PluginProps } from '@stackpress/idea-transformer/types'; +import fs from 'fs/promises'; +import path from 'path'; + +interface TestDataConfig { + output: string; + format: 'json' | 'typescript' | 'javascript'; + count?: number; + seed?: number; + locale?: string; + generateFactories?: boolean; + generateFixtures?: boolean; + customGenerators?: Record; + relationships?: boolean; +} + +export default async function generateTestData( + props: PluginProps<{ config: TestDataConfig }> +) { + const { config, schema, transformer } = props; + + // Implementation here... +}`; + +//--------------------------------------------------------------------// + +export default function PluginStructure() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Plugin Structure Section Content */} +
+

{_('3. Plugin Structure')}

+

+ + The following code shows how to generally layout the + plugin so you can focus on the implementation. + +

+ + {pluginStructureExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/test-data-plugin/Prerequisites.tsx b/packages/www/plugins/docs/components/test-data-plugin/Prerequisites.tsx new file mode 100644 index 0000000..2ffb67b --- /dev/null +++ b/packages/www/plugins/docs/components/test-data-plugin/Prerequisites.tsx @@ -0,0 +1,57 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C } from '../../../docs/components/index.js'; + +export default function Prerequisites() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Prerequisites Section Content */} +
+

{_('2. Prerequisites')}

+

+ + Before creating this plugin, you should have the + following knowledge and tools: + +

+
    +
  • + + Node.js 16+ and npm/yarn + +
  • +
  • + + TypeScript 4.0+ + +
  • +
  • + + Faker.js 8.0+ (for realistic data generation) + +
  • +
  • + + Basic understanding of testing concepts + +
  • +
  • + + Familiarity with the @stackpress/idea-transformer + library + +
  • +
  • + + Understanding of .idea schema format + +
  • +
+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/test-data-plugin/SchemaConfiguration.tsx b/packages/www/plugins/docs/components/test-data-plugin/SchemaConfiguration.tsx new file mode 100644 index 0000000..dce68e1 --- /dev/null +++ b/packages/www/plugins/docs/components/test-data-plugin/SchemaConfiguration.tsx @@ -0,0 +1,166 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +import { Table, Thead, Trow, Tcol } from 'frui/element/Table'; +//local +import { H1, H2, P, C, SS } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const schemaConfigExample = + `plugin "./plugins/test-data.js" { + output "./generated/test-data.ts" + format "typescript" + count 20 + seed 12345 + locale "en" + generateFactories true + generateFixtures true + relationships true + customGenerators { + Email "faker.internet.email()" + Password "faker.internet.password()" + Slug "faker.lorem.slug()" + } +}`; + +//--------------------------------------------------------------------// + +export default function SchemaConfiguration() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Schema Configuration Section Content */} +
+

{_('5. Schema Configuration')}

+

+ + The schema configuration section demonstrates how to + integrate the test data plugin into your .idea schema + files. This includes plugin declaration syntax, configuration + options, and examples of how to customize the plugin + behavior for different use cases. + +

+

+ + Add the Test Data plugin to your .idea schema file: + +

+ + {schemaConfigExample} + + +

{_('5.1. Configuration Options')}

+

+ + The following options will be processed by the test data + plugin in this tutorial. + +

+ + + + Option + Type + Default + Description + + + output + string + Required + + + Output file path for test data + + + + + format + 'json'|'typescript'|'javascript' + Required + + + Output format + + + + + count + number + 10 + + + Number of records to generate per model + + + + + seed + number + undefined + + + Seed for reproducible data generation + + + + + locale + string + 'en' + + + Locale for faker.js data generation + + + + + generateFactories + boolean + true + + + Generate data factory functions + + + + + generateFixtures + boolean + true + + + Generate test fixtures + + + + + customGenerators + object + {`{}`} + + + Custom data generators for specific types + + + + + relationships + boolean + false + + + Handle model relationships + + + +
+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/test-data-plugin/index.tsx b/packages/www/plugins/docs/components/test-data-plugin/index.tsx new file mode 100644 index 0000000..c7eca0a --- /dev/null +++ b/packages/www/plugins/docs/components/test-data-plugin/index.tsx @@ -0,0 +1,8 @@ +//exporting all components to have multiple imports from a single file +export { default as Conclusion } from './Conclusion.js'; +export { default as CorePluginFunction } from './CorePluginFunction.js'; +export { default as GenerationFunctions } from './GenerationFunctions.js'; +export { default as Overview } from './Overview.js'; +export { default as PluginStructure } from './PluginStructure.js'; +export { default as Prerequisites } from './Prerequisites.js'; +export { default as SchemaConfiguration } from './SchemaConfiguration.js'; \ No newline at end of file diff --git a/packages/www/plugins/docs/components/ts-morph-plugin-guide/AdvanceTsMorphPlugin.tsx b/packages/www/plugins/docs/components/ts-morph-plugin-guide/AdvanceTsMorphPlugin.tsx new file mode 100644 index 0000000..cb63b1a --- /dev/null +++ b/packages/www/plugins/docs/components/ts-morph-plugin-guide/AdvanceTsMorphPlugin.tsx @@ -0,0 +1,215 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const examples = [ + `// Add a class with decorators +sourceFile.addClass({ + name: "UserController", + isExported: true, + decorators: [ + { + name: "Controller", + arguments: ["'users'"], + }, + ], + methods: [ + { + name: "getUser", + decorators: [ + { + name: "Get", + arguments: ["':id'"], + }, + ], + parameters: [ + { + name: "id", + type: "string", + decorators: [ + { + name: "Param", + arguments: ["'id'"], + }, + ], + }, + ], + returnType: "Promise", + statements: "return this.userService.findById(id);", + }, + ], +});`, + + //------------------------------------------------------------------// + + `// Generate mapped types +sourceFile.addTypeAlias({ + name: "PartialUser", + type: "{ [K in keyof User]?: User[K] }", +}); + +// Generate conditional types +sourceFile.addTypeAlias({ + name: "NonNullable", + typeParameters: [{ name: "T" }], + type: "T extends null | undefined ? never : T", +}); + +// Generate template literal types +sourceFile.addTypeAlias({ + name: "EventName", + typeParameters: [{ name: "T", constraint: "string" }], + type: \`on\${Capitalize}\`, +});`, + + //------------------------------------------------------------------// + + `// Add module declaration +sourceFile.addModule({ + name: "Express", + declarationKind: ModuleDeclarationKind.Module, + statements: [ + { + kind: StructureKind.Interface, + name: "Request", + properties: [ + { name: "user", type: "User", hasQuestionToken: true }, + ], + }, + ], +}); + +// Add ambient module +sourceFile.addModule({ + name: '"my-library"', + declarationKind: ModuleDeclarationKind.Module, + hasDeclareKeyword: true, + statements: [ + "export function myFunction(): void;", + ], +});`, + + //------------------------------------------------------------------// + + `// Find and modify existing interfaces +const existingInterface = sourceFile.getInterface("User"); +if (existingInterface) { + // Add new properties + existingInterface.addProperty({ + name: "lastLoginAt", + type: "Date", + hasQuestionToken: true, + }); + + // Modify existing properties + const emailProp = existingInterface.getProperty("email"); + if (emailProp) { + emailProp.setType("string & { readonly brand: 'Email' }"); + } + + // Add extends clause + existingInterface.addExtends("BaseEntity"); +} + +// Remove nodes +const deprecatedMethod = sourceFile.getFunction("oldFunction"); +deprecatedMethod?.remove();` +]; + +//--------------------------------------------------------------------// + +export default function AdvanceTsMorphPlugin() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Advanced ts-morph Features Section Content*/} +
+

{_('6. Advanced ts-morph Features')}

+

+ + Advanced ts-morph features enable sophisticated code + generation scenarios including decorators, complex type + systems, module declarations, and code manipulation. + These features are essential for building production-ready + plugins that handle enterprise-level requirements. + +

+ +

{_('6.1. Working with Decorators')}

+

+ + Decorators are essential for modern TypeScript applications, + especially when working with frameworks like Angular, NestJS, + or TypeORM. ts-morph provides comprehensive support for + generating classes and methods with decorators. + +

+ + {examples[0]} + + +

{_('6.2. Generating Complex Types')}

+

+ + Complex type generation includes mapped types, conditional + types, and template literal types that leverage TypeScript's + advanced type system. These features enable the creation + of sophisticated type-safe APIs and utility types. + +

+ + {examples[1]} + + +

{_('6.3. Working with Modules')}

+

+ + Module declarations and ambient modules are crucial for + creating type definitions and extending existing libraries. + This section covers both namespace-style modules and modern + ES module patterns. + +

+ + {examples[2]} + + +

{_('6.4. Manipulating Existing Code')}

+

+ + Code manipulation capabilities allow plugins to modify + existing TypeScript files, add new functionality, and + refactor code structures. This is particularly useful + for migration tools and code modernization plugins. + +

+ + {examples[3]} + +
+ + ) +} diff --git a/packages/www/plugins/docs/components/ts-morph-plugin-guide/BestPractices.tsx b/packages/www/plugins/docs/components/ts-morph-plugin-guide/BestPractices.tsx new file mode 100644 index 0000000..3d9f886 --- /dev/null +++ b/packages/www/plugins/docs/components/ts-morph-plugin-guide/BestPractices.tsx @@ -0,0 +1,300 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const examples = [ + `interface PluginOptions { + readonly input: string; + readonly output: string; + readonly strict?: boolean; +} + +function validateOptions(options: unknown): asserts options is PluginOptions { + if (typeof options !== 'object' || options === null) { + throw new Error('Options must be an object'); + } + + const opts = options as Record; + + if (typeof opts.input !== 'string') { + throw new Error('input must be a string'); + } + + if (typeof opts.output !== 'string') { + throw new Error('output must be a string'); + } +}`, + + //------------------------------------------------------------------// + + `class PluginError extends Error { + constructor( + message: string, + public readonly code: string, + public readonly details?: any + ) { + super(message); + this.name = 'PluginError'; + } +} + +async function safeGenerate(config: PluginConfig): Promise { + try { + await generator.generate(); + } catch (error) { + if (error instanceof SyntaxError) { + throw new PluginError( + 'Invalid JSON in input file', + 'INVALID_JSON', + { originalError: error.message } + ); + } + + if (error.code === 'ENOENT') { + throw new PluginError( + 'Input file not found', + 'FILE_NOT_FOUND', + { path: config.input } + ); + } + + throw error; + } +}`, + + //------------------------------------------------------------------// + + `class OptimizedGenerator { + private typeCache = new Map(); + private interfaceCache = new Map(); + + private getCachedType(property: SchemaProperty): string { + const cacheKey = JSON.stringify(property); + + if (this.typeCache.has(cacheKey)) { + return this.typeCache.get(cacheKey)!; + } + + const type = this.mapSchemaTypeToTypeScript(property); + this.typeCache.set(cacheKey, type); + + return type; + } + + private batchAddProperties( + interfaceDecl: InterfaceDeclaration, + properties: Record + ): void { + const propertyStructures = Object.entries(properties).map(([name, prop]) => ({ + name, + type: this.getCachedType(prop), + hasQuestionToken: !prop.required, + })); + + interfaceDecl.addProperties(propertyStructures); + } +}`, + + //------------------------------------------------------------------// + + `// generators/interface-generator.ts +export class InterfaceGenerator { + generate(schema: Schema): InterfaceDeclaration { + // Interface-specific logic + } +} + +// generators/type-generator.ts +export class TypeGenerator { + generate(schema: Schema): TypeAliasDeclaration { + // Type alias-specific logic + } +} + +// generators/enum-generator.ts +export class EnumGenerator { + generate(schema: EnumSchema): EnumDeclaration { + // Enum-specific logic + } +} + +// main-plugin.ts +export class MainPlugin { + constructor( + private interfaceGenerator: InterfaceGenerator, + private typeGenerator: TypeGenerator, + private enumGenerator: EnumGenerator + ) {} + + async generate(config: PluginConfig): Promise { + // Orchestrate all generators + } +}`, + + //------------------------------------------------------------------// + + `function generateJSDocComment( + property: SchemaProperty, + includeExamples: boolean = true +): string { + const parts: string[] = []; + + if (property.description) { + parts.push(property.description); + } + + if (property.default !== undefined) { + parts.push(\`@default \${JSON.stringify(property.default)}\`); + } + + if (includeExamples && property.example) { + parts.push(\`@example \${property.example}\`); + } + + if (property.deprecated) { + parts.push(\`@deprecated \${property.deprecated}\`); + } + + return parts.length > 0 ? parts.join('\\n') : ''; +}` +]; + +//--------------------------------------------------------------------// + +export default function BestPractices() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Best Practices Section Content */} +
+

{_('8. Best Practices')}

+

+ + Following best practices ensures your plugins are maintainable, + performant, and reliable in production environments. These + guidelines cover type safety, error handling, performance + optimization, and code organization strategies. + +

+ +

{_('8.1. Type Safety')}

+

+ + Type safety is fundamental to building reliable plugins + that catch errors at compile time rather than runtime. + Always use TypeScript interfaces and proper type validation + throughout your plugin implementation. + +

+

+ + Always use TypeScript interfaces for your plugin + configuration and data structures: + +

+ + {examples[0]} + + +

{_('8.2. Error Handling')}

+

+ + Comprehensive error handling provides clear feedback to + users and helps with debugging when things go wrong. + Implement custom error types and meaningful error + messages to improve the developer experience. + +

+

+ + Implement comprehensive error handling: + +

+ + {examples[1]} + + +

{_('8.3. Performance Optimization')}

+

+ + Performance optimization becomes crucial when dealing + with large schemas or generating substantial amounts of + code. Implement caching strategies and batch processing + to maintain reasonable execution times. + +

+

+ + For large schemas, optimize performance: + +

+ + {examples[2]} + + +

{_('8.4. Code Organization')}

+

+ + Proper code organization makes your plugin easier to + maintain, test, and extend. Separate concerns into focused + classes and modules that each handle specific aspects of + the generation process. + +

+

+ + Structure your plugin code for maintainability: + +

+ + {examples[3]} + + +

{_('8.5. Documentation Generation')}

+

+ + Documentation generation ensures your generated code is + self-documenting and provides valuable context for developers. + Implement comprehensive JSDoc comment generation with examples + and type information. + +

+

+ + Add comprehensive JSDoc comments: + +

+ + {examples[4]} + +
+ + ) +} diff --git a/packages/www/plugins/docs/components/ts-morph-plugin-guide/CreateFirstPlugin.tsx b/packages/www/plugins/docs/components/ts-morph-plugin-guide/CreateFirstPlugin.tsx new file mode 100644 index 0000000..aea4157 --- /dev/null +++ b/packages/www/plugins/docs/components/ts-morph-plugin-guide/CreateFirstPlugin.tsx @@ -0,0 +1,634 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, C } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const examples = [ + `// src/types.ts +export interface SchemaProperty { + type: string; + required?: boolean; + description?: string; + default?: any; + items?: SchemaProperty; // For arrays + properties?: Record; // For objects +} + +export interface Schema { + name: string; + description?: string; + properties: Record; + required?: string[]; +} + +export interface PluginConfig { + input: string; + output: string; + namespace?: string; + generateComments?: boolean; + generateUtilityTypes?: boolean; + exportType?: 'named' | 'default' | 'namespace'; +}`, + + //------------------------------------------------------------------// + + `// src/plugin.ts +import { Project, SourceFile, InterfaceDeclaration } from "ts-morph"; +import { Schema, SchemaProperty, PluginConfig } from "./types"; +import fs from "fs/promises"; +import path from "path"; + +export class TypeScriptInterfaceGenerator { + private project: Project; + private config: PluginConfig; + + constructor(config: PluginConfig) { + this.config = config; + this.project = new Project({ + compilerOptions: { + target: 99, // Latest + module: 1, // CommonJS + declaration: true, + strict: true, + }, + }); + } + + async generate(): Promise { + try { + // Read input schema + const schemas = await this.loadSchemas(); + + // Create source file + const sourceFile = this.project.createSourceFile( + this.config.output, + "", + { overwrite: true } + ); + + // Generate file header + this.addFileHeader(sourceFile); + + // Generate interfaces for each schema + for (const schema of schemas) { + this.generateInterface(sourceFile, schema); + } + + // Generate utility types if requested + if (this.config.generateUtilityTypes) { + this.generateUtilityTypes(sourceFile, schemas); + } + + // Wrap in namespace if specified + if (this.config.namespace) { + this.wrapInNamespace(sourceFile); + } + + // Save the file + await sourceFile.save(); + + console.log(\`✅ Generated TypeScript interfaces: \${this.config.output}\`); + } catch (error) { + console.error("❌ Generation failed:", error); + throw error; + } + } + + private async loadSchemas(): Promise { + const content = await fs.readFile(this.config.input, "utf-8"); + const data = JSON.parse(content); + + // Handle both single schema and array of schemas + return Array.isArray(data) ? data : [data]; + } + + private addFileHeader(sourceFile: SourceFile): void { + const timestamp = new Date().toISOString(); + sourceFile.insertText(0, \` +/** + * Generated TypeScript interfaces + * Generated at: \${timestamp} + * Source: \${this.config.input} + * + * This file is auto-generated. Do not edit manually. + */ +\`); + } + + private generateInterface(sourceFile: SourceFile, schema: Schema): void { + const interfaceDeclaration = sourceFile.addInterface({ + name: schema.name, + isExported: this.config.exportType !== 'namespace', + }); + + // Add JSDoc comment if enabled + if (this.config.generateComments && schema.description) { + interfaceDeclaration.addJsDoc({ + description: schema.description, + }); + } + + // Add properties + for (const [propName, propSchema] of Object.entries(schema.properties)) { + this.addProperty(interfaceDeclaration, propName, propSchema, schema.required); + } + } + + private addProperty( + interfaceDecl: InterfaceDeclaration, + name: string, + property: SchemaProperty, + requiredFields?: string[] + ): void { + const isRequired = requiredFields?.includes(name) ?? property.required ?? false; + const typeString = this.mapSchemaTypeToTypeScript(property); + + const propertySignature = interfaceDecl.addProperty({ + name, + type: typeString, + hasQuestionToken: !isRequired, + }); + + // Add JSDoc comment if enabled + if (this.config.generateComments) { + const jsdocParts: string[] = []; + + if (property.description) { + jsdocParts.push(property.description); + } + + if (property.default !== undefined) { + jsdocParts.push(\`@default \${JSON.stringify(property.default)}\`); + } + + if (jsdocParts.length > 0) { + propertySignature.addJsDoc({ + description: jsdocParts.join('\n'), + }); + } + } + } + + private mapSchemaTypeToTypeScript(property: SchemaProperty): string { + switch (property.type) { + case 'string': + return 'string'; + case 'number': + case 'integer': + return 'number'; + case 'boolean': + return 'boolean'; + case 'array': + if (property.items) { + const itemType = this.mapSchemaTypeToTypeScript(property.items); + return \`\${itemType}[]\`; + } + return 'any[]'; + case 'object': + if (property.properties) { + // Generate inline interface + const props = Object.entries(property.properties) + .map(([key, prop]) => { + const type = this.mapSchemaTypeToTypeScript(prop); + const optional = prop.required ? '' : '?'; + return \`\${key}\${optional}: \${type}\`; + }) + .join('; '); + return \`{ \${props} }\`; + } + return 'Record'; + default: + // Assume it's a reference to another interface + return property.type; + } + } + + private generateUtilityTypes(sourceFile: SourceFile, schemas: Schema[]): void { + sourceFile.addStatements("\n// Utility Types"); + + for (const schema of schemas) { + const interfaceName = schema.name; + + // Generate Create input type (omit auto-generated fields) + sourceFile.addTypeAlias({ + name: \`Create\${interfaceName}Input\`, + isExported: this.config.exportType !== 'namespace', + type: \`Omit<\${interfaceName}, 'id' | 'createdAt' | 'updatedAt'>\`, + }); + + // Generate Update input type (all fields optional) + sourceFile.addTypeAlias({ + name: \`Update\${interfaceName}Input\`, + isExported: this.config.exportType !== 'namespace', + type: \`Partial<\${interfaceName}>\`, + }); + + // Generate keys type + sourceFile.addTypeAlias({ + name: \`\${interfaceName}Keys\`, + isExported: this.config.exportType !== 'namespace', + type: \`keyof \${interfaceName}\`, + }); + } + + // Generate union type of all models + if (schemas.length > 1) { + const allTypes = schemas.map(s => s.name).join(' | '); + sourceFile.addTypeAlias({ + name: 'AnyModel', + isExported: this.config.exportType !== 'namespace', + type: allTypes, + }); + } + } + + private wrapInNamespace(sourceFile: SourceFile): void { + const content = sourceFile.getFullText(); + sourceFile.removeText(); + + // Extract header comments + const headerMatch = content.match(/^(\/\*\*[\s\S]*?\*\/\s*)/); + const header = headerMatch ? headerMatch[1] : ''; + const bodyContent = content.replace(header, ''); + + // Add header back + if (header) { + sourceFile.insertText(0, header); + } + + // Create namespace + const namespace = sourceFile.addNamespace({ + name: this.config.namespace!, + isExported: this.config.exportType === 'default' ? false : true, + }); + + // Add content to namespace + namespace.addStatements(bodyContent.trim()); + + // Add default export if specified + if (this.config.exportType === 'default') { + sourceFile.addExportAssignment({ + expression: this.config.namespace!, + isExportEquals: false, + }); + } + } +}`, + + //------------------------------------------------------------------// + + `// src/index.ts +import { TypeScriptInterfaceGenerator } from "./plugin"; +import { PluginConfig } from "./types"; + +export async function generateTypeScriptInterfaces(config: PluginConfig): Promise { + const generator = new TypeScriptInterfaceGenerator(config); + await generator.generate(); +} + +export * from "./types"; +export { TypeScriptInterfaceGenerator }; + +// CLI usage +if (require.main === module) { + const config: PluginConfig = { + input: process.argv[2] || "examples/input.json", + output: process.argv[3] || "examples/output.ts", + generateComments: true, + generateUtilityTypes: true, + exportType: 'named', + }; + + generateTypeScriptInterfaces(config).catch(console.error); +}`, + + //------------------------------------------------------------------// + + `// examples/input.json +[ + { + "name": "User", + "description": "Represents a user in the system", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the user" + }, + "email": { + "type": "string", + "description": "User's email address" + }, + "name": { + "type": "string", + "description": "User's full name" + }, + "age": { + "type": "number", + "description": "User's age in years" + }, + "isActive": { + "type": "boolean", + "description": "Whether the user account is active", + "default": true + }, + "roles": { + "type": "array", + "items": { + "type": "string" + }, + "description": "User's assigned roles" + }, + "profile": { + "type": "object", + "properties": { + "bio": { + "type": "string" + }, + "avatar": { + "type": "string" + } + }, + "description": "User's profile information" + }, + "createdAt": { + "type": "string", + "description": "Account creation timestamp" + } + }, + "required": ["id", "email", "name"] + }, + { + "name": "Post", + "description": "Represents a blog post", + "properties": { + "id": { + "type": "string", + "description": "Unique identifier for the post" + }, + "title": { + "type": "string", + "description": "Post title" + }, + "content": { + "type": "string", + "description": "Post content" + }, + "authorId": { + "type": "string", + "description": "ID of the post author" + }, + "tags": { + "type": "array", + "items": { + "type": "string" + }, + "description": "Post tags" + }, + "publishedAt": { + "type": "string", + "description": "Publication timestamp" + } + }, + "required": ["id", "title", "content", "authorId"] + } +]`, + + //------------------------------------------------------------------// + + `npx ts-node src/index.ts examples/input.json examples/output.ts`, + + //------------------------------------------------------------------// + + `// examples/output.ts +/** + * Generated TypeScript interfaces + * Generated at: 2024-01-15T10:30:00.000Z + * Source: examples/input.json + * + * This file is auto-generated. Do not edit manually. + */ + +/** + * Represents a user in the system + */ +export interface User { + /** + * Unique identifier for the user + */ + id: string; + /** + * User's email address + */ + email: string; + /** + * User's full name + */ + name: string; + /** + * User's age in years + */ + age?: number; + /** + * Whether the user account is active + * @default true + */ + isActive?: boolean; + /** + * User's assigned roles + */ + roles?: string[]; + /** + * User's profile information + */ + profile?: { bio?: string; avatar?: string }; + /** + * Account creation timestamp + */ + createdAt?: string; +} + +/** + * Represents a blog post + */ +export interface Post { + /** + * Unique identifier for the post + */ + id: string; + /** + * Post title + */ + title: string; + /** + * Post content + */ + content: string; + /** + * ID of the post author + */ + authorId: string; + /** + * Post tags + */ + tags?: string[]; + /** + * Publication timestamp + */ + publishedAt?: string; +} + +// Utility Types +export type CreateUserInput = Omit; + +export type UpdateUserInput = Partial; + +export type UserKeys = keyof User; + +export type CreatePostInput = Omit; + +export type UpdatePostInput = Partial; + +export type PostKeys = keyof Post; + +export type AnyModel = User | Post;` +]; + +//--------------------------------------------------------------------// + +export default function CreateFirstPlugin() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Creating Your First Plugin Section Content */} +
+

{_('5. Creating Your First Plugin')}

+

+ + Creating your first plugin with ts-morph involves + understanding the complete workflow from schema processing + to code generation. This comprehensive example demonstrates + building a TypeScript interface generator that transforms + JSON schemas into properly typed interfaces with full feature + support. + +

+

+ + Let's create a plugin that generates TypeScript interfaces + from JSON schema definitions. This will demonstrate the core + concepts of using ts-morph for code generation. + +

+ +

{_('5.1. Define the Plugin Interface')}

+

+ + Defining clear interfaces for your plugin ensures type safety + and provides a solid foundation for implementation. This + section establishes the data structures and configuration + options that will guide the entire plugin development process. + +

+

+ + First, let's define the types for our plugin: + +

+ + {examples[0]} + + +

{_('5.2. Core Plugin Implementation')}

+

+ + The core plugin implementation orchestrates the entire code + generation process, from loading input schemas to generating and + saving TypeScript files. This comprehensive class demonstrates + best practices for plugin architecture and error handling. + +

+ + {examples[1]} + + +

{_('5.3. Plugin Entry Point')}

+

+ + The plugin entry point provides a clean API for consumers and + handles CLI integration. This section shows how to create both + programmatic and command-line interfaces for your plugin, making + it accessible in different usage scenarios. + +

+ + {examples[2]} + + +

{_('5.4. Example Usage')}

+

+ + Example usage demonstrates the plugin in action with + realistic data structures. This comprehensive example + shows how the plugin processes complex schemas with + various property types, relationships, and validation + rules. + +

+

+ + Create an example schema file: + +

+ + {examples[3]} + +

+ + Run the plugin: + +

+ + {examples[4]} + +

+ + Generated output: + +

+ + {examples[5]} + +
+ + ) +} diff --git a/packages/www/plugins/docs/components/ts-morph-plugin-guide/Installation.tsx b/packages/www/plugins/docs/components/ts-morph-plugin-guide/Installation.tsx new file mode 100644 index 0000000..2ed3669 --- /dev/null +++ b/packages/www/plugins/docs/components/ts-morph-plugin-guide/Installation.tsx @@ -0,0 +1,96 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C, SS } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const examples = + `# Using npm +npm install --save-dev ts-morph + +# Using yarn +yarn add --dev ts-morph + +# Using Deno +deno add ts-morph@jsr:@ts-morph/ts-morph`; + +//--------------------------------------------------------------------// + +export default function installation() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Installation Section Content */} +
+

{_('2. Installation')}

+

+ + Before starting with ts-morph plugin development, + ensure you have the necessary tools and knowledge. This + section outlines the essential requirements for successful + plugin creation and provides installation guidance. + +

+ +

+ + Before starting, ensure you have: + +

+ +
    +
  • + {_('Node.js 16+')} + + and npm/yarn installed + +
  • +
  • + {_('TypeScript 4.0+')} + + knowledge + +
  • +
  • + + Basic understanding of Abstract Syntax Trees (AST) + +
  • +
  • + + Familiarity with TypeScript interfaces, classes, and + modules + +
  • +
+ +

+ + Installing ts-morph is straightforward and can be + done using your preferred package manager. The library is + available through npm, yarn, and even Deno for different + development environments. + +

+ +

+ + Install ts-morph in your project: + +

+ + {examples} + +
+ + ) +} diff --git a/packages/www/plugins/docs/components/ts-morph-plugin-guide/Introduction.tsx b/packages/www/plugins/docs/components/ts-morph-plugin-guide/Introduction.tsx new file mode 100644 index 0000000..543c287 --- /dev/null +++ b/packages/www/plugins/docs/components/ts-morph-plugin-guide/Introduction.tsx @@ -0,0 +1,147 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, C, SS } from '../../../docs/components/index.js'; + +export default function Introduction() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Introduction Section Content */} +
+

{_('Creating Plugins with ts-morph: A Comprehensive Guide')}

+

+ + This guide demonstrates how to create powerful code + generation plugins using ts-morph, a TypeScript library + that provides an easier way to programmatically navigate + and manipulate TypeScript and JavaScript code. We'll walk + through creating a complete plugin that generates TypeScript + interfaces from schema definitions. + +

+ +

{_('1. Introduction')}

+

+ + ts-morph is a powerful TypeScript library that + wraps the TypeScript Compiler API, making it much easier + to work with TypeScript Abstract Syntax Trees (AST). This + introduction covers the fundamental concepts and advantages + of using ts-morph for plugin development. + +

+

+ + Unlike string-based code generation, ts-morph + provides: + +

+
    +
  • + {_('Type-safe code manipulation:')} + + Work with actual TypeScript nodes instead of strings + +
  • +
  • + {_('Automatic formatting:')} + + Generated code is properly formatted and follows + TypeScript + conventions + +
  • +
  • + {_('IntelliSense support:')} + + Full IDE support when writing your plugins + +
  • +
  • + {_('AST navigation:')} + + Easy traversal and modification of code structures + +
  • +
  • + {_('Validation:')} + + Automatic syntax validation of generated code + +
  • +
+ +

{_('Why Use ts-morph for Plugins?')}

+

+ + Understanding the advantages of ts-morph over + traditional code generation approaches helps you make + informed decisions about plugin architecture. This + comparison highlights the key benefits that make ts- + morph an excellent choice for TypeScript code + generation. + +

+

+ + Traditional code generation often involves: + +

+
    +
  • + + Concatenating strings to build code + +
  • +
  • + + Manual indentation and formatting + +
  • +
  • + + Error-prone syntax construction + +
  • +
  • + + Difficulty maintaining complex code structures + +
  • +
+ +

+ + With ts-morph, you can: + +

+
    +
  • + + Create TypeScript constructs programmatically + +
  • +
  • + + Leverage the compiler's knowledge for validation + +
  • +
  • + + Generate properly formatted, syntactically correct + code + +
  • +
  • + + Easily modify existing code structures + +
  • +
+
+ + ) +} diff --git a/packages/www/plugins/docs/components/ts-morph-plugin-guide/References.tsx b/packages/www/plugins/docs/components/ts-morph-plugin-guide/References.tsx new file mode 100644 index 0000000..2fc05b7 --- /dev/null +++ b/packages/www/plugins/docs/components/ts-morph-plugin-guide/References.tsx @@ -0,0 +1,194 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, H3, P } from '../../../docs/components/index.js' + +export default function References() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* References Section Content */} +
+

{_('10. References')}

+

+ + This section provides comprehensive resources for continued + learning and development with ts-morph. These references + include official documentation, community resources, and + related tools that enhance the plugin development experience. + +

+
+ + {/* Official Documentation */} +
+

{_('10.1. Official Documentation')}

+

+ + Official documentation provides authoritative information + about ts-morph APIs, TypeScript compiler internals, and AST + manipulation techniques. + +

+

+ + ts-morph Documentation + : + https://ts-morph.com/ +

+

+ + TypeScript Compiler API + : + https://github.com/Microsoft/TypeScript/wiki/Using-the-Compiler-API +

+

+ + TypeScript AST Viewer + : + https://ts-ast-viewer.com/ +

+
+ + {/* Useful Resources */} +
+

{_('10.2. Useful Resources')}

+

+ + Additional resources provide practical examples, community + insights, and tools that complement the official documentation + for comprehensive plugin development. + +

+

+ + ts-morph GitHub Repository + : + https://github.com/dsherret/ts-morph +

+

+ + TypeScript Handbook + : + https://www.typescriptlang.org/docs/ +

+

+ AST Explorer: + https://astexplorer.net/ +

+
+ + {/* Community Examples and Related Tools */} +
+

{_('10.3. Community Examples')}

+

+ + Community examples showcase real-world usage patterns + and provide inspiration for advanced plugin development + techniques. + +

+

+ + ts-morph Examples + : + https://github.com/dsherret/ts-morph/tree/latest/packages/ts-morph/scripts +

+

+ + Code Generation Patterns + : + https://github.com/topics/code-generation +

+ +

{_('Related Tools')}

+

+ + TypeScript ESLint + : + + For linting generated code + +

+

+ Prettier: + + For formatting generated code + +

+

+ ts-node: + + For running TypeScript directly + +

+

+ Jest: + + For testing your plugins + +

+ +

+ + This comprehensive guide provides everything you need + to create powerful code generation plugins using ts-morph. + The library's type-safe approach to code manipulation + makes it an excellent choice for building robust, maintainable + code generators that produce high-quality TypeScript output. + +

+
+ + ) +} diff --git a/packages/www/plugins/docs/components/ts-morph-plugin-guide/SettingUpProject.tsx b/packages/www/plugins/docs/components/ts-morph-plugin-guide/SettingUpProject.tsx new file mode 100644 index 0000000..a9578fb --- /dev/null +++ b/packages/www/plugins/docs/components/ts-morph-plugin-guide/SettingUpProject.tsx @@ -0,0 +1,113 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const examples = [ + `mkdir ts-morph-plugin-tutorial +cd ts-morph-plugin-tutorial +npm init -y +npm install --save-dev typescript ts-morph @types/node`, + + //------------------------------------------------------------------// + + `{ + "compilerOptions": { + "target": "ES2020", + "module": "commonjs", + "lib": ["ES2020"], + "outDir": "./dist", + "rootDir": "./src", + "strict": true, + "esModuleInterop": true, + "skipLibCheck": true, + "forceConsistentCasingInFileNames": true, + "declaration": true, + "declarationMap": true, + "sourceMap": true + }, + "include": ["src/**/*"], + "exclude": ["node_modules", "dist"] +}`, + + //------------------------------------------------------------------// + + `ts-morph-plugin-tutorial/ +├── src/ +│ ├── index.ts +│ ├── plugin.ts +│ └── types.ts +├── examples/ +│ ├── input.json +│ └── output.ts +├── tests/ +│ └── plugin.test.ts +├── package.json +└── tsconfig.json` +]; + +//--------------------------------------------------------------------// + +export default function SettingUpProject() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Setting Up the Project Section Content */} +
+

{_('3. Setting Up the Project')}

+

+ + Setting up a proper project structure is crucial for + maintainable plugin development. This section guides you + through creating a well-organized TypeScript project with + all necessary configurations and dependencies + +

+

+ + Let's create a new TypeScript project for our plugin: + +

+ + {examples[0]} + + +

+ + Create a basic tsconfig.json: + +

+ + {examples[1]} + + +

+ + Create the project structure: + +

+ + {examples[2]} + +
+ + ) +} diff --git a/packages/www/plugins/docs/components/ts-morph-plugin-guide/TestingYourPlugin.tsx b/packages/www/plugins/docs/components/ts-morph-plugin-guide/TestingYourPlugin.tsx new file mode 100644 index 0000000..e5ae128 --- /dev/null +++ b/packages/www/plugins/docs/components/ts-morph-plugin-guide/TestingYourPlugin.tsx @@ -0,0 +1,184 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js' +import Code from '../../../docs/components/Code.js' + +//code examples +//--------------------------------------------------------------------// + +const examples = [ + `// tests/plugin.test.ts +import { TypeScriptInterfaceGenerator } from "../src/plugin"; +import { PluginConfig, Schema } from "../src/types"; +import { Project } from "ts-morph"; +import fs from "fs/promises"; +import path from "path"; + +describe("TypeScriptInterfaceGenerator", () => { + const testOutputDir = path.join(__dirname, "output"); + + beforeAll(async () => { + await fs.mkdir(testOutputDir, { recursive: true }); + }); + + afterAll(async () => { + await fs.rmdir(testOutputDir, { recursive: true }); + }); + + test("should generate basic interface", async () => { + const schema: Schema = { + name: "TestUser", + properties: { + id: { type: "string" }, + name: { type: "string" }, + age: { type: "number" }, + }, + required: ["id", "name"], + }; + + const inputFile = path.join(testOutputDir, "test-input.json"); + const outputFile = path.join(testOutputDir, "test-output.ts"); + + await fs.writeFile(inputFile, JSON.stringify(schema, null, 2)); + + const config: PluginConfig = { + input: inputFile, + output: outputFile, + generateComments: true, + }; + + const generator = new TypeScriptInterfaceGenerator(config); + await generator.generate(); + + // Verify the output + const generatedContent = await fs.readFile(outputFile, "utf-8"); + + expect(generatedContent).toContain("export interface TestUser"); + expect(generatedContent).toContain("id: string;"); + expect(generatedContent).toContain("name: string;"); + expect(generatedContent).toContain("age?: number;"); + }); + + test("should generate utility types", async () => { + const schema: Schema = { + name: "Product", + properties: { + id: { type: "string" }, + name: { type: "string" }, + price: { type: "number" }, + }, + required: ["id", "name", "price"], + }; + + const inputFile = path.join(testOutputDir, "product-input.json"); + const outputFile = path.join(testOutputDir, "product-output.ts"); + + await fs.writeFile(inputFile, JSON.stringify(schema, null, 2)); + + const config: PluginConfig = { + input: inputFile, + output: outputFile, + generateUtilityTypes: true, + }; + + const generator = new TypeScriptInterfaceGenerator(config); + await generator.generate(); + + const generatedContent = await fs.readFile(outputFile, "utf-8"); + + expect(generatedContent).toContain("CreateProductInput"); + expect(generatedContent).toContain("UpdateProductInput"); + expect(generatedContent).toContain("ProductKeys"); + }); + + test("should validate generated TypeScript", async () => { + const schema: Schema = { + name: "ValidatedInterface", + properties: { + id: { type: "string" }, + data: { + type: "object", + properties: { + nested: { type: "boolean" }, + }, + }, + }, + }; + + const inputFile = path.join(testOutputDir, "validated-input.json"); + const outputFile = path.join(testOutputDir, "validated-output.ts"); + + await fs.writeFile(inputFile, JSON.stringify(schema, null, 2)); + + const config: PluginConfig = { + input: inputFile, + output: outputFile, + }; + + const generator = new TypeScriptInterfaceGenerator(config); + await generator.generate(); + + // Validate the generated TypeScript compiles + const project = new Project(); + const sourceFile = project.addSourceFileAtPath(outputFile); + + const diagnostics = sourceFile.getPreEmitDiagnostics(); + expect(diagnostics).toHaveLength(0); + }); +});`, + + //------------------------------------------------------------------// + + `npm test` +]; + +//--------------------------------------------------------------------// + +export default function TestingYourPlugin() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Testing Your Plugin Section Content */} +
+

{_('7. Testing Your Plugin')}

+

+ + Comprehensive testing ensures your plugin works correctly + across different scenarios and maintains reliability as + it evolves. This section covers unit testing, integration + testing, and validation strategies for ts-morph plugins. + +

+ +

+ + Create comprehensive tests for your plugin: + +

+ + {examples[0]} + + +

+ + Run tests: + +

+ + {examples[1]} + +
+ + ) +} diff --git a/packages/www/plugins/docs/components/ts-morph-plugin-guide/Troubleshooting.tsx b/packages/www/plugins/docs/components/ts-morph-plugin-guide/Troubleshooting.tsx new file mode 100644 index 0000000..85fd9b1 --- /dev/null +++ b/packages/www/plugins/docs/components/ts-morph-plugin-guide/Troubleshooting.tsx @@ -0,0 +1,273 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, H3, P } from '../../../docs/components/index.js' +import Code from '../../../docs/components/Code.js' + +//code examples +//--------------------------------------------------------------------// + +const examples = [ +`function validateGeneratedCode(sourceFile: SourceFile): void { + const diagnostics = sourceFile.getPreEmitDiagnostics(); + + if (diagnostics.length > 0) { + const errors = diagnostics.map(d => ({ + message: d.getMessageText(), + line: d.getLineNumber(), + file: d.getSourceFile()?.getFilePath() + })); + + throw new Error(\`Generated TypeScript has errors: \${JSON.stringify(errors, null, 2)}\`); + } +}`, + +//--------------------------------------------------------------------// + +`function detectCircularReferences(schemas: Schema[]): string[] { + const graph = new Map>(); + const cycles: string[] = []; + + // Build dependency graph + for (const schema of schemas) { + const deps = new Set(); + + for (const prop of Object.values(schema.properties)) { + if (prop.type && schemas.some(s => s.name === prop.type)) { + deps.add(prop.type); + } + } + + graph.set(schema.name, deps); + } + + // Detect cycles using DFS + const visited = new Set(); + const recursionStack = new Set(); + + function hasCycle(node: string): boolean { + if (recursionStack.has(node)) { + cycles.push(node); + return true; + } + + if (visited.has(node)) { + return false; + } + + visited.add(node); + recursionStack.add(node); + + const deps = graph.get(node) || new Set(); + for (const dep of deps) { + if (hasCycle(dep)) { + return true; + } + } + + recursionStack.delete(node); + return false; + } + + for (const schema of schemas) { + hasCycle(schema.name); + } + + return cycles; +}`, + +//--------------------------------------------------------------------// + +`class StreamingGenerator { + async generateLargeSchema(schemas: Schema[]): Promise { + const batchSize = 10; + + for (let i = 0; i < schemas.length; i += batchSize) { + const batch = schemas.slice(i, i + batchSize); + + // Process batch + await this.processBatch(batch); + + // Clear memory + if (global.gc) { + global.gc(); + } + } + } + + private async processBatch(schemas: Schema[]): Promise { + // Process smaller batches to avoid memory issues + } +}`, + +//--------------------------------------------------------------------// + +`const DEBUG = process.env.DEBUG === 'true'; + +function debugLog(message: string, data?: any): void { + if (DEBUG) { + console.log(\`[DEBUG] \${message}\`, data ? JSON.stringify(data, null, 2) : ''); + } +} + +// Usage +debugLog('Processing schema', schema); +debugLog('Generated interface', interfaceDeclaration.getText());`, + +//--------------------------------------------------------------------// + +`async function saveIntermediateResults( + sourceFile: SourceFile, + step: string +): Promise { + if (process.env.SAVE_INTERMEDIATE === 'true') { + const outputPath = \`debug-\${step}-\${Date.now()}.ts\`; + await fs.writeFile(outputPath, sourceFile.getFullText()); + console.log(\`Saved intermediate result: \${outputPath}\`); + } +}`, + +//--------------------------------------------------------------------// + +`function validateStep( + sourceFile: SourceFile, + stepName: string +): void { + try { + const diagnostics = sourceFile.getPreEmitDiagnostics(); + if (diagnostics.length > 0) { + throw new Error(\`Step \${stepName} produced invalid TypeScript\`); + } + console.log(\`✅ Step \${stepName} completed successfully\`); + } catch (error) { + console.error(\`❌ Step \${stepName} failed:\`, error.message); + throw error; + } +}` +]; + +//--------------------------------------------------------------------// + +export default function Troubleshooting() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Troubleshooting Section Content */} +
+

{_('9. Troubleshooting')}

+

+ + Troubleshooting guides help developers quickly identify + and resolve common issues encountered during plugin + development. This section covers validation, debugging + techniques, and solutions for typical problems. + +

+
+ + {/* Common Issues Section Content */} +
+

{_('9.1. Common Issues')}

+

+ + Common issues in ts-morph plugin development typically + involve syntax validation, circular references, and + memory management. Understanding these patterns helps + prevent and resolve problems efficiently. + +

+ +

{_('9.1.1. Invalid TypeScript Syntax')}

+

+ + Invalid TypeScript syntax can break the compilation + process and prevent your plugin from generating usable + code. Implement validation checks to catch syntax errors + early in the generation process. + +

+ + {examples[0]} + + +

{_('9.1.2. Circular Type References')}

+

+ + Circular type references can cause infinite loops and + compilation errors. Detecting and handling these scenarios + is crucial for plugins that work with complex, interconnected + data structures. + +

+ + {examples[1]} + + +

{_('9.1.3. Memory Issues with Large Schemas')}

+

+ + Memory management becomes important when processing large + schemas or generating substantial amounts of code. Implement + streaming and batching strategies to handle large-scale + generation efficiently. + +

+ + {examples[2]} + +
+ + {/* Debugging Techniques Section Content */} +
+

{_('9.2. Debugging Tips')}

+

+ + Effective debugging techniques help identify issues + quickly and understand the plugin's behavior during + development. These tools and strategies provide visibility + into the generation process. + +

+ +

{_('9.2.1. Enable Verbose Logging')}

+

+ + Verbose logging provides detailed information about the + plugin's execution flow, helping identify where issues + occur and what data is being processed at each step. + +

+ + {examples[3]} + + +

{_('9.2.2. Save Intermediate Results')}

+

+ + Saving intermediate results allows you to inspect the + code generation process at different stages, making it + easier to identify where problems occur and verify that + each step produces the expected output. + +

+ + {examples[4]} + + +

{_('9.2.3. Validate Each Step')}

+

+ + Step-by-step validation ensures that each phase of the + generation process produces valid TypeScript code, helping + catch issues early before they compound into larger problems. + +

+ + {examples[5]} + +
+ + ) +} diff --git a/packages/www/plugins/docs/components/ts-morph-plugin-guide/UnderstandingTsMorphBasics.tsx b/packages/www/plugins/docs/components/ts-morph-plugin-guide/UnderstandingTsMorphBasics.tsx new file mode 100644 index 0000000..3db3900 --- /dev/null +++ b/packages/www/plugins/docs/components/ts-morph-plugin-guide/UnderstandingTsMorphBasics.tsx @@ -0,0 +1,723 @@ +//moudles +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, C } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const examples = [ + `import { Project } from "ts-morph"; + +// Create a new project +const project = new Project({ + compilerOptions: { + target: ScriptTarget.ES2020, + module: ModuleKind.CommonJS, + }, +}); + +// Create a source file +const sourceFile = project.createSourceFile("example.ts", ""); + +// Add content to the file +sourceFile.addInterface({ + name: "User", + properties: [ + { name: "id", type: "string" }, + { name: "name", type: "string" }, + ], +}); + +// Get the generated code +console.log(sourceFile.getFullText()); +// Output: +// interface User { +// id: string; +// name: string; +// }`, + + //------------------------------------------------------------------// + + `// Add imports +sourceFile.addImportDeclaration({ + moduleSpecifier: "react", + namedImports: ["useState", "useEffect"], +}); + +// Add a class +sourceFile.addClass({ + name: "UserService", + isExported: true, + methods: [ + { + name: "getUser", + parameters: [{ name: "id", type: "string" }], + returnType: "Promise", + statements: "return fetch('/api/users/' + id).then(r => r.json());", + }, + ], +}); + +// Add a function +sourceFile.addFunction({ + name: "createUser", + isExported: true, + isAsync: true, + parameters: [{ name: "userData", type: "Partial" }], + returnType: "Promise", + statements: [ + "const response = await fetch('/api/users', {", + " method: 'POST',", + " headers: { 'Content-Type': 'application/json' },", + " body: JSON.stringify(userData)", + "});", + "return response.json();", + ], +}); + +// Add type aliases +sourceFile.addTypeAlias({ + name: "UserId", + isExported: true, + type: "string", +}); + +// Add enums +sourceFile.addEnum({ + name: "UserRole", + isExported: true, + members: [ + { name: "ADMIN", value: "admin" }, + { name: "USER", value: "user" }, + { name: "GUEST", value: "guest" }, + ], +});`, + + //------------------------------------------------------------------// + + `import { Project } from "ts-morph"; + +const project = new Project(); + +const source = project.createSourceFile("newFile.ts", null, { overwrite: true }); + +const myClass = source.addClass({ + name: "MyClass", +}); + +myClass.addMethod({ + name: "myMethod", + isDefaultExport: true + parameters: [{ name: "param1", type: "string" }], + returnType: "void", + statements: "console.log(param1);" +}); + +project.saveSync();`, + + //------------------------------------------------------------------// + + `export default class MyClass { + myMethod(param1: string): void { + console.log(param1); + } +}`, + + //------------------------------------------------------------------// + + `import { Project } from "ts-morph"; + +const project = new Project(); + +const source = project.createSourceFile("newFile.ts", null, { overwrite: true }); + +source.addFunction({ + name: "myFunction", + isExported: true, + isAsync: true, + parameters: [ + { name: "param1", type: "string" }, + { name: "param2", type: "number" } + ], + returnType: "void", + statements: [ + "console.log(param1);", + "console.log(param2);" + ] +}); + +project.saveSync();`, + + //------------------------------------------------------------------// + + `export async function myFunction(param1: string, param2: number): void { + console.log(param1); + console.log(param2); +}`, + + //------------------------------------------------------------------// + + `import { VariableDeclarationKind } from 'ts-morph'; + +source.addVariableStatement({ + isExported: true, + declarationKind: VariableDeclarationKind.Const, + declarations: [{ + name: "foo", + initializer: '\'bar\'' + }] +});`, + + //------------------------------------------------------------------// + + `export const foo = 'bar';`, + + //------------------------------------------------------------------// + + `source.addExportDeclaration({ + namedExports: ['ComponentA', 'ComponentB', 'ComponentC'] +});`, + + //------------------------------------------------------------------// + + `source.addTypeAlias({ + name: "ExampleType", + isExported: true, + type: "string | number" +});`, + + //------------------------------------------------------------------// + + `export type ExampleType = string | number;`, + + //------------------------------------------------------------------// + + `source.addTypeAlias({ + name: "AnotherType", + isExported: true, + type: "boolean" +}); + +source.addInterface({ + name: "ExampleInterface", + isExported: true, + properties: [ + { name: "id", type: "number" }, + { name: "name", type: "string" } + ] +}); + +// Optionally, use addExportDeclaration to export all at once +source.addExportDeclaration({ + namedExports: ["ExampleType", "AnotherType", "ExampleInterface"] +});`, + + //------------------------------------------------------------------// + + `export type ExampleType = string | number; +export type AnotherType = boolean; +export interface ExampleInterface { + id: number; + name: string; +}`, + + //------------------------------------------------------------------// + + `source.addImportDeclaration({ + moduleSpecifier: 'react', + namedImports: [ 'useState', 'useEffect' ] +});`, + + //------------------------------------------------------------------// + + `import { useState, useEffect } from 'react';`, + + //------------------------------------------------------------------// + + `source.addImportDeclaration({ + moduleSpecifier: 'next', + namedImports: [ + 'NextApiRequest as Request', + 'NextApiResponse as as Response' + ] +});`, + + //------------------------------------------------------------------// + + `import type { + NextApiRequest as Request, + NextApiResponse as Response +} from 'next';`, + + //------------------------------------------------------------------// + + `source.addImportDeclaration({ + moduleSpecifier: 'react', + defaultImport: 'React' +});`, + + //------------------------------------------------------------------// + + `import React from 'react';`, + + //------------------------------------------------------------------// + + `// Load existing files +project.addSourceFilesAtPaths("src/**/*.ts"); + +// Get a specific file +const existingFile = project.getSourceFile("src/models/User.ts"); + +// Find and modify existing constructs +const userInterface = existingFile?.getInterface("User"); +if (userInterface) { + // Add a new property + userInterface.addProperty({ + name: "email", + type: "string", + hasQuestionToken: true, // Makes it optional + }); + + // Add JSDoc comments + userInterface.addJsDoc({ + description: "Represents a user in the system", + tags: [ + { tagName: "example", text: "const user: User = { id: '1', name: 'John' };" }, + ], + }); +}` +]; + +//--------------------------------------------------------------------// + +export default function UnderstandingTsMorphBasics() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Understanding ts-morph Basics Section Content*/} +
+

{_('4. Understanding ts-morph Basics')}

+

+ + Understanding the fundamental concepts of ts-morph is + essential for effective plugin development. This section covers + the core APIs, project management, source file manipulation, + and code generation patterns that form the foundation of all + ts-morph operations. + +

+
+ + {/* Project and Source Files Section Content */} +
+

{_('4.1. Project and Source Files')}

+

+ + The Project class is the entry point for all ts-morph + operations, providing methods to create, load, and manage + TypeScript source files. Understanding how to work with projects + and source files is fundamental to building effective code + generation plugins. + +

+ + {examples[0]} + +
+ + {/* Adding Different Constructs Section Content */} +
+

{_('4.2. Adding Different Constructs')}

+

+ + ts-morph provides comprehensive APIs for adding various + TypeScript constructs including imports, classes, functions, + types, and enums. This section demonstrates the most commonly + used patterns for generating different types of TypeScript code. + +

+ + {examples[1]} + +
+ + {/* Exporting a Class Section Content */} +
+

{_('4.3. Exporting a Class')}

+

+ + Creating and exporting classes is a common requirement in + TypeScript code generation. This example demonstrates the basic + pattern for generating classes with methods, including proper + export declarations and method implementations. + +

+

+ + A simple example of how to create a new TypeScript file with a + class and a method using ts-morph looks like the + following: + +

+ + {examples[2]} + + +

+ + This code will create a new TypeScript file newFile.ts + with the following content: + +

+ + {examples[3]} + +

+ + You can use isExported or isDefaultExport to + export or export default respectively. Also + statements can be a string or an array of strings + (string[]). + +

+
+ + {/* Exporting a Function Section Content */} +
+

{_('4.4. Exporting a Function')}

+

+ + Function generation at the source file level provides flexibility + for creating utility functions, API endpoints, and standalone + operations. This section shows how to create functions with + various configurations including async operations, parameters, + and return types. + +

+

+ + Similar to adding a method to a class, you can use + addFunction to add a function at the source file level. + An example of how to use addFunction to add a function + with arguments and a body looks like the following: + +

+ + {examples[4]} + +

+ + In the above example, myFunction takes two parameters, + param1 of type string and param2 of type number. + The function body contains two console.log statements. + +

+

+ + After running the above code, the content of newFile.ts + would look like the following: + +

+ + {examples[5]} + +
+ + {/* Exporting a Const Section Content */} +
+

{_('4.5. Exporting a Const')}

+

+ + Constant declarations are essential for defining configuration + values, default settings, and immutable data structures. The + addVariableStatement method provides flexible options for + creating various types of variable declarations with proper export + handling. + +

+

+ + To export a constant in ts-morph, you can utilize the + addVariableStatement method on a SourceFile object. + This method allows you to add a variable declaration to the file, + including the capability to export the declaration. + +

+ + {examples[6]} + +

+ + The provided ts-morph script will generate the following + code in the source file. + +

+ + {examples[7]} + +
+ + {/* Exporting an Object Section Content */} +
+

{_('4.6. Exporting an Object')}

+

+ + Export declarations provide a clean way to re-export multiple + entities from other modules or to export collections of related + functionality. This pattern is commonly used in index files and + module aggregation scenarios. + +

+

+ + To generate an export statement that directly exports multiple + imported entities in a single line using ts-morph, you + don't need to declare them as variables first. Instead, you can + use the addExportDeclaration method directly after your + imports. This approach is more straightforward and aligns with + typical TypeScript import-export patterns. + +

+ + {examples[8]} + +
+ + {/* Exporting Types Section Content */} +
+

{_('4.7. Exporting Types')}

+

+ + Type exports are crucial for creating reusable type definitions + that can be consumed by other modules. ts-morph provides + dedicated methods for creating both type aliases and interfaces + with proper export configurations. + +

+

+ + To export a single type, you can use the addTypeAlias or + addInterface method (depending on whether you are defining + an alias or an interface), and set the isExported property + to true. An example of exporting a type alias looks like the + following: + +

+ + {examples[9]} + +

+ + This will generate a file with the following content: + +

+ + {examples[10]} + +

+ + To export multiple types at the same time, you can add multiple + type declarations (either type aliases or interfaces) with the + isExported property set to true for each. Alternatively, + you can use the addExportDeclaration method to export + previously declared types. An example of declaring and exporting + multiple types looks like the following: + +

+ + {examples[11]} + +

+ + This will generate a file with the following content: + +

+ + {examples[12]} + +
+ + {/* Importing Values Section Content */} +
+

{_('4.8. Importing Values')}

+

+ + Import declarations are essential for bringing external + dependencies and modules into your generated code. The + addImportDeclaration method provides comprehensive options + for creating various types of import statements including named + imports, default imports, and type imports. + +

+

+ + To import a set of values from a module in ts-morph, you + can use the addImportDeclaration method on a + SourceFile object. This method allows you to add an import + declaration to the code file you are working with. Here's how to + use this method to import specific values from the react + module: + +

+ + {examples[13]} + +

+ + The provided ts-morph script will generate the following + code in the source file: + +

+ + {examples[14]} + +

+ + You can also import types like the following: + +

+ + {examples[15]} + +

+ + The above code renders the following: + +

+ + {examples[16]} + +
+ + {/* Importing Defaults Section Content */} +
+

{_('4.9. Importing Defaults')}

+

+ + Default imports are commonly used for importing the main export + from a module, such as React components or utility libraries. The + same addImportDeclaration method handles default imports + with a slightly different configuration. + +

+

+ + To import a default from a module in ts-morph, you can + also use the addImportDeclaration method: + +

+ + {examples[17]} + +

+ + This would create the following code: + +

+ + {examples[18]} + +
+ + {/* Working with Existing Code Section Content */} +
+

{_('4.10. Working with Existing Code')}

+

+ + Working with existing code is a powerful feature of + ts-morph that allows you to modify, extend, and refactor + existing TypeScript files. This capability is essential for + plugins that need to augment or update existing codebases rather + than generating new files from scratch. + +

+ + {examples[19]} + +
+ + ) +} diff --git a/packages/www/plugins/docs/components/ts-morph-plugin-guide/index.tsx b/packages/www/plugins/docs/components/ts-morph-plugin-guide/index.tsx new file mode 100644 index 0000000..60dd4e3 --- /dev/null +++ b/packages/www/plugins/docs/components/ts-morph-plugin-guide/index.tsx @@ -0,0 +1,11 @@ +//exporting all components to have multiple imports from a single file +export { default as AdvanceTsMorphPlugin } from './AdvanceTsMorphPlugin.js'; +export { default as BestPractices } from './BestPractices.js'; +export { default as CreateFirstPlugin } from './CreateFirstPlugin.js'; +export { default as Installation } from './Installation.js'; +export { default as Introduction } from './Introduction.js'; +export { default as References } from './References.js'; +export { default as SettingUpProject } from './SettingUpProject.js'; +export { default as TestingYourPlugin } from './TestingYourPlugin.js'; +export { default as Troubleshooting } from './Troubleshooting.js'; +export { default as UnderstandingTsMorphBasics } from './UnderstandingTsMorphBasics.js'; \ No newline at end of file diff --git a/packages/www/plugins/docs/components/typescript-interface-plugin/AdvancedFeatures.tsx b/packages/www/plugins/docs/components/typescript-interface-plugin/AdvancedFeatures.tsx new file mode 100644 index 0000000..ed6a252 --- /dev/null +++ b/packages/www/plugins/docs/components/typescript-interface-plugin/AdvancedFeatures.tsx @@ -0,0 +1,207 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, Code } from '../../../docs/components/index.js'; + +//code examples +//--------------------------------------------------------------------// + +const namespaceConfigurationExample = + `// With namespace configuration +namespace: "MyApp" +exportType: "namespace"`; + +const namespaceOutputExample = + `// Generated output: +export namespace MyApp { + export enum UserRole { + ADMIN = "admin", + USER = "user", + } + + export interface User { + id: string; + name: string; + role: UserRole; + } +}`; + +//--------------------------------------------------------------------// + +const standardEnumExample = + `// Standard enum (default) +enumType: "enum" +export enum UserRole { + ADMIN = "admin", + USER = "user", +}`; + +//--------------------------------------------------------------------// + +const unionTypeExample = + `// Union type +enumType: "union" +export type UserRole = "admin" | "user";`; + +//--------------------------------------------------------------------// + +const constAssertionExample = + `// Const assertion +enumType: "const" +export const UserRole = { + ADMIN: "admin", + USER: "user", +} as const; +export type UserRole = typeof UserRole[keyof typeof UserRole];`; + +//--------------------------------------------------------------------// + +const relationshipHandlingExample = + `function handleRelationships( + column: any, + config: TypeScriptConfig, + availableTypes: Set +): string { + // Check if the column type is another model/type + if (availableTypes.has(column.type)) { + let type = column.type; + + if (column.multiple) { + type = \`\${type}[]\`; + } + + if (!column.required && config.strictNullChecks) { + type = \`\${type} | null\`; + } + + return type; + } + + return formatPropertyType(column, config, availableTypes); +}`; + +//--------------------------------------------------------------------// + +const genericTypeSupportExample = + `function generateGenericTypes( + models: Record, + config: TypeScriptConfig +): string { + let content = '// Generic Types\\n'; + + // Generate paginated response type + content += \`export interface PaginatedResponse { + data: T[]; + total: number; + page: number; + limit: number; +}\\n\\n\`; + + // Generate API response type + content += \`export interface ApiResponse { + success: boolean; + data?: T; + error?: string; + errors?: Record; +}\\n\\n\`; + + return content; +}`; + +//--------------------------------------------------------------------// + +export default function AdvancedFeatures() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Advanced Features Section Content */} +
+

{_('7. Advanced Features')}

+

+ + Advanced features extend the basic TypeScript interface + generation with sophisticated organization, multiple enum + types, relationship handling, and generic type support. + These features enable production-ready TypeScript definitions + that handle complex scenarios. + +

+
+ + {/* Namespace Support Section Content */} +
+

{_('Namespace Support')}

+

+ + Namespace support allows you to organize generated types within + TypeScript namespaces, preventing naming conflicts and providing + better code organization. This feature is particularly useful + for large projects with multiple schema files. + +

+ + {namespaceConfigurationExample} + + + {namespaceOutputExample} + +
+ + {/* Different Enum Types Section Content */} +
+

{_('Different Enum Types')}

+

+ + Different enum types provide flexibility in how enumerations + are represented in TypeScript. The plugin supports standard + enums, union types, and const assertions, each with different + runtime characteristics and use cases. + +

+ + {standardEnumExample} + + + {unionTypeExample} + + + {constAssertionExample} + +
+ + {/* Relationship Handling Section Content */} +
+

{_('Relationship Handling')}

+

+ + Relationship handling manages references between different types + and models in your schema. This ensures that type relationships + are properly represented in the generated TypeScript code with + correct type references and nullability handling. + +

+ + {relationshipHandlingExample} + +
+ + {/* Generic Type Support Section Content */} +
+

{_('Generic Type Support')}

+

+ + Generic type support enables the generation of reusable type + definitions that work with multiple data types. This includes + common patterns like paginated responses and API response + wrappers that enhance type safety across your application. + +

+ + {genericTypeSupportExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/typescript-interface-plugin/BestPractices.tsx b/packages/www/plugins/docs/components/typescript-interface-plugin/BestPractices.tsx new file mode 100644 index 0000000..3ef2072 --- /dev/null +++ b/packages/www/plugins/docs/components/typescript-interface-plugin/BestPractices.tsx @@ -0,0 +1,201 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, Code } from '../../../docs/components/index.js'; + +//code examples +//--------------------------------------------------------------------// + +const typeSafetyInterface = + `interface TypeScriptColumn { + name: string; + type: string; + required: boolean; + multiple: boolean; + description?: string; + attributes?: Record; +}`; + +//--------------------------------------------------------------------// + +const columnValidation = + `function validateColumn(column: any): column is TypeScriptColumn { + return ( + typeof column.name === 'string' && + typeof column.type === 'string' && + typeof column.required === 'boolean' + ); +}`; + +//--------------------------------------------------------------------// + +const typeNameSanitization = + `function sanitizeTypeName(name: string): string { + // Ensure TypeScript-valid names + return name + .replace(/[^a-zA-Z0-9_]/g, '_') + .replace(/^[0-9]/, '_$&') + .replace(/^_+|_+$/g, ''); +}`; + +//--------------------------------------------------------------------// + +const pascalCaseConversion = + `function toPascalCase(str: string): string { + return str + .split(/[-_\\s]+/) + .map(word => + word.charAt(0).toUpperCase() + word.slice(1).toLowerCase() + ) + .join(''); +}`; + +//--------------------------------------------------------------------// + +const jsDocGeneration = + `function generateJSDocComment( + column: any, + includeAttributes: boolean = true +): string { + const lines: string[] = []; + + if (column.description) { + lines.push(column.description); + } + + if (includeAttributes && column.attributes) { + if (column.attributes.default) { + lines.push(\`@default \${column.attributes.default}\`); + } + if (column.attributes.example) { + lines.push(\`@example \${column.attributes.example}\`); + } + } + + if (lines.length === 0) return ''; + + if (lines.length === 1) { + return \` /** \${lines[0]} */\\n\`; + } + + return \` /**\\n\${lines.map(line => + \` * \${line}\`).join('\\n')}\\n */\\n\`; +}`; + +//--------------------------------------------------------------------// + +const typeCacheOptimization = + `// Cache type mappings +const typeCache = new Map(); + +function getCachedTypeMapping( + schemaType: string, + strictNullChecks: boolean +): string { + const cacheKey = \`\${schemaType}:\${strictNullChecks}\`; + + if (typeCache.has(cacheKey)) { + return typeCache.get(cacheKey)!; + } + + const mappedType = mapSchemaTypeToTypeScript( + schemaType, + strictNullChecks + ); + typeCache.set(cacheKey, mappedType); + + return mappedType; +}`; + +//--------------------------------------------------------------------// + +export default function BestPractices() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Best Practices Section Content */} +
+

{_('8. Best Practices')}

+

+ + Best practices ensure your generated TypeScript interfaces + are maintainable, reliable, and follow industry standards. + These guidelines cover type safety, naming conventions, + documentation generation, and performance optimization. + +

+
+ + {/* Type Safety Section Content */} +
+

{_('Type Safety')}

+

+ + Type safety is crucial for preventing runtime errors and + improving developer experience. Always validate input data + and use proper TypeScript types throughout the plugin + implementation to ensure reliable code generation. + +

+ + {typeSafetyInterface} + + + {columnValidation} + +
+ + {/* Naming Conventions Section Content */} +
+

{_('Naming Conventions')}

+

+ + Naming conventions ensure that generated TypeScript identifiers + are valid and follow established patterns. Proper naming improves + code readability and prevents conflicts with reserved keywords + or invalid characters. + +

+ + {typeNameSanitization} + + + {pascalCaseConversion} + +
+ + {/* Documentation Generation Section Content */} +
+

{_('Documentation Generation')}

+

+ + Documentation generation creates comprehensive JSDoc + comments that provide context and examples for the generated + types. This improves the developer experience by providing + inline documentation in IDEs and code editors. + +

+ + {jsDocGeneration} + +
+ +
+

{_('Performance Optimization')}

+

+ + Performance optimization techniques help maintain reasonable + generation times when working with large schemas. Caching + strategies and efficient algorithms ensure the plugin scales + well with complex type hierarchies. + +

+ + {typeCacheOptimization} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/typescript-interface-plugin/Implementation.tsx b/packages/www/plugins/docs/components/typescript-interface-plugin/Implementation.tsx new file mode 100644 index 0000000..b6f9bc1 --- /dev/null +++ b/packages/www/plugins/docs/components/typescript-interface-plugin/Implementation.tsx @@ -0,0 +1,323 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, C, Code } from '../../../docs/components/index.js'; + +//code examples +//--------------------------------------------------------------------// + +const corePluginFunctionExample = + `export default async function generateTypeScriptInterfaces( + props: PluginProps<{ config: TypeScriptConfig }> +) { + const { config, schema, transformer } = props; + + try { + // Validate configuration + validateConfig(config); + + // Generate TypeScript content + let content = ''; + + // Add file header + content += generateFileHeader(); + + // Generate enums + if (config.generateEnums !== false && schema.enum) { + content += generateEnums(schema.enum, config); + } + + // Generate custom types + if (schema.type) { + content += generateCustomTypes(schema.type, config); + } + + // Generate interfaces from models + if (schema.model) { + content += generateInterfaces(schema.model, config); + } + + // Generate utility types + if (config.generateUtilityTypes) { + content += generateUtilityTypes(schema, config); + } + + // Wrap in namespace if specified + if (config.namespace) { + content = wrapInNamespace(content, config.namespace, + config.exportType); + } + + // Write to output file + const outputPath = await transformer.loader.absolute(config.output); + await fs.mkdir(path.dirname(outputPath), { recursive: true }); + await fs.writeFile(outputPath, content, 'utf8'); + + console.log(\`✅ TypeScript interfaces generated: \${outputPath}\`); + + } catch (error) { + console.error( + '❌ TypeScript interface generation failed:', + error.message + ); + throw error; + } +}`; + +//--------------------------------------------------------------------// + +const typeMappingFunctionsExample = + `function mapSchemaTypeToTypeScript( + schemaType: string, + strictNullChecks: boolean = true +): string { + const typeMap: Record = { + 'String': 'string', + 'Number': 'number', + 'Integer': 'number', + 'Boolean': 'boolean', + 'Date': 'Date', + 'JSON': 'any', + 'ID': 'string' + }; + + const baseType = typeMap[schemaType] || schemaType; + + // Handle strict null checks + if (!strictNullChecks && baseType !== 'any') { + return \`\${baseType} | null | undefined\`; + } + + return baseType; +} + +function formatPropertyType( + column: any, + config: TypeScriptConfig, + availableTypes: Set = new Set() +): string { + let type = column.type; + + // Check if it's a reference to another type + if (availableTypes.has(column.type)) { + type = column.type; + } else { + type = mapSchemaTypeToTypeScript(column.type, config.strictNullChecks); + } + + // Handle arrays + if (column.multiple) { + type = \`\${type}[]\`; + } + + // Handle optional properties + if (!column.required && config.strictNullChecks) { + type = \`\${type} | null\`; + } + + return type; +}` + +//--------------------------------------------------------------------// + +const generationFunctionsExample = + `function generateFileHeader(): string { + const timestamp = new Date().toISOString(); + return \`/** + * Generated TypeScript interfaces + * Generated at: \${timestamp} + * + * This file is auto-generated. Do not edit manually. + */ + +\`; +} + +function generateEnums( + enums: Record, + config: TypeScriptConfig +): string { + let content = '// Enums\\n'; + + for (const [enumName, enumDef] of Object.entries(enums)) { + if (config.includeComments) { + content += \`/**\\n * \${enumName} enumeration\\n */\\n\`; + } + + switch (config.enumType) { + case 'union': + content += generateUnionEnum(enumName, enumDef); + break; + case 'const': + content += generateConstEnum(enumName, enumDef); + break; + default: + content += generateStandardEnum(enumName, enumDef); + } + + content += '\\n'; + } + + return content + '\\n'; +} + +function generateStandardEnum(enumName: string, enumDef: any): string { + let content = \`export enum \${enumName} {\\n\`; + + for (const [key, value] of Object.entries(enumDef)) { + content += \` \${key} = "\${value}",\\n\`; + } + + content += '}'; + return content; +} + +function generateInterfaces( + models: Record, + config: TypeScriptConfig +): string { + let content = '// Model Interfaces\\n'; + const availableTypes = new Set([ + ...Object.keys(models), + ...(config.namespace ? [] : Object.keys(models)) + ]); + + for (const [modelName, model] of Object.entries(models)) { + if (config.includeComments) { + content += \`/**\\n * \${modelName} model interface\\n\`; + if (model.description) { + content += \` * \${model.description}\\n\`; + } + content += \` */\\n\`; + } + + content += \`export interface \${modelName} {\\n\`; + + for (const column of model.columns || []) { + const propertyType = formatPropertyType(column, config, + availableTypes); + const optional = !column.required ? '?' : ''; + + if (config.includeComments) { + let comment = ''; + if (column.description) { + comment += column.description; + } + if (column.attributes?.default) { + comment += comment ? + \` (default: \${column.attributes.default})\` : + \`Default: \${column.attributes.default}\`; + } + if (comment) { + content += \` /** \${comment} */\\n\`; + } + } + + content += \` \${column.name}\${optional}: \${propertyType};\\n\`; + } + + content += '}\\n\\n'; + } + + return content; +}`; + +//--------------------------------------------------------------------// + +const validationFunctionsExample = + `function validateConfig(config: any): asserts config is TypeScriptConfig { + if (!config.output || typeof config.output !== 'string') { + throw new Error( + 'TypeScript plugin requires "output" configuration as string' + ); + } + + if (config.exportType && + !['named', 'default', 'namespace'].includes(config.exportType)) { + throw new Error( + 'exportType must be one of: named, default, namespace' + ); + } + + if (config.enumType && + !['enum', 'union', 'const'].includes(config.enumType)) { + throw new Error('enumType must be one of: enum, union, const'); + } +}` + +//--------------------------------------------------------------------// + +export default function Implementation() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Implementation Section Content */} +
+

{_('4. Implementation')}

+

+ + The implementation section covers the core plugin function and + supporting utilities that handle TypeScript interface generation. + This includes configuration validation, content generation, file + writing, and error handling throughout the generation process. + +

+ +

{_('Core Plugin Function')}

+

+ + The core plugin function serves as the main entry point for + TypeScript interface generation. It orchestrates the entire + process from configuration validation through content generation + to file output, ensuring proper error handling and logging + throughout. + +

+ + {corePluginFunctionExample} + + +

{_('Type Mapping Functions')}

+

+ + Type mapping functions handle the conversion of .idea + schema types to their TypeScript equivalents. These functions + ensure proper type safety and handle complex scenarios like + nullable types, arrays, and custom type references. + +

+ + {typeMappingFunctionsExample} + + +

{_('Generation Functions')}

+

+ + Generation functions create specific parts of the TypeScript output + including enums, interfaces, and utility types. These functions + handle formatting, documentation generation, and proper TypeScript + syntax construction. + +

+ + {generationFunctionsExample} + + +

{_('Validation Functions')}

+

+ + Validation functions ensure that the plugin configuration is correct + and that the generated TypeScript code meets quality standards. + These functions catch configuration errors early and prevent invalid + output generation. + +

+ + {validationFunctionsExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/typescript-interface-plugin/Introduction.tsx b/packages/www/plugins/docs/components/typescript-interface-plugin/Introduction.tsx new file mode 100644 index 0000000..35d0bf1 --- /dev/null +++ b/packages/www/plugins/docs/components/typescript-interface-plugin/Introduction.tsx @@ -0,0 +1,25 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C } from '../../../docs/components/index.js'; + +export default function Introduction() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* TypeScript Interface Generator Plugin Tutorial */} +

{_('TypeScript Interface Generator Plugin Tutorial')}

+

+ + This tutorial demonstrates how to create a plugin that + generates TypeScript interfaces and types from .idea + schema files. The plugin will transform your schema models, + types, and enums into proper TypeScript definitions with + full type safety. + +

+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/typescript-interface-plugin/Overview.tsx b/packages/www/plugins/docs/components/typescript-interface-plugin/Overview.tsx new file mode 100644 index 0000000..9fbbbe0 --- /dev/null +++ b/packages/www/plugins/docs/components/typescript-interface-plugin/Overview.tsx @@ -0,0 +1,65 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C, SS } from '../../../docs/components/index.js'; + +export default function Overview() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Overview Section Content */} +
+

{_('1. Overview')}

+

+ + TypeScript interfaces provide compile-time type checking + and excellent IDE support. This plugin transforms your + .idea schema definitions into comprehensive Type + Script type definitions that integrate seamlessly with + your development workflow and provide robust type safety + throughout your application. + +

+

+ + This plugin generates TypeScript definitions from your + .idea schema, including: + +

+
    +
  • + + Interfaces: TypeScript interfaces from schema + models + +
  • +
  • + + Types: Custom types and type aliases + +
  • +
  • + + Enums: TypeScript enums with multiple output + formats + +
  • +
  • + + Utility Types: Helper types for CRUD + operations + +
  • +
  • + + Namespaces: Organized code with namespace + support + +
  • +
+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/typescript-interface-plugin/PluginStructure.tsx b/packages/www/plugins/docs/components/typescript-interface-plugin/PluginStructure.tsx new file mode 100644 index 0000000..865a662 --- /dev/null +++ b/packages/www/plugins/docs/components/typescript-interface-plugin/PluginStructure.tsx @@ -0,0 +1,63 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const pluginStructureExample = + `import type { PluginProps } from '@stackpress/idea-transformer/types'; +import fs from 'fs/promises'; +import path from 'path'; + +interface TypeScriptConfig { + output: string; + namespace?: string; + exportType?: 'named' | 'default' | 'namespace'; + generateUtilityTypes?: boolean; + includeComments?: boolean; + strictNullChecks?: boolean; + generateEnums?: boolean; + enumType?: 'enum' | 'union' | 'const'; +} + +export default async function generateTypeScriptInterfaces( + props: PluginProps<{ config: TypeScriptConfig }> +) { + const { config, schema, transformer } = props; + + // Implementation here... +}`; + +//--------------------------------------------------------------------// + +export default function PluginStructure() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Plugin Structure Section Content */} +
+

{_('3. Plugin Structure')}

+

+ + The plugin structure defines the core architecture and + configuration interface for the TypeScript interface generator. + This includes the main plugin function, configuration types, + and the overall organization of the generated TypeScript code. + +

+ + {pluginStructureExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/typescript-interface-plugin/Prerequisites.tsx b/packages/www/plugins/docs/components/typescript-interface-plugin/Prerequisites.tsx new file mode 100644 index 0000000..01cff4f --- /dev/null +++ b/packages/www/plugins/docs/components/typescript-interface-plugin/Prerequisites.tsx @@ -0,0 +1,49 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C } from '../../../docs/components/index.js'; + +export default function Prerequisites() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Prerequisites Section Content */} +
+

{_('2. Prerequisites')}

+

+ + Before implementing the TypeScript interface generator plugin, + ensure you have the necessary development environment and + knowledge. This section covers the essential requirements for + successful plugin creation and TypeScript integration. + +

+
    +
  • + + Node.js 16+ and npm/yarn + +
  • +
  • + + TypeScript 4.0+ development experience + +
  • +
  • + + Familiarity with the @stackpress/idea-transformer + library + +
  • +
  • + + Understanding of .idea schema format + +
  • +
+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/typescript-interface-plugin/SchemaConfiguration.tsx b/packages/www/plugins/docs/components/typescript-interface-plugin/SchemaConfiguration.tsx new file mode 100644 index 0000000..6a7d1ad --- /dev/null +++ b/packages/www/plugins/docs/components/typescript-interface-plugin/SchemaConfiguration.tsx @@ -0,0 +1,144 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +import { Table, Thead, Trow, Tcol } from 'frui/element/Table'; +//local +import { H1, H2, P, C } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const basicConfigurationExample = + `plugin "./plugins/typescript-interfaces.js" { + output "./generated/types.ts" + namespace "MyApp" + exportType "named" + generateUtilityTypes true + includeComments true + strictNullChecks true + generateEnums true + enumType "enum" +}`; + +//--------------------------------------------------------------------// + +const configurationTableData = [ + { + option: 'output', + type: 'string', + defaultValue: 'Required', + description: 'Output file path for TypeScript definitions' + }, + { + option: 'namespace', + type: 'string', + defaultValue: 'undefined', + description: 'Wrap types in a namespace' + }, + { + option: 'exportType', + type: "'named'|'default'|'namespace'", + defaultValue: "'named'", + description: 'Export style for types' + }, + { + option: 'generateUtilityTypes', + type: 'boolean', + defaultValue: 'false', + description: 'Generate helper utility types' + }, + { + option: 'includeComments', + type: 'boolean', + defaultValue: 'false', + description: 'Include JSDoc comments' + }, + { + option: 'strictNullChecks', + type: 'boolean', + defaultValue: 'true', + description: 'Handle null/undefined types' + }, + { + option: 'generateEnums', + type: 'boolean', + defaultValue: 'true', + description: 'Generate enum definitions' + }, + { + option: 'enumType', + type: "'enum'|'union'|'const'", + defaultValue: "'enum'", + description: 'Enum generation style' + } +]; + +//----------------------------------------------------------------- + +export default function SchemaConfiguration() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Schema Configuration Section Content */} +
+

{_('5. Schema Configuration')}

+

+ + Schema configuration demonstrates how to integrate the + TypeScript interface generator into your .idea + schema files. This section covers plugin configuration + options and their effects on the generated TypeScript output. + +

+

+ + Add the TypeScript plugin to your .idea schema file: + +

+ + {basicConfigurationExample} + + +

{_('Configuration Options')}

+

+ + Configuration options control how TypeScript interfaces are + generated, including output formatting, type handling, and + feature enablement. Understanding these options helps you + customize the plugin to meet your specific project requirements. + +

+ + + + Option + Type + Default + Description + + {configurationTableData.map((row, index) => ( + + + {row.option} + + + {row.type} + + + {row.defaultValue} + + + {row.description} + + + ))} +
+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/typescript-interface-plugin/Troubleshooting.tsx b/packages/www/plugins/docs/components/typescript-interface-plugin/Troubleshooting.tsx new file mode 100644 index 0000000..6dfad80 --- /dev/null +++ b/packages/www/plugins/docs/components/typescript-interface-plugin/Troubleshooting.tsx @@ -0,0 +1,232 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, C, Code } from '../../../docs/components/index.js'; + +//code examples +//--------------------------------------------------------------------// + +const typeNameValidation = + `function validateTypeName(name: string): void { + if (!/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(name)) { + throw new Error(\`Invalid TypeScript identifier: \${name}\`); + } +}`; + +//--------------------------------------------------------------------// + +const circularReferenceDetection = + `function detectCircularReferences( + types: Record +): string[] { + const visited = new Set(); + const recursionStack = new Set(); + const cycles: string[] = []; + + function visit(typeName: string): void { + if (recursionStack.has(typeName)) { + cycles.push(typeName); + return; + } + + if (visited.has(typeName)) return; + + visited.add(typeName); + recursionStack.add(typeName); + + // Check type dependencies... + + recursionStack.delete(typeName); + } + + for (const typeName of Object.keys(types)) { + visit(typeName); + } + + return cycles; +}`; + +//--------------------------------------------------------------------// + +const dependencyValidation = + `function validateTypeDependencies( + schema: any +): void { + const availableTypes = new Set([ + ...Object.keys(schema.model || {}), + ...Object.keys(schema.type || {}), + ...Object.keys(schema.enum || {}) + ]); + + // Validate all type references... +}`; + +//--------------------------------------------------------------------// + +const verboseLogging = + `const VERBOSE = process.env.TS_PLUGIN_VERBOSE === 'true'; + +function verboseLog(message: string, data?: any) { + if (VERBOSE) { + console.log(\`[TypeScript Plugin] \${message}\`, data || ''); + } +}`; + +//--------------------------------------------------------------------// + +const typeScriptValidation = + `import { transpile, ScriptTarget } from 'typescript'; + +function validateGeneratedTypeScript(content: string): void { + try { + transpile(content, { + target: ScriptTarget.ES2020, + strict: true + }); + console.log('✅ Generated TypeScript is valid'); + } catch (error) { + throw new Error(\`Invalid TypeScript: \${error.message}\`); + } +}`; + +//--------------------------------------------------------------------// + +export default function Troubleshooting() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Troubleshooting Section Content */} +
+

{_('9. Troubleshooting')}

+

+ + This section addresses common issues encountered when + generating TypeScript interfaces from .idea files + and provides solutions for debugging and resolving problems. + Understanding these troubleshooting techniques helps ensure + reliable TypeScript interface generation. + +

+
+ + {/* Common Issues Section Content */} +
+

{_('Common Issues')}

+

+ + Common issues include invalid TypeScript identifiers, circular + type references, and missing dependencies. These problems + typically arise from schema complexity or configuration + mismatches that can be resolved with proper validation and + error handling. + +

+ +
+

{_('Invalid TypeScript Names')}

+

+ + Invalid TypeScript names occur when schema identifiers + contain characters that are not valid in TypeScript. The + plugin should validate and sanitize names to ensure they + conform to TypeScript identifier rules. + +

+ + {typeNameValidation} + +
+ + {/* Circular Type References Section Content */} +
+

{_('Circular Type References')}

+

+ + Circular type references can cause infinite loops during + generation or compilation errors in the generated TypeScript + code. Detecting and handling these scenarios is essential for + robust type generation. + +

+ + {circularReferenceDetection} + +
+ + {/* Missing Type Dependencies Section Content */} +
+

{_('Missing Type Dependencies')}

+

+ + Missing type dependencies occur when a type references + another type that doesn't exist in the schema. Validating + type dependencies ensures all references are resolvable + and prevents compilation errors. + +

+ + {dependencyValidation} + +
+
+ + {/* Debugging Tips Section Content */} +
+

{_('Debugging Tips')}

+

+ + Debugging tips help identify and resolve issues during TypeScript + interface generation. These techniques provide visibility into + the generation process and help diagnose problems with schema + processing or output generation. + +

+ + {/* Enable Verbose Output Section Content */} +
+

{_('Enable Verbose Output')}

+

+ + Verbose output provides detailed logging during the generation + process, helping identify where issues occur and what data is + being processed at each step. + +

+ + {verboseLogging} + +
+ + {/* Validate Generated TypeScript Section Content */} +
+

{_('Validate Generated TypeScript')}

+

+ + Validating generated TypeScript ensures that the output is + syntactically correct and will compile successfully. This + validation step catches generation errors before the code is + used in development. + +

+ + {typeScriptValidation} + +
+
+ + {/* Conclusion Section Content */} +
+

+ + This tutorial provides a comprehensive foundation for creating + TypeScript interface generators from .idea files. The + generated types can be used throughout your TypeScript projects + for compile-time type checking and enhanced IDE support. + +

+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/typescript-interface-plugin/UsageExamples.tsx b/packages/www/plugins/docs/components/typescript-interface-plugin/UsageExamples.tsx new file mode 100644 index 0000000..c9925e7 --- /dev/null +++ b/packages/www/plugins/docs/components/typescript-interface-plugin/UsageExamples.tsx @@ -0,0 +1,155 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const basicSchemaExample = + `enum UserRole { + ADMIN "admin" + USER "user" + GUEST "guest" +} + +type Address { + street String @required + city String @required + country String @required + postal String +} + +model User { + id String @id @default("nanoid()") + email String @unique @required + name String @required + role UserRole @default("USER") + address Address? + active Boolean @default(true) + createdAt Date @default("now()") +} + +plugin "./plugins/typescript-interfaces.js" { + output "./types.ts" + generateUtilityTypes true + includeComments true +}`; + +//--------------------------------------------------------------------// + +const generatedOutputExample = + `/** + * Generated TypeScript interfaces + * Generated at: 2024-01-15T10:30:00.000Z + * + * This file is auto-generated. Do not edit manually. + */ + +// Enums +/** + * UserRole enumeration + */ +export enum UserRole { + ADMIN = "admin", + USER = "user", + GUEST = "guest", +} + +// Custom Types +/** + * Address type definition + */ +export interface Address { + street: string; + city: string; + country: string; + postal?: string | null; +} + +// Model Interfaces +/** + * User model interface + */ +export interface User { + /** Default: nanoid() */ + id: string; + email: string; + name: string; + /** Default: USER */ + role: UserRole; + address?: Address | null; + /** Default: true */ + active: boolean; + /** Default: now() */ + createdAt: Date; +} + +// Utility Types +export type CreateUserInput = Omit; + +export type UpdateUserInput = Partial; + +export type AnyModel = User; + +export type UserKeys = keyof User;`; + +//--------------------------------------------------------------------// + +export default function UsageExamples() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Usage Examples Section Content */} +
+

{_('6. Usage Examples')}

+

+ + Usage examples demonstrate practical applications of the + TypeScript interface generator with real-world scenarios. + These examples show how to configure the plugin for different + use cases and how the generated TypeScript code integrates + into development workflows. + +

+ +

{_('Basic Schema')}

+

+ + A basic schema example shows the fundamental structure + needed to generate TypeScript interfaces. This includes + model definitions with proper attributes, enum declarations, + and plugin configuration that produces clean, type-safe + TypeScript code. + +

+ + {basicSchemaExample} + + +

{_('Generated Output')}

+

+ + The generated output demonstrates the TypeScript code + produced by the plugin from the basic schema example. + This shows how schema definitions are transformed into + proper TypeScript interfaces with full type safety and + documentation. + +

+ + {generatedOutputExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/typescript-interface-plugin/index.tsx b/packages/www/plugins/docs/components/typescript-interface-plugin/index.tsx new file mode 100644 index 0000000..fa590ad --- /dev/null +++ b/packages/www/plugins/docs/components/typescript-interface-plugin/index.tsx @@ -0,0 +1,11 @@ +//exporting all components to have multiple imports from a single file +export { default as AdvancedFeatures } from './AdvancedFeatures.js'; +export { default as BestPractices } from './BestPractices.js'; +export { default as Implementation } from './Implementation.js'; +export { default as Introduction } from './Introduction.js'; +export { default as Overview } from './Overview.js'; +export { default as PluginStructure } from './PluginStructure.js'; +export { default as Prerequisites } from './Prerequisites.js'; +export { default as SchemaConfiguration } from './SchemaConfiguration.js'; +export { default as Troubleshooting } from './Troubleshooting.js'; +export { default as UsageExamples } from './UsageExamples.js'; \ No newline at end of file diff --git a/packages/www/plugins/docs/components/validation-plugin/AdvancedFeatures.tsx b/packages/www/plugins/docs/components/validation-plugin/AdvancedFeatures.tsx new file mode 100644 index 0000000..73bc4ff --- /dev/null +++ b/packages/www/plugins/docs/components/validation-plugin/AdvancedFeatures.tsx @@ -0,0 +1,160 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const customValidatorsExample = +`// In plugin configuration +customValidators: { + Email: "z.string().email().transform(val => val.toLowerCase())", + Password: "z.string().min(8).regex(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)/)", + Slug: "z.string().regex(/^[a-z0-9-]+$/)", + Color: "z.string().regex(/^#[0-9A-F]{6}$/i)", + JSON: "z.string().transform(val => JSON.parse(val))" +}` + +//--------------------------------------------------------------------// + +const conditionalValidationExample = +`// Generated schema with conditional validation +export const UserSchema = z.object({ + id: z.string(), + email: z.string().email(), + role: UserRoleSchema, + adminCode: z.string().optional(), +}).refine((data) => { + // Admin users must have admin code + if (data.role === 'admin' && !data.adminCode) { + return false; + } + return true; +}, { + message: "Admin users must provide an admin code", + path: ["adminCode"], +});` + +//--------------------------------------------------------------------// + +const transformPreprocessExample = +`// Add transforms to generated schemas +function addTransforms(schema: string, column: any): string { + if (column.attributes?.transform) { + switch (column.attributes.transform) { + case 'lowercase': + return schema + '.transform(val => val.toLowerCase())'; + case 'uppercase': + return schema + '.transform(val => val.toUpperCase())'; + case 'trim': + return schema + '.transform(val => val.trim())'; + case 'slug': + return schema + '.transform(val => val.toLowerCase().replace(/\\s+/g, "-"))'; + } + } + + return schema; +}` + +//--------------------------------------------------------------------// + +const asyncValidationExample = +`// Generate async validation schemas +export const UserSchemaAsync = UserSchema.extend({ + email: z.string().email().refine(async (email) => { + // Check if email is unique + const exists = await checkEmailExists(email); + return !exists; + }, { + message: "Email already exists", + }), +}); + +// Usage +const validateUserAsync = async (data: unknown) => { + try { + const user = await UserSchemaAsync.parseAsync(data); + return { success: true, data: user }; + } catch (error) { + return { success: false, errors: error.errors }; + } +};` + +//--------------------------------------------------------------------// + +export default function AdvancedFeatures() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Advanced Features Section Content */} +
+

{_('7. Advanced Features')}

+

+ + Advanced features extend basic Zod schema generation, adding + validation patterns, conditional logic, data transformation, + and async validation. These features enable production-ready + validation for complex business requirements. + +

+ +

{_('7.1. Custom Validators')}

+

+ + Custom validators let you define specialized validation logic for + certain data types or business rules. This feature lets you create + reusable validation patterns that can be used across many + schema definitions. + +

+ + {customValidatorsExample} + + +

{_('7.2. Conditional Validation')}

+

+ + Conditional validation enables complex validation logic that + depends on the values of other fields. This feature is + essential for implementing business rules that require + cross-field validation and context-dependent constraints. + +

+ + {conditionalValidationExample} + + +

{_('7.3. Transform and Preprocess')}

+

+ + Transform and preprocess capabilities allow you to modify data + during validation. This enables data normalization, formatting, + and cleanup. Using this feature ensures data consistency and + proper formatting before validation occurs. + +

+ + {transformPreprocessExample} + + +

{_('7.4. Async Validation')}

+

+ + Async validation enables validation rules that require + external data sources or API calls, such as checking for + unique values or validating against external services. + This feature is crucial for comprehensive data validation + in real applications. + +

+ + {asyncValidationExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/validation-plugin/BestPractices.tsx b/packages/www/plugins/docs/components/validation-plugin/BestPractices.tsx new file mode 100644 index 0000000..341df7f --- /dev/null +++ b/packages/www/plugins/docs/components/validation-plugin/BestPractices.tsx @@ -0,0 +1,184 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const errorHandlingExample = +`// Centralized validation error handling +class ValidationError extends Error { + constructor(public errors: z.ZodError) { + super('Validation failed'); + this.name = 'ValidationError'; + } + + getFieldErrors(): Record { + const fieldErrors: Record = {}; + + this.errors.errors.forEach((error) => { + const field = error.path.join('.'); + fieldErrors[field] = error.message; + }); + + return fieldErrors; + } +} + +// Usage +function validateWithErrorHandling(schema: z.ZodSchema, data: unknown): T { + const result = schema.safeParse(data); + + if (!result.success) { + throw new ValidationError(result.error); + } + + return result.data; +}` + +//--------------------------------------------------------------------// + +const schemaCompositionExample = `// Compose schemas for reusability +const BaseEntitySchema = z.object({ + id: z.string(), + createdAt: z.date(), + updatedAt: z.date(), +}); + +const UserSchema = BaseEntitySchema.extend({ + email: z.string().email(), + name: z.string().min(1), +}); + +const PostSchema = BaseEntitySchema.extend({ + title: z.string().min(1), + content: z.string(), + authorId: z.string(), +});` + +//--------------------------------------------------------------------// + +const typeGuardsExample = +`// Generate type guards from schemas +export const isUser = (data: unknown): data is User => { + return UserSchema.safeParse(data).success; +}; + +export const isCreateUserInput = (data: unknown): data is CreateUserInput => { + return CreateUserSchema.safeParse(data).success; +}; + +// Usage +function processUserData(data: unknown) { + if (isUser(data)) { + // TypeScript knows data is User + console.log(data.email); + } +}`; + +//--------------------------------------------------------------------// + +const apiIntegrationExample = +`// Middleware for API validation +function validateBody(schema: z.ZodSchema) { + return (req: Request, res: Response, next: NextFunction) => { + const result = schema.safeParse(req.body); + + if (!result.success) { + return res.status(400).json({ + success: false, + error: 'Validation failed', + errors: result.error.errors.reduce((acc, err) => { + const field = err.path.join('.'); + acc[field] = err.message; + return acc; + }, {} as Record) + }); + } + + req.body = result.data; + next(); + }; +} + +// Usage +app.post('/users', validateBody(CreateUserSchema), (req, res) => { + // req.body is now typed and validated + const user = req.body; // Type: CreateUserInput +});` + +//--------------------------------------------------------------------// + +export default function BestPractices() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Best Practices Section Content */} +
+

{_('8. Best Practices')}

+

+ + Best practices ensure your generated Zod validation schemas are + maintainable, performant, and provide excellent developer experience. + These guidelines cover error handling, schema composition, type safety, + and API integration patterns. + +

+ +

{_('8.1. Error Handling')}

+

+ + Proper error handling ensures that validation failures provide clear, + actionable feedback to users and developers. Implement centralized error + handling patterns and meaningful error messages to improve the overall + user experience. + +

+ + {errorHandlingExample} + + +

{_('8.2. Schema Composition')}

+

+ + Schema composition enables the creation of reusable validation components + that can be combined to build complex validation schemas. This approach + promotes code reuse and maintains consistency across your validation logic. + +

+ + {schemaCompositionExample} + + +

{_('8.3. Type Guards')}

+

+ + Type guards provide runtime type checking that integrates seamlessly + with TypeScript's type system. Generated type guards enable safe type + narrowing and improve code reliability by ensuring data conforms to + expected types. + +

+ + {typeGuardsExample} + + +

{_('8.4. API Integration')}

+

+ + API integration patterns show how to use generated Zod schemas for + request validation in web applications. This includes middleware creation, + error response formatting, and type-safe request handling. + +

+ + {apiIntegrationExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/validation-plugin/Implementation.tsx b/packages/www/plugins/docs/components/validation-plugin/Implementation.tsx new file mode 100644 index 0000000..14acc06 --- /dev/null +++ b/packages/www/plugins/docs/components/validation-plugin/Implementation.tsx @@ -0,0 +1,541 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const corePluginFunction = + `export default async function generateZodSchemas( + props: PluginProps<{ config: ZodConfig }> +) { + const { config, schema, transformer } = props; + + try { + // Validate configuration + validateConfig(config); + + // Generate Zod content + let content = ''; + + // Add file header and imports + content += generateFileHeader(); + content += generateImports(config); + + // Generate enums if requested + if (config.includeEnums && schema.enum) { + content += generateEnumSchemas(schema.enum, config); + } + + // Generate custom type schemas + if (schema.type) { + content += generateTypeSchemas(schema.type, config); + } + + // Generate model schemas + if (schema.model) { + content += generateModelSchemas(schema.model, config); + } + + // Generate utility schemas + content += generateUtilitySchemas(schema, config); + + // Generate main export + content += generateMainExport(schema, config); + + // Write to output file + const outputPath = await transformer.loader.absolute(config.output); + await fs.mkdir(path.dirname(outputPath), { recursive: true }); + await fs.writeFile(outputPath, content, 'utf8'); + + console.log(\`✅ Zod validation schemas generated: \${outputPath}\`); + + } catch (error) { + console.error('❌ Zod schema generation failed:', error.message); + throw error; + } +}` + +//--------------------------------------------------------------------// + +const enumGeneration = + `function generateEnumSchemas(enums: Record, config: ZodConfig): string { + let content = '// Enum Schemas\\n'; + + for (const [enumName, enumDef] of Object.entries(enums)) { + const values = Object.values(enumDef); + const zodValues = values.map(v => \`"\${v}"\`).join(', '); + + content += \`export const \${enumName}Schema = z.enum([\${zodValues}]);\\n\`; + + if (config.generateTypes) { + content += \`export type \${enumName} = z.infer;\\n\`; + } + + content += '\\n'; + } + + return content + '\\n'; +}` + +//--------------------------------------------------------------------// + +const typeGeneration = + `function generateTypeSchemas(types: Record, config: ZodConfig): string { + let content = '// Type Schemas\\n'; + + for (const [typeName, typeDef] of Object.entries(types)) { + content += \`export const \${typeName}Schema = z.object({\\n\`; + + for (const column of typeDef.columns || []) { + const fieldSchema = generateFieldSchema(column, config); + content += \` \${column.name}: \${fieldSchema},\\n\`; + } + + content += '})'; + + // Add strict mode if enabled + if (config.strictMode) { + content += '.strict()'; + } + + content += ';\\n'; + + if (config.generateTypes) { + content += \`export type \${typeName} = z.infer;\\n\`; + } + + content += '\\n'; + } + + return content; +}` + +//--------------------------------------------------------------------// + +const modelGeneration = + `function generateModelSchemas(models: Record, config: ZodConfig): string { + let content = '// Model Schemas\\n'; + + for (const [modelName, model] of Object.entries(models)) { + content += \`export const \${modelName}Schema = z.object({\\n\`; + + for (const column of model.columns || []) { + const fieldSchema = generateFieldSchema(column, config); + content += \` \${column.name}: \${fieldSchema},\\n\`; + } + + content += '})'; + + // Add strict mode if enabled + if (config.strictMode) { + content += '.strict()'; + } + + content += ';\\n'; + + if (config.generateTypes) { + content += \`export type \${modelName} = z.infer;\\n\`; + } + + // Generate input schemas + content += generateInputSchemas(modelName, model, config); + + content += '\\n'; + } + + return content; +}` + +//--------------------------------------------------------------------// + +const fieldMapping = + `function generateFieldSchema(column: any, config: ZodConfig): string { + let schema = mapTypeToZod(column.type, config); + + // Handle arrays + if (column.multiple) { + schema = \`z.array(\${schema})\`; + } + + // Handle optional fields + if (!column.required) { + schema += '.optional()'; + } + + // Add custom validations based on attributes + if (column.attributes) { + schema = addAttributeValidations(schema, column.attributes, config); + } + + return schema; +} + +function mapTypeToZod(schemaType: string, config: ZodConfig): string { + // Check for custom validators first + if (config.customValidators && config.customValidators[schemaType]) { + return config.customValidators[schemaType]; + } + + const typeMap: Record = { + 'String': 'z.string()', + 'Number': 'z.number()', + 'Integer': 'z.number().int()', + 'Boolean': 'z.boolean()', + 'Date': 'z.date()', + 'JSON': 'z.any()', + 'ID': 'z.string()' + }; + + return typeMap[schemaType] || \`\${schemaType}Schema\`; +}` + +//--------------------------------------------------------------------// + +const attributeValidations = + `function addAttributeValidations(schema: string, attributes: any, config: ZodConfig): string { + let validatedSchema = schema; + + // String validations + if (attributes.min && schema.includes('z.string()')) { + validatedSchema += \`.min(\${attributes.min})\`; + } + + if (attributes.max && schema.includes('z.string()')) { + validatedSchema += \`.max(\${attributes.max})\`; + } + + if (attributes.email && schema.includes('z.string()')) { + validatedSchema += '.email()'; + } + + if (attributes.url && schema.includes('z.string()')) { + validatedSchema += '.url()'; + } + + if (attributes.uuid && schema.includes('z.string()')) { + validatedSchema += '.uuid()'; + } + + if (attributes.regex && schema.includes('z.string()')) { + validatedSchema += \`.regex(/\${attributes.regex}/)\`; + } + + // Number validations + if (attributes.min && schema.includes('z.number()')) { + validatedSchema += \`.min(\${attributes.min})\`; + } + + if (attributes.max && schema.includes('z.number()')) { + validatedSchema += \`.max(\${attributes.max})\`; + } + + if (attributes.positive && schema.includes('z.number()')) { + validatedSchema += '.positive()'; + } + + if (attributes.negative && schema.includes('z.number()')) { + validatedSchema += '.negative()'; + } + + if (attributes.nonnegative && schema.includes('z.number()')) { + validatedSchema += '.nonnegative()'; + } + + // Array validations + if (attributes.minLength && schema.includes('z.array(')) { + validatedSchema += \`.min(\${attributes.minLength})\`; + } + + if (attributes.maxLength && schema.includes('z.array(')) { + validatedSchema += \`.max(\${attributes.maxLength})\`; + } + + if (attributes.nonempty && schema.includes('z.array(')) { + validatedSchema += '.nonempty()'; + } + + // Custom error messages + if (config.errorMessages) { + const fieldName = extractFieldName(schema); + if (fieldName && config.errorMessages[fieldName]) { + validatedSchema += \`.describe("\${config.errorMessages[fieldName]}")\`; + } + } + + return validatedSchema; +} + +function extractFieldName(schema: string): string | null { + // Extract field name from schema for error message lookup + const match = schema.match(/(\\w+)Schema/); + return match ? match[1] : null; +}` + +//--------------------------------------------------------------------// + +const inputSchemas = + `function generateInputSchemas(modelName: string, model: any, config: ZodConfig): string { + let content = ''; + + // Generate create input schema (omit auto-generated fields) + const createFields = model.columns?.filter((col: any) => + !col.attributes?.id && !col.attributes?.default + ) || []; + + if (createFields.length > 0) { + content += \`export const Create\${modelName}Schema = z.object({\\n\`; + + for (const column of createFields) { + const fieldSchema = generateFieldSchema(column, config); + content += \` \${column.name}: \${fieldSchema},\\n\`; + } + + content += '})'; + + if (config.strictMode) { + content += '.strict()'; + } + + content += ';\\n'; + + if (config.generateTypes) { + content += \`export type Create\${modelName}Input = z.infer;\\n\`; + } + } + + // Generate update input schema (all fields optional) + content += \`export const Update\${modelName}Schema = \${modelName}Schema.partial()\`; + + if (config.strictMode) { + content += '.strict()'; + } + + content += ';\\n'; + + if (config.generateTypes) { + content += \`export type Update\${modelName}Input = z.infer;\\n\`; + } + + return content; +}` + +//--------------------------------------------------------------------// + +const utilitySchemas = + `function generateUtilitySchemas(schema: any, config: ZodConfig): string { + let content = '// Utility Schemas\\n'; + + // Generate pagination schema + content += \`export const PaginationSchema = z.object({ + page: z.number().int().positive().default(1), + limit: z.number().int().positive().max(100).default(10), + search: z.string().optional(), + sort: z.string().optional(), +}); + +\`; + + if (config.generateTypes) { + content += \`export type PaginationParams = z.infer;\\n\\n\`; + } + + // Generate API response schemas + content += \`export const APIResponseSchema = (dataSchema: T) => + z.object({ + success: z.boolean(), + data: dataSchema.optional(), + error: z.string().optional(), + errors: z.record(z.array(z.string())).optional(), + }); + +export const PaginatedResponseSchema = (dataSchema: T) => + z.object({ + success: z.boolean(), + data: z.array(dataSchema).optional(), + total: z.number().int().nonnegative(), + page: z.number().int().positive(), + limit: z.number().int().positive(), + error: z.string().optional(), + errors: z.record(z.array(z.string())).optional(), + }); + +\`; + + return content; +}` + +//--------------------------------------------------------------------// + +const exportFunctions = + `function generateMainExport(schema: any, config: ZodConfig): string { + if (config.exportStyle === 'namespace') { + return generateNamespaceExport(schema, config); + } + + if (config.exportStyle === 'default') { + return generateDefaultExport(schema, config); + } + + // Named exports (default) + return '// All schemas are exported as named exports above\\n'; +} + +function generateNamespaceExport(schema: any, config: ZodConfig): string { + let content = 'export namespace Schemas {\\n'; + + // Export enums + if (config.includeEnums && schema.enum) { + for (const enumName of Object.keys(schema.enum)) { + content += \` export const \${enumName} = \${enumName}Schema;\\n\`; + } + } + + // Export types + if (schema.type) { + for (const typeName of Object.keys(schema.type)) { + content += \` export const \${typeName} = \${typeName}Schema;\\n\`; + } + } + + // Export models + if (schema.model) { + for (const modelName of Object.keys(schema.model)) { + content += \` export const \${modelName} = \${modelName}Schema;\\n\`; + content += \` export const Create\${modelName} = Create\${modelName}Schema;\\n\`; + content += \` export const Update\${modelName} = Update\${modelName}Schema;\\n\`; + } + } + + content += '}\\n\\n'; + return content; +} + +function generateDefaultExport(schema: any, config: ZodConfig): string { + let content = 'const schemas = {\\n'; + + // Add enums + if (config.includeEnums && schema.enum) { + for (const enumName of Object.keys(schema.enum)) { + content += \` \${enumName}: \${enumName}Schema,\\n\`; + } + } + + // Add types + if (schema.type) { + for (const typeName of Object.keys(schema.type)) { + content += \` \${typeName}: \${typeName}Schema,\\n\`; + } + } + + // Add models + if (schema.model) { + for (const modelName of Object.keys(schema.model)) { + content += \` \${modelName}: \${modelName}Schema,\\n\`; + content += \` Create\${modelName}: Create\${modelName}Schema,\\n\`; + content += \` Update\${modelName}: Update\${modelName}Schema,\\n\`; + } + } + + content += \` Pagination: PaginationSchema, + APIResponse: APIResponseSchema, + PaginatedResponse: PaginatedResponseSchema, +}; + +export default schemas; +\`; + + return content; +}` + +//--------------------------------------------------------------------// + +const configValidation = +`function validateConfig(config: any): asserts config is ZodConfig { + if (!config.output || typeof config.output !== 'string') { + throw new Error('Zod plugin requires "output" configuration as string'); + } + + if (config.exportStyle && !['named', 'default', 'namespace'].includes(config.exportStyle)) { + throw new Error('exportStyle must be one of: named, default, namespace'); + } +}` + +//--------------------------------------------------------------------// + +export default function Implementation() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Implementation Section Content */} +
+

{_('4. Implementation')}

+

+ + The implementation section covers the core plugin function and + supporting utilities that handle Zod schema generation. This + includes configuration validation, content generation, file writing, + and error handling throughout the generation process. + +

+ +

{_('4.1. Core Plugin Function')}

+

+ + The core plugin function serves as the main entry point for Zod + schema generation. It orchestrates the entire process from + configuration validation through content generation to file output, + ensuring proper error handling and logging throughout. + +

+ + {corePluginFunction} + + +

{_('4.2. Generation Functions')}

+

+ + Generation functions create specific parts of the Zod validation + output including enum schemas, type schemas, model schemas, and + utility schemas. These functions handle proper Zod syntax + construction and validation rule application. + +

+ + {corePluginFunction} + + + {enumGeneration} + + + {typeGeneration} + + + {modelGeneration} + + + {fieldMapping} + + + {attributeValidations} + + + {inputSchemas} + + + {utilitySchemas} + + + {exportFunctions} + + + {configValidation} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/validation-plugin/Introduction.tsx b/packages/www/plugins/docs/components/validation-plugin/Introduction.tsx new file mode 100644 index 0000000..20f0eaf --- /dev/null +++ b/packages/www/plugins/docs/components/validation-plugin/Introduction.tsx @@ -0,0 +1,26 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C } from '../../../docs/components/index.js'; + +export default function Introduction() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Creating a Validation Schema Generator Plugin */} +
+

{_('Validation Schema Generator Plugin Tutorial')}

+

+ + This tutorial guides you through building a plugin that creates + Zod validation schemas from .idea schema files. With this + plugin, your schema models become type-safe validation schemas + with complete validation rules. + +

+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/validation-plugin/Overview.tsx b/packages/www/plugins/docs/components/validation-plugin/Overview.tsx new file mode 100644 index 0000000..d7b4d2b --- /dev/null +++ b/packages/www/plugins/docs/components/validation-plugin/Overview.tsx @@ -0,0 +1,65 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C, SS } from '../../../docs/components/index.js'; + +export default function Overview() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Overview Section Content */} +
+

{_('1. Overview')}

+

+ + Zod is a TypeScript-first schema validation library that + provides runtime type checking and validation. This plugin + transforms your .idea schema definitions into + comprehensive Zod validation schemas that offer robust + runtime validation with excellent TypeScript integration. + +

+

+ + This plugin generates Zod schemas from your .idea + schema, including: + +

+
    +
  • + + Schema Validation: Zod schemas for all models + and types + +
  • +
  • + + Type Inference: TypeScript types inferred from + Zod schemas + +
  • +
  • + + Custom Validators: Support for custom validation + rules + +
  • +
  • + + Error Messages: Customizable validation error + messages + +
  • +
  • + + Nested Validation: Support for nested objects + and arrays + +
  • +
+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/validation-plugin/PluginStructure.tsx b/packages/www/plugins/docs/components/validation-plugin/PluginStructure.tsx new file mode 100644 index 0000000..4f22233 --- /dev/null +++ b/packages/www/plugins/docs/components/validation-plugin/PluginStructure.tsx @@ -0,0 +1,59 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const pluginStructureExample = + `import type { PluginProps } from '@stackpress/idea-transformer/types'; +import fs from 'fs/promises'; +import path from 'path'; + +interface ZodConfig { + output: string; + generateTypes?: boolean; + includeEnums?: boolean; + customValidators?: Record; + errorMessages?: Record; + strictMode?: boolean; + exportStyle?: 'named' | 'default' | 'namespace'; +} + +export default async function generateZodSchemas( + props: PluginProps<{ config: ZodConfig }> +) { + const { config, schema, transformer } = props; + + // Implementation here... +}`; + +//--------------------------------------------------------------------// + +export default function PluginStructure() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Plugin Structure Section Content */} +
+

{_('3. Plugin Structure')}

+

+ + The plugin structure defines the core architecture and + configuration interface for the Zod validation schema + generator. This includes the main plugin function, + configuration types, and the overall organization of + the generated validation code. + +

+ + {pluginStructureExample} + +
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/validation-plugin/Prerequisites.tsx b/packages/www/plugins/docs/components/validation-plugin/Prerequisites.tsx new file mode 100644 index 0000000..bef276c --- /dev/null +++ b/packages/www/plugins/docs/components/validation-plugin/Prerequisites.tsx @@ -0,0 +1,53 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C } from '../../../docs/components/index.js'; + +export default function Prerequisites() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Prerequisites Section Content */} +
+

{_('2. Prerequisites')}

+

+ + Before implementing the Zod validation schema generator + plugin, ensure you have the necessary development environment + and knowledge. This section covers the essential requirements + for successful plugin creation and Zod integration. + +

+
    +
  • + Node.js 16+ and npm/yarn +
  • +
  • + TypeScript 4.0+ +
  • +
  • + Zod 3.0+ +
  • +
  • + + Basic understanding of validation concepts + +
  • +
  • + + Familiarity with the @stackpress/idea-transformer + library + +
  • +
  • + + Understanding of .idea schema format + +
  • +
+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/validation-plugin/SchemaConfiguration.tsx b/packages/www/plugins/docs/components/validation-plugin/SchemaConfiguration.tsx new file mode 100644 index 0000000..b2d1a26 --- /dev/null +++ b/packages/www/plugins/docs/components/validation-plugin/SchemaConfiguration.tsx @@ -0,0 +1,135 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +import { Table, Thead, Trow, Tcol } from 'frui/element/Table'; +//local +import { H1, H2, P, C } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const basicConfiguration = + `plugin "./plugins/zod-validation.js" { + output "./generated/validation.ts" + generateTypes true + includeEnums true + strictMode true + exportStyle "named" + customValidators { + Email "z.string().email()" + Password "z.string().min(8).regex(/^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)/)" + PhoneNumber "z.string().regex(/^\\+?[1-9]\\d{1,14}$/)" + } + errorMessages { + email "Please enter a valid email address" + password "Password must be at least 8 characters with uppercase, lowercase, and number" + required "This field is required" + } +}`; + +//--------------------------------------------------------------------// + +const configurationOptions = [ + { + option: 'output', + type: 'string', + description: 'Output file path for validation schemas', + default: 'Required' + }, + { + option: 'generateTypes', + type: 'boolean', + description: 'Generate TypeScript types from schemas', + default: 'true' + }, + { + option: 'includeEnums', + type: 'boolean', + description: 'Generate enum validation schemas', + default: 'true' + }, + { + option: 'customValidators', + type: 'object', + description: 'Custom Zod validators for specific types', + default: '{}' + }, + { + option: 'errorMessages', + type: 'object', + description: 'Custom error messages for validation', + default: '{}' + }, + { + option: 'strictMode', + type: 'boolean', + description: 'Use strict object validation', + default: 'false' + }, + { + option: 'exportStyle', + type: '\'named\'|\'default\'|\'namespace\'', + description: 'Export style for schemas', + default: '\'named\'' + } +]; + +//--------------------------------------------------------------------// + +export default function SchemaConfiguration() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Schema Configuration Section Content */} +
+

{_('5. Schema Configuration')}

+

+ + Schema configuration shows how to use the Zod validation + generator with your .idea schema files. This section covers + the plugin configuration options and how they affect the + generated validation schemas. + +

+ +

+ + Add the Zod validation plugin to your .idea schema file: + +

+ + {basicConfiguration} + + +

{_('Configuration Options')}

+

+ + Configuration options control how Zod validation schemas are + generated, including output formatting, validation strictness, + and feature enablement. Understanding these options helps you + customize the plugin to meet your specific validation + requirements. + +

+ + + Option + Type + Description + Default + + {configurationOptions.map(config => ( + + {config.option} + {config.type} + {_(config.description)} + {config.default} + + ))} +
+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/validation-plugin/Troubleshooting.tsx b/packages/www/plugins/docs/components/validation-plugin/Troubleshooting.tsx new file mode 100644 index 0000000..bf34981 --- /dev/null +++ b/packages/www/plugins/docs/components/validation-plugin/Troubleshooting.tsx @@ -0,0 +1,205 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const circularDependenciesExample = + `// Handle circular references with lazy evaluation +const UserSchema: z.ZodSchema = z.lazy(() => z.object({ + id: z.string(), + posts: z.array(PostSchema), +})); + +const PostSchema: z.ZodSchema = z.lazy(() => z.object({ + id: z.string(), + author: UserSchema, +}));`; + +//--------------------------------------------------------------------// + +const complexValidationExample = + `// Use refinements for complex validation +const PasswordSchema = z.string() + .min(8, "Password must be at least 8 characters") + .refine((password) => /[A-Z]/.test(password), { + message: "Password must contain at least one uppercase letter", + }) + .refine((password) => /[a-z]/.test(password), { + message: "Password must contain at least one lowercase letter", + }) + .refine((password) => /\\d/.test(password), { + message: "Password must contain at least one number", + });`; + +//--------------------------------------------------------------------// + +const performanceOptimizationExample = + `// Use preprocess for expensive operations +const OptimizedSchema = z.preprocess( + (data) => { + // Expensive preprocessing + return normalizeData(data); + }, + z.object({ + // Schema definition + }) +);`; + +//--------------------------------------------------------------------// + +const schemaTestingExample = + `// Test schemas with various inputs +describe('UserSchema', () => { + it('should validate valid user data', () => { + const validData = { + email: 'test@example.com', + name: 'Test User', + age: 25 + }; + + expect(() => UserSchema.parse(validData)).not.toThrow(); + }); + + it('should reject invalid email', () => { + const invalidData = { + email: 'invalid-email', + name: 'Test User', + age: 25 + }; + + expect(() => UserSchema.parse(invalidData)).toThrow(); + }); +});`; + +//--------------------------------------------------------------------// + +const errorCustomizationExample = + `// Customize error messages for better UX +const UserSchema = z.object({ + email: z.string().email("Please enter a valid email address"), + age: z.number().min(18, "You must be at least 18 years old"), +});`; + +//--------------------------------------------------------------------// + +export default function Troubleshooting() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Troubleshooting Section Content */} +
+

{_('9. Troubleshooting')}

+

+ + This section addresses common issues that you may find when + generating Zod validation schemas. It also provides solutions + for debugging and resolving problems. By learning these + troubleshooting techniques, you can help ensure that your + validation schema generation is reliable. + +

+ +

{_('9.1. Common Issues')}

+

+ + Common issues include circular dependencies, complex + validation rules, and performance problems with large + schemas. These problems typically arise from schema + complexity or validation requirements that need specialized + handling. + +

+ +

{_('9.1.1. Circular Dependencies')}

+

+ + Circular dependencies occur when schemas reference each + other in a way that creates infinite loops. Zod provides + lazy evaluation to handle these scenarios while maintaining + type safety and validation integrity. + +

+ + {circularDependenciesExample} + + +

{_('9.1.2. Complex Validation Rules')}

+

+ + Complex validation rules require sophisticated logic that + goes beyond simple type checking. Use Zod's refinement + capabilities to implement business rules and cross-field + validation while maintaining clear error messages. + +

+ + {complexValidationExample} + + +

{_('9.1.3. Performance Issues')}

+

+ + Performance issues can arise when validation schemas are + complex or when handling large datasets. Improve validation + performance by using preprocessing, caching, and designing + efficient schemas with optimal patterns. + +

+ + {performanceOptimizationExample} + + +

{_('9.2. Debugging Tips')}

+

+ + Debugging tips help identify and resolve issues during Zod + schema generation and usage. These techniques provide + visibility into validation behavior and help diagnose + problems with schema logic or performance. + +

+ +

{_('9.2.1. Schema Testing')}

+

+ + Schema testing ensures your validation works in all situations + by verifying logic against many scenarios. Comprehensive tests + catch edge cases and guarantee validation acts as expected + in production. + +

+ + {schemaTestingExample} + + +

{_('9.2.2. Error Message Customization')}

+

+ + Error message customization makes the user experience better by + giving clear, actionable feedback when validation fails. Good + error messages help users understand what went wrong and what + steps to take to fix it. + +

+ + {errorCustomizationExample} + + +

+ + This tutorial provides a comprehensive foundation for creating + Zod validation schemas from .idea files. The generated schemas + provide runtime type checking and validation with excellent + TypeScript integration. + +

+
+ + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/components/validation-plugin/UsageExamples.tsx b/packages/www/plugins/docs/components/validation-plugin/UsageExamples.tsx new file mode 100644 index 0000000..19504a7 --- /dev/null +++ b/packages/www/plugins/docs/components/validation-plugin/UsageExamples.tsx @@ -0,0 +1,189 @@ +//modules +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P } from '../../../docs/components/index.js'; +import Code from '../../../docs/components/Code.js'; + +//code examples +//--------------------------------------------------------------------// + +const basicSchemaExample = +`enum UserRole { + ADMIN "admin" + USER "user" + GUEST "guest" +} + +model User { + id String @id @default("nanoid()") + email String @email @required + name String @min(2) @max(50) @required + age Number @min(18) @max(120) + role UserRole @default("USER") + active Boolean @default(true) + createdAt Date @default("now()") +} + +plugin "./plugins/zod-validation.js" { + output "./validation.ts" + generateTypes true + strictMode true +}` + +//--------------------------------------------------------------------// + +const generatedValidationUsage = `import { + UserSchema, + CreateUserSchema, + UpdateUserSchema, + UserRole +} from './validation'; + +// Validate complete user object +const validateUser = (data: unknown) => { + try { + const user = UserSchema.parse(data); + console.log('Valid user:', user); + return { success: true, data: user }; + } catch (error) { + console.error('Validation failed:', error.errors); + return { success: false, errors: error.errors }; + } +}; + +// Validate user creation data +const validateCreateUser = (data: unknown) => { + const result = CreateUserSchema.safeParse(data); + + if (result.success) { + console.log('Valid create data:', result.data); + return result.data; + } else { + console.error('Validation errors:', result.error.errors); + throw new Error('Invalid user data'); + } +}; + +// Validate user update data +const validateUpdateUser = (data: unknown) => { + return UpdateUserSchema.parse(data); +}; + +// Example usage +const userData = { + email: 'john@example.com', + name: 'John Doe', + age: 30, + role: 'user' as UserRole +}; + +const validUser = validateCreateUser(userData);` + +//--------------------------------------------------------------------// + +const formValidationExample = +`import { CreateUserSchema } from './validation'; + +// React form validation +function UserForm() { + const [errors, setErrors] = useState>({}); + + const handleSubmit = (formData: FormData) => { + const data = Object.fromEntries(formData); + + const result = CreateUserSchema.safeParse(data); + + if (!result.success) { + const fieldErrors: Record = {}; + + result.error.errors.forEach((error) => { + const field = error.path[0] as string; + fieldErrors[field] = error.message; + }); + + setErrors(fieldErrors); + return; + } + + // Submit valid data + submitUser(result.data); + }; + + return ( +
+ + {errors.email && {errors.email}} + + + {errors.name && {errors.name}} + + + {errors.age && {errors.age}} + + +
+ ); +}` + +//--------------------------------------------------------------------// + +export default function UsageExamples() { + //hooks + const { _ } = useLanguage(); + + return ( + <> + {/* Usage Examples Section Content */} +
+

{_('6. Usage Examples')}

+

+ + Usage examples demonstrate practical applications of the Zod + validation generator with real-world scenarios. These examples + show how to configure the plugin for different use cases and + how the generated validation schemas integrate into development + workflows. + +

+ +

{_('6.1. Basic Schema')}

+

+ + A basic schema example shows the fundamental structure needed + to generate Zod validation schemas. This includes model + definitions with proper validation attributes and plugin + configuration that produces comprehensive validation rules. + +

+ + {basicSchemaExample} + + +

{_('6.2. Generated Validation Usage')}

+

+ + The generated validation usage demonstrates how to use the Zod + schemas produced by the plugin in real applications. This shows + practical patterns for data validation, error handling, and + type safety in TypeScript applications. + +

+ + {generatedValidationUsage} + + +

{_('6.3. Form Validation Example')}

+

+ + Zod schemas with frontend frameworks for user input validation. + This demonstrates real-world usage patterns for form handling + and user feedback. + +

+ + {formValidationExample} + +
+ + ); +} diff --git a/packages/www/plugins/docs/components/validation-plugin/index.tsx b/packages/www/plugins/docs/components/validation-plugin/index.tsx new file mode 100644 index 0000000..fa590ad --- /dev/null +++ b/packages/www/plugins/docs/components/validation-plugin/index.tsx @@ -0,0 +1,11 @@ +//exporting all components to have multiple imports from a single file +export { default as AdvancedFeatures } from './AdvancedFeatures.js'; +export { default as BestPractices } from './BestPractices.js'; +export { default as Implementation } from './Implementation.js'; +export { default as Introduction } from './Introduction.js'; +export { default as Overview } from './Overview.js'; +export { default as PluginStructure } from './PluginStructure.js'; +export { default as Prerequisites } from './Prerequisites.js'; +export { default as SchemaConfiguration } from './SchemaConfiguration.js'; +export { default as Troubleshooting } from './Troubleshooting.js'; +export { default as UsageExamples } from './UsageExamples.js'; \ No newline at end of file diff --git a/packages/www/plugins/docs/plugin.ts b/packages/www/plugins/docs/plugin.ts new file mode 100644 index 0000000..79f6614 --- /dev/null +++ b/packages/www/plugins/docs/plugin.ts @@ -0,0 +1,102 @@ +//stackpress +import type { Server, Response } from 'stackpress/server'; +//view +import type { ViewConfig, BrandConfig, LanguageConfig } from 'stackpress'; + +export function setServerProps(server: Server, res: Response) { + //get the view, brand and auth config + const view = server.config.path('view', {}); + const brand = server.config.path('brand', {}); + const language = server.config.path('language', { + key: 'locale', + locale: 'en_US', + languages: {} + }); + //set data for template layer + res.data.set('view', { + base: view.base || '/', + props: view.props || {} + }); + res.data.set('brand', { + name: brand.name || 'Stackpress', + logo: brand.logo || '/logo.png', + icon: brand.icon || '/icon.png', + favicon: brand.favicon || '/favicon.ico', + }); + res.data.set('language', { + key: language.key || 'locale', + locale: language.locale || 'en_US', + languages: language.languages || {} + }); +} + +export default function plugin(server: Server) { + //on route, add docs routes + server.on('route', _ => { + server.get('/docs', (_req, res, ctx) => setServerProps(ctx, res)); + server.get('/docs/**', (_req, res, ctx) => setServerProps(ctx, res)); + server.get('/docs', '@/plugins/docs/views/index', -100); + server.get('/docs/introduction', '@/plugins/docs/views/index', -100); + + //other routes + [ + 'getting-started', + //specifications + 'specifications/introduction', + 'specifications/syntax-overview', + 'specifications/data-types', + 'specifications/schema-elements', + 'specifications/schema-structure', + 'specifications/schema-directives', + 'specifications/processing-flow', + 'specifications/plugin-system', + 'specifications/complete-examples', + 'specifications/best-practices', + 'specifications/error-handling', + //parser + 'parser/installation', + 'parser/core-concepts', + 'parser/api-reference', + 'parser/examples', + 'parser/best-practices', + 'parser/api-references/compiler', + 'parser/api-references/lexer', + 'parser/api-references/ast', + 'parser/api-references/tokens', + 'parser/api-references/exception-handling', + //transformers + 'transformers/introduction', + 'transformers/api-reference', + 'transformers/architecture', + 'transformers/usage-patterns', + 'transformers/common-use-cases', + 'transformers/examples', + 'transformers/error-handling', + 'transformers/best-practices', + 'transformers/api-references/transformer', + 'transformers/api-references/terminal', + //plugins + 'plugin-development/plugin-development-guide', + 'plugin-development/plugin-examples', + 'plugin-development/plugin-configuration', + 'plugin-development/error-handling', + 'plugin-development/best-practices', + 'plugin-development/available-tutorials', + 'plugin-development/advanced-tutorials', + 'plugin-development/getting-started', + //tutorials + 'tutorials/tsmorph-plugin-guide', + 'tutorials/mysql-table-plugin', + 'tutorials/html-form-plugin', + 'tutorials/markdown-documentation-plugin', + 'tutorials/graphql-schema-plugin', + 'tutorials/typescript-interface-plugin', + 'tutorials/api-client-plugin', + 'tutorials/validation-plugin', + 'tutorials/test-data-plugin', + 'tutorials/openapi-specification-plugin', + ].map(route => { + server.get(`/docs/${route}`, `@/plugins/docs/views/${route}`, -100); + }); + }); +}; \ No newline at end of file diff --git a/packages/www/plugins/docs/styles/styles.css b/packages/www/plugins/docs/styles/styles.css new file mode 100644 index 0000000..84da1e6 --- /dev/null +++ b/packages/www/plugins/docs/styles/styles.css @@ -0,0 +1,3 @@ +@import url('https://fonts.googleapis.com/css2?family=Poppins:ital,wght@0,100;0,200;0,300;0,400;0,500;0,600;0,700;0,800;0,900;1,100;1,200;1,300;1,400;1,500;1,600;1,700;1,800;1,900&display=swap'); + +* { font-family: 'Poppins', sans-serif; } \ No newline at end of file diff --git a/packages/www/plugins/docs/views/getting-started.tsx b/packages/www/plugins/docs/views/getting-started.tsx new file mode 100644 index 0000000..983e880 --- /dev/null +++ b/packages/www/plugins/docs/views/getting-started.tsx @@ -0,0 +1,235 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useState } from 'react'; +import { useLanguage, Translate } from 'r22n'; +import clsx from 'clsx'; +//local +import { H1, P, C, Nav } from '../components/index.js'; +import Code from '../components/Code.js'; +import Layout from '../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const npmInstallCommand = 'npm i -D @stackpress/idea'; + +//--------------------------------------------------------------------// + +const yarnInstallCommand = 'yarn add --dev @stackpress/idea'; + +//--------------------------------------------------------------------// + +const schemaExample = +`model User { + id String @id @default("nanoid()") + name String @required + email String @unique @required + created Date @default("now()") +} + +plugin "./plugins/typescript-generator.js" { + output "./generated/types.ts" +}`; + +//--------------------------------------------------------------------// + +const generateCommand = 'npx idea transform --input schema.idea'; + +//styles +//--------------------------------------------------------------------// + +const packageStyle = clsx( + 'bg-yellow-800', + 'text-white' +); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Getting Started'); + const description = _('describe'); + return ( + <> + {title} + + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ); +} + +export function Body() { + //hooks + const [install, setInstall] = useState('npm'); + const { _ } = useLanguage(); + + return ( +
+ {/* Getting Started Section Content */} +
+

{_('Getting Started')}

+

+ + The following is a guide to get you started with Idea. + +

+
+ + {/* Horizontal Rule */} +
+ + {/* Installation */} +
+

{_('Installation')}

+
+
+
setInstall('npm')} + > + +
+
setInstall('yarn')} + > + +
+
+ + {npmInstallCommand} + + + {yarnInstallCommand} + +
+
+ + {/* Horizontal Rule */} +
+ + {/* Create Schema Content */} +
+

{_('Create your first schema')}

+

+ + Create a new file called schema.idea + +

+ + {schemaExample} + +
+ + {/* Horizontal Rule */} +
+ + {/* Generate Code Content */} +
+

{_('Generate Code')}

+ + {generateCommand} + +
+ + {/* Horizontal Rule */} +
+ + {/* Explore the Results Content */} +
+

{_('Explore the Results')}

+

+ + Check the generated files in your output directories! + +

+
+ + {/* Page Navigation */} +
+ ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/views/index.tsx b/packages/www/plugins/docs/views/index.tsx new file mode 100644 index 0000000..a50c049 --- /dev/null +++ b/packages/www/plugins/docs/views/index.tsx @@ -0,0 +1,360 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +import clsx from 'clsx'; +//local +import { H1, H2, P, Nav } from '../components/index.js'; +import Layout from '../components/Layout.js'; +import Code from '../components/Code.js'; + +//code example +//--------------------------------------------------------------------// + +const schemaExample = +`// schema.idea +enum UserRole { + ADMIN "Administrator" + CUSTOMER "Customer" +} + +model User { + id String @id @default("nanoid()") + email String @unique @required + name String @required + role UserRole @default("CUSTOMER") + orders Order[] @relation(Order.userId) +} + +model Product { + id String @id @default("nanoid()") + name String @required + price Number @required + inStock Boolean @default(true) +} + +model Order { + id String @id @default("nanoid()") + userId String @relation(User.id) + total Number @required + status String @default("PENDING") +} + +// Generate everything with plugins +plugin "./plugins/typescript-generator.js" { + output "./src/types/schema.ts" +} + +plugin "./plugins/database-generator.js" { + output "./database/schema.sql" + dialect "postgresql" +} + +plugin "./plugins/react-forms.js" { + output "./src/components/forms/" + framework "react" + styling "tailwind" +} + +plugin "./plugins/api-generator.js" { + output "./src/api/" + framework "express" + includeValidation true +}`; + +//--------------------------------------------------------------------// + +//styles +//--------------------------------------------------------------------// + +const iconStyle = clsx( + 'fa-circle-check', + 'fa-solid', + 'mx-2', + 'text-green-500' +); + +//--------------------------------------------------------------------// + +export function DocumentationHead(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const url = request.url?.pathname || '/docs'; + const title = _('What is .idea?'); + const description = _( + 'The .idea file format is a declarative schema definition language' + + 'designed to simplify application development by providing a single' + + 'source of truth for data structures, relationships, and code generation.' + ); + return ( + <> + {title} + + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function DocumentationBody() { + //hooks + const { _ } = useLanguage(); + + return ( +
+ {/* Introduction */} +
+

{_('What is .idea?')}

+ +

+ + The .idea file format is a declarative schema definition + language designed to simplify application development by + providing a single source of truth for data structures, + relationships, and code generation. It enables developers + to define their application's data model once and generate + multiple outputs including database schemas, TypeScript + interfaces, API documentation, forms, and more. + +

+ +

+ + Think of it as the bridge between AI prompting and full- + stack code generation - where a simple schema definition can + automatically generate everything from database tables to + React components, API endpoints to documentation sites. + +

+
+ + {/* Horizontal Rule */} +
+ + {/* Why use .idea? */} +
+

{_('Why Use .idea?')}

+ +
    +
  • +

    {_('Single Source of Truth')}

    + + Define your data model once, use it everywhere. No more + maintaining separate schemas for database, frontend, and + API. + +
  • +
  • +

    {_('Type Safety Everywhere')}

    + + Generate type-safe code across languages - TypeScript, + Python, Rust, Go, and more. Catch errors at compile time. + +
  • +
  • +

    {_('Rapid Development')}

    + + Generate boilerplate code, forms, and documentation in + seconds. What used to take hours now happens instantly. + +
  • +
+
+ + {/* Horizontal Rule */} +
+ + {/* Who Should Use This? */} +
+

{_('Who Should Use This?')}

+ +
    +
  • +

    {_('Junior Developers')}

    + + Easy syntax, rapid prototyping, learn best practices + through generated code. + +
  • +
  • +

    {_('Senior Developers')}

    + + Powerful features, extensible plugins, maintain + consistency across large codebases. + +
  • +
  • +

    {_('CTOs & Technical Leaders')}

    + + Reduce development time by 60-80%, improve consistency, + accelerate time-to-market. + +
  • +
+
+ + {/* Horizontal Rule */} +
+ + {/* The Plugin Ecosystem */} +
+

{_('The Plugin Ecosystem')}

+ +

+ + The power of .idea comes from its plugin system. Generate + code for any technology: + +

+ +
    +
  • +

    {_('Languages')}

    + + TypeScript, Python, Rust, Go, Java, C#, PHP, and more. + +
  • +
  • +

    {_('Frameworks')}

    + + React, Vue, Angular, Next.js, Express, FastAPI, Django, + and more. + +
  • +
  • +

    {_('Databases')}

    + + PostgreSQL, MySQL, MongoDB, Neo4j, and more. + +
  • +
+
+ + {/* Horizontal Rule */} +
+ + {/* Real-World Example */} +
+

{_('Real-World Example')}

+ +

+ + Here's how a simple e-commerce schema becomes a full + application: + +

+ + + {schemaExample} + + +

+ + From this single schema, generate: + +

+ +
    +
  • + + {_('TypeScript interfaces')} +
  • +
  • + + {_('PostgreSQL schema')} +
  • +
  • + + {_('React components')} +
  • +
  • + + {_('API documentation')} +
  • +
  • + + {_('Validation schemas')} +
  • +
  • + + {_('Test data')} +
  • +
+
+ + {/* Horizontal Rule */} +
+ + {/* AI-Powered Workflow */} +
+

{_('AI-Powered Workflow')}

+ +

+ + The perfect workflow for AI-driven development: + +

+ +
    +
  1. {_('Describe your app to an AI')}
  2. +
  3. {_('Get a .idea schema')}
  4. +
  5. {_('Configure plugins')}
  6. +
  7. {_('Generate full-stack code')}
  8. +
  9. {_('Iterate and improve')}
  10. +
+ +

+ + Go from idea to working application in minutes, not days. + +

+
+ + {/* Page Navigation */} +
+ ); +} + +export function DocumentationPage(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} + +export const Head = DocumentationHead; +export default DocumentationPage; \ No newline at end of file diff --git a/packages/www/plugins/docs/views/parser/api-reference.tsx b/packages/www/plugins/docs/views/parser/api-reference.tsx new file mode 100644 index 0000000..e6d39d9 --- /dev/null +++ b/packages/www/plugins/docs/views/parser/api-reference.tsx @@ -0,0 +1,320 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +import clsx from 'clsx'; +//local +import { H1, H2, P, C, Nav, SS } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const parseExample = +`import { parse } from '@stackpress/idea-parser'; + +const result = parse(\` +prop Text { type "text" } +model User { + name String @field.input(Text) +} +\`); + +console.log(result); +// Output includes prop references: { prop: { Text: { type: "text" } }, ... }`; + +//--------------------------------------------------------------------// + +const finalExample = +`import { final } from '@stackpress/idea-parser'; + +const result = final(\` +prop Text { type "text" } +model User { + name String @field.input(Text) +} +\`); + +console.log(result); +// Output has resolved references: { model: { User: { ... } } } +// No 'prop' section in output`; + +//--------------------------------------------------------------------// + +const exceptionExample = +`import { Exception } from '@stackpress/idea-parser'; + +try { + const result = parse(invalidCode); +} catch (error) { + if (error instanceof Exception) { + console.log('Parsing error:', error.message); + } +}`; + +//--------------------------------------------------------------------// + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx( + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500' +); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('API Reference'); + const description = _( + 'Complete API reference for the Idea Parser library, ' + + 'including detailed documentation for all classes, ' + + 'methods, and interfaces.' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + + return ( + + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
+

{_('API Reference')}

+ + {/* Main Function Section Content */} +
+

{_('Main Functions')}

+

+ parse(code: string) +

+ + Converts schema code into a JSON representation with + references preserved. + + {_('Parameters:')}: +
  • + code (string): {_('The schema code to parse')} +
  • + + {_('Returns:')}: +
  • + SchemaConfig: {_('JSON object representing the ' + + 'parse schema')} +
  • + +

    {_('Example:')}

    + + {parseExample} + + +

    + final(code: string) +

    + + + Converts schema code into a clean JSON representation with + references resolved and removed. + + + {_('Parameters')} +
  • + code (string): {_('The schema code to parse')} +
  • + + {_('Returns:')}: +
  • + FinalSchemaConfig: {_('Clean JSON object without ' + + 'prop/use references')} +
  • + + {_('Example:')} + + {finalExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Core Classes Section Content */} +
    +

    {_('Core Classes')}

    +
      +
    • + + Compiler: + {_('Static methods for converting AST tokens to JSON')} +
    • +
    • + + Lexer: + {_('Tokenization and parsing utilities')} +
    • +
    • + SchemaTree: + {_('Main parser for complete schema files')} +
    • +
    • + + Syntax Trees: + {_('Individual parsers for different schema elements')} +
    • +
    • + + Tokens: + {_('AST token structures and type definitions')} +
    • +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Exception Handling Section Content */} +
    +

    {_('Exception Handling')}

    + + The library uses a custom Exception class that extends the + standard Exception class for better error reporting. + + + {exceptionExample} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + } + > + + + ); +} diff --git a/packages/www/plugins/docs/views/parser/api-references/ast.tsx b/packages/www/plugins/docs/views/parser/api-references/ast.tsx new file mode 100644 index 0000000..e80f6e4 --- /dev/null +++ b/packages/www/plugins/docs/views/parser/api-references/ast.tsx @@ -0,0 +1,1536 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { Table, Thead, Trow, Tcol } from 'frui/element/Table'; +import { useLanguage, Translate } from 'r22n'; +import clsx from 'clsx'; +//local +import { H1, H2, C, SS, Nav, P } from '../../../components/index.js'; +import Code from '../../../components/Code.js'; +import Layout from '../../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const examples = [ + `import { + SchemaTree, + EnumTree, + ModelTree, + TypeTree, + PropTree, + PluginTree, + UseTree +} from '@stackpress/idea-parser';`, + + //--------------------------------------------------------------- + + `import { SchemaTree, Lexer } from '@stackpress/idea-parser'; + +const lexer = new Lexer(); +SchemaTree.definitions(lexer); + +// Lexer now has definitions for all schema constructs: +// enum, prop, type, model, plugin, use keywords and structures`, + + //--------------------------------------------------------------- + + `import { SchemaTree } from '@stackpress/idea-parser'; + +const schemaCode = \` +plugin "./database" { + provider "postgresql" +} + +enum Status { + ACTIVE "Active" + INACTIVE "Inactive" +} + +prop Text { type "text" } + +model User { + id String @id + name String @field.input(Text) + status Status +} +\`; + +const ast = SchemaTree.parse(schemaCode); +console.log(ast.type); // 'Program' +console.log(ast.kind); // 'schema' +console.log(ast.body.length); // 4 (plugin, enum, prop, model)`, + + //--------------------------------------------------------------- + + `import { SchemaTree } from '@stackpress/idea-parser'; + +const tree = new SchemaTree(); +const schemaCode = 'enum Status { ACTIVE "Active" }'; + +const result = tree.parse(schemaCode, 0); +console.log(result.body[0].kind); // 'enum'`, + + //--------------------------------------------------------------- + + `import { EnumTree, Lexer } from '@stackpress/idea-parser'; + +const lexer = new Lexer(); +EnumTree.definitions(lexer); + +// Adds 'EnumWord' token definition for 'enum' keyword`, + + //--------------------------------------------------------------- + + `import { EnumTree } from '@stackpress/idea-parser'; + +const enumCode = \`enum Roles { + ADMIN "Admin" + MANAGER "Manager" + USER "User" +}\`; + +const ast = EnumTree.parse(enumCode); +console.log(ast.kind); // 'enum' +console.log(ast.declarations[0].id.name); // 'Roles' +console.log(ast.declarations[0].init.properties.length); // 3 +console.log(ast.declarations[0].init.properties[0].key.name); // 'ADMIN' +console.log(ast.declarations[0].init.properties[0].value.value); // 'Admin'`, + + //--------------------------------------------------------------- + + `const tree = new EnumTree(); +tree._lexer.load('enum Status { ACTIVE "Active" INACTIVE "Inactive" }'); + +const enumToken = tree.enum(); +console.log(enumToken.declarations[0].id.name); // 'Status' +console.log(enumToken.declarations[0].init.properties[0].key.name); // 'ACTIVE' +console.log(enumToken.declarations[0].init.properties[0].value.value); // 'Active'`, + + //--------------------------------------------------------------- + + `// Inside enum parsing, after opening brace +const property = tree.property(); +console.log(property.key.name); // e.g., 'ADMIN' +console.log(property.value.value); // e.g., 'Admin'`, + //--------------------------------------------------------------- + + `import { ModelTree } from '@stackpress/idea-parser'; + +const modelCode = \`model User @label("User" "Users") { + id String @label("ID") @id @default("nanoid(20)") + username String @label("Username") @searchable @field.input(Text) @is.required + password String @label("Password") @field.password @is.clt(80) @is.cgt(8) @is.required @list.hide @view.hide + role Roles @label("Role") @filterable @field.select @list.text(Uppercase) @view.text(Uppercase) + address Address? @label("Address") @list.hide + age Number @label("Age") @unsigned @filterable @sortable @field.number(Age) @is.gt(0) @is.lt(150) + active Boolean @label("Active") @default(true) @filterable @field.switch @list.yesno @view.yesno + created Date @label("Created") @default("now()") @filterable @sortable @list.date(Pretty) +}\`; + +const ast = ModelTree.parse(modelCode); +console.log(ast.kind); // 'model' +console.log(ast.mutable); // false (because of '!' modifier) +console.log(ast.declarations[0].id.name); // 'User'`, + + //--------------------------------------------------------------- + + `const tree = new ModelTree(); +tree._lexer.load('model User { id String @id }'); + +const modelToken = tree.model(); +console.log(modelToken.kind); // 'model' +console.log(modelToken.mutable); // false (immutable due to '!')`, + + //--------------------------------------------------------------- + + `import { TypeTree } from '@stackpress/idea-parser'; + +const typeCode = \`type Address @label("Address" "Addresses") { + street String @field.input @is.required + city String @field.input @is.required + country String @field.select + postal String @field.input +}\`; + +const ast = TypeTree.parse(typeCode); +console.log(ast.kind); // 'type' +console.log(ast.mutable); // true (mutable by default) +console.log(ast.declarations[0].id.name); // 'Address'`, + + //--------------------------------------------------------------- + + `const tree = new TypeTree(); +tree._lexer.load('type Address { street String city String }'); + +const typeToken = tree.type(); +console.log(typeToken.kind); // 'type' +console.log(typeToken.mutable); // true (default for types)`, + + //--------------------------------------------------------------- + + `// Inside type parsing +const property = tree.property(); +console.log(property.key.name); // e.g., 'street' +console.log(property.value); // Object containing type and attributes`, + + //--------------------------------------------------------------- + + `// For parsing generic type parameters +const parameter = tree.parameter(); +console.log(parameter.key.name); // Parameter name +console.log(parameter.value); // Parameter type/constraint`, + + //--------------------------------------------------------------- + + `import { PropTree } from '@stackpress/idea-parser'; + +const propCode = \`prop EmailInput { + type "email" + format "email" + placeholder "Enter your email" + required true +}\`; + +const ast = PropTree.parse(propCode); +console.log(ast.kind); // 'prop' +console.log(ast.declarations[0].id.name); // 'EmailInput'`, + + //--------------------------------------------------------------- + + `const tree = new PropTree(); +tree._lexer.load('prop Text { type "text" format "lowercase" }'); + +const propToken = tree.prop(); +console.log(propToken.kind); // 'prop' +console.log(propToken.declarations[0].id.name); // 'Text'`, + + //--------------------------------------------------------------- + + `import { PluginTree } from '@stackpress/idea-parser'; + +const pluginCode = \`plugin "./database-plugin" { + provider "postgresql" + url env("DATABASE_URL") + previewFeatures ["fullTextSearch"] +}\`; + +const ast = PluginTree.parse(pluginCode); +console.log(ast.kind); // 'plugin' +console.log(ast.declarations[0].id.name); // './database-plugin'`, + + //--------------------------------------------------------------- + + `const tree = new PluginTree(); +tree._lexer.load('plugin "./custom" { provider "custom-provider" }'); + +const pluginToken = tree.plugin(); +console.log(pluginToken.kind); // 'plugin' +console.log(pluginToken.declarations[0].id.name); // './custom'`, + + //--------------------------------------------------------------- + + `import { UseTree } from '@stackpress/idea-parser'; + +const useCode = 'use "./shared/types.idea"'; + +const ast = UseTree.parse(useCode); +console.log(ast.type); // 'ImportDeclaration' +console.log(ast.source.value); // './shared/types.idea'`, + + //--------------------------------------------------------------- + + `const tree = new UseTree(); +tree._lexer.load('use "./another.idea"'); + +const useToken = tree.use(); +console.log(useToken.type); // 'ImportDeclaration' +console.log(useToken.source.value); // './another.idea'`, + + //--------------------------------------------------------------- + + `import { EnumTree, ModelTree, TypeTree } from '@stackpress/idea-parser'; + +// Parse individual enum +const enumAST = EnumTree.parse(\`enum Roles { + ADMIN "Admin" + MANAGER "Manager" + USER "User" +}\`); + +// Parse individual model +const modelAST = ModelTree.parse(\`model User { + id String @id + username String @is.required +}\`); + +// Parse individual type +const typeAST = TypeTree.parse(\`type Address { + street String + city String +}\`);`, + + //--------------------------------------------------------------- + + `import { EnumTree, Compiler } from '@stackpress/idea-parser'; + +// Parse and compile in one step +const enumAST = EnumTree.parse(\`enum Status { + ACTIVE "Active" + INACTIVE "Inactive" +}\`); +const [enumName, enumConfig] = Compiler.enum(enumAST); + +console.log(enumName); // 'Status' +console.log(enumConfig); // { ACTIVE: 'Active', INACTIVE: 'Inactive' }`, + + //--------------------------------------------------------------- + + `import { AbstractTree, Lexer } from '@stackpress/idea-parser'; +import type { DeclarationToken } from '@stackpress/idea-parser'; + +class CustomTree extends AbstractTree { + static definitions(lexer: Lexer) { + super.definitions(lexer); + // Add custom token definitions + lexer.define('CustomKeyword', (code, index) => { + // Custom token reader implementation + }); + return lexer; + } + + static parse(code: string, start = 0) { + return new this().parse(code, start); + } + + parse(code: string, start = 0): DeclarationToken { + this._lexer.load(code, start); + return this.customDeclaration(); + } + + customDeclaration(): DeclarationToken { + // Custom parsing logic + const keyword = this._lexer.expect('CustomKeyword'); + // ... more parsing logic + + return { + type: 'VariableDeclaration', + kind: 'custom', + start: keyword.start, + end: this._lexer.index, + declarations: [/* ... */] + }; + } +}`, + + //--------------------------------------------------------------- + + `import { SchemaTree, Exception } from '@stackpress/idea-parser'; + +try { + // Invalid syntax - missing closing brace + SchemaTree.parse('enum Status { ACTIVE "Active"'); +} catch (error) { + if (error instanceof Exception) { + console.log('Parse error:', error.message); + console.log('Position:', error.start, '-', error.end); + } +}`, + + //--------------------------------------------------------------- + + `try { + // Invalid - 'enum' keyword expected but found 'model' + EnumTree.parse('model User { id String }'); +} catch (error) { + console.log('Expected enum but found model'); +}`, + + //--------------------------------------------------------------- + + `import { EnumTree } from '@stackpress/idea-parser'; + +try { + // Empty string will throw an error + EnumTree.parse(''); +} catch (error) { + console.log('Error:', error.message); // 'Unexpected end of input' +}`, + + //--------------------------------------------------------------- + + `import { ModelTree } from '@stackpress/idea-parser'; + +try { + // Invalid - model names must be capitalized + ModelTree.parse('model user { id String }'); +} catch (error) { + console.log('Expected CapitalIdentifier but got something else'); +}`, + + //--------------------------------------------------------------- + + `// This is what happens internally: +import { SchemaTree, Compiler } from '@stackpress/idea-parser'; + +export function parse(code: string) { + const ast = SchemaTree.parse(code); // Parse to AST + return Compiler.schema(ast); // Compile to JSON +} + +export function final(code: string) { + const ast = SchemaTree.parse(code); // Parse to AST + return Compiler.final(ast); // Compile and clean up +}`, + + //--------------------------------------------------------------- + + `import { Lexer, SchemaTree } from '@stackpress/idea-parser'; + +// Create and configure lexer once +const lexer = new Lexer(); +SchemaTree.definitions(lexer); + +// Reuse for multiple parses +const tree = new SchemaTree(lexer); + +const result1 = tree.parse(code1); +const result2 = tree.parse(code2); +const result3 = tree.parse(code3);`, + + //--------------------------------------------------------------- + + `// Inside tree parsing methods +const checkpoint = this._lexer.clone(); + +try { + // Try to parse optional structure + return this.parseOptionalStructure(); +} catch (error) { + // Restore lexer state and continue + this._lexer = checkpoint; + return this.parseAlternativeStructure(); +}`, + + //--------------------------------------------------------------- + + `const enumCode = \`enum Roles { + ADMIN "Admin" + MANAGER "Manager" + USER "User" +}\`; + +const ast = EnumTree.parse(enumCode); +// Produces a complete AST with all three enum values`, + + //--------------------------------------------------------------- + + `const modelCode = \`model User @label("User" "Users") { + id String @label("ID") @id @default("nanoid(20)") + username String @label("Username") @searchable @field.input(Text) @is.required + password String @label("Password") @field.password @is.clt(80) @is.cgt(8) @is.required @list.hide @view.hide + role Roles @label("Role") @filterable @field.select @list.text(Uppercase) @view.text(Uppercase) + address Address? @label("Address") @list.hide + age Number @label("Age") @unsigned @filterable @sortable @field.number(Age) @is.gt(0) @is.lt(150) + balance Number[] @label("Balance") @filterable @sortable @field.number() @list.number() @view.number + active Boolean @label("Active") @default(true) @filterable @field.switch @list.yesno @view.yesno + created Date @label("Created") @default("now()") @filterable @sortable @list.date(Pretty) + updated Date @label("Updated") @default("updated()") @filterable @sortable @list.date(Pretty) + company Company? @label("My Company") +}\`; + +const ast = ModelTree.parse(modelCode); +// Produces a complete model AST with all columns and attributes` +]; + +//--------------------------------------------------------------------// + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx( + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500' +); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Syntax Trees'); + const description = _( + 'The AST classes are responsible for parsing specific parts ' + + 'of schema code into Abstract Syntax Trees (ASTs). Each AST ' + + 'class handles a different type of declaration or construct ' + + 'in the schema language.' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + + return ( + + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Syntax Trees Section Content */} +
    +

    {_('Syntax Trees')}

    + + The AST classes are responsible for parsing specific parts + of schema code into Abstract Syntax Trees (ASTs). Each AST + class handles a different type of declaration or construct + in the schema language. + + + {examples[0]} + +
    + + {/* Horizontal Rule */} +
    + + {/* SchemaTree Section Content */} +
    +

    {_('1. SchemaTree')}

    +

    + + Parses complete schema files containing multiple declarations. + +

    + + {/* Static Methods Section Content */} +
    +

    {_('1.1 Static Methods')}

    + +

    {_('1.1.1 Setting Up Schema Definitions')}

    +

    + + The following example shows how to configure a lexer for + schema parsing. + +

    + + {examples[1]} + + +

    {_('Parameters')}

    + + + Parameter + Type + Description + + + lexer + Lexer + {_('The lexer instance to configure')} + +
    + + {_('Returns')} +
      +
    • {_('The configured lexer instance.')}
    • +
    +
    + + {/* Parsing Complete Schemas */} +
    +

    {_('1.1.2 Parsing Complete Schemas')}

    + + The following example shows how to parse a complete + schema file. + + + {examples[2]} + + +

    {_('Parameters')}

    + + + Parameter + Type + Description + + + code + string + {_('The complete schema code to parse')} + +
    + + {_('Returns')} +
      +
    • + {_('A SchemaToken representing the entire parsed schema.')} +
    • +
    +
    + + {/* Methods Section Content */} +
    +

    {_('1.2 Methods')}

    + +

    {_('1.2.1 Parsing Schema Content')}

    + + The following example shows how to parse schema content + with custom starting position. + + + {examples[3]} + + +

    {_('Parameters')}

    + + + Parameter + Type + Description + + + code + string + {_('The schema code to parse')} + + + start + number + {_('Starting position in the code (default: 0)')} + +
    + + {_('Returns')} +
      +
    • {_('A SchemaToken containing all parsed declarations.')}
    • +
    +
    +
    + + {/* Horizontal Rule */} +
    + + {/* EnumTree Section Content */} +
    +

    {_('2. EnumTree')}

    + + Parses enum declarations into AST tokens. + + +

    {_('2.1 Static Methods')}

    + +

    {_('2.1.1 Setting Up Enum Definitions')}

    + + The following example shows how to configure a lexer for + enum parsing. + + + {examples[4]} + + +

    {_('2.1.2 Parsing Enum Declarations')}

    + + The following example shows how to parse enum declarations + based on the test fixtures. + + + {examples[5]} + + +

    {_('Parameters')}

    + + Parameter + Type + Description + + code + string + {_('The enum declaration code to parse')} + + + start + number + {_('Starting position in the code (default: 0)')} + +
    + + {_('Returns')} +
  • + + A DeclarationToken representing the parsed enum. + +
  • + +

    {_('2.2 Methods')}

    + +

    {_('2.2.1 Parsing Enum Structure')}

    + + The following example shows how to parse the enum structure. + + + {examples[6]} + + + {_('Returns')} +
  • + + A DeclarationToken representing the enum structure. + +
  • + +

    {_('2.2.2 Parsing Enum Properties')}

    + + The following example shows how individual enum properties + are parsed. + + + {examples[7]} + + + {_('Returns')} +
      +
    • + + A PropertyToken representing a single enum key-value + pair. + +
    • +
    +
    + + {/* Horizontal Rule */} +
    + + {/* ModelTree Section Content */} +
    +

    {_('3. ModelTree')}

    + + Parses model declarations (extends TypeTree for shared + functionality). + + +

    {_('3.1 Static Methods')}

    + +

    {_('3.1.1 Parsing Model Declarations')}

    + + The following example shows how to parse model declarations + based on the test fixtures. + + + {examples[8]} + + +

    {_('Parameters')}

    + + + Parameter + Type + Description + + + code + string + {_('The model declaration code to parse')} + + + start + number + {_('Starting position in the code (default: 0)')} + +
    + + {_('Returns')} +
      +
    • + + A DeclarationToken representing the parsed model. + +
    • +
    + +

    {_('3.2 Methods')}

    + +

    {_('3.2.1 Parsing Model Structure')}

    + + The following example shows how to parse the model structure. + + + {examples[9]} + + + {_('Returns')} +
      +
    • + + A DeclarationToken representing the model structure. + +
    • +
    +
    + + {/* Horizontal Rule */} +
    + + {/* TypeTree Section */} +
    +

    {_('4. TypeTree')}

    + + Parses type declarations. + + +

    {_('4.1 Static Methods')}

    + +

    {_('4.1.1 Parsing Type Declarations')}

    + + The following example shows how to parse type declarations. + + + {examples[10]} + + +

    {_('Parameters')}

    + + + Parameter + Type + Description + + + code + string + {_('The type declaration code to parse')} + + + start + number + {_('Starting position in the code (default: 0)')} + +
    + + {_('Returns')} +
      +
    • + + A DeclarationToken representing the parsed type. + +
    • +
    + +

    {_('4.2 Methods')}

    + +

    {_('4.2.1 Parsing Type Structure')}

    + + The following example shows how to parse the type structure. + + + {examples[11]} + + + {_('Returns')} +
  • + + A DeclarationToken representing the type structure. + +
  • + +

    {_('4.2.2 Parsing Type Properties')}

    + + The following example shows how type properties (columns) + are parsed. + + + {examples[12]} + + + {_('Returns')} +
  • + + A PropertyToken representing a type column definition. + +
  • + +

    {_('4.2.3 Parsing Type Parameters')}

    + + The following example shows how type parameters are parsed. + + + {examples[13]} + + + {_('Returns')} +
      +
    • + + A ParameterToken representing a type parameter. + +
    • +
    +
    + + {/* Horizontal Rule */} +
    + + {/* PropTree Section */} +
    +

    {_('5. PropTree')}

    + + Parses prop (property configuration) declarations. + + +

    {_('5.1 Static Methods')}

    + +

    {_('5.1.1 Parsing Prop Declarations')}

    + + The following example shows how to parse prop declarations. + + + {examples[14]} + + +

    {_('Parameters')}

    + + + Parameter + Type + Description + + + code + string + {_('The prop declaration code to parse')} + + + start + number + {_('Starting position in the code (default: 0)')} + +
    + + {_('Returns')} +
      +
    • + + A DeclarationToken representing the parsed prop. + +
    • +
    + +

    {_('5.2 Methods')}

    + +

    {_('5.2.1 Parsing Prop Structure')}

    + + The following example shows how to parse the prop structure. + + + {examples[15]} + + + {_('Returns')} +
      +
    • + + A DeclarationToken representing the prop configuration. + +
    • +
    +
    + + {/* Horizontal Rule */} +
    + + {/* PluginTree Section */} +
    +

    {_('6. PluginTree')}

    + + Parses plugin declarations. + + +

    {_('6.1 Static Methods')}

    + +

    {_('6.1.1 Parsing Plugin Declarations')}

    + + The following example shows how to parse plugin declarations. + + + {examples[16]} + + +

    {_('Parameters')}

    + + + Parameter + Type + Description + + + code + string + {_('The plugin declaration code to parse')} + + + start + number + {_('Starting position in the code (default: 0)')} + +
    + + {_('Returns')} +
      +
    • {_('A DeclarationToken representing the parsed plugin.')}
    • +
    + +

    {_('6.2 Methods')}

    + +

    {_('6.2.1 Parsing Plugin Structure')}

    + + The following example shows how to parse the plugin structure. + + + {examples[17]} + + + {_('Returns')} +
      +
    • + + A DeclarationToken representing the plugin configuration. + +
    • +
    +
    + + {/* Horizontal Rule */} +
    + + {/* UseTree Section Content */} +
    +

    {_('7. UseTree')}

    + + Parses use (import) declarations. + + +

    {_('7.1 Static Methods')}

    + +

    {_('7.1.1Parsing Use Declarations')}

    + + The following example shows how to parse use declarations. + + + {examples[18]} + + +

    {_('Parameters')}

    + + + Parameter + Type + Description + + + code + string + {_('The use declaration code to parse')} + + + start + number + {_('Starting position in the code (default: 0)')} + +
    + + {_('Returns')} +
      +
    • {_('An ImportToken representing the parsed use statement.')}
    • +
    + +

    {_('7.2 Methods')}

    + +

    {_('7.2.1 Parsing Use Structure')}

    + + The following example shows how to parse the use structure. + + + {examples[19]} + + + {_('Returns')} +

    + + An ImportToken representing the import statement. + +

    +
    + + {/* Horizontal Rule */} +
    + + {/* Usage Patterns Section Content */} +
    +

    {_('8. Usage Patterns')}

    + +

    {_('8.1 Parsing Individual Components')}

    + + {examples[20]} + + +

    {_('8.2 Using with Compiler')}

    + + {examples[21]} + + +

    {_('8.3 Custom AST Classes')}

    +

    + + You can extend AbstractTree to create custom parsers: + +

    + + {examples[22]} + +
    + + {/* Horizontal Rule */} +
    + + {/* Error Handling Section Content */} +
    +

    {_('9. Error Handling')}

    + + AST classes provide detailed error information when + parsing fails: + + +

    {_('Syntax Errors')}

    + + {examples[23]} + + +

    {_('Unexpected Tokens')}

    + + {examples[24]} + + +

    {_('Empty Input Handling')}

    + + {examples[25]} + + +

    {_('Invalid Identifiers')}

    + + {examples[26]} + +
    + + {/* Horizontal Rule */} +
    + + {/* Integration with Main Functions Section Content */} +
    +

    {_('10. Integration with Main Functions')}

    + + AST classes are used internally by the main parse and + final functions: + + + {examples[27]} + +
    + + {/* Horizontal Rule */} +
    + + {/* Performance Considerations Section Content */} +
    +

    {_('11. Performance Considerations')}

    + +

    {_('11.1 Lexer Reuse')}

    +

    + + AST classes can share lexer instances for better performance: + +

    + + {examples[28]} + + +

    {_('11.2 Cloning for Backtracking')}

    +

    + + AST classes use lexer cloning for safe parsing attempts: + +

    + + {examples[29]} + +
    + + {/* Horizontal Rule */} +
    + + {/* Test-Driven Examples Section Content */} +
    +

    {_('12. Test-Driven Examples')}

    +

    + + Based on the test fixtures, here are real-world examples: + +

    + +

    {_('Enum with Multiple Values')}

    + + {examples[30]} + + +

    {_('Complex Model with Attributes')}

    + + {examples[31]} + + +

    + + This demonstrates the parser's ability to handle: + +

    + +
      +
    • + + Model mutability (! modifier) + +
    • +
    • + + Attributes (@label, @id, @default, etc.) + +
    • +
    • + + Optional types (Address?, Company?) + +
    • +
    • + + Array types (Number[]) + +
    • +
    • + + Complex attribute parameters (@field.input(Text), + @is.clt(80)) + +
    • +
    +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + } + > + + + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/views/parser/api-references/compiler.tsx b/packages/www/plugins/docs/views/parser/api-references/compiler.tsx new file mode 100644 index 0000000..ffc8fda --- /dev/null +++ b/packages/www/plugins/docs/views/parser/api-references/compiler.tsx @@ -0,0 +1,1360 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +import { Table, Thead, Trow, Tcol } from 'frui/element/Table'; +import clsx from 'clsx'; +//local +import { H1, H2, P, C, Nav } from '../../../components/index.js'; +import Code from '../../../components/Code.js'; +import Layout from '../../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const basicImportExample = + `import { Compiler } from '@stackpress/idea-parser';`; + +//--------------------------------------------------------------------// + +const arrayTokenExample = + `import { Compiler } from '@stackpress/idea-parser'; + +// Example array token from parsing ["value1", "value2", "value3"] +const arrayToken = { + type: 'ArrayExpression', + elements: [ + { type: 'Literal', value: 'value1' }, + { type: 'Literal', value: 'value2' }, + { type: 'Literal', value: 'value3' } + ] +}; + +const result = Compiler.array(arrayToken); +console.log(result); // ['value1', 'value2', 'value3']`; + +//--------------------------------------------------------------------// + +const dataTokenExample = + `import { Compiler } from '@stackpress/idea-parser'; + +// Compile different types of data tokens +const literalResult = Compiler.data({ type: 'Literal', value: 'hello' }); +console.log(literalResult); // 'hello' + +const objectResult = Compiler.data({ + type: 'ObjectExpression', + properties: [ + { + key: { name: 'name' }, + value: { type: 'Literal', value: 'John' } + } + ] +}); +console.log(objectResult); // { name: 'John' }`; + +//--------------------------------------------------------------------// + +const enumTokenExample = + `import { Compiler } from '@stackpress/idea-parser'; + +// Example enum token from parsing: +// enum Status { ACTIVE "Active" INACTIVE "Inactive" } +const enumToken = { + kind: 'enum', + declarations: [{ + id: { name: 'Status' }, + init: { + properties: [ + { + key: { name: 'ACTIVE' }, + value: { type: 'Literal', value: 'Active' } + }, + { + key: { name: 'INACTIVE' }, + value: { type: 'Literal', value: 'Inactive' } + } + ] + } + }] +}; + +const [name, config] = Compiler.enum(enumToken); +console.log(name); // 'Status' +console.log(config); // { ACTIVE: 'Active', INACTIVE: 'Inactive' }`; + +//--------------------------------------------------------------------// + +const finalSchemaExample = + `import { Compiler } from '@stackpress/idea-parser'; + +// This method removes prop and use references for a clean final output +const finalSchema = Compiler.final(schemaToken); +console.log(finalSchema); +// Output will not contain 'prop' or 'use' sections`; + +//--------------------------------------------------------------------// + +const identifierTokenExample = + `import { Compiler } from '@stackpress/idea-parser'; + +// With references provided +const references = { MyProp: { type: 'text' } }; +const result1 = Compiler.identifier({ name: 'MyProp' }, references); +console.log(result1); // { type: 'text' } + +// Without references (returns template string) +const result2 = Compiler.identifier({ name: 'MyProp' }, false); +console.log(result2); // '\${MyProp}' + +// With empty references (throws error) +try { + Compiler.identifier({ name: 'UnknownProp' }, {}); +} catch (error) { + console.log(error.message); // 'Unknown reference UnknownProp' +}`; + +//--------------------------------------------------------------------// + +const literalTokenExample = + `import { Compiler } from '@stackpress/idea-parser'; + +const stringLiteral = Compiler.literal({ type: 'Literal', value: 'hello' }); +console.log(stringLiteral); // 'hello' + +const numberLiteral = Compiler.literal({ type: 'Literal', value: 42 }); +console.log(numberLiteral); // 42 + +const booleanLiteral = Compiler.literal({ type: 'Literal', value: true }); +console.log(booleanLiteral); // true`; + +//--------------------------------------------------------------------// + +const modelTokenExample = + `import { Compiler } from '@stackpress/idea-parser'; + +// Example model token from parsing: +// model User { id String @id name String } +const modelToken = { + kind: 'model', + mutable: false, // model User! would be true + declarations: [{ + id: { name: 'User' }, + init: { + properties: [ + { + key: { name: 'columns' }, + value: { + type: 'ObjectExpression', + properties: [ + { + key: { name: 'id' }, + value: { + type: 'ObjectExpression', + properties: [ + { + key: { name: 'type' }, + value: { type: 'Literal', value: 'String' } + }, + { key: { name: 'attributes' }, value: { /* attributes */ } } + ] + } + } + ] + } + } + ] + } + }] +}; + +const [name, config] = Compiler.model(modelToken); +console.log(name); // 'User' +console.log(config.mutable); // false +console.log(config.columns); // Array of column configurations`; + +//--------------------------------------------------------------------// + +const objectTokenExample = + `import { Compiler } from '@stackpress/idea-parser'; + +// Example object token from parsing { name "John" age 30 } +const objectToken = { + type: 'ObjectExpression', + properties: [ + { key: { name: 'name' }, value: { type: 'Literal', value: 'John' } }, + { key: { name: 'age' }, value: { type: 'Literal', value: 30 } } + ] +}; + +const result = Compiler.object(objectToken); +console.log(result); // { name: 'John', age: 30 }`; + +//--------------------------------------------------------------------// + +const pluginTokenExample = + `import { Compiler } from '@stackpress/idea-parser'; + +// Example plugin token from parsing: +// plugin "./database" { provider "postgresql" } +const pluginToken = { + kind: 'plugin', + declarations: [{ + id: { name: './database' }, + init: { + properties: [ + { + key: { name: 'provider' }, + value: { type: 'Literal', value: 'postgresql' } + } + ] + } + }] +}; + +const [name, config] = Compiler.plugin(pluginToken); +console.log(name); // './database' +console.log(config); // { provider: 'postgresql' }`; + +//--------------------------------------------------------------------// + +const propTokenExample = + `import { Compiler } from '@stackpress/idea-parser'; + +// Example prop token from parsing: +// prop Text { type "text" format "lowercase" } +const propToken = { + kind: 'prop', + declarations: [{ + id: { name: 'Text' }, + init: { + properties: [ + { key: { name: 'type' }, value: { type: 'Literal', value: 'text' } }, + { + key: { name: 'format' }, + value: { type: 'Literal', value: 'lowercase' } + } + ] + } + }] +}; + +const [name, config] = Compiler.prop(propToken); +console.log(name); // 'Text' +console.log(config); // { type: 'text', format: 'lowercase' }`; + +//--------------------------------------------------------------------// + +const schemaDeclarationExample = + `import { Compiler } from '@stackpress/idea-parser'; + +// Compile a complete schema with all declaration types +const schemaConfig = Compiler.schema(schemaToken); +console.log(schemaConfig); +// Output contains: { enum: {...}, prop: {...}, type: {...}, model: {...}, plugin: {...}, use: [...] } + +// Compile with finalization (resolves references) +const finalizedConfig = Compiler.schema(schemaToken, true); +console.log(finalizedConfig); +// References are resolved in the output`; + +//--------------------------------------------------------------------// + +const typeTokenExample = + `import { Compiler } from '@stackpress/idea-parser'; + +// Example type token from parsing: +// type Address { street String city String } +const typeToken = { + kind: 'type', + mutable: true, // type Address (mutable) vs type Address! (immutable) + declarations: [{ + id: { name: 'Address' }, + init: { + properties: [ + { + key: { name: 'columns' }, + value: { + type: 'ObjectExpression', + properties: [ + { + key: { name: 'street' }, + value: { + type: 'ObjectExpression', + properties: [ + { key: { name: 'type' }, value: { type: 'Literal', value: 'String' } } + ] + } + } + ] + } + } + ] + } + }] +}; + +const [name, config] = Compiler.type(typeToken); +console.log(name); // 'Address' +console.log(config.mutable); // true +console.log(config.columns); // Array of column configurations`; + +//--------------------------------------------------------------------// + +const useTokenExample = + `import { Compiler } from '@stackpress/idea-parser'; + +// Example use token from parsing: use "./another.idea" +const useToken = { + type: 'ImportDeclaration', + source: { type: 'Literal', value: './another.idea' } +}; + +const importPath = Compiler.use(useToken); +console.log(importPath); // './another.idea'`; + +//--------------------------------------------------------------------// + +const invalidTokenTypesExample = + `// Throws: "Invalid data token type" +Compiler.data({ type: 'UnknownType' }); + +// Throws: "Invalid Enum" +Compiler.enum({ kind: 'notAnEnum' }); + +// Throws: "Invalid Plugin" +Compiler.plugin({ kind: 'notAPlugin' }); + +// Throws: "Invalid Prop" +Compiler.prop({ kind: 'notAProp' }); + +// Throws: "Invalid Schema" +Compiler.schema({ kind: 'notASchema' }); + +// Throws: "Invalid Type" +Compiler.type({ kind: 'notAType' }); + +// Throws: "Invalid Import" +Compiler.use({ type: 'NotAnImportDeclaration' });`; + +//--------------------------------------------------------------------// + +const missingPropertiesExample = + `// Throws: "Expecting a columns property" +Compiler.model({ + kind: 'model', + declarations: [{ + id: { name: 'User' }, + init: { properties: [] } // Missing columns + }] +});`; + +//--------------------------------------------------------------------// + +const unknownReferencesExample = + `// Throws: "Unknown reference MyProp" +Compiler.identifier({ name: 'MyProp' }, {});`; + +//--------------------------------------------------------------------// + +const duplicateDeclarationsExample = + `// Throws: "Duplicate MyEnum" when compiling schema with duplicate names +Compiler.schema(schemaWithDuplicates);`; + +//--------------------------------------------------------------------// + +const typeModifiersExample = + `Optional types: String? → { type: 'String', required: false } +Array types: String[] → { type: 'String', multiple: true } +Combined: String[]? → { type: 'String', required: false, multiple: true }`; + +//--------------------------------------------------------------------// + +const columnConfigurationExample = + `// Input object format +{ + columns: { + id: { type: 'String', attributes: { id: true } }, + name: { type: 'String', attributes: { required: true } } + } +} + +// Output array format +{ + columns: [ + { name: 'id', type: 'String', required: true, multiple: false, + attributes: { id: true } }, + { name: 'name', type: 'String', required: true, multiple: false, + attributes: { required: true } } + ] +}`; + +//--------------------------------------------------------------------// + +const usageWithASTExample = + `import { Compiler, EnumTree, ModelTree, SchemaTree } from '@stackpress/idea-parser'; + +// Parse and compile individual components +const enumAST = EnumTree.parse('enum Status { ACTIVE "Active" }'); +const [enumName, enumConfig] = Compiler.enum(enumAST); + +const modelAST = ModelTree.parse('model User { id String @id }'); +const [modelName, modelConfig] = Compiler.model(modelAST); + +// Parse and compile complete schema +const schemaAST = SchemaTree.parse(schemaCode); +const schemaConfig = Compiler.schema(schemaAST);`; + +//--------------------------------------------------------------------// + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx([ + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500', +]); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Compiler'); + const description = _( + 'Compiler class documentation for the Idea Parser library, ' + + 'including methods for compiling AST tokens into structured ' + + 'JSON configurations.' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + + return ( + + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Compiler Section Content */} +
    +

    {_('Compiler')}

    +

    + + The Compiler class provides static methods for converting + Abstract Syntax Tree (AST) tokens into structured JSON + configurations. It serves as the bridge between parsed + tokens and the final JSON output. + +

    + + {basicImportExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Static Methods Section Content */} +
    +

    {_('1. Static Methods')}

    +

    + + The following methods can be accessed directly from the + Compiler class. + +

    + + {/* Converting Array Tokens Section Content */} +
    +

    {_('1.1 Converting Array Tokens')}

    +

    + + The following example shows how to compile array tokens + into actual arrays. + +

    + + {arrayTokenExample} + + +

    {_('Parameters')}

    + + + Parameter + Type + Description + + + token + ArrayToken + + + The array token to compile + + + + + references + UseReferences + + + Reference map for resolving identifiers (default: false) + + + +
    + +

    {_('Returns')}

    +

    + + An array containing the compiled elements. + +

    +
    + + + {/* Converting Data Tokens Section Content */} +
    +

    {_('1.2 Converting Data Tokens')}

    +

    + + The following example shows how to compile data tokens + into JavaScript values. + +

    + + {dataTokenExample} + + +

    {_('Parameters')}

    + + + Parameter + Type + Description + + + token + DataToken + + + The data token to compile (can be object, array, + literal, or identifier) + + + + + references + UseReferences + + + Reference map for resolving identifiers (default: + false) + + + +
    + +

    {_('Returns')}

    +

    + + The compiled data value based on the token type. + +

    +
    + + {/* Converting Enum Declarations Section Content */} +
    +

    {_('1.3 Converting Enum Declarations')}

    +

    + + The following example shows how to compile enum + declarations into JSON configurations. + +

    + + {enumTokenExample} + + +

    {_('Parameters')}

    + + Parameter + Type + Description + + token + DeclarationToken + + + The enum declaration token to compile + + + +
    + +

    {_('Returns')}

    +

    + + A tuple containing the enum name and its configuration + object. + +

    +
    + + {/* Converting Final Schema Section Content */} +
    +

    {_('1.4 Converting Schema to Final JSON')}

    +

    + + The following example shows how to compile a schema token + into a final JSON configuration. + +

    + + {finalSchemaExample} + + +

    {_('Parameters')}

    + + Parameter + Type + Description + + token + SchemaToken + + + The schema token to compile into final form + + + +
    + +

    {_('Returns')}

    +

    + + A FinalSchemaConfig object with references resolved + and removed. + +

    +
    + + {/* Converting Identifier Tokens Section Content */} +
    +

    {_('1.5 Converting Identifier Tokens')}

    +

    + + The following example shows how to resolve identifier + tokens to their actual values. + +

    + + {identifierTokenExample} + + +

    {_('Parameters')}

    + + + Parameter + Type + Description + + + token + IdentifierToken + + + The identifier token to resolve + + + + + references + UseReferences + + + Reference map for resolving the identifier + + + +
    + +

    {_('Returns')}

    +

    + + The resolved value from references, a template string, + or throws an error. + +

    +
    + + {/* Converting Literal Tokens Section Content */} +
    +

    {_('1.6 Converting Literal Tokens')}

    +

    + + The following example shows how to extract values from + literal tokens. + +

    + + {literalTokenExample} + + +

    {_('Parameters')}

    + + Parameter + Type + Description + + token + LiteralToken + + + The literal token to extract value from + + + +
    + +

    {_('Returns')}

    +

    + + The literal value (string, number, boolean, etc.). + +

    +
    + + {/* Converting Model Declarations Section Content */} +
    +

    {_('1.7 Converting Model Declarations')}

    +

    + + The following example shows how to compile model + declarations into JSON configurations. + +

    + + {modelTokenExample} + + +

    {_('Parameters')}

    + + + Parameter + Type + Description + + + token + DeclarationToken + + + The model declaration token to compile + + + + + references + UseReferences + + + Reference map for resolving identifiers (default: + false) + + + +
    + +

    {_('Returns')}

    +

    + + A tuple containing the model name and its configuration + object. + +

    +
    + + {/* Converting Object Tokens Section Content */} +
    +

    {_('1.8 Converting Object Tokens')}

    +

    + + The following example shows how to compile object tokens + into actual objects. + +

    + + {objectTokenExample} + + +

    {_('Parameters')}

    + + Parameter + Type + Description + + token + ObjectToken + + + The object token to compile + + + + + references + UseReferences + + + Reference map for resolving identifiers (default: + false) + + + +
    + +

    {_('Returns')}

    +

    + + An object with compiled key-value pairs. + +

    +
    + + {/* Converting Plugin Declarations Section Content */} +
    +

    {_('1.9 Converting Plugin Declarations')}

    +

    + + The following example shows how to compile plugin + declarations into JSON configurations. + +

    + + {pluginTokenExample} + + +

    {_('Parameters')}

    + + Parameter + Type + Description + + token + DeclarationToken + + + The plugin declaration token to compile + + + +
    + +

    {_('Returns')}

    +

    + + A tuple containing the plugin name and its configuration + object. + +

    +
    + + {/* Converting Prop Declarations Section Content */} +
    +

    {_('1.10 Converting Prop Declarations')}

    +

    + + The following example shows how to compile prop + declarations into JSON configurations. + +

    + + {propTokenExample} + + +

    {_('Parameters')}

    + + Parameter + Type + Description + + token + DeclarationToken + + + The prop declaration token to compile + + + + + references + UseReferences + + + Reference map for resolving identifiers (default: + false) + + + +
    + +

    {_('Returns')}

    +

    + + A tuple containing the prop name and its configuration + object. + +

    +
    + + {/* Converting Schema Declarations Section Content */} +
    +

    {_('1.11 Converting Schema Declarations')}

    +

    + + The following example shows how to compile complete + schema tokens into JSON configurations. + +

    + + {schemaDeclarationExample} + + +

    {_('Parameters')}

    + + Parameter + Type + Description + + token + SchemaToken + + + The schema token to compile + + + + + finalize + boolean + + + Whether to resolve references (default: false) + + + +
    + +

    {_('Returns')}

    +

    + + A SchemaConfig object containing all compiled + declarations. + +

    +
    + + {/* Converting Type Declarations Section Content */} +
    +

    {_('1.12 Converting Type Declarations')}

    +

    + + The following example shows how to compile type declarations + into JSON configurations. + +

    + + {typeTokenExample} + + +

    {_('Parameters')}

    + + Parameter + Type + Description + + + token + + + DeclarationToken + + + + The type declaration token to compile + + + + + references + UseReferences + + + Reference map for resolving identifiers (default: + false) + + + +
    + +

    {_('Returns')}

    +

    + + A tuple containing the type name and its configuration + object. + +

    +
    + + {/* Converting Use Declarations Section Content */} +
    +

    {_('1.13 Converting Use Declarations')}

    +

    + + The following example shows how to compile use (import) + declarations. + +

    + + {useTokenExample} + + +

    {_('Parameters')}

    + + Parameter + Type + Description + + + token + + + ImportToken + + + + The import declaration token to compile + + + +
    + +

    {_('Returns')}

    +

    + + The import path as a string. + +

    +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Error Handling Section Content */} +
    +

    {_('Error Handling')}

    +

    + + The Compiler class throws Exception errors for various + invalid conditions: + +

    + +

    {_('Invalid Token Types')}

    + + {invalidTokenTypesExample} + + +

    {_('Missing Required Properties')}

    + + {missingPropertiesExample} + + +

    {_('Unknown References')}

    + + {unknownReferencesExample} + + +

    {_('Duplicate Declarations')}

    + + {duplicateDeclarationsExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Type Processing Section Content */} +
    +

    {_('Type Processing')}

    +

    + + The Compiler automatically processes type information for + models and types: + +

    + +

    {_('Type Modifiers')}

    + + {typeModifiersExample} + + +

    {_('Column Configuration')}

    +

    + + Models and types are converted from object format to array + format to preserve column order: + +

    + + {columnConfigurationExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Usage with AST Section Content */} +
    +

    {_('Usage with AST')}

    +

    + + The Compiler is typically used in conjunction with AST + classes: + +

    + + {usageWithASTExample} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + } + > + + + ); +} + + + + diff --git a/packages/www/plugins/docs/views/parser/api-references/exception-handling.tsx b/packages/www/plugins/docs/views/parser/api-references/exception-handling.tsx new file mode 100644 index 0000000..d910824 --- /dev/null +++ b/packages/www/plugins/docs/views/parser/api-references/exception-handling.tsx @@ -0,0 +1,551 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +import clsx from 'clsx'; +//local +import { H1, H2, SS, Nav, P } from '../../../components/index.js'; +import Code from '../../../components/Code.js'; +import Layout from '../../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const examples = [ + `import { Exception } from '@stackpress/idea-parser';`, + + //------------------------------------------------------------------// + `import { parse, Exception } from '@stackpress/idea-parser'; + +try { + const result = parse('invalid schema syntax'); +} catch (error) { + if (error instanceof Exception) { + console.log('Parser error:', error.message); + console.log('Error position:', error.start, '-', error.end); + console.log('Stack trace:', error.stack); + } +}`, + + //------------------------------------------------------------------// + + `import { EnumTree, Exception } from '@stackpress/idea-parser'; + +try { + // Missing closing brace + EnumTree.parse('enum Status { ACTIVE "Active"'); +} catch (error) { + if (error instanceof Exception) { + console.log('Error message:', error.message); + console.log('Error starts at character:', error.start); + console.log('Error ends at character:', error.end); + + // Can be used for syntax highlighting in editors + const errorRange = { start: error.start, end: error.end }; + } +}`, + + //------------------------------------------------------------------// + + `try { + parse('enum Status { ACTIVE "Active"'); // Missing closing brace +} catch (error) { + console.log(error.message); // "Unexpected end of input expecting }" +}`, + + //------------------------------------------------------------------// + + `try { + parse('model user { id String }'); // Invalid - should be capitalized +} catch (error) { + console.log(error.message); // "Expected CapitalIdentifier but got something else" +}`, + + //------------------------------------------------------------------// + + `try { + parse('model User { name String @field.input(UnknownProp) }'); +} catch (error) { + console.log(error.message); // "Unknown reference UnknownProp" +}`, + + //------------------------------------------------------------------// + + `try { + parse(\` + enum Status { ACTIVE "Active" } + enum Status { INACTIVE "Inactive" } + \`); +} catch (error) { + console.log(error.message); // "Duplicate Status" +}`, + + //------------------------------------------------------------------// + + `import { SchemaTree, EnumTree, ModelTree, Exception } from '@stackpress/idea-parser'; + +// Any parsing operation can throw Exception +try { + const schema = SchemaTree.parse(schemaCode); + const enumAST = EnumTree.parse(enumCode); + const modelAST = ModelTree.parse(modelCode); +} catch (error) { + if (error instanceof Exception) { + // Handle parser-specific errors + console.error('Parsing failed:', error.message); + } else { + // Handle other types of errors + console.error('Unexpected error:', error); + } +}`, + + //------------------------------------------------------------------// + + `import { parse, Exception } from '@stackpress/idea-parser'; + +function parseWithFallback(code: string, fallbackCode?: string) { + try { + return parse(code); + } catch (error) { + if (error instanceof Exception && fallbackCode) { + console.warn('Primary parsing failed, trying fallback:', error.message); + return parse(fallbackCode); + } + throw error; // Re-throw if no fallback or different error type + } +}`, + + //------------------------------------------------------------------// + + `import { parse, Exception } from '@stackpress/idea-parser'; + +function validateSchema(code: string) { + try { + parse(code); + return { valid: true, errors: [] }; + } catch (error) { + if (error instanceof Exception) { + return { + valid: false, + errors: [{ + message: error.message, + range: { + start: error.start, + end: error.end + }, + severity: 'error' + }] + }; + } + throw error; + } +}`, + + //------------------------------------------------------------------// + + `try { + parse(schemaCode); +} catch (error) { + if (error instanceof Exception) { + // Handle parser errors specifically + handleParserError(error); + } else { + // Handle other errors (network, file system, etc.) + handleGenericError(error); + } +}`, + + //------------------------------------------------------------------// + + `function highlightError(code: string, error: Exception) { + const lines = code.split('\\n'); + let currentPos = 0; + + for (let i = 0; i < lines.length; i++) { + const lineEnd = currentPos + lines[i].length; + + if (error.start >= currentPos && error.start <= lineEnd) { + const lineStart = error.start - currentPos; + const lineEnd = Math.min(error.end - currentPos, lines[i].length); + + console.log(\`Line \${i + 1}: \${lines[i]}\`); + console.log(' '.repeat(lineStart + 8) + '^'.repeat(lineEnd - lineStart)); + break; + } + + currentPos = lineEnd + 1; // +1 for newline + } +}`, + + //------------------------------------------------------------------// + + `function parseWithContext(code: string, filename?: string) { + try { + return parse(code); + } catch (error) { + if (error instanceof Exception) { + const context = filename ? \` in \${filename}\` : ''; + throw new Exception( + \`Parse error\${context}: \${error.message}\`, + error.code + ).withPosition(error.start, error.end); + } + throw error; + } +}` +]; + +//--------------------------------------------------------------------// + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx( + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500', +); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Exception'); + const description = _( + 'The Exception class extends the Exception class from ' + + '@stackpress/lib to provide enhanced error handling specific ' + + 'to the idea parser library. It includes position information ' + + 'and better error reporting for parsing failures.' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + + return ( + + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Exception Section Content */} +
    +

    {_('Exception')}

    +

    + + The Exception class extends the Exception class from + @stackpress/lib to provide enhanced error handling specific + to the idea parser library. It includes position information + and better error reporting for parsing failures. + +

    + + {examples[0]} + +
    + + {/* Horizontal Rule */} +
    + + {/* Overview Section Content */} +
    +

    {_('Overview')}

    + + Exception is a specialized error class that extends the + base Exception class with additional functionality for + parser-specific error handling. It automatically includes + position information when parsing fails, making it easier + to identify and fix syntax errors in schema files. + +
    + + {/* Horizontal Rule */} +
    + + {/* Usage Examples Section Content */} +
    +

    {_('Usage Examples')}

    + +

    {_('Basic Error Handling')}

    + + {examples[1]} + + +

    {_('Position Information')}

    + + Exception includes position information to help locate + errors in the source code: + + + {examples[2]} + + +

    {_('Common Error Scenarios')}

    + + {_('Syntax Errors')} + + {examples[3]} + + + {_('Invalid Token Types')} + + {examples[4]} + + + {_('Unknown References')} + + {examples[5]} + + + {_('Duplicate Declarations')} + + {examples[6]} + +
    + + {/* Horizontal Rule */} +
    + + {/* Integration with AST Section Content */} +
    +

    {_('Integration with AST')}

    + + All AST classes throw Exception when parsing fails: + + + {examples[7]} + +
    + + {/* Horizontal Rule */} +
    + + {/* Error Recovery Section Content */} +
    +

    {_('Error Recovery')}

    + + While Exception indicates parsing failure, you can + implement error recovery strategies: + + + {examples[8]} + +
    + + {/* Horizontal Rule */} +
    + + {/* Language Server Integration Section Content */} +
    +

    {_('Language Server Integration')}

    + + Exception's position information makes it ideal for language + server implementations: + + + {examples[9]} + +
    + + {/* Horizontal Rule */} +
    + + {/* Inherited Features Section Content */} +
    +

    {_('Inherited Features')}

    + + Since Exception extends the base Exception class from + @stackpress/lib, it inherits all the enhanced error handling + features: + +
      +
    • {_('Template-based error messages')}
    • +
    • {_('Enhanced stack trace parsing')}
    • +
    • {_('Position information support')}
    • +
    • {_('HTTP status code integration')}
    • +
    • {_('Validation error aggregation')}
    • +
    + + For more details on the base Exception functionality, refer to the + + {' '}@stackpress/lib Exception documentation + . + +
    + + {/* Horizontal Rule */} +
    + + {/* Best Practices Section Content */} +
    +

    {_('Best Practices')}

    + +

    {_('Always Check Error Type')}

    + + {examples[10]} + + +

    {_('Use Position Information')}

    + + {examples[11]} + + +

    {_('Provide Helpful Error Messages')}

    + + {examples[12]} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + } + > + + + ); +} diff --git a/packages/www/plugins/docs/views/parser/api-references/lexer.tsx b/packages/www/plugins/docs/views/parser/api-references/lexer.tsx new file mode 100644 index 0000000..edd1f21 --- /dev/null +++ b/packages/www/plugins/docs/views/parser/api-references/lexer.tsx @@ -0,0 +1,1278 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +import clsx from 'clsx'; +//local +import { H1, H2, P, C, Nav, SS } from '../../../components/index.js'; +import Code from '../../../components/Code.js'; +import Layout from '../../../components/Layout.js'; +import { Table, Thead, Trow, Tcol } from 'frui/element/Table'; + +//code examples +//--------------------------------------------------------------------// + +const examples = [ + `import { Lexer } from '@stackpress/idea-parser';`, + + //------------------------------------------------------------------// + + `import { Lexer } from '@stackpress/idea-parser'; + +const lexer = new Lexer(); +lexer.load('enum Status { ACTIVE "Active" }'); +lexer.define('enum', enumReader); + +// Clone preserves code, index position, and all definitions +const clonedLexer = lexer.clone(); +console.log(clonedLexer.index); // Same index as original +console.log(clonedLexer.dictionary); // Same definitions as original`, + + //------------------------------------------------------------------// + + `import { Lexer } from '@stackpress/idea-parser'; +import definitions from '@stackpress/idea-parser/definitions'; + +const lexer = new Lexer(); + +// Load all predefined token definitions +Object.keys(definitions).forEach((key) => { + lexer.define(key, definitions[key]); +}); + +// Define a custom token +lexer.define('customKeyword', (code, start, lexer) => { + if (code.substring(start, start + 6) === 'custom') { + return { + type: 'Keyword', + value: 'custom', + start: start, + end: start + 6 + }; + } + return undefined; +});`, + + //------------------------------------------------------------------// + + `import { Lexer } from '@stackpress/idea-parser'; +import definitions, { data } from '@stackpress/idea-parser/definitions'; + +const lexer = new Lexer(); +Object.keys(definitions).forEach((key) => { + lexer.define(key, definitions[key]); +}); + +// Parse a float literal +lexer.load('4.4'); +const floatToken = lexer.expect('Float'); +console.log(floatToken.value); // 4.4 +console.log(floatToken.start); // 0 +console.log(floatToken.end); // 3 + +// Parse any data type (scalar, object, or array) +lexer.load('"hello world"'); +const stringToken = lexer.expect(data); +console.log(stringToken.value); // 'hello world' + +// Expect one of multiple token types +lexer.load('true'); +const booleanToken = lexer.expect(['Boolean', 'String', 'Integer']); +console.log(booleanToken.value); // true`, + + //------------------------------------------------------------------// + + `import { Lexer } from '@stackpress/idea-parser'; + +const lexer = new Lexer(); +lexer.define('String', definitions['String']); + +const definition = lexer.get('String'); +if (definition) { + console.log('Definition key:', definition.key); // 'String' + console.log('Reader function:', typeof definition.reader); // 'function' +} else { + console.log('Definition not found'); +}`, + + //------------------------------------------------------------------// + + `import { Lexer } from '@stackpress/idea-parser'; + +const lexer = new Lexer(); + +// Load code from the beginning +lexer.load('enum Status { ACTIVE "Active" }'); +console.log(lexer.index); // 0 + +// Load code starting from a specific position +lexer.load('enum Status { ACTIVE "Active" }', 5); +console.log(lexer.index); // 5 +console.log(lexer.substring(5, 11)); // 'Status'`, + + //------------------------------------------------------------------// + + `import { Lexer } from '@stackpress/idea-parser'; + +const lexer = new Lexer(); +lexer.define('literal', (code, start) => { + if (code.startsWith('42', start)) { + return { type: 'Literal', value: 42, start, end: start + 2 }; + } + return undefined; +}); + +const code = '42'; + +// Match against specific token types +const match = lexer.match(code, 0, ['literal']); +if (match) { + console.log('Matched:', match.type); // 'Literal' + console.log('Value:', match.value); // 42 +} + +// Match against all available definitions (pass undefined for keys) +const match2 = lexer.match('42', 0, undefined); +if (match2) { + console.log('Matched:', match2.type); // 'Literal' +}`, + + //------------------------------------------------------------------// + + `import { Lexer } from '@stackpress/idea-parser'; +import definitions from '@stackpress/idea-parser/definitions'; + +const lexer = new Lexer(); +Object.keys(definitions).forEach((key) => { + lexer.define(key, definitions[key]); +}); + +lexer.load('enum Status { ACTIVE "Active" }'); + +// Test if next token matches (doesn't advance index) +if (lexer.next('AnyIdentifier')) { + console.log('Next token is an identifier'); + console.log(lexer.index); // Still 0 +} + +// Test for multiple possible tokens +if (lexer.next(['String', 'Integer', 'Boolean'])) { + console.log('Next token is a literal value'); +}`, + + //------------------------------------------------------------------// + + `import { Lexer } from '@stackpress/idea-parser'; +import definitions from '@stackpress/idea-parser/definitions'; + +const lexer = new Lexer(); +Object.keys(definitions).forEach((key) => { + lexer.define(key, definitions[key]); +}); + +lexer.load('/* some comment */ enum Status'); + +// Try to parse optional whitespace/comments +const comment = lexer.optional('note'); +if (comment) { + console.log('Found comment:', comment.value); // '/* some comment */' +} + +// Skip optional whitespace +lexer.optional('whitespace'); + +// Now parse the enum keyword +const enumToken = lexer.expect('AnyIdentifier'); +console.log(enumToken.name); // 'enum'`, + + //------------------------------------------------------------------// + + `import { Lexer } from '@stackpress/idea-parser'; + +const lexer = new Lexer(); +lexer.load(''); // Empty string + +// Read the next token (tries all definitions) +const nextToken = lexer.read(); +console.log(nextToken); // undefined (no tokens in empty string) + +lexer.load('42'); +lexer.define('Integer', definitions['Integer']); + +const token = lexer.read(); +if (token) { + console.log('Token type:', token.type); // 'Literal' + console.log('Token value:', token.value); // 42 +}`, + + //------------------------------------------------------------------// + + `import { Lexer } from '@stackpress/idea-parser'; + +const lexer = new Lexer(); +lexer.load('some code'); + +// Extract specific portions of code +const substring = lexer.substring(5, 9); +console.log(substring); // 'code' + +// Return empty string when start and end are the same +const empty = lexer.substring(5, 5); +console.log(empty); // ''`, + + //------------------------------------------------------------------// + + `import { Lexer } from '@stackpress/idea-parser'; + +const lexer = new Lexer(); +lexer.load('enum Status { ACTIVE "Active" }'); + +// Find next space from current position +const spaceIndex = lexer.nextSpace(); +console.log(spaceIndex); // 4 (position of space after 'enum') + +// If no space found, returns code length +lexer.load('enumStatus'); +const endIndex = lexer.nextSpace(); +console.log(endIndex); // 10 (length of code)`, + + //------------------------------------------------------------------// + + `import { Lexer } from '@stackpress/idea-parser'; +import { Compiler } from '@stackpress/idea-parser'; +import definitions, { data } from '@stackpress/idea-parser/definitions'; + +const lexer = new Lexer(); +Object.keys(definitions).forEach((key) => { + lexer.define(key, definitions[key]); +}); + +// Parse a simple object +lexer.load('{ foo "bar" bar 4.4 }'); +const objectToken = lexer.expect('Object'); +const compiled = Compiler.object(objectToken); +console.log(compiled); // { foo: 'bar', bar: 4.4 } + +// Parse nested objects +lexer.load('{ foo "bar" zoo { foo false bar null } }'); +const nestedToken = lexer.expect('Object'); +const nestedCompiled = Compiler.object(nestedToken); +console.log(nestedCompiled.zoo.foo); // false +console.log(nestedCompiled.zoo.bar); // null`, + + //------------------------------------------------------------------// + + `// Parse a simple array +lexer.load('[ 4.4 "bar" false null ]'); +const arrayToken = lexer.expect('Array'); +const compiledArray = Compiler.array(arrayToken); +console.log(compiledArray); // [4.4, 'bar', false, null] + +// Parse nested arrays +lexer.load('[ 4.4 "bar" [ 4 true ] ]'); +const nestedArrayToken = lexer.expect('Array'); +const nestedArray = Compiler.array(nestedArrayToken); +console.log(nestedArray[2]); // [4, true] + +// Parse array of objects +lexer.load('[ { label "US" value "United States" } { label "CA" value "Canada" } ]'); +const objectArrayToken = lexer.expect('Array'); +const objectArray = Compiler.array(objectArrayToken); +console.log(objectArray[0].label); // 'US' +console.log(objectArray[1].value); // 'Canada'`, + + //------------------------------------------------------------------// + + `// Parse block comments +lexer.load('/* some comment */'); +const noteToken = lexer.expect('note'); +console.log(noteToken.type); // '_Note' +console.log(noteToken.value); // '/* some comment */' + +// Parse line comments +lexer.load('//some comment'); +const commentToken = lexer.expect('comment'); +console.log(commentToken.type); // '_Comment' +console.log(commentToken.value); // '//some comment' + +// Parse multiline block comments +lexer.load("/* + some + // comment +*/"); +const multilineToken = lexer.expect('note'); +console.log(multilineToken.value); // Contains newlines and nested //`, + + //------------------------------------------------------------------// + + `const lexer = new Lexer(); + +// Throws: "Unknown definition unknownKey" +try { + lexer.expect('unknownKey'); +} catch (error) { + console.log(error.message); // "Unknown definition unknownKey" +} + +// Throws: "Unknown definition missingKey" +try { + lexer.match('some code', 0, ['missingKey']); +} catch (error) { + console.log(error.message); // "Unknown definition missingKey" +}`, + + //------------------------------------------------------------------// + + `import { Exception } from '@stackpress/idea-parser'; + +const lexer = new Lexer(); +lexer.define('String', definitions['String']); +lexer.load('42'); // Number, not string + +try { + lexer.expect('String'); // Expecting string but found number +} catch (error) { + if (error instanceof Exception) { + console.log(error.message); // "Unexpected 42 expecting String" + console.log(error.start); // Position where error occurred + console.log(error.end); // End position for error highlighting + } +}`, + + //------------------------------------------------------------------// + + `import { Lexer, EnumTree } from '@stackpress/idea-parser'; + +// AST classes configure lexers with appropriate definitions +const lexer = new Lexer(); +EnumTree.definitions(lexer); // Adds enum-specific token definitions + +lexer.load('enum Status { ACTIVE "Active" INACTIVE "Inactive" }'); + +const enumTree = new EnumTree(lexer); +const result = enumTree.enum(); // Parse enum using configured lexer`, + + //------------------------------------------------------------------// + + `// Save current state for potential backtracking +const checkpoint = lexer.clone(); + +try { + // Try to parse complex structure + const result = parseComplexStructure(lexer); + return result; +} catch (error) { + // Restore state and try alternative parsing + const restoredLexer = checkpoint; + return parseAlternativeStructure(restoredLexer); +}`, + + //------------------------------------------------------------------// + + `// Parse different types based on lookahead +if (lexer.next('AnyIdentifier')) { + const identifier = lexer.expect('AnyIdentifier'); + if (identifier.name === 'enum') { + // Parse enum declaration + } else if (identifier.name === 'model') { + // Parse model declaration + } +}`, + + //------------------------------------------------------------------// + `import type { Reader } from '@stackpress/idea-parser'; + +const customReader: Reader = (code, start, lexer) => { + // Check if pattern matches at current position + if (!code.startsWith('custom', start)) { + return undefined; // No match + } + + // Calculate end position + const end = start + 6; + + // Return token object + return { + type: 'CustomToken', + value: 'custom', + start: start, + end: end + }; +}; + +// Register the custom reader +lexer.define('custom', customReader);` +]; + +//--------------------------------------------------------------------// + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx( + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500', +); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Lexer'); + const description = _( + 'The Lexer class implements the Parser interface and provides ' + + 'tokenization and parsing utilities for schema code. It manages ' + + 'a dictionary of token definitions and handles the parsing ' + + 'process by matching patterns against the input code.' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + + return ( + + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Lexer Section Content */} +
    +

    {_('Lexer')}

    + + The Lexer class implements the Parser interface and provides + tokenization and parsing utilities for schema code. It manages + a dictionary of token definitions and handles the parsing + process by matching patterns against the input code. + + + {examples[0]} + +
    + + {/* Horizontal Rule */} +
    + + {/* Properties Section Content */} +
    +

    {_('1. Properties')}

    +

    + + The following properties are available when instantiating a Lexer. + +

    + + + {_('Property')} + {_('Type')} + {_('Description')} + + dictionary + Record‹string, Definition› {_( + 'Shallow copy of all token definitions' + )} + {_('The current index position in the code')} + + + index + number + {_('Current parsing position in the code')} + +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Methods Section Content */} +
    +

    {_('2. Methods')}

    +

    + + The following methods are available when instantiating + a Lexer. + +

    + + {/* Cloning the Lexer Section Content */} +
    +

    {_('2.1 Cloning the Lexer')}

    +

    + + The following example shows how to create an exact copy + of the Lexer's current state. + +

    + + {examples[1]} + + + {_('Returns')} +
  • + + A new Lexer instance with identical state to original + +
  • +
    + + {/* Defining Token Patterns Section Content */} +
    +

    {_('2.2 Defining Token Patterns')}

    +

    + + The following example shows how to register token + definitions for parsing. + +

    + + {examples[2]} + + +

    {_('Parameters')}

    + + {_('Parameter')} + {_('Type')} + {_('Description')} + + key + string + {_('Unique identifier for the token definition')} + + + reader + Reader + + + Function that attempts to match and parse the token + + + +
    + + {_('Returns')} +
  • + + Void (modifies the lexer's internal dictionary). + +
  • +
    + + {/* Expecting Specific Tokens Section Content */} +
    +

    {_('2.3 Expecting Specific Tokens')}

    +

    + + The following example shows how to require specific + tokens at the current position. + +

    + + {examples[3]} + + +

    {_('Parameters')}

    + + {_('Parameter')} + {_('Type')} + {_('Description')} + + keys + string | string[] + {_('Token definition key(s) to expect')} + +
    + + {_('Returns')} +
  • + + The matched token object, or throws an exception if + no match is found. + +
  • +
    + + {/* Getting Token Definitions Section Content */} +
    +

    {_('2.4 Getting Token Definitions')}

    +

    + + The following example shows how to retrieve registered + token definitions. + +

    + + {examples[4]} + + +

    {_('Parameters')}

    + + {_('Parameter')} + {_('Type')} + {_('Description')} + + key + string + {_('The token definition key to retrieve')} + +
    + + {_('Returns')} +
  • + + The Definition object if found, undefined otherwise. + +
  • +
    + + {/* Loading Code Section Content */} +
    +

    {_('2.5 Loading Code')}

    +

    + + The following example shows how to load code for parsing. + +

    + + {examples[5]} + + +

    {_('Parameters')}

    + + {_('Parameter')} + {_('Type')} + {_('Description')} + + code + string + {_('The source code to parse')} + + + index + number + + + Starting position in the code (default: 0) + + + +
    + + {_('Returns')} +
  • + + The Lexer instance to allow method chaining. + +
  • +
    + + {/* Matching Tokens Section Content */} +
    +

    {_('2.6 Matching Tokens')}

    +

    + + The following example shows how to find the first + matching token from available definitions. + +

    + + {examples[6]} + + +

    {_('Parameters')}

    + + {_('Parameter')} + {_('Type')} + {_('Description')} + + code + string + {_('The code to match against')} + + + start + number + {_('Starting position for matching')} + + + keys + string[] + + + Optional array of definition keys to try (default: + all definitions) + + + +
    + + {_('Returns')} +
  • + + The first matching token object, or null if no match + is found. + +
  • +
    + + {/* Testing for Next Tokens Section Content */} +
    +

    {_('2.7 Testing for Next Tokens')}

    +

    + + The following example shows how to check if the next + tokens match without consuming them. + +

    + + {examples[7]} + + +

    {_('Parameters')}

    + + {_('Parameter')} + {_('Type')} + {_('Description')} + + names + string | string[] + {_('Token definition key(s) to test for')} + +
    + + {_('Returns')} +
  • + + true if the next token(s) match, false otherwise. + Does not advance the index. + +
  • +
    + + {/* Optional Token Parsing Section Content */} +
    +

    {_('2.8 Optional Token Parsing')}

    +

    + + The following example shows how to optionally parse + tokens without throwing errors. + +

    + + {examples[8]} + + +

    {_('Parameters')}

    + + {_('Parameter')} + {_('Type')} + {_('Description')} + + names + string | string[] + {_('Token definition key(s) to try parsing')} + +
    + + {_('Returns')} +
  • + + The matched token object if found, undefined otherwise. + +
  • +
    + + {/* Reading Ahead Section Content */} +
    +

    {_('2.9 Reading Ahead')}

    +

    + + The following example shows how to read the next + available token. + +

    + + {examples[9]} + + + {_('Returns')} +
  • + + The next available token object, or undefined if no + token can be parsed. + +
  • +
    + + {/* Getting Substrings Section Content */} +
    +

    {_('2.10 Getting Substrings')}

    +

    + + The following example shows how to extract portions + of the source code. + +

    + + {examples[10]} + + +

    {_('Parameters')}

    + + {_('Parameter')} + {_('Type')} + {_('Description')} + + start + number + {_('Starting position in the code')} + + + end + number + {_('Ending position in the code')} + +
    + + {_('Returns')} +
  • + + The substring of code between start and end positions. + +
  • +
    + + {/* Finding Next Space Section Content */} +
    +

    {_('2.11 Finding Next Space')}

    +

    + + The following example shows how to find the next + whitespace character (useful for error reporting). + +

    + + {examples[11]} + + + {_('Returns')} +
  • + + The index of the next space character, or the code + length if no space is found. + +
  • +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Parsing Complex Data Structures Section Content */} +
    +

    {_('3. Parsing Complex Data Structures')}

    +

    + + The Lexer can parse complex nested data structures using + the predefined token definitions: + +

    + +

    {_('Parsing Objects')}

    + + {examples[12]} + + +

    {_('Parsing Arrays')}

    + + {examples[13]} + + +

    {_('Parsing Comments')}

    + + {examples[14]} + +
    + + {/* Horizontal Rule */} +
    + + {/* Error Handling Section Content */} +
    +

    {_('4. Error Handling')}

    +

    + + The Lexer provides detailed error information when + parsing fails: + +

    + +

    {_('Unknown Definitions')}

    + + {examples[15]} + + +

    {_('Unexpected Tokens')}

    + + {examples[16]} + +
    + + {/* Horizontal Rule */} +
    + + {/* Predefined Token Definitions Section Content */} +
    +

    {_('5. Predefined Token Definitions')}

    +

    + + The library comes with comprehensive predefined token definitions: + +

    + +

    {_('Literals')}

    +
      +
    • Null: {_('Matches null keyword')}
    • +
    • Boolean: {_('Matches true and false')}
    • +
    • String: {_( + 'Matches quoted strings "hello"' + )}
    • +
    • Float: {_( + 'Matches decimal numbers 4.4, -3.14' + )}
    • +
    • Integer: {_( + 'Matches whole numbers 42, -10' + )}
    • +
    • Environment: {_( + 'Matches environment variables env("VAR_NAME")' + )}
    • +
    + +

    {_('Identifiers')}

    +
      +
    • AnyIdentifier: {_( + 'Matches any valid identifier [a-z_][a-z0-9_]*' + )}
    • +
    • UpperIdentifier: {_( + 'Matches uppercase identifiers [A-Z_][A-Z0-9_]*' + )}
    • +
    • CapitalIdentifier: {_( + 'Matches capitalized identifiers [A-Z_][a-zA-Z0-9_]*' + )}
    • +
    • CamelIdentifier: {_( + 'Matches camelCase identifiers [a-z_][a-zA-Z0-9_]*' + )}
    • +
    • LowerIdentifier: {_( + 'Matches lowercase identifiers [a-z_][a-z0-9_]*' + )}
    • +
    • AttributeIdentifier: {_( + 'Matches attribute identifiers @field.input' + )}
    • +
    + +

    {_('Structural')}

    +
      +
    • Array: {_( + 'Matches array expressions [ ... ]' + )}
    • +
    • Object: {_( + 'Matches object expressions { ... }' + )}
    • +
    • {, }, [, ], (, ): {_( + 'Bracket and brace tokens' + )}
    • +
    • !: {_('Final modifier token')}
    • +
    + +

    {_('Whitespace and Comments')}

    +
      +
    • whitespace: {_( + 'Matches any whitespace \\s+' + )}
    • +
    • space: {_('Matches spaces only')}
    • +
    • line: {_('Matches line breaks')}
    • +
    • note: {_( + 'Matches block comments /* ... */' + )}
    • +
    • comment: {_( + 'Matches line comments // ...' + )}
    • +
    + +

    {_('Data Groups')}

    +
      +
    • scalar: {_( + 'Array of scalar types [\'Null\', \'Boolean\', \'String\', ' + + '\'Float\', \'Integer\', \'Environment\']' + )}
    • +
    • data: {_( + 'Array of all data types [...scalar, \'Object\', \'Array\']' + )}
    • +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Usage with AST Section Content */} +
    +

    {_('6. Usage with AST')}

    +

    + + The Lexer is typically used by AST classes for parsing + specific language constructs: + +

    + + {examples[17]} + +
    + + {/* Horizontal Rule */} +
    + + {/* Advanced Usage Patterns Section Content */} +
    +

    {_('7. Advanced Usage Patterns')}

    + +

    {_('Backtracking with Clone')}

    + + {examples[18]} + + +

    {_('Conditional Parsing')}

    + + {examples[19]} + + +

    {_('Custom Reader Functions')}

    +

    + + Reader functions should follow this pattern: + +

    + + {examples[20]} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + } + > + + + ); +} + + + + diff --git a/packages/www/plugins/docs/views/parser/api-references/tokens.tsx b/packages/www/plugins/docs/views/parser/api-references/tokens.tsx new file mode 100644 index 0000000..75bdd61 --- /dev/null +++ b/packages/www/plugins/docs/views/parser/api-references/tokens.tsx @@ -0,0 +1,1958 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +import { Table, Thead, Trow, Tcol } from 'frui/element/Table'; +import clsx from 'clsx'; +//local +import { H1, H2, C, SS, Nav, P } from '../../../components/index.js'; +import Code from '../../../components/Code.js'; +import Layout from '../../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const examples = [ + `import type { + SchemaToken, + DeclarationToken, + IdentifierToken, + LiteralToken, + ObjectToken, + ArrayToken, + PropertyToken, + ImportToken +} from '@stackpress/idea-parser';`, + + //------------------------------------------------------------------// + + `const unknownToken: UnknownToken = { + type: 'CustomType', + start: 0, + end: 10, + value: 'some value', + raw: 'raw text' +};`, + + //------------------------------------------------------------------// + + `const identifierToken: IdentifierToken = { + type: 'Identifier', + name: 'UserRole', + start: 5, + end: 13 +};`, + + //------------------------------------------------------------------// + + `// From enum.json fixture +{ + "type": "Identifier", + "start": 5, + "end": 10, + "name": "Roles" +} + +// Property key identifier +{ + "type": "Identifier", + "start": 15, + "end": 20, + "name": "ADMIN" +}`, + + //------------------------------------------------------------------// + + `const stringLiteral: LiteralToken = { + type: 'Literal', + start: 21, + end: 28, + value: 'Admin', + raw: '"Admin"' +}; + +const numberLiteral: LiteralToken = { + type: 'Literal', + start: 10, + end: 12, + value: 42, + raw: '42' +};`, + + //------------------------------------------------------------------// + + `// From enum.json fixture +{ + "type": "Literal", + "start": 21, + "end": 28, + "value": "Admin", + "raw": "'Admin'" +}`, + + //------------------------------------------------------------------// + + `const objectToken: ObjectToken = { + type: 'ObjectExpression', + start: 0, + end: 64, + properties: [ + { + type: 'Property', + kind: 'init', + start: 15, + end: 28, + method: false, + shorthand: false, + computed: false, + key: { type: 'Identifier', name: 'ADMIN', start: 15, end: 20 }, + value: { + type: 'Literal', + value: 'Admin', + start: 21, + end: 28, + raw: '"Admin"' + } + } + ] +};`, + + //------------------------------------------------------------------// + + `const arrayToken: ArrayToken = { + type: 'ArrayExpression', + start: 0, + end: 25, + elements: [ + { type: 'Literal', value: 'item1', start: 2, end: 9, raw: '"item1"' }, + { type: 'Literal', value: 'item2', start: 11, end: 18, raw: '"item2"' } + ] +};`, + + //------------------------------------------------------------------// + + `const propertyToken: PropertyToken = { + type: 'Property', + kind: 'init', + start: 15, + end: 28, + method: false, + shorthand: false, + computed: false, + key: { + type: 'Identifier', + name: 'ADMIN', + start: 15, + end: 20 + }, + value: { + type: 'Literal', + value: 'Admin', + start: 21, + end: 28, + raw: '"Admin"' + } +};`, + + //------------------------------------------------------------------// + + `const enumDeclaration: DeclarationToken = { + type: 'VariableDeclaration', + kind: 'enum', + start: 0, + end: 64, + declarations: [{ + type: 'VariableDeclarator', + start: 5, + end: 64, + id: { + type: 'Identifier', + name: 'Roles', + start: 5, + end: 10 + }, + init: { + type: 'ObjectExpression', + start: 0, + end: 64, + properties: [/* property tokens */] + } + }] +};`, + + //------------------------------------------------------------------// + + `const declaratorToken: DeclaratorToken = { + type: 'VariableDeclarator', + start: 5, + end: 64, + id: { + type: 'Identifier', + name: 'Roles', + start: 5, + end: 10 + }, + init: { + type: 'ObjectExpression', + start: 0, + end: 64, + properties: [/* property tokens */] + } +};`, + + //------------------------------------------------------------------// + + `const importToken: ImportToken = { + type: 'ImportDeclaration', + start: 0, + end: 25, + specifiers: [], + source: { + type: 'Literal', + value: './shared/types.idea', + start: 4, + end: 25, + raw: '"./shared/types.idea"' + } +};`, + + //------------------------------------------------------------------// + + `const schemaToken: SchemaToken = { + type: 'Program', + kind: 'schema', + start: 0, + end: 150, + body: [ + // ImportTokens for use statements + { + type: 'ImportDeclaration', + start: 0, + end: 25, + specifiers: [], + source: { type: 'Literal', value: './types.idea', start: 4, end: 25, raw: '"./types.idea"' } + }, + // DeclarationTokens for enums, props, types, models, plugins + { + type: 'VariableDeclaration', + kind: 'enum', + start: 27, + end: 91, + declarations: [/* declarator */] + } + ] +};`, + + //------------------------------------------------------------------// + + `type Token = DataToken | UnknownToken;`, + + //------------------------------------------------------------------// + + `type DataToken = IdentifierToken | LiteralToken | ObjectToken | ArrayToken;`, + + //------------------------------------------------------------------// + + `type Reader = ( + code: string, + start: number, + lexer: Parser +) => Token | undefined;`, + + //------------------------------------------------------------------// + + `type Definition = { + key: string, + reader: Reader +};`, + + //------------------------------------------------------------------// + + `interface Parser { + get dictionary(): Record; + get index(): number; + clone(): Parser; + define(key: string, reader: Reader, type?: string): void; + expect(keys: string | string[]): T; + get(key: string): Definition | undefined; + load(code: string, index: number): this; + match(code: string, start: number, keys?: string[]): Token | null; + next(keys: string | string[]): boolean; + optional(keys: string | string[]): T | undefined; + read(): Token | undefined; +}`, + + //------------------------------------------------------------------// + + `type UseReferences = Record | false;`, + + //------------------------------------------------------------------// + + `type Scalar = string | number | null | boolean;`, + + //------------------------------------------------------------------// + + `type Data = Scalar | Data[] | { [key: string]: Data };`, + + //------------------------------------------------------------------// + + `import { EnumTree } from '@stackpress/idea-parser'; + +const enumCode = \`enum Roles { + ADMIN "Admin" + MANAGER "Manager" + USER "User" +}\`; + +// Parse generates a DeclarationToken +const enumToken = EnumTree.parse(enumCode); +console.log(enumToken.kind); // 'enum' +console.log(enumToken.declarations[0].id.name); // 'Roles'`, + + //------------------------------------------------------------------// + + `import { Compiler } from '@stackpress/idea-parser'; + +// Convert DeclarationToken to configuration +const [enumName, enumConfig] = Compiler.enum(enumToken); +console.log(enumName); // 'Roles' +console.log(enumConfig); // { ADMIN: 'Admin', MANAGER: 'Manager', USER: 'User' }`, + + //------------------------------------------------------------------// + + `// ObjectToken processing +const objectToken: ObjectToken = { + type: 'ObjectExpression', + start: 0, + end: 30, + properties: [ + { + type: 'Property', + kind: 'init', + start: 2, + end: 15, + method: false, + shorthand: false, + computed: false, + key: { type: 'Identifier', name: 'type', start: 2, end: 6 }, + value: { type: 'Literal', value: 'text', start: 7, end: 13, raw: '"text"' } + } + ] +}; + +const compiled = Compiler.object(objectToken); +console.log(compiled); // { type: 'text' }`, + + //------------------------------------------------------------------// + + `import { Exception } from '@stackpress/idea-parser'; + +try { + const invalidToken = { kind: 'invalid' } as DeclarationToken; + Compiler.enum(invalidToken); +} catch (error) { + if (error instanceof Exception) { + console.log('Token error:', error.message); // 'Invalid Enum' + } +}`, + + //------------------------------------------------------------------// + + `// Position information for error highlighting +const token: IdentifierToken = { + type: 'Identifier', + name: 'InvalidName', + start: 10, + end: 21 +}; + +// Can be used to highlight errors in editors +const errorRange = { start: token.start, end: token.end };` +]; + +//--------------------------------------------------------------------// + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx( + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500', +); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Tokens'); + const description = _( + 'Token types define the Abstract Syntax Tree (AST) structures ' + + 'used by the idea parser to represent parsed schema code. These ' + + 'types form the foundation of the parsing system, providing ' + + 'type-safe representations of schema elements.' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + + return ( + + ); +} + + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Tokens Section Content */} +
    +

    {_('Tokens')}

    + + Token types define the Abstract Syntax Tree (AST) structures + used by the idea parser to represent parsed schema code. + These types form the foundation of the parsing system, + providing type-safe representations of schema elements. + + + {examples[0]} + +
    + + {/* Horizontal Rule */} +
    + + {/* Core Token Types */} +
    +

    {_('1. Core Token Types')}

    +

    + + The following types define the fundamental token + structures used throughout the parsing system. + +

    + + {/* UnknownToken Section Content */} +
    +

    {_('1.1 UnknownToken')}

    +

    + + Base token structure for unrecognized or generic + tokens during parsing. + +

    + + {examples[1]} + + +

    {_('Properties')}

    + + Property + Type + Description + + type + string + + + Token type identifier + + + + + start + number + + + Starting character position in source code + + + + + end + number + + + Ending character position in source code + + + + + value + any + + + Parsed value of the token + + + + + raw + string + + + Raw text from source code + + + +
    + + {_('Usage')} + + Used as a fallback for tokens that don't match specific + patterns and as a base structure for other token types. + +
    + + {/* IdentifierToken Section Content */} +
    +

    {_('1.2 IdentifierToken')}

    + + Represents identifiers such as variable names, type names, + and property keys. + + + {examples[2]} + + +

    {_('Properties')}

    + + Property + Type + Description + + type + 'Identifier' + + + Always 'Identifier' for identifier tokens + + + + + name + string + + + The identifier name + + + + + start + number + + + Starting character position + + + + + end + number + + + Ending character position + + + +
    + + {_('Usage')} + Used throughout the parser for: +
      +
    • Enum names: enum UserRole
    • +
    • Model names: model User
    • +
    • Property names: name String
    • +
    • Type references: role UserRole
    • +
    + + {_('Examples from Tests')} + + {examples[3]} + +
    + + {/* LiteralToken Section Content */} +
    +

    {_('1.3 LiteralToken')}

    + + Represents literal values such as strings, numbers, + booleans, and null. + + + {examples[4]} + + +

    {_('Properties')}

    + + Property + Type + Description + + type + 'Literal' + Always 'Literal' for literal tokens + + + start + number + Starting character position + + + end + number + Ending character position + + + value + any + The parsed literal value + + + raw + string + Raw text representation from source + +
    + + {_('Usage')} + + Used for all scalar values in schema definitions: + +
      +
    • + String literals: "Admin", "localhost" +
    • +
    • + Number literals: 5432, 3.14 +
    • +
    • + Boolean literals: true, false +
    • +
    • + Null literals: null +
    • +
    + + {_('Examples from Tests')} + + {examples[5]} + +
    + + {/* ObjectToken Section Content */} +
    +

    {_('1.4 ObjectToken')}

    + + Represents object expressions containing key-value + pairs. + + + {examples[6]} + + +

    {_('Properties')}

    + + Property + Type + Description + + type + 'ObjectExpression' + + + Always 'ObjectExpression' for object tokens + + + + + start + number + + + Starting character position + + + + + end + number + + + Ending character position + + + + + properties + PropertyToken[] + + + Array of property tokens + + + +
    + + {_('Usage')} + Used for: +
      +
    • + Enum definitions: + { ADMIN "Admin", USER "User" } +
    • +
    • + Model column definitions: + { id String @id, name String } +
    • +
    • + Plugin configurations: + { provider "postgresql", url env("DATABASE_URL") + } +
    • +
    • + Attribute parameters: + @field.input({ type "text" }) +
    • +
    + + {_('Examples from Tests')} + + The enum fixture shows an ObjectToken containing three + PropertyTokens for ADMIN, MANAGER, and USER enum values. + +
    + + {/* ArrayToken Section Content */} +
    +

    {_('1.5 ArrayToken')}

    + + Represents array expressions containing ordered elements. + + + {examples[7]} + + +

    {_('Properties')}

    + + Property + Type + Description + + type + 'ArrayExpression' + + + Always 'ArrayExpression' for array tokens + + + + + start + number + + + Starting character position + + + + + end + number + + + Ending character position + + + + + elements + DataToken[] + + + Array of data tokens + + + +
    + + {_('Usage')} + Used for: +
      +
    • + Array type definitions: + String[] +
    • +
    • + Plugin feature lists: + previewFeatures ["fullTextSearch", "metrics"] +
    • +
    • + Attribute arrays: + @is.oneOf(["admin", "user", "guest"]) +
    • +
    +
    + + {/* PropertyToken Section Content */} +
    +

    {_('1.6 PropertyToken')}

    + + Represents key-value pairs within object expressions. + + + {examples[8]} + + +

    {_('Properties')}

    + + Property + Type + Description + + type + 'Property' + + + Always 'Property' for property tokens + + + + + kind + 'init' + + + Always 'init' for initialization properties + + + + + start + number + + + Starting character position + + + + + end + number + + + Ending character position + + + + + method + boolean + + + Always false (not used for method properties) + + + + + shorthand + boolean + + + Always false (not used for shorthand properties) + + + + + computed + boolean + + + Always false (not used for computed properties) + + + + + key + IdentifierToken + + + Property key identifier + + + + + value + DataToken + + + Property value (literal, object, array, or + identifier) + + + +
    + + {_('Usage')} + Used within ObjectTokens for: +
      +
    • + Enum key-value pairs: ADMIN "Admin" +
    • +
    • + Model column definitions: id String +
    • +
    • + Plugin configuration options: provider "postgresql" +
    • +
    • + Attribute parameters: type "text" +
    • +
    + + {_('Examples from Tests')} + + From the enum fixture, each enum value is represented + as a PropertyToken with an IdentifierToken key and + LiteralToken value. + +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Declaration Tokens Section Content*/} +
    +

    {_('2. Declaration Tokens')}

    + + The following types represent top-level declarations in + schema files. + + + {/* DeclarationToken Section Content */} +
    +

    {_('2.1 DeclarationToken')}

    + + Represents variable declarations for enums, props, + types, models, and plugins. + + + {examples[9]} + + +

    {_('Properties')}

    + + Property + Type + Description + + type + 'VariableDeclaration' + + + Always 'VariableDeclaration' for declarations + + + + + kind + string + + Declaration type: 'enum', 'prop', 'type', 'model', + 'plugin' + + + + mutable + boolean + + + Optional mutability flag (for types and models) + + + + + start + number + + + Starting character position + + + + + end + number + + + Ending character position + + + + + declarations + [DeclaratorToken] + + + Array with single declarator token + + + +
    + + {_('Usage')} + + Used by all tree parsers (EnumTree, PropTree, TypeTree, + ModelTree, PluginTree) to represent their respective + declarations. The kind property determines how + the Compiler processes the declaration. + + + {_('Examples from Tests')} + + The enum fixture shows a complete DeclarationToken with + kind 'enum' containing the Roles enum definition. + +
    + + {/* DeclaratorToken Section Content */} +
    +

    {_('2.2 DeclaratorToken')}

    + + Represents the declarator part of a variable declaration, + containing the identifier and initialization. + + + {examples[10]} + + +

    {_('Properties')}

    + + Property + Type + Description + + type + 'VariableDeclarator' + + + Always 'VariableDeclarator' for declarators + + + + + start + number + + + Starting character position + + + + + end + number + + + Ending character position + + + + + id + IdentifierToken + + + Declaration identifier (name) + + + + + init + ObjectToken + + + Initialization object containing the declaration + body + + + +
    + + {_('Usage')} + + Used within DeclarationTokens to separate the declaration + name from its body. The id contains the name + (e.g., "Roles", "User") and init contains the + definition object. + +
    + + {/* ImportToken Section Content */} +
    +

    {_('2.3 ImportToken')}

    + + Represents use statements for importing other schema files. + + + {examples[11]} + + +

    {_('Properties')}

    + + Property + Type + Description + + type + 'ImportDeclaration' + + + Always 'ImportDeclaration' for imports + + + + + start + number + + + Starting character position + + + + + end + number + + + Ending character position + + + + + specifiers + [] + + + Always empty array (not used for named imports) + + + + + source + LiteralToken + + + Source file path as literal token + + + +
    + + {_('Usage')} + + Used by UseTree to represent use "./path/to/file.idea" + statements. The Compiler extracts the source path for + dependency resolution. + +
    + + {/* SchemaToken Section Content */} +
    +

    {_('2.4 SchemaToken')}

    + + Represents the complete parsed schema file containing all + declarations and imports. + + + {examples[12]} + + +

    {_('Properties')}

    + + Property + Type + Description + + type + 'Program' + + + Always 'Program' for complete schemas + + + + + kind + 'schema' + + + Always 'schema' for schema files + + + + + start + number + + + Starting character position (usually 0) + + + + + end + number + + + Ending character position + + + + + body + (DeclarationToken|ImportToken)[] + + + Array of all declarations and imports + + + +
    + + {_('Usage')} +

    + + Used by SchemaTree as the root token representing the + entire parsed schema file. The Compiler processes the + body array to generate the final schema configuration. + +

    +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Union Types Section Content */} +
    +

    {_('3. Union Types')}

    + + The following types provide flexible token handling for + different contexts. + + + {/* Token Section Content */} +
    +

    {_('3.1 Token')}

    + + Union type for all possible token types that can be + returned by readers. + + + {examples[13]} + + + {_('Usage')} + + Used as the return type for lexer operations and reader + functions. Allows handling both recognized data tokens + and unknown tokens. + +
    + + {/* Data Token Section */} +
    +

    {_('3.2 DataToken')}

    + + Union type for tokens representing data values. + + + {examples[14]} + + + {_('Usage')} + + Used throughout the Compiler for processing data values. + These tokens can be converted to actual JavaScript values + using Compiler.data(). + +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Parser Interface Section Content */} +
    +

    {_('4. Parser Interface')}

    + + The following types define the parser interface and reader + functions. + + + + {/* Reader Function Section */} +
    +

    {_('4.1 Reader')}

    + + Function type for token readers that attempt to parse + specific patterns. + + + {examples[15]} + + +

    {_('Parameters')}

    + + Parameter + Type + Description + + code + string + + + Source code being parsed + + + + + start + number + + + Starting position to attempt parsing + + + + + lexer + Parser + + + Parser instance for recursive parsing + + + +
    + + {_('Returns')} + + Token object if pattern matches, undefined otherwise. + + + {_('Usage')} + + Used to define token recognition patterns in the definitions + system. Each token type has a corresponding reader function. + +
    + + {/* Token Definition Section */} +
    +

    {_('4.2 Definition')}

    + + Pairs a token key with its reader function for lexer + registration. + + + {examples[16]} + + +

    {_('Properties')}

    + + Property + Type + Description + + key + string + + + Unique identifier for the token type + + + + + reader + Reader + + + Function that attempts to parse the token + + + +
    + + Usage + + Used by the Lexer to register and manage token definitions. + The key identifies the token type, and the reader attempts + to parse it. + +
    + + {/* Parser Interface Section */} +
    +

    {_('4.3 Parser')}

    + + Interface defining the contract for parser implementations. + + + {examples[17]} + + + Usage + + Implemented by the Lexer class to provide consistent + parsing operations across all tree parsers. + +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Reference Types Section Content */} +
    +

    {_('5. Reference Types')}

    + + The following types handle reference resolution and data + processing. + + + {/* UseReferences Section Content */} +
    +

    {_('5.1 UseReferences')}

    + + Type for managing prop and type references during + compilation. + + + {examples[18]} + + + {_('Usage')} + + Used by the Compiler to resolve identifier references: + +
      +
    • + false: Return template strings like + ${PropName} +
    • +
    • + Record<string, any>: Resolve identifiers + to actual values +
    • +
    • + Empty object {}: Throw error for + unknown references +
    • +
    +
    + + {/* Scalar Section Content */} +
    +

    {_('5.2 Scalar')}

    + + Union type for primitive values that can be stored in + schema configurations. + + + {examples[19]} + + + {_('Usage')} + + Used in enum configurations and other places where only + primitive values are allowed. + +
    + + {/* Data Section Content */} +
    +

    {_('5.3 Data')}

    + + Recursive type for nested data structures in schema + configurations. + + + {examples[20]} + + + {_('Usage')} + + Used throughout the system for representing complex nested + data structures in plugin configurations, attributes, and + other schema elements. + +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Usage Examples Section Content */} +
    +

    {_('6. Usage Examples')}

    + +

    {_('6.1 Parsing and Token Generation')}

    + + {examples[21]} + + +

    {_('6.2 Token Processing with Compiler')}

    + + {examples[22]} + + +

    {_('6.3 Working with Complex Tokens')}

    + + {examples[23]} + + +

    {_('6.4 Error Handling with Tokens')}

    + + {examples[24]} + +
    + + {/* Horizontal Rule */} +
    + + {/* Token Validation Section Content */} +
    +

    {_('7. Token Validation')}

    + + Tokens include position information for error reporting and + validation: + + + {examples[25]} + +
    + + {/* Horizontal Rule */} +
    + + {/* Integration With AST Section Content */} +
    +

    {_('8. Integration with AST')}

    + + AST classes generate specific token types: + +
      +
    • + EnumTree: + Generates DeclarationToken with kind: 'enum' +
    • +
    • + PropTree: + Generates DeclarationToken with kind: 'prop' +
    • +
    • + TypeTree: + Generates DeclarationToken with kind: 'type' +
    • +
    • + ModelTree: + Generates DeclarationToken with kind: 'model' +
    • +
    • + PluginTree: + Generates DeclarationToken with kind: 'plugin' +
    • +
    • + UseTree: + Generates ImportToken +
    • +
    • + SchemaTree: + Generates SchemaToken containing all other tokens +
    • +
    + + + Each AST class uses the Lexer to generate appropriate tokens, + which are then processed by the Compiler to produce the final + JSON configuration. + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + } + > + + + ); +} diff --git a/packages/www/plugins/docs/views/parser/best-practices.tsx b/packages/www/plugins/docs/views/parser/best-practices.tsx new file mode 100644 index 0000000..6a9bef5 --- /dev/null +++ b/packages/www/plugins/docs/views/parser/best-practices.tsx @@ -0,0 +1,321 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, C, Nav, SS } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const typeSafetyExample = + `import type { SchemaConfig, ModelConfig } from '@stackpress/idea-parser'; + +const schema: SchemaConfig = parse(code);`; + +//--------------------------------------------------------------------// + +const errorHandlingExample = + `import { parse, Exception } from '@stackpress/idea-parser'; + +try { + const result = parse(schemaCode); + // Process result +} catch (error) { + if (error instanceof Exception) { + console.error('Schema parsing failed:', error.message); + // Handle parsing error + } else { + console.error('Unexpected error:', error); + // Handle other errors + } +}`; + +//--------------------------------------------------------------------// + +const schemaStructureExample = + `// Good: Proper model structure +model User { + id String @id + name String +} + +// Bad: Missing required properties +model User { + // Missing columns - will throw error +}`; + +//--------------------------------------------------------------------// + +const namingExample = + `// Good +enum UserStatus { ACTIVE "Active" SUSPENDED "Suspended" } +prop EmailInput { type "email" format "email" } + +// Less clear +enum Status { A "Active" S "Suspended" } +prop Input { type "email" }`; + +//--------------------------------------------------------------------// + +const errorExamples = { + invalidSchema: 'Error: "Invalid Schema"', + missingColumns: 'Error: "Expecting a columns property"', + duplicateName: 'Error: "Duplicate [name]"', + unknownReference: 'Error: "Unknown reference [name]"' +}; + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Best Practices'); + const description = _( + 'Best practices and guidelines for using the Idea Parser ' + + 'library effectively, including error handling, type safety, ' + + 'and common pitfalls to avoid.' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    +

    {_('Best Practices')}

    +

    + + Follow these best practices to use the parser library + effectively and avoid common pitfalls. + +

    + + {/* Horizontal Rule */} +
    + + {/* Type Safety Section Content */} +
    +

    {_('1. Use Type Safety')}

    +

    + + The library is built with TypeScript and provides + comprehensive type definitions + +

    + + {typeSafetyExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Error Handling Section Content */} +
    +

    {_('2. Handle Errors Gracefully')}

    +

    + + Always wrap parsing operations in try-catch blocks + +

    + + {errorHandlingExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Choose the Right Function Section Content */} +
    +

    {_('3. Choose the Right Function')}

    +
  • + Use parse() + + when you need to preserve references for further processing + +
  • +
  • + Use final() + + when you want a clean output for final consumption + +
  • +
    + + {/* Horizontal Rule */} +
    + + {/* Validate Schema Structure Section Content */} +
    +

    {_('4. Validate Schema Structure')}

    +

    + + Ensure your schema follows the expected structure: + +

    + + {schemaStructureExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Use Meaningful Names Section Content */} +
    +

    {_('5. Use Meaningful Names')}

    +

    + + Choose descriptive names for your schema elements: + +

    + + {namingExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Error Examples Section Content */} +
    +

    {_('Error Handling')}

    +

    + Common errors and their solutions: +

    + +

    {_('Invalid Schema Structure')}

    + + {errorExamples.invalidSchema} + +
  • + Solution: + + Ensure your schema follows the correct syntax and structure. + +
  • + +

    {_('Missing Required Properties')}

    + + {errorExamples.missingColumns} + +
  • + Solution: + + Models and types must have a columns definition. + +
  • + +

    {_('Duplicate Declarations')}

    + + {errorExamples.duplicateName} + +
  • + Solution: + + Each declaration name must be unique within the schema. + +
  • + +

    {_('Unknown References')}

    + + {errorExamples.unknownReference} + +
  • + Solution: + + Ensure all referenced props and types are defined before use. + +
  • +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/parser/core-concepts.tsx b/packages/www/plugins/docs/views/parser/core-concepts.tsx new file mode 100644 index 0000000..5f66a7d --- /dev/null +++ b/packages/www/plugins/docs/views/parser/core-concepts.tsx @@ -0,0 +1,195 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, C, Nav, SS } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const processingFlow = +`Raw Schema Code → SchemaTree → Compiler → JSON Output`; + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Core Concepts'); + const description = _( + 'Learn the core concepts of the Idea Parser library including ' + + 'schema structure, processing flow, and key components.' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    +

    {_('Core Concepts')}

    + + {/* Schema Structure Section Content */} +
    +

    {_('Schema Structure')}

    +

    + + A complete .idea schema file can contain multiple + elements organized in a specific structure: + +

    + +
      +
    1. + Plugins:{' '} + + External integrations and configurations + +
    2. +
    3. + Use statements:{' '} + + Import other schema files + +
    4. +
    5. + Props:{' '} + + Reusable property configurations + +
    6. +
    7. + Enums:{' '} + + Enumerated value definitions + +
    8. +
    9. + Types:{' '} + + Custom type definitions with columns + +
    10. +
    11. + Models:{' '} + + Database model definitions + +
    12. +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Processing Flow Section Content */} +
    +

    {_('Processing Flow')}

    +

    + + The library follows this processing flow: + +

    + + + {processingFlow} + + +
      +
    1. + Raw Code: + + Your .idea schema file content + +
    2. +
    3. + SchemaTree: + + Parses the entire file into an 'Abstract Syntax Tree' + +
    4. +
    5. + Compiler: + + Converts AST tokens into structured JSON + +
    6. +
    7. + JSON Output: + + Final configuration object + +
    8. +
    +
    + + +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/parser/examples.tsx b/packages/www/plugins/docs/views/parser/examples.tsx new file mode 100644 index 0000000..e248092 --- /dev/null +++ b/packages/www/plugins/docs/views/parser/examples.tsx @@ -0,0 +1,186 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { Translate, useLanguage } from 'r22n'; +//local +import { H1, H2, Nav, P } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const completeSchemaExamples = +`import { final } from '@stackpress/idea-parser'; + +const schemaCode = \` +plugin "./database-plugin" { + provider "postgresql" + url env("DATABASE_URL") +} + +prop Text { type "text" } +prop Email { type "email" format "email" } + +enum UserRole { + ADMIN "Administrator" + USER "Regular User" + GUEST "Guest User" +} + +type Address { + street String @field.input(Text) @is.required + city String @field.input(Text) @is.required + country String @field.select + postal String @field.input(Text) +} + +model User! { + id String @id @default("nanoid()") + email String @field.input(Email) @is.required @is.unique + name String @field.input(Text) @is.required + role UserRole @default("USER") + address Address? + active Boolean @default(true) + created Date @default("now()") + updated Date @default("updated()") +} +\`; + +const result = final(schemaCode); +console.log(JSON.stringify(result, null, 2));`; + +//--------------------------------------------------------------------// + +const individualComponentsExample = +`import { Compiler, EnumTree, ModelTree } from '@stackpress/idea-parser'; + +// Parse individual enum +const enumCode = \`enum Status { ACTIVE "Active" INACTIVE "Inactive" }\`; +const enumAST = EnumTree.parse(enumCode); +const [enumName, enumConfig] = Compiler.enum(enumAST); + +// Parse individual model +const modelCode = \`model User { id String @id name String }\`; +const modelAST = ModelTree.parse(modelCode); +const [modelName, modelConfig] = Compiler.model(modelAST);`; + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Examples'); + const description = _( + 'Practical examples showing how to use the Idea Parser ' + + 'library for parsing schema files and working with ' + + 'individual components.' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    +

    {_('Examples')}

    +

    + + Explore practical examples demonstrating how to use the + parser library for common tasks such as parsing complete + schema files and working with individual components. + +

    + + {/* Horizontal Rule */} +
    + + {/* Complete Schema Example Section */} +
    +

    {_('Complete Schema Example')}

    + + {completeSchemaExamples} + +
    + + {/* Horizontal Rule */} +
    + + {/* Working with Individual Components Section */} +
    +

    {_('Working with Individual Components')}

    + + {individualComponentsExample} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/parser/installation.tsx b/packages/www/plugins/docs/views/parser/installation.tsx new file mode 100644 index 0000000..2670a54 --- /dev/null +++ b/packages/www/plugins/docs/views/parser/installation.tsx @@ -0,0 +1,196 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'stackpress/view/client'; +//locals +import { H1, H2, P, C, Nav } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const installCommand = `npm install @stackpress/idea-parser`; + +//--------------------------------------------------------------------// + +const usageExample = +`import { parse, final } from '@stackpress/idea-parser'; + +// Parse a schema file into JSON (includes references) +const schemaCode = \` +prop Text { type "text" } +enum Roles { + ADMIN "Admin" + USER "User" +} +model User { + id String @id + name String @field.input(Text) + role Roles +} +\`; + +// Parse with references intact +const parsedSchema = parse(schemaCode); + +// Parse and clean up references (final version) +const finalSchema = final(schemaCode);`; + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Installation'); + const description = _( + 'A TypeScript library for parsing .idea schema files into ' + + 'Abstract Syntax Trees (AST) and converting them to readable ' + + 'JSON configurations. This library is designed to help ' + + 'developers work with schema definitions in a structured and ' + + 'type-safe manner.' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Idea Parser Section Content */} +
    +

    {_('Idea Parser')}

    + + A TypeScript library for parsing .idea schema files into + Abstract Syntax Trees (AST) and converting them to readable + JSON configurations. This library is designed to help + developers work with schema definitions in a structured + and type-safe manner. + +
    + + {/* Horizontal Rule */} +
    + + {/* Installation Section Content */} +
    +

    {_('Installation')}

    +

    + Install the package using npm: +

    + + {installCommand} + +
    + + {/* Horizontal Rule */} +
    + + {/* Quick Start Section Content */} +
    +

    {_('Quick Start')}

    +

    + + The library provides two main functions for parsing schema + files: + +

    + +

    {_('Basic Usage')}

    + + {usageExample} + + +
      +
    • + + Difference between parse and final + +
    • +
    • + parse(code: string): + + Converts schema code to JSON while preserving prop and use + references + +
    • +
    • + final(code: string): + + Like parse but removes prop and use references for a clean + final output + +
    • +
    +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/plugin-development/advanced-tutorials.tsx b/packages/www/plugins/docs/views/plugin-development/advanced-tutorials.tsx new file mode 100644 index 0000000..391e219 --- /dev/null +++ b/packages/www/plugins/docs/views/plugin-development/advanced-tutorials.tsx @@ -0,0 +1,470 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +import clsx from 'clsx'; +//local +import { H1, H2, H3, P, SS, Nav } from '../../components/index.js'; +import Layout from '../../components/Layout.js'; + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx([ + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500', +]); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Advanced Tutorials'); + const description = _( + 'Advanced plugin development topics for developers who need to ' + + 'create sophisticated code generation tools' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + + return ( + +
    + {_('Advanced Tutorials')} +
    + +
    + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Advanced Tutorials Section Content */} +
    +

    {_('Advanced Tutorials')}

    +

    + + This section covers advanced plugin development topics for + developers who need to create sophisticated code generation + tools. These tutorials demonstrate complex patterns and + integration techniques for building enterprise-grade plugins. + +

    +
    + + {/* API Development Plugins Section */} +
    +

    {_('7.1. API Development Plugins')}

    + +

    {_('7.1.1. GraphQL Schema Plugin')}

    +

    + + The + GraphQL Schema Plugin + tutorial teaches you how to create a plugin that + generates GraphQL type definitions and schemas from your + schema. + +

    + +

    {_("What you'll learn:")}

    +
      +
    • + + Generate GraphQL type definitions from models and types + +
    • +
    • + + Create queries, mutations, and subscriptions + +
    • +
    • + + Support for custom scalars and directives + +
    • +
    • + + Handle relationships and nested types + +
    • +
    • + + Generate complete GraphQL schema files + +
    • +
    + +

    + + Generated Output: GraphQL schema files with + type definitions, queries, and mutations + +

    + +

    {_('7.1.2. TypeScript Interface Plugin')}

    +

    + + The + TypeScript Interface Plugin + tutorial demonstrates how to create a plugin that + generates TypeScript interfaces and types from your schema. + +

    + +

    {_("What you'll learn:")}

    +
      +
    • + + Generate TypeScript interfaces from models and types + +
    • +
    • + + Create enums and utility types + +
    • +
    • + + Support for namespaces and modules + +
    • +
    • + + Handle optional and array types + +
    • +
    • + + Generate comprehensive type definitions + +
    • +
    + +

    + + Generated Output: TypeScript definition files + with interfaces, types, and enums + +

    + +

    {_('7.1.3. API Client Plugin')}

    +

    + + The + API Client Plugin + tutorial shows how to create a plugin that generates + API client libraries from your schema. + +

    + +

    {_("What you'll learn:")}

    +
      +
    • + + Generate REST and GraphQL API clients + +
    • +
    • + + Support multiple authentication strategies + +
    • +
    • + + Create type-safe client methods + +
    • +
    • + + Handle request/response transformations + +
    • +
    • + + Generate both JavaScript and TypeScript clients + +
    • +
    + +

    + + Generated Output: Complete API client + libraries with methods and types + +

    +
    + + {/* Validation and Testing Plugins Section */} +
    +

    {_('7.2. Validation and Testing Plugins')}

    +

    + + Validation and testing plugins help ensure data quality and + application reliability by generating validation schemas and + test data. These plugins are essential for building robust + applications that can handle edge cases and maintain data + integrity across different environments. + +

    + +

    {_('7.2.1. Validation Plugin')}

    +

    + + The + Validation Plugin + tutorial teaches you how to create a plugin that + generates Zod validation schemas from your schema. + +

    + +

    {_("What you'll learn:")}

    +
      +
    • + + Generate Zod schemas from models and types + +
    • +
    • + + Create custom validators and transformations + +
    • +
    • + + Handle complex validation rules + +
    • +
    • + + Support for nested object validation + +
    • +
    • + + Generate comprehensive validation suites + +
    • +
    + +

    + + Generated Output: Zod validation schemas with + custom validators + +

    + +

    {_('7.2.2. Test Data Plugin')}

    +

    + + The + Test Data Plugin + tutorial demonstrates how to create a plugin that + generates realistic test data and fixtures from your schema. + +

    + +

    {_("What you'll learn:")}

    +
      +
    • + + Generate realistic mock data using Faker.js + +
    • +
    • + + Create factory functions for dynamic data generation + +
    • +
    • + + Support for relationships and constraints + +
    • +
    • + + Generate test fixtures and seed data + +
    • +
    • + + Handle localization and custom generators + +
    • +
    + +

    + + Generated Output: Test data files, factories, + and fixtures in multiple formats + +

    +
    + + {/* Documentation and Specification Plugins Section */} +
    +

    {_('7.3. Documentation and Specification Plugins')}

    +

    + + The + OpenAPI Specification Plugin + tutorial shows how to create a plugin that generates + OpenAPI 3.0 specifications from your schema. + +

    + +

    {_('What you\'ll learn:')}

    +
      +
    • + + Generate OpenAPI 3.0 compliant specifications + +
    • +
    • + + Create schemas and CRUD endpoints automatically + +
    • +
    • + + Support multiple authentication schemes + +
    • +
    • + + Generate multiple output formats (JSON, YAML, HTML) + +
    • +
    • + + Include validation rules and examples + +
    • +
    + +

    + + Generated Output: Complete OpenAPI + specifications with interactive documentation + +

    +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + } + > + + + ); +} diff --git a/packages/www/plugins/docs/views/plugin-development/available-tutorials.tsx b/packages/www/plugins/docs/views/plugin-development/available-tutorials.tsx new file mode 100644 index 0000000..2904cb7 --- /dev/null +++ b/packages/www/plugins/docs/views/plugin-development/available-tutorials.tsx @@ -0,0 +1,317 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +import clsx from 'clsx'; +//local +import { H1, H2, H3, P, C, Nav, SS } from '../../components/index.js'; +import Layout from '../../components/Layout.js'; + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx([ + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500', +]); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Available Tutorials'); + const description = _( + 'Comprehensive tutorials for creating specific types of plugins ' + + 'with step-by-step instructions and complete code examples' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + + return ( + +
    + {_('Available Tutorials')} +
    + +
    + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Available Tutorials Section Content */} +
    +

    {_('Available Tutorials')}

    +

    + + This section provides links to comprehensive tutorials for + creating specific types of plugins. Each tutorial includes + step-by-step instructions, complete code examples, and + explanations of key concepts for building production-ready + plugins. + +

    + +

    {_('6.1. Meta Coding With TSMorph')}

    +

    + + The + TSMorph Plugin Guide + demonstrates how to create powerful code generation + plugins using ts-morph, a TypeScript library that + provides an easier way to programmatically navigate and + manipulate TypeScript and JavaScript code. This guide is + essential for developers who need to generate complex + TypeScript code with proper syntax and formatting. + +

    +
    + + {/* Database Integration Plugins Section */} +
    +

    {_('6.2. Database Integration Plugins')}

    +

    + + The + MySQL Tables Plugin + tutorial teaches you how to create a plugin that + generates MySQL CREATE TABLE statements from your + schema. + +

    + +

    {_("What you'll learn:")}

    +
      +
    • + + Parse schema models and their columns + +
    • +
    • + + Map schema types to MySQL data types + +
    • +
    • + + Generate SQL DDL statements with constraints + +
    • +
    • + + Handle primary keys, foreign keys, and indexes + +
    • +
    • + + Implement proper error handling and validation + +
    • +
    + +

    + + Generated Output: SQL files that can be + executed to create database tables + +

    +
    + + {/* Frontend Development Plugins Section */} +
    +

    {_('6.3. Frontend Development Plugins')}

    +

    + + The + HTML Form Plugin + tutorial demonstrates how to create a plugin that + generates responsive HTML forms from your schema. + +

    + +

    {_("What you'll learn:")}

    +
      +
    • + + Generate HTML form elements based on field types + +
    • +
    • + + Support multiple CSS frameworks (Bootstrap, Tailwind, + Custom) + +
    • +
    • + + Include client-side validation and constraints + +
    • +
    • + + Handle different form layouts and themes + +
    • +
    • + + Create accessible, responsive forms + +
    • +
    + +

    + + Generated Output: Complete HTML files with + forms, styling, and JavaScript validation + +

    +
    + + {/* Documentation Generation Plugins Section */} +
    +

    {_('6.4. Documentation Generation Plugins')}

    +

    + + The + Markdown Documentation Plugin + tutorial shows how to create a plugin that generates + comprehensive markdown documentation from your schema. + +

    + +

    {_("What you'll learn:")}

    +
      +
    • + + Parse all schema elements (models, types, enums, props) + +
    • +
    • + + Generate structured documentation with navigation + +
    • +
    • + + Include examples and cross-references + +
    • +
    • + + Support multiple documentation formats and templates + +
    • +
    • + + Create both single-file and multi-file documentation + +
    • +
    + +

    + + Generated Output: Markdown documentation + files with complete schema reference + +

    +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + } + > + + + ); +} diff --git a/packages/www/plugins/docs/views/plugin-development/best-practices.tsx b/packages/www/plugins/docs/views/plugin-development/best-practices.tsx new file mode 100644 index 0000000..287fc0c --- /dev/null +++ b/packages/www/plugins/docs/views/plugin-development/best-practices.tsx @@ -0,0 +1,277 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, Nav } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const typeSafetyExample = +`// Always use proper typing for plugin props +import type { + PluginProps, + PluginWithCLIProps +} from '@stackpress/idea-transformer/types'; + +// Define custom config types +interface MyPluginConfig { + output: string; + format: 'typescript' | 'javascript'; + strict?: boolean; +} + +// Use typed props +export default async function typedPlugin( + props: PluginProps<{ config: MyPluginConfig }> +) { + const { config } = props; + + // TypeScript will enforce config structure + const output: string = config.output; // ✅ Type-safe + const format: 'typescript' | 'javascript' = config.format; + // ✅ Type-safe + const strict: boolean = config.strict ?? false; + // ✅ Type-safe with default +}`; + +//--------------------------------------------------------------------// + +const configurationValidationExample = +`function validateConfig( + config: any +): asserts config is MyPluginConfig { + if (!config.output || typeof config.output !== 'string') { + throw new Error( + 'Plugin requires "output" configuration as string' + ); + } + + if ( + !config.format || + !['typescript', 'javascript'].includes(config.format) + ) { + throw new Error( + 'Plugin requires "format" to be "typescript" or ' + + '"javascript"' + ); + } +} + +export default async function validatedPlugin( + props: PluginProps<{}> +) { + validateConfig(props.config); + + // Now config is properly typed + const { output, format } = props.config; +}`; + +//--------------------------------------------------------------------// + +const fileOperationsExample = +`// Use transformer's file loader for consistent path resolution +export default async function filePlugin(props: PluginProps<{}>) { + const { config, transformer } = props; + + // ✅ Use transformer.loader for path resolution + const outputPath = await transformer.loader.absolute( + config.output + ); + + // ✅ Create directories if needed + await fs.mkdir(path.dirname(outputPath), { recursive: true }); + + // ✅ Write file with proper error handling + try { + await fs.writeFile(outputPath, content, 'utf8'); + } catch (error) { + throw new Error( + \`Failed to write output file: \${error.message}\` + ); + } +}`; + +//--------------------------------------------------------------------// + +const cliIntegrationExample = +`// Use CLI props when available +export default async function adaptivePlugin( + props: PluginWithCLIProps +) { + const { cli, config } = props; + + // Adapt behavior based on CLI context + const outputDir = config.outputDir || + path.join(cli.cwd, 'generated'); + const verbose = config.verbose || false; + + if (verbose) { + console.log(\`Generating files in: \${outputDir}\`); + console.log(\`Working directory: \${cli.cwd}\`); + console.log(\`File extension: \${cli.extname}\`); + } + + // Use CLI working directory for relative paths + const absoluteOutputDir = path.resolve(cli.cwd, outputDir); + + // Generate files... +}`; + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Best Practices'); + const description = _( + 'Essential best practices for plugin development covering type ' + + 'safety, configuration validation, file operations, and CLI ' + + 'integration' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Best Practices Section Content */} +
    +

    {_('Best Practices')}

    +

    + + This section outlines essential best practices for plugin + development, covering type safety, configuration validation, + file operations, and CLI integration. Following these practices + ensures that plugins are reliable, maintainable, and provide + excellent developer experiences. + +

    + +

    {_('5.1. Type Safety')}

    +

    + + Type safety is crucial for creating reliable plugins that + catch errors at compile time rather than runtime. This section + demonstrates how to use TypeScript effectively in plugin + development, including proper typing for configuration objects + and plugin properties. + +

    + + + {typeSafetyExample} + +
    + + {/* Configuration Validation Section */} +
    +

    {_('5.2. Configuration Validation')}

    +

    + + Configuration validation ensures that plugins receive valid + configuration options and fail early with clear error messages + when configuration is invalid. This approach prevents runtime + errors and provides better debugging experiences for plugin + users. + +

    + + + {configurationValidationExample} + +
    + + {/* File Operations Section */} +
    +

    {_('5.3. File Operations')}

    +

    + + File operations in plugins should follow consistent patterns + for path resolution, directory creation, and error handling. + This section demonstrates best practices for working with files + and directories in a way that's compatible with the idea + transformer system. + +

    + + + {fileOperationsExample} + +
    + + {/* CLI Integration Section */} +
    +

    {_('5.4. CLI Integration')}

    +

    + + CLI integration enables plugins to provide rich command-line + experiences by adapting behavior based on the execution context. + This section shows how to use CLI properties effectively and + create plugins that work well in both programmatic and + interactive environments. + +

    + + + {cliIntegrationExample} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/plugin-development/error-handling.tsx b/packages/www/plugins/docs/views/plugin-development/error-handling.tsx new file mode 100644 index 0000000..96b447d --- /dev/null +++ b/packages/www/plugins/docs/views/plugin-development/error-handling.tsx @@ -0,0 +1,213 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, Nav } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const pluginErrorHandlingExample = +`import type { PluginProps } from '@stackpress/idea-transformer/types'; + +export default async function safePlugin(props: PluginProps<{}>) { + const { config, schema, transformer } = props; + + try { + // Validate required configuration + if (!config.output) { + throw new Error( + 'Missing required "output" configuration' + ); + } + + // Validate schema has required elements + if ( + !schema.model || + Object.keys(schema.model).length === 0 + ) { + throw new Error( + 'Schema must contain at least one model' + ); + } + + // Process schema + const content = await processSchema(schema); + + // Write output + const outputPath = await transformer.loader.absolute( + config.output + ); + await writeOutput(outputPath, content); + + console.log( + \`✅ Plugin completed successfully: \${outputPath}\` + ); + + } catch (error) { + console.error(\`❌ Plugin failed:\`, error.message); + throw error; // Re-throw to stop transformation + } +}`; + +//--------------------------------------------------------------------// + +const gracefulErrorRecoveryExample = +`export default async function resilientPlugin( + props: PluginProps<{}> +) { + const { config, schema, transformer } = props; + + const warnings: string[] = []; + + try { + // Attempt primary functionality + await primaryGeneration(schema, config); + } catch (error) { + warnings.push( + \`Primary generation failed: \${error.message}\` + ); + + // Fallback to basic generation + try { + await fallbackGeneration(schema, config); + warnings.push('Used fallback generation'); + } catch (fallbackError) { + throw new Error( + \`Both primary and fallback generation failed: \` + + \`\${fallbackError.message}\` + ); + } + } + + // Report warnings + if (warnings.length > 0) { + console.warn('Plugin completed with warnings:'); + warnings.forEach(warning => + console.warn(\` ⚠️ \${warning}\`) + ); + } +}`; + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Error Handling'); + const description = _( + 'Proper error handling is essential for creating robust plugins ' + + 'that provide clear feedback when issues occur' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Error Handling Section Content */} +
    +

    {_('Error Handling')}

    +

    + + Proper error handling is essential for creating robust plugins + that provide clear feedback when issues occur. This section + covers error handling strategies, validation patterns, and + techniques for graceful failure recovery in plugin development. + +

    +
    + + {/* Plugin Error Handling Section */} +
    +

    {_('4.1. Plugin Error Handling')}

    +

    + + Plugin error handling demonstrates how to implement + comprehensive error checking and reporting in plugins. This + approach ensures that plugins fail gracefully with meaningful + error messages, helping users quickly identify and resolve + configuration or schema issues. + +

    + + + {pluginErrorHandlingExample} + +
    + + {/* Graceful Error Recovery Section */} +
    +

    {_('4.2. Graceful Error Recovery')}

    +

    + + Graceful error recovery shows how plugins can implement + fallback mechanisms and continue operation even when primary + functionality fails. This approach improves plugin reliability + and provides better user experiences by attempting alternative + approaches when errors occur. + +

    + + + {gracefulErrorRecoveryExample} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/plugin-development/getting-started.tsx b/packages/www/plugins/docs/views/plugin-development/getting-started.tsx new file mode 100644 index 0000000..6938492 --- /dev/null +++ b/packages/www/plugins/docs/views/plugin-development/getting-started.tsx @@ -0,0 +1,633 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, H3, C, Nav, SS } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const commonPluginStructureExample = +`import type { PluginProps } from '@stackpress/idea-transformer/types'; +import fs from 'fs/promises'; +import path from 'path'; + +interface MyPluginConfig { + output: string; + // ... other configuration options +} + +export default async function myPlugin( + props: PluginProps<{ config: MyPluginConfig }> +) { + const { config, schema, transformer, cwd } = props; + + // 1. Validate configuration + if (!config.output) { + throw new Error('Plugin requires "output" configuration'); + } + + // 2. Process schema + const content = processSchema(schema); + + // 3. Write output + const outputPath = await transformer.loader.absolute( + config.output + ); + await fs.mkdir(path.dirname(outputPath), { recursive: true }); + await fs.writeFile(outputPath, content, 'utf8'); + + console.log(\`✅ Generated: \${outputPath}\`); +}`; + +//--------------------------------------------------------------------// + +const schemaStructureExample = +`{ + model: { + [modelName]: { + mutable: boolean, + columns: [ + { + name: string, + type: string, + required: boolean, + multiple: boolean, + attributes: object + } + ] + } + }, + enum: { + [enumName]: { + [key]: value + } + }, + type: { + [typeName]: { + mutable: boolean, + columns: [...] + } + }, + prop: { + [propName]: { + // Property configuration + } + } +}`; + +//--------------------------------------------------------------------// + +const typeSafetyExample = +`import type { PluginProps } from '@stackpress/idea-transformer/types'; + +interface MyPluginConfig { + output: string; + format?: 'json' | 'yaml'; +} + +export default async function myPlugin( + props: PluginProps<{ config: MyPluginConfig }> +) { + // TypeScript will enforce the config structure +}`; + +//--------------------------------------------------------------------// + +const configurationValidationExample = + `function validateConfig(config: any): void { + if (!config.output) { + throw new Error('Plugin requires "output" configuration'); + } + + if (config.format && !['json', 'yaml'].includes(config.format)) { + throw new Error( + \`Unsupported format: \${config.format}\` + ); + } +}`; + +//--------------------------------------------------------------------// + +const fileOperationsExample = +`// ✅ Good - uses transformer's file loader +const outputPath = await transformer.loader.absolute( + config.output +); + +// ✅ Good - creates directories if needed +await fs.mkdir(path.dirname(outputPath), { recursive: true }); + +// ✅ Good - proper error handling +try { + await fs.writeFile(outputPath, content, 'utf8'); +} catch (error) { + throw new Error( + \`Failed to write file: \${error.message}\` + ); +}`; + +//--------------------------------------------------------------------// + +const errorHandlingExample = +`export default async function myPlugin(props: PluginProps<{}>) { + try { + // Validate configuration + validateConfig(props.config); + + // Check for required schema elements + if ( + !props.schema.model || + Object.keys(props.schema.model).length === 0 + ) { + console.warn( + '⚠️ No models found in schema. Skipping generation.' + ); + return; + } + + // Process and generate + // ... + + console.log('✅ Plugin completed successfully'); + + } catch (error) { + console.error(\`❌ Plugin failed: \${error.message}\`); + throw error; + } +}`; + +//--------------------------------------------------------------------// + +const schemaProcessingExample = + `// ✅ Good - checks for existence before processing +if (schema.model) { + for (const [modelName, model] of Object.entries( + schema.model + )) { + // Process model + } +} + +// ✅ Good - provides defaults for optional attributes +const attributes = column.attributes || {}; +const label = attributes.label || column.name; +const description = attributes.description || '';`; + +//--------------------------------------------------------------------// + +const usageInSchemaFilesExample = +`// schema.idea +plugin "./plugins/mysql-tables-plugin.js" { + output "./database/tables.sql" + database "my_app" + engine "InnoDB" +} + +plugin "./plugins/html-form-plugin.js" { + output "./forms/user-form.html" + title "User Registration" + theme "bootstrap" +} + +plugin "./plugins/markdown-docs-plugin.js" { + output "./docs/schema.md" + title "API Documentation" + format "single" + includeExamples true +} + +model User { + id String @id @default("nanoid()") + email String @unique @field.input(Email) + name String @field.input(Text) + role UserRole @default("USER") + active Boolean @default(true) + created Date @default("now()") +} + +enum UserRole { + ADMIN "Administrator" + USER "Regular User" +}`; + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Getting Started'); + const description = _( + 'Essential information for developers who are new to plugin ' + + 'development with prerequisites, basic concepts, and step-by-step ' + + 'guidance' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Getting Started Section Content */} +
    +

    {_('Getting Started')}

    + + This section provides essential information for developers who + are new to plugin development. It covers prerequisites, basic + concepts, and step-by-step guidance for creating your first + plugin. + +
    + + {/* Prerequisites Section */} +
    +

    {_('8.1. Prerequisites')}

    + + Before starting plugin development, ensure you have the + necessary knowledge and tools. These prerequisites will help + you understand the examples and successfully implement your + own plugins. + + + + Before starting these tutorials, make sure you have: + + +
      +
    • + + Basic understanding of TypeScript/JavaScript + +
    • +
    • + + Familiarity with the idea-transformer plugin system + +
    • +
    • + + Understanding of the target technology + (MySQL, HTML/CSS, Markdown) + +
    • +
    +
    + + {/* Plugin Development Basics Section */} +
    +

    {_('8.2. Plugin Development Basics')}

    + + Plugin development follows consistent patterns that make it + easy to create new plugins once you understand the core + concepts. This section outlines the fundamental steps and + patterns used across all plugin types. + + + + All plugins in the idea-transformer system follow a + similar pattern: + + +
      +
    1. + + Import Types: Use the provided TypeScript + types for type safety + +
    2. +
    3. + + Define Configuration: Specify what + configuration options your plugin accepts + +
    4. +
    5. + + Validate Input: Check that required + configuration is provided + +
    6. +
    7. + + Process Schema: Parse the schema and + extract relevant information + +
    8. +
    9. + + Generate Output: Create the target files + or content + +
    10. +
    11. + + Handle Errors: Provide meaningful error + messages and graceful failure + +
    12. +
    +
    + + {/* Common Plugin Structure Section */} +
    +

    {_('8.3. Common Plugin Structure')}

    + + The common plugin structure provides a template that can be + adapted for any type of code generation. This structure + ensures consistency across plugins and includes all essential + components for robust plugin development. + + + + {commonPluginStructureExample} + +
    + + {/* Schema Structure Section */} +
    +

    {_('8.4. Schema Structure')}

    + + Understanding the schema structure is crucial for plugin + development. The processed schema provides a standardized + format that plugins can rely on, regardless of the original + .idea file structure. + + + + All plugins receive a processed schema with this structure: + + + + {schemaStructureExample} + +
    + + {/* Implementation Guidelines Section */} +
    +

    {_('8.5. Implementation Guidelines')}

    + + These implementation guidelines help ensure that your plugins + are reliable, maintainable, and follow established patterns. + Following these guidelines will make your plugins easier to + debug and extend. + + +
    +

    {_('8.5.1. Type Safety')}

    + + Type safety prevents runtime errors and provides better + development experiences through IDE support and compile-time + error checking. + + + + Always use the provided TypeScript types: + + + + {typeSafetyExample} + +
    + +
    +

    {_('8.5.2. Configuration Validation')}

    + + Configuration validation ensures that plugins receive valid + input and fail early with clear error messages when + configuration is incorrect. + + + + Validate all required configuration upfront: + + + + {configurationValidationExample} + +
    + +
    +

    {_('8.5.3. File Operations')}

    + + File operations should follow consistent patterns for path + resolution, directory creation, and error handling to ensure + compatibility with the idea transformer system. + + + + Use the transformer's file loader for consistent path + resolution: + + + + {fileOperationsExample} + +
    + +
    +

    {_('8.5.4. Error Handling')}

    + + Comprehensive error handling provides better user experiences + and makes plugins more reliable in production environments. + + + + Provide meaningful error messages and handle edge cases: + + + + {errorHandlingExample} + +
    + +
    +

    {_('8.5.5. Schema Processing')}

    + + Schema processing should handle optional elements gracefully + and provide meaningful defaults to ensure plugins work with + various schema configurations. + + + + Handle optional schema elements gracefully: + + + + {schemaProcessingExample} + +
    +
    + + {/* Usage in Schema Files Section */} +
    +

    {_('8.6. Usage in Schema Files')}

    + + This section demonstrates how to use plugins within + .idea schema files, showing the declarative syntax + for plugin configuration and how multiple plugins can work + together to generate comprehensive outputs. + + + + To use any of these plugins in your schema file: + + + + {usageInSchemaFilesExample} + +
    + + {/* Next Steps Section */} +
    +

    {_('8.7. Next Steps')}

    + + After completing the getting started section, you'll be ready + to dive into specific tutorials and start building your own + plugins. These next steps will guide you toward becoming + proficient in plugin development. + + +
      +
    1. + + Choose a Tutorial: Start with the tutorial + that matches your immediate needs + +
    2. +
    3. + + Follow Along: Each tutorial provides + step-by-step instructions with complete code examples + +
    4. +
    5. + + Customize: Adapt the examples to your + specific requirements + +
    6. +
    7. + + Extend: Use the patterns learned to + create your own custom plugins + +
    8. +
    +
    + + {/* Additional Plugin Ideas Section */} +
    +

    {_('8.8. Additional Plugin Ideas')}

    + + Beyond the provided tutorials, there are many other types of + plugins you can create using the patterns and techniques + covered in this documentation: + + +
      +
    • + + Database Migration Generator: Create + migration files for various databases + +
    • +
    • + + Form Validation Generator: Generate + client-side validation rules + +
    • +
    • + + Mock Server Generator: Create mock API + servers for testing + +
    • +
    • + + Documentation Site Generator: Build + complete documentation websites + +
    • +
    • + + Configuration File Generator: Generate + app configuration files + +
    • +
    • + + Seed Data Generator: Create database + seed scripts + +
    • +
    • + + API Test Generator: Generate automated + API test suites + +
    • +
    + + + Happy coding! 🚀 + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/plugin-development/plugin-configuration.tsx b/packages/www/plugins/docs/views/plugin-development/plugin-configuration.tsx new file mode 100644 index 0000000..e81a52f --- /dev/null +++ b/packages/www/plugins/docs/views/plugin-development/plugin-configuration.tsx @@ -0,0 +1,168 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, Nav } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const schemaPluginDefinitionExample = +`// schema.idea +plugin "./plugins/my-plugin.js" { + output "./generated/output.ts" + format "typescript" + options { + strict true + comments true + } +}`; + +//--------------------------------------------------------------------// + +const pluginConfigurationAccessExample = +`export default async function myPlugin(props: PluginProps<{}>) { + const { config } = props; + + // Access top-level config + const output = config.output; + const format = config.format; + + // Access nested options + const options = config.options || {}; + const strict = options.strict || false; + const comments = options.comments || false; + + // Use configuration in plugin logic + if (strict) { + // Enable strict mode + } + + if (comments) { + // Add comments to generated code + } +}`; + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Plugin Configuration'); + const description = _( + 'Plugin configuration enables developers to customize plugin ' + + 'behavior through schema declarations' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Plugin Configuration Section Content */} +
    +

    {_('Plugin Configuration')}

    +

    + + Plugin configuration enables developers to customize plugin + behavior through schema declarations. This section covers + how to define configuration options in schema files, access + configuration within plugins, and implement flexible plugin + behavior based on user preferences. + +

    +
    + + {/* Schema Plugin Definition Section */} +
    +

    {_('3.1. Schema Plugin Definition')}

    +

    + + Schema plugin definitions specify how plugins are declared + and configured within .idea schema files. This declarative + approach allows users to configure multiple plugins with + different settings while maintaining clean, readable schema + files. + +

    + + + {schemaPluginDefinitionExample} + +
    + + {/* Plugin Configuration Access Section */} +
    +

    {_('3.2. Plugin Configuration Access')}

    +

    + + Plugin configuration access demonstrates how plugins can + read and utilize configuration options provided in schema + files. This section shows how to access both simple and + nested configuration values, provide defaults, and implement + conditional behavior based on configuration settings. + +

    + + + {pluginConfigurationAccessExample} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/plugin-development/plugin-development-guide.tsx b/packages/www/plugins/docs/views/plugin-development/plugin-development-guide.tsx new file mode 100644 index 0000000..f807b2f --- /dev/null +++ b/packages/www/plugins/docs/views/plugin-development/plugin-development-guide.tsx @@ -0,0 +1,394 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, H3, P, C, Nav } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; +import { Table, Thead, Trow, Tcol } from 'frui/element/Table'; + +//code examples +//--------------------------------------------------------------------// + +const basicPluginExample = + `import type { PluginWithCLIProps } from '@stackpress/idea'; + +export default function generate(props: PluginWithCLIProps) {}`; + +//--------------------------------------------------------------------// + +const basicPluginStructureExample = +`import type { PluginProps } from '@stackpress/idea-transformer/types'; +import fs from 'fs/promises'; +import path from 'path'; + +export default async function myPlugin(props: PluginProps<{}>) { + const { config, schema, transformer, cwd } = props; + + // 1. Validate configuration + if (!config.output) { + throw new Error('Plugin requires "output" configuration'); + } + + // 2. Process schema + const content = processSchema(schema); + + // 3. Resolve output path + const outputPath = await transformer.loader.absolute(config.output); + + // 4. Write output + await fs.writeFile(outputPath, content, 'utf8'); +} + +function processSchema(schema: SchemaConfig): string { + // Implementation for processing schema + return '// Generated content'; +}`; + +//--------------------------------------------------------------------// + +const cliPluginExample = +`import type { PluginWithCLIProps } from '@stackpress/idea-transformer/types'; +import fs from 'fs/promises'; + +export default async function cliPlugin(props: PluginWithCLIProps) { + const { config, schema, transformer, cwd, cli } = props; + + // Access CLI properties + const workingDir = cli.cwd; + const fileExtension = cli.extname; + + // Use CLI for logging or user interaction + console.log(\`Processing schema in: \${workingDir}\`); + + // Process based on CLI context + if (config.interactive) { + // Interactive mode logic + console.log('Running in interactive mode...'); + } + + // Generate output + const content = generateContent(schema, { workingDir, fileExtension }); + + // Write to file + const outputPath = path.resolve(workingDir, config.output); + await fs.writeFile(outputPath, content, 'utf8'); + + console.log(\`Generated: \${outputPath}\`); +}`; + +//--------------------------------------------------------------------// + +const customPluginPropsExample = +`import type { PluginProps } from '@stackpress/idea-transformer/types'; + +// Define custom props +interface CustomProps { + timestamp: string; + version: string; + debug: boolean; +} + +// Use custom props in plugin +export default async function customPlugin(props: PluginProps) { + const { config, schema, transformer, cwd, timestamp, version, debug } = props; + + if (debug) { + console.log(\`Plugin executed at \${timestamp} for version \${version}\`); + } + + // Plugin implementation +} + +// Usage with transformer +const transformer = await Transformer.load('./schema.idea'); +await transformer.transform({ + timestamp: new Date().toISOString(), + version: '1.0.0', + debug: true +});`; + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Plugin Development Guide'); + const description = _( + 'Comprehensive guide covering everything from basic plugin' + + ' structure to advanced development patterns for the idea ecosystem' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Idea Plugins Section Content */} +
    +

    {_('Idea Plugins')}

    +

    + + The following documentation explains how to develop plugins + for .idea files. This comprehensive guide covers everything + from basic plugin structure to advanced development patterns, + providing developers with the knowledge needed to create + powerful code generation plugins for the idea ecosystem. + +

    +
    + + {/* Horizontal Rule */} +
    + + {/* Plugin Development Guide Section Content */} +
    +

    {_('1. Plugin Development Guide')}

    +

    + + This section covers the fundamental concepts and structures + needed to create effective plugins for the idea ecosystem. + Plugins are JavaScript or TypeScript modules that process + schema definitions and generate various outputs like code, + documentation, or configuration files. + +

    + +

    + + Creating a plugin involves just exporting a function like the + example below: + +

    + + + {basicPluginExample} + +
    + + {/* Basic Plugin Structure Section */} +
    +

    {_('1.1. Basic Plugin Structure')}

    +

    + + The basic plugin structure provides the foundation for all + idea plugins. This structure ensures consistency across + plugins and provides access to essential functionality like + schema processing, file operations, and configuration + management. + +

    + + + {basicPluginStructureExample} + + +

    {_('Properties')}

    +

    + + The PluginProps contains the following properties. + +

    + + + + Property + Type + Description + + + config + PluginConfig + + + Plugin-specific configuration from the schema + + + + + schema + SchemaConfig + + + Complete processed schema configuration + + + + + transformer + Transformer<{}> + + + The transformer instance executing the plugin + + + + + cwd + string + + + Current working directory for file operations + + + +
    +
    + + {/* CLI-Aware Plugin Structure */} +
    +

    {_('1.2. CLI-Aware Plugin Structure')}

    +

    + + CLI-aware plugins extend the basic plugin structure to + include command-line interface capabilities. These plugins + can interact with the terminal, access CLI-specific + properties, and provide enhanced user experiences through + interactive features and detailed logging. + +

    + + + {cliPluginExample} + + +

    {_('Properties')}

    +

    + + The PluginWithCLIProps contains the following properties. + +

    + + + + Property + Type + Description + + + config + PluginConfig + + + Plugin-specific configuration from the schema + + + + + schema + SchemaConfig + + + Complete processed schema configuration + + + + + transformer + Transformer<{}> + + + The transformer instance executing the plugin + + + + + cwd + string + + + Current working directory for file operations + + + + + cli + Terminal + + + Terminal instance for CLI interactions + + + +
    +
    + + {/* Custom Plugin Props */} +
    +

    {_('1.3. Custom Plugin Props')}

    +

    + + Custom plugin props allow developers to extend the base + plugin functionality with additional properties and + configuration options. This feature enables plugins to + receive custom data, maintain state, and implement + specialized behaviors beyond the standard plugin interface. + +

    + +

    + + You can extend the base plugin props with custom properties: + +

    + + + {customPluginPropsExample} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/plugin-development/plugin-examples.tsx b/packages/www/plugins/docs/views/plugin-development/plugin-examples.tsx new file mode 100644 index 0000000..65e0b42 --- /dev/null +++ b/packages/www/plugins/docs/views/plugin-development/plugin-examples.tsx @@ -0,0 +1,318 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, Nav } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const typescriptInterfaceGeneratorExample = +`import type { PluginProps } from '@stackpress/idea-transformer/types'; +import fs from 'fs/promises'; +import path from 'path'; + +interface TypeGenConfig { + output: string; + namespace?: string; + exportType?: 'named' | 'default'; +} + +export default async function generateInterfaces( + props: PluginProps<{ config: TypeGenConfig }> +) { + const { config, schema, transformer, cwd } = props; + + let content = ''; + + // Add namespace if specified + if (config.namespace) { + content += \`export namespace \${config.namespace} {\\n\`; + } + + // Generate interfaces from models + if (schema.model) { + for (const [name, model] of Object.entries(schema.model)) { + content += generateInterface(name, model); + } + } + + // Generate types from type definitions + if (schema.type) { + for (const [name, type] of Object.entries(schema.type)) { + content += generateType(name, type); + } + } + + // Close namespace + if (config.namespace) { + content += '}\\n'; + } + + // Write to output file + const outputPath = await transformer.loader.absolute(config.output); + await fs.writeFile(outputPath, content, 'utf8'); +} + +function generateInterface(name: string, model: any): string { + let content = \`export interface \${name} {\\n\`; + + for (const column of model.columns || []) { + const optional = column.required ? '' : '?'; + const type = mapToTypeScript(column.type); + content += \` \${column.name}\${optional}: \${type};\\n\`; + } + + content += '}\\n\\n'; + return content; +} + +function generateType(name: string, type: any): string { + // Implementation for generating TypeScript types + return \`export type \${name} = any; // TODO: Implement\\n\\n\`; +} + +function mapToTypeScript(schemaType: string): string { + const typeMap: Record = { + 'String': 'string', + 'Number': 'number', + 'Boolean': 'boolean', + 'Date': 'Date', + 'JSON': 'any' + }; + + return typeMap[schemaType] || 'any'; +}`; + +//--------------------------------------------------------------------// + +const enumGeneratorExample = + `import type { PluginProps } from '@stackpress/idea-transformer/types'; +import fs from 'fs/promises'; + +export default async function generateEnums(props: PluginProps<{}>) { + const { config, schema, transformer } = props; + + if (!schema.enum) { + console.log('No enums found in schema'); + return; + } + + let content = '// Generated Enums\\n\\n'; + + for (const [name, enumDef] of Object.entries(schema.enum)) { + content += \`export enum \${name} {\\n\`; + + for (const [key, value] of Object.entries(enumDef)) { + content += \` \${key} = "\${value}",\\n\`; + } + + content += '}\\n\\n'; + } + + const outputPath = await transformer.loader.absolute(config.output); + await fs.writeFile(outputPath, content, 'utf8'); + + console.log(\`Generated enums: \${outputPath}\`); +}`; + +//--------------------------------------------------------------------// + +const cliInteractivePluginExample = +`import type { PluginWithCLIProps } from '@stackpress/idea-transformer/types'; +import fs from 'fs/promises'; +import path from 'path'; + +export default async function interactiveGenerator(props: PluginWithCLIProps) { + const { config, schema, transformer, cli } = props; + + // Use CLI for interactive prompts + console.log(\`\\n🚀 Interactive Generator\`); + console.log(\`Working Directory: \${cli.cwd}\`); + console.log(\`Schema Extension: \${cli.extname}\`); + + // Process based on available schema elements + const hasModels = schema.model && Object.keys(schema.model).length > 0; + const hasEnums = schema.enum && Object.keys(schema.enum).length > 0; + const hasTypes = schema.type && Object.keys(schema.type).length > 0; + + console.log(\`\\n📊 Schema Summary:\`); + console.log(\` Models: \${hasModels ? Object.keys(schema.model!).length : 0}\`); + console.log(\` Enums: \${hasEnums ? Object.keys(schema.enum!).length : 0}\`); + console.log(\` Types: \${hasTypes ? Object.keys(schema.type!).length : 0}\`); + + // Generate based on configuration + const outputs: string[] = []; + + if (config.generateModels && hasModels) { + const modelContent = generateModels(schema.model!); + const modelPath = path.resolve(cli.cwd, 'generated/models.ts'); + await fs.mkdir(path.dirname(modelPath), { recursive: true }); + await fs.writeFile(modelPath, modelContent, 'utf8'); + outputs.push(modelPath); + } + + if (config.generateEnums && hasEnums) { + const enumContent = generateEnums(schema.enum!); + const enumPath = path.resolve(cli.cwd, 'generated/enums.ts'); + await fs.mkdir(path.dirname(enumPath), { recursive: true }); + await fs.writeFile(enumPath, enumContent, 'utf8'); + outputs.push(enumPath); + } + + // Report results + console.log(\`\\n✅ Generated \${outputs.length} files:\`); + outputs.forEach(file => console.log(\` 📄 \${file}\`)); +} + +function generateModels(models: Record): string { + // Implementation for generating models + return '// Generated models\\n'; +} + +function generateEnums(enums: Record): string { + // Implementation for generating enums + return '// Generated enums\\n'; +}`; + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Plugin Examples'); + const description = _( + 'Practical examples of common plugin implementations ' + + 'demonstrating real-world patterns and best practices' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Plugin Examples Section Content */} +
    +

    {_('Plugin Examples')}

    +

    + + This section provides practical examples of common plugin + implementations. These examples demonstrate real-world + patterns and best practices for creating plugins that + generate TypeScript interfaces, enums, and interactive + CLI tools. + +

    +
    + + {/* TypeScript Interface Generator Section Content */} +
    +

    {_('2.1. TypeScript Interface Generator')}

    +

    + + The TypeScript interface generator demonstrates how to + create a plugin that processes schema models and types to + generate TypeScript interface definitions. This example + shows how to handle type mapping, optional properties, and + namespace organization. + +

    + + + {typescriptInterfaceGeneratorExample} + +
    + + {/* Enum Generator Section Content */} +
    +

    {_('2.2. Enum Generator')}

    +

    + + The enum generator plugin shows how to process schema enum + definitions and convert them into TypeScript enum + declarations. This example demonstrates simple schema + processing and file generation patterns that can be adapted + for other output formats. + +

    + + + {enumGeneratorExample} + +
    + + {/* CLI-Interactive Plugin Section Content */} +
    +

    {_('2.3. CLI-Interactive Plugin')}

    +

    + + The CLI-interactive plugin demonstrates how to create + plugins that provide rich command-line experiences. This + example shows how to use the CLI properties for user + interaction, progress reporting, and adaptive behavior + based on the execution context. + +

    + + + {cliInteractivePluginExample} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/specifications/best-practices.tsx b/packages/www/plugins/docs/views/specifications/best-practices.tsx new file mode 100644 index 0000000..d04076d --- /dev/null +++ b/packages/www/plugins/docs/views/specifications/best-practices.tsx @@ -0,0 +1,375 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, Nav } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const bestPractices = [` +// ✅ Good +enum UserAccountStatus { + ACTIVE "Active Account" + SUSPENDED "Temporarily Suspended" + DEACTIVATED "Permanently Deactivated" +} + +// ❌ Avoid +enum Status { + A "Active" + S "Suspended" + D "Deactivated" +}`, + + //------------------------------------------------------------------// + + `// User-related enums +enum UserRole { /* ... */ } +enum UserStatus { /* ... */ } + +// User-related types +type UserProfile { /* ... */ } +type UserPreferences { /* ... */ } + +// User-related models +model User { /* ... */ } +model UserSession { /* ... */ }`, + `// Models: PascalCase +model UserAccount { /* ... */ } + +// Enums: PascalCase +enum OrderStatus { /* ... */ } + +// Props: PascalCase +prop EmailInput { /* ... */ } + +// Columns: camelCase +model User { + firstName String + lastName String + emailAddress String +}`, + + //------------------------------------------------------------------// + + `type Money { + amount Number @required @min(0) + currency String @default("USD") +} + +type Coordinates { + latitude Number @required @min(-90) @max(90) + longitude Number @required @min(-180) @max(180) +} + +model Product { + price Money @required + location Coordinates? +}`, + + //------------------------------------------------------------------// + + `// ✅ Good - type-safe and self-documenting +enum Priority { + LOW "Low Priority" + MEDIUM "Medium Priority" + HIGH "High Priority" + URGENT "Urgent" +} + +model Task { + priority Priority @default("MEDIUM") +} + +// ❌ Avoid - error-prone and unclear +model Task { + priority String @default("medium") +}`, + + //------------------------------------------------------------------// + + `model User { + email String @required @unique @pattern("^[^\s@]+@[^\s@]+\.[^\s@]+$") + age Number @min(13) @max(120) + username String @required @minLength(3) @maxLength(30) @pattern("^[a-zA-Z0-9_]+$") + bio String @maxLength(500) + tags String[] @maxItems(10) +}`, + + //------------------------------------------------------------------// + + `model User { + role UserRole @default("USER") + active Boolean @default(true) + emailVerified Boolean @default(false) + created Date @default("now()") + updated Date @default("updated()") + preferences { + theme String @default("light") + language String @default("en") + notifications Boolean @default(true) + } +}`, + + //------------------------------------------------------------------// + + `// One-to-many relationship +model User { + id String @id + posts Post[] @relation(Post.authorId) +} + +model Post { + id String @id + authorId String @relation(User.id) + author User @relation(User, authorId) +} + +// Many-to-many relationship +model Post { + id String @id + tags Tag[] @relation(PostTag.postId) +} + +model Tag { + id String @id + posts Post[] @relation(PostTag.tagId) +} + +model PostTag { + postId String @relation(Post.id) + tagId String @relation(Tag.id) +}`, + + //------------------------------------------------------------------// + + `// Type generation +plugin "./plugins/typescript-generator.js" { + output "./src/types/schema.ts" + namespace "Schema" +} + +// Database schema +plugin "./plugins/database-generator.js" { + output "./database/schema.sql" + dialect "postgresql" +} + +// API documentation +plugin "./plugins/openapi-generator.js" { + output "./docs/api.yaml" + version "1.0.0" +} + +// Form generation +plugin "./plugins/form-generator.js" { + output "./src/components/forms/" + framework "react" + styling "tailwind" +}` +]; + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Best Practices'); + const description = _( + 'Best practices for using the .idea file format to generate ' + + 'various outputs like TypeScript interfaces, database schemas, ' + + 'API documentation, and more.' + ); + return ( + <> + {title} + + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( + <> +
    +

    {_('Best Practices')}

    + + {/* Schema Organization Content */} +
    +

    {_('1. Schema Organization')}

    +

    + Use Descriptive Names +

    + + {bestPractices[0]} + + +

    + Group Related Elements +

    + + {bestPractices[1]} + + +

    + Use Consistent Naming Conventions +

    + + {bestPractices[2]} + +
    + + {/* Type Safety Content */} +
    +

    {_('2. Type Safety')}

    +

    + Define Custom Types for Complex Data +

    + + {bestPractices[3]} + + +

    + Use Enums for Fixed Sets of Values +

    + + {bestPractices[4]} + +
    + + {/* Validation and Constraints Content */} +
    +

    {_('3. Validation and Constraints')}

    +

    + Use Appropriate Validation Attributes +

    + + {bestPractices[5]} + + +

    + Provide Meaningful Defaults +

    + + {bestPractices[6]} + +
    + + {/* Relationships Content */} +
    +

    {_('4. Relationships')}

    +

    + Use Clear Relationship Patterns +

    + + {bestPractices[7]} + +
    + + {/* Plugin Configuration Content */} +
    +

    {_('5. Plugin Configuration')}

    +

    + Organize Plugins by Purpose +

    + + {bestPractices[8]} + +
    + + {/* Page Navigation */} +
    + + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/specifications/complete-examples.tsx b/packages/www/plugins/docs/views/specifications/complete-examples.tsx new file mode 100644 index 0000000..68cbd2a --- /dev/null +++ b/packages/www/plugins/docs/views/specifications/complete-examples.tsx @@ -0,0 +1,414 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage } from 'r22n'; +//local +import { H1, H2, Nav } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const ecommerceSchema = + `// E-commerce application schema +plugin "./plugins/generate-types.js" { + output "./src/types/schema.ts" +} + +plugin "./plugins/generate-database.js" { + output "./database/schema.sql" + dialect "postgresql" +} + +plugin "./plugins/generate-api-docs.js" { + output "./docs/api.yaml" + format "openapi" +} + +// Reusable props +prop Email { + type "email" + validation { + required true + format "email" + } + ui { + placeholder "Enter email address" + icon "envelope" + } +} + +prop Currency { + type "number" + format "currency" + validation { + min 0 + precision 2 + } + ui { + symbol "$" + locale "en-US" + } +} + +prop Text { + type "text" + validation { + maxLength 255 + } +} + +// Enums +enum UserRole { + ADMIN "Administrator" + CUSTOMER "Customer" + VENDOR "Vendor" +} + +enum OrderStatus { + PENDING "Pending" + CONFIRMED "Confirmed" + SHIPPED "Shipped" + DELIVERED "Delivered" + CANCELLED "Cancelled" +} + +enum PaymentStatus { + PENDING "Pending" + COMPLETED "Completed" + FAILED "Failed" + REFUNDED "Refunded" +} + +// Types +type Address { + street String @required @field.input(Text) + city String @required @field.input(Text) + state String @required @field.select + postalCode String @required @field.input(Text) + country String @default("US") @field.select +} + +type Money { + amount Number @required @field.input(Currency) + currency String @default("USD") +} + +// Models +model User! { + id String @id @default("nanoid()") + email String @unique @required @field.input(Email) + username String @unique @required @field.input(Text) + firstName String @required @field.input(Text) + lastName String @required @field.input(Text) + role UserRole @default("CUSTOMER") + addresses Address[] @relation(UserAddress.userId) + orders Order[] @relation(Order.userId) + active Boolean @default(true) + emailVerified Boolean @default(false) + created Date @default("now()") + updated Date @default("updated()") +} + +model Category { + id String @id @default("nanoid()") + name String @unique @required @field.input(Text) + slug String @unique @generated + description String @field.textarea + parentId String? @relation(Category.id) + parent Category? @relation(Category, parentId) + children Category[] @relation(Category.parentId) + products Product[] @relation(Product.categoryId) + active Boolean @default(true) + created Date @default("now()") +} + +model Product! { + id String @id @default("nanoid()") + name String @required @field.input(Text) + slug String @unique @generated + description String @field.richtext + shortDescription String @field.textarea + sku String @unique @required @field.input(Text) + price Money @required + comparePrice Money? + cost Money? + categoryId String @relation(Category.id) + category Category @relation(Category, categoryId) + images String[] @field.upload + inventory { + quantity Number @default(0) + trackQuantity Boolean @default(true) + allowBackorder Boolean @default(false) + } + seo { + title String @field.input(Text) + description String @field.textarea + keywords String[] @field.tags + } + active Boolean @default(true) + featured Boolean @default(false) + created Date @default("now()") + updated Date @default("updated()") +} + +model Order { + id String @id @default("nanoid()") + orderNumber String @unique @generated + userId String @relation(User.id) + user User @relation(User, userId) + items OrderItem[] @relation(OrderItem.orderId) + status OrderStatus @default("PENDING") + paymentStatus PaymentStatus @default("PENDING") + shippingAddress Address @required + billingAddress Address @required + subtotal Money @required + tax Money @required + shipping Money @required + total Money @required + notes String? @field.textarea + created Date @default("now()") + updated Date @default("updated()") +} + +model OrderItem { + id String @id @default("nanoid()") + orderId String @relation(Order.id) + order Order @relation(Order, orderId) + productId String @relation(Product.id) + product Product @relation(Product, productId) + quantity Number @required @min(1) + price Money @required + total Money @required +}` + +//--------------------------------------------------------------------// + +const blogSchema = + `// Blog application schema +plugin "./plugins/generate-types.js" { + output "./src/types/blog.ts" +} + +plugin "./plugins/generate-forms.js" { + output "./src/components/forms/" + framework "react" +} + +// Props +prop RichText { + type "richtext" + validation { + required true + minLength 100 + } + ui { + toolbar ["bold", "italic", "link", "image"] + placeholder "Write your content here..." + } +} + +prop Slug { + type "text" + validation { + pattern "^[a-z0-9-]+$" + maxLength 100 + } + ui { + placeholder "url-friendly-slug" + } +} + +// Enums +enum PostStatus { + DRAFT "Draft" + PUBLISHED "Published" + ARCHIVED "Archived" +} + +enum CommentStatus { + PENDING "Pending Moderation" + APPROVED "Approved" + REJECTED "Rejected" +} + +// Models +model Author! { + id String @id @default("nanoid()") + email String @unique @required @field.input(Email) + name String @required @field.input(Text) + bio String @field.textarea + avatar String @field.upload + social { + twitter String? @field.input(Text) + github String? @field.input(Text) + website String? @field.input(URL) + } + posts Post[] @relation(Post.authorId) + active Boolean @default(true) + created Date @default("now()") +} + +model Category { + id String @id @default("nanoid()") + name String @unique @required @field.input(Text) + slug String @unique @field.input(Slug) + description String @field.textarea + color String @field.color + posts Post[] @relation(PostCategory.categoryId) + created Date @default("now()") +} + +model Tag { + id String @id @default("nanoid()") + name String @unique @required @field.input(Text) + slug String @unique @field.input(Slug) + posts Post[] @relation(PostTag.tagId) + created Date @default("now()") +} + +model Post! { + id String @id @default("nanoid()") + title String @required @field.input(Text) + slug String @unique @field.input(Slug) + excerpt String @field.textarea + content String @required @field.input(RichText) + featuredImage String @field.upload + authorId String @relation(Author.id) + author Author @relation(Author, authorId) + categories Category[] @relation(PostCategory.postId) + tags Tag[] @relation(PostTag.postId) + status PostStatus @default("DRAFT") + publishedAt Date? @field.datetime + seo { + title String @field.input(Text) + description String @field.textarea + keywords String[] @field.tags + } + stats { + views Number @default(0) + likes Number @default(0) + shares Number @default(0) + } + comments Comment[] @relation(Comment.postId) + created Date @default("now()") + updated Date @default("updated()") +} + +model Comment { + id String @id @default("nanoid()") + postId String @relation(Post.id) + post Post @relation(Post, postId) + authorName String @required @field.input(Text) + authorEmail String @required @field.input(Email) + content String @required @field.textarea + status CommentStatus @default("PENDING") + parentId String? @relation(Comment.id) + parent Comment? @relation(Comment, parentId) + replies Comment[] @relation(Comment.parentId) + created Date @default("now()") +}` + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Complete Examples'); + const description = _( + 'Complete examples of how to use the .idea file format to ' + + 'generate various outputs like TypeScript interfaces, database ' + + 'schemas, API documentation, and more.' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    +

    {_('Complete Examples')}

    + + {/* E-commerce Example Content */} +
    +

    {_('E-commerce Application Schema')}

    + + {ecommerceSchema} + +
    + + {/* Blog Example Content */} +
    +

    {_('Blog Application Schema')}

    + + {blogSchema} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/specifications/data-types.tsx b/packages/www/plugins/docs/views/specifications/data-types.tsx new file mode 100644 index 0000000..b31ba5f --- /dev/null +++ b/packages/www/plugins/docs/views/specifications/data-types.tsx @@ -0,0 +1,179 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +import clsx from 'clsx'; +//local +import { H1, P, Nav } from '../../components/index.js'; +import Layout from '../../components/Layout.js'; +//data types components +import { + Enums, + Models, + Props, + Type +} from '../../components/specifications/data-types/index.js'; + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx( + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500' +); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Data Types'); + const description = _( + 'The .idea format supports four primary data types that form ' + + 'the building blocks of your application schema.' + ); + return ( + <> + {title} + + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + + return ( + + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Data Types Content */} +
    +

    {_('Data Types')}

    +

    + + The .idea format supports four primary data types that + form the building blocks of your application schema. + +

    +
    + + {/* Horizontal Rule */} +
    + + {/* Enums, Props, Type, Models Content */} +
    + {/* Enums Section */} + + + {/* Horizontal Rule */} +
    + + {/* Props Section */} + + + {/* Horizontal Rule */} +
    + + {/* Type Section */} + + + {/* Horizontal Rule */} +
    + + {/* Models Section */} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + } + > + + + ); +} diff --git a/packages/www/plugins/docs/views/specifications/error-handling.tsx b/packages/www/plugins/docs/views/specifications/error-handling.tsx new file mode 100644 index 0000000..051ab74 --- /dev/null +++ b/packages/www/plugins/docs/views/specifications/error-handling.tsx @@ -0,0 +1,403 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, C, Nav, SS } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const errorsExamples = [` +// ❌ Invalid - missing quotes around enum values +enum Status { + ACTIVE Active + INACTIVE Inactive +} + +// ✅ Valid - proper enum syntax +enum Status { + ACTIVE "Active" + INACTIVE "Inactive" +}`, + + //------------------------------------------------------------------// + + `// ❌ Invalid - empty model +model User { +} + +// ✅ Valid - model with columns +model User { + id String @id + name String @required +}`, + + //------------------------------------------------------------------// + + `// ❌ Invalid - duplicate model names +model User { + id String @id +} + +model User { // Duplicate! + name String +} + +// ✅ Valid - unique names +model User { + id String @id +} + +model UserProfile { + name String +}`, + + //------------------------------------------------------------------// + + `// ❌ Invalid - EmailInput prop not defined +model User { + email String @field.input(EmailInput) +} + +// ✅ Valid - define prop first +prop EmailInput { + type "email" + validation { required true } +} + +model User { + email String @field.input(EmailInput) +}`, + + //------------------------------------------------------------------// + + `// ❌ Invalid - Boolean can't have @minLength +model User { + active Boolean @minLength(5) +} + +// ✅ Valid - appropriate attributes for type +model User { + active Boolean @default(true) + name String @minLength(2) @maxLength(50) +}` +]; + +//--------------------------------------------------------------------// + +const errorPrevention = [` +import type { PluginProps, SchemaConfig } from '@stackpress/idea-transformer/types'; + +export default async function myPlugin(props: PluginProps<{}>) { + // TypeScript will catch type errors at compile time + const { config, schema } = props; + + // Validate configuration + if (!config.output) { + throw new Error('Output path is required'); + } + + // Process schema safely + if (schema.model) { + for (const [modelName, model] of Object.entries(schema.model)) { + // Process each model + } + } +}`, + + //------------------------------------------------------------------// + + `// Always validate required fields +model User { + id String @id @required + email String @required @unique + name String @required +} + +// Use appropriate data types +model Product { + price Number @min(0) // Not String + active Boolean // Not Number + created Date @default("now()") // Not String +}`, + + //------------------------------------------------------------------// + + `// Consistent ID patterns +model User { + id String @id @default("nanoid()") +} + +model Post { + id String @id @default("nanoid()") +} + +// Consistent timestamp patterns +model User { + created Date @default("now()") + updated Date @default("updated()") +}`, + + //------------------------------------------------------------------// + + `# Parse schema to check for errors +npm run idea:parse schema.idea + +# Transform schema to validate plugins +npm run idea:transform schema.idea + +# Generate output to verify results +npm run idea:generate` +]; + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Error Handling'); + const description = _( + 'Error handling is a crucial aspect of any application. The ' + + '.idea file format provides a way to handle errors in a ' + + 'structured way.' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    +

    {_('Error Handling')}

    + + {/* Common Errors and Solutions Section */} +
    +

    {_('Common Errors and Solutions')}

    + +

    {_('1. Invalid Schema Structure')}

    +

    + {_('Error: ')} + {_('Invalid Schema')} +

    + +

    + {_('Cause:')} + + Syntax errors or malformed declarations + +

    + +

    {_('Solution:')}

    + + + {errorsExamples[0]} + + +

    {_('2. Missing Required Properties')}

    +

    + {_('Error:')} + {_('Expecting a columns property')} +

    + +

    + {_('Cause:')} + + Models and types must have column definitions + +

    + +

    {_('Solution:')}

    + + + {errorsExamples[1]} + + +

    {_('3. Duplicate Declarations')}

    +

    + {_('Error:')} + {_('Duplicate [name]')} +

    + +

    + {_('Cause:')} + + Models and types must have column definitions + +

    + +

    + {_('Solution:')} + + Multiple declarations with the same name + +

    + + + {errorsExamples[2]} + + +

    {_('4. Unknown References')}

    +

    + {_('Error:')} + {_('Unknown reference [name]')} +

    + +

    + {_('Cause:')} + + Referencing undefined props, types, or enums + +

    + +

    {_('Solution:')}

    + + + {errorsExamples[3]} + + +

    {_('5. Type Mismatches')}

    +

    + {_('Error:')} + {_('Type mismatch')} +

    + +

    + {_('Cause:')} + + Using incompatible types or attributes + +

    + +

    {_('Solution:')}

    + + + {errorsExamples[4]} + +
    + + {/* Horizontal Rule */} +
    + + {/* Error Prevention Section */} +
    +

    {_('Error Prevention')}

    + +

    {_('1. Use TypeScript for Plugin Development')}

    + + + {errorPrevention[0]} + + +

    {_('2. Validate Schema Before Processing')}

    + + {errorPrevention[1]} + + +

    {_('3. Use Consistent Patterns')}

    + + {errorPrevention[2]} + + +

    {_('4. Test Schema Changes')}

    + + {errorPrevention[3]} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/specifications/plugin-system.tsx b/packages/www/plugins/docs/views/specifications/plugin-system.tsx new file mode 100644 index 0000000..76d41ec --- /dev/null +++ b/packages/www/plugins/docs/views/specifications/plugin-system.tsx @@ -0,0 +1,189 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C, Nav } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; +import { Table, Thead, Trow, Tcol } from 'frui/element/Table'; + +//code examples +//--------------------------------------------------------------------// + +const pluginDeclaration = [` + plugin "./path/to/plugin.js" { + output "./generated/output.ts" + format "typescript" + options { + strict true + comments true + } +}`, + + //------------------------------------------------------------------// + + `import type { PluginProps } from '@stackpress/idea-transformer/types'; + +export default async function myPlugin(props: PluginProps<{}>) { + const { config, schema, transformer } = props; + + // Process schema and generate output + const content = generateFromSchema(schema); + + // Write to configured output path + const outputPath = await transformer.loader.absolute(config.output); + await writeFile(outputPath, content); +}` +]; + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Plugin System'); + const description = _( + 'The plugin system enables extensible code generation from ' + + 'your schema definitions.' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Plugin System Content */} +
    +

    {_('Plugin System')}

    +

    + + The plugin system enables extensible code generation from + your schema definitions. + +

    +
    + + {/* Horizontal Rule */} +
    + + {/* Plugin Declaration Content */} +
    +

    {_('Plugin Declaration')}

    + + {pluginDeclaration[0]} + + +

    {_('Common Plugin Types')}

    + + + + Plugin Type + Purpose + Output + + + TypeScript Generator + Generate interfaces and types + .ts files + + + Database Schema + Generate SQL DDL + .sql files + + + API Documentation + Generate OpenAPI Specs + .json/.yaml files + + + Form Generator + Generate HTML Forms + .html files + + + Validation Schema + Generate Zod/Joi schemas + .ts files + + + Mock Data + Generate test fixtures + .json files + +
    + +

    {_('Plugin Development')}

    + + {pluginDeclaration[1]} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/specifications/processing-flow.tsx b/packages/www/plugins/docs/views/specifications/processing-flow.tsx new file mode 100644 index 0000000..2c4fb4d --- /dev/null +++ b/packages/www/plugins/docs/views/specifications/processing-flow.tsx @@ -0,0 +1,166 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H2, P, C, Nav, SS } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//processing flow diagram example +//--------------------------------------------------------------------// + +const processingFlowDiagram = ` +┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ +│ .idea File │───▶│ Parser │───▶│ AST (JSON) │ +│ │ │ │ │ │ +└─────────────────┘ └─────────────────┘ └─────────────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ Validation │ │ Transformer │ + │ │ │ │ + └─────────────────┘ └─────────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Plugins │ + │ │ + └─────────────────┘ + │ + ▼ + ┌─────────────────┐ + │ Generated Code │ + │ │ + └─────────────────┘ +` + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Processing Flow'); + const description = _( + 'The .idea file format follows a structured processing ' + + 'flow:' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Processing Flow Content */} +
    +

    {_('Processing Flow')}

    +

    + + The .idea file format follows a structured + processing flow: + +

    + + + {processingFlowDiagram} + + +

    {_('Processing Steps')}

    +
      +
    1. + {_('Parsing:')} + + Convert .idea syntax into Abstract Syntax Tree (AST) + +
    2. +
    3. + {_('Validation:')} + + Check for syntax errors, type consistency, and constraint + violations + +
    4. +
    5. + {_('Transformation:')} + + Convert AST into structured JSON configuration + +
    6. +
    7. + {_('Plugin Execution:')} + + Run configured plugins to generate output files + +
    8. +
    9. + {_('Code Generation:')} + + Create TypeScript, SQL, documentation, forms, etc. + +
    10. +
    +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/specifications/schema-directives.tsx b/packages/www/plugins/docs/views/specifications/schema-directives.tsx new file mode 100644 index 0000000..332f56b --- /dev/null +++ b/packages/www/plugins/docs/views/specifications/schema-directives.tsx @@ -0,0 +1,150 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +import clsx from 'clsx'; +//local +import { H1, P, Nav } from '../../components/index.js'; +import Layout from '../../components/Layout.js'; +//multiple components +import { + Plugin, + Use +} from '../../components/specifications/schema-directives/index.js'; + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx( + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500' +); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Schema Directives'); + const description = _( + 'Schema directives are special declarations that control how ' + + 'the schema is processed and what outputs are generated.' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + const { _ } = useLanguage(); + return ( + + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Schema Directives Content */} +
    +

    {_('Schema Directives')}

    +

    + + Schema directives are special declarations that control + how the schema is processed and what outputs are generated. + +

    +
    + + {/* Horizontal Rule */} +
    + + {/* Use, Plugin Content */} +
    + {/* Use Section */} + + + {/* Horizontal Rule */} +
    + + {/* Plugin Section */} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + } + > + + + ); +} diff --git a/packages/www/plugins/docs/views/specifications/schema-elements.tsx b/packages/www/plugins/docs/views/specifications/schema-elements.tsx new file mode 100644 index 0000000..60ad8c0 --- /dev/null +++ b/packages/www/plugins/docs/views/specifications/schema-elements.tsx @@ -0,0 +1,356 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//locals +import { H1, H2, P, C, H, Nav, SS } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; +import { Table, Thead, Trow, Tcol } from 'frui/element/Table'; + +//code examples +//--------------------------------------------------------------------// + +const examples = [ + `// Simple boolean attribute (sets value to true) +@filterable + +// Function with single argument +@label("Name") + +// Function with multiple arguments +@is.cgt(3 "Name should be more than 3 characters") + +// Function with object argument +@view.image({ width 100 height 100 }) + +// Nested attribute names using periods +@field.input(Email) +@validation.required +@ui.component("CustomInput")`, + + //------------------------------------------------------------------// + + `// Boolean (implicit true) +@required +@unique +@filterable + +// String values +@label("User Name") +@placeholder("Enter your name") +@description("This field is required") + +// Number values +@min(0) +@max(100) +@precision(2) + +// Object values +@validation({ required true minLength 3 }) +@ui({ component "Input" placeholder "Enter text" }) +@options({ multiple true searchable false }) + +// Array values +@tags(["admin" "user" "guest"]) +@options(["small" "medium" "large"]) +@toolbar(["bold" "italic" "underline"]) + +// Mixed arguments +@between(1 100 "Value must be between 1 and 100") +@pattern("^[a-zA-Z]+$" "Only letters allowed")`, + + //------------------------------------------------------------------// + + `// Model-level attributes +model User @table("users") @index(["email" "created"]) { + // Column-level attributes + id String @id @default("nanoid()") + name String @required @minLength(2) +} + +// Type-level attributes +type Address @serializable @cacheable(3600) { + street String @required + city String @required +}`, + + //------------------------------------------------------------------// + + `model User { + name String // Required string + bio String? // Optional string + tags String[] // Array of strings + addresses Address[] // Array of custom types + metadata JSON? // Optional JSON +}`, + + //------------------------------------------------------------------// + + `model User { + profile { + firstName String + lastName String + social { + twitter String? + github String? + } + } + settings { + theme String @default("light") + notifications Boolean @default(true) + } +}` +]; + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Schema Elements'); + const description = _( + 'Schema elements are the building blocks of your application schema.' + ); + return ( + <> + {title} + + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    +

    {_('Schema Elements')}

    + + {/* Attributes Content */} +
    +

    {_('Attributes (@)')}

    +

    + + Attributes provide metadata and configuration for columns, + types, and models. They define validation rules, UI + components, relationships, and behavior. Attributes can + be attached to any schema element and are processed by + plugins according to their specific needs. + +

    + + + {_('Note:')} + + There are no reserved or pre-defined attributes in idea. + You can define any arbitrary attributes in your schema. + It\'s up to the plugins to recognize and process them. + + + +

    {_('Attribute Syntax')}

    +

    + + Attributes always start with the at symbol (@) followed + by letters, numbers, and periods. They can be expressed + in several forms. + +

    + + {examples[0]} + + +

    {_('Attribute Value Types')}

    +

    + + Attributes can hold different types of values: + +

    + + {examples[1]} + + +

    {_('Attribute Scope')}

    +

    + + Attributes can be applied to different schema elements: + +

    + + {examples[2]} + +
    + + {/* Horizontal Rule */} +
    + + {/* Columns Content */} +
    +

    {_('Columns')}

    +

    + + Columns define the individual fields within models and + types, specifying their data type, constraints, and behavior. + +

    + + + Types + Description + Example + + + String + + Text data + name String + + + + Number + + Numeric data + age Number + + + + Boolean + + True or false values + active Boolean + + + + Date + + Date/time values + created Date + + + + JSON + + JSON Objects + metadata JSON + + + + CustomType + + User-defined types + address Address + + + + EnumType + + Enum values + role UserRole + +
    + +

    {_('Optional and Array Types')}

    + + {examples[3]} + + +

    {_('Nested Types')}

    + + {examples[4]} + +
    + +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/specifications/schema-structure.tsx b/packages/www/plugins/docs/views/specifications/schema-structure.tsx new file mode 100644 index 0000000..7b5ce9f --- /dev/null +++ b/packages/www/plugins/docs/views/specifications/schema-structure.tsx @@ -0,0 +1,157 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C, Nav } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//code example +//--------------------------------------------------------------------// + +const schemaExample = +`// 1. Plugin declarations +plugin "./plugins/generate-types.js" { + output "./generated/types.ts" +} + +plugin "./plugins/generate-database.js" { + output "./database/schema.sql" + dialect "postgresql" +} + +// 2. Use statements (imports) +use "./shared/common-types.idea" +use "./auth/user-types.idea" + +// 3. Prop definitions +prop Email { + type "email" + validation { required true } +} + +prop Text { + type "text" + validation { maxLength 255 } +} + +// 4. Enum definitions +enum UserRole { + ADMIN "Administrator" + USER "Regular User" +} + +// 5. Type definitions +type Address { + street String @required + city String @required + country String @default("US") +} + +// 6. Model definitions +model User! { + id String @id @default("nanoid()") + email String @unique @field.input(Email) + name String @field.input(Text) + role UserRole @default("USER") + address Address? + active Boolean @default(true) + created Date @default("now()") +}`; + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Schema Structure'); + const description = _( + 'A complete .idea schema file can contain multiple elements ' + + 'organized in a specific structure.' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Schema Structure Content */} +
    +

    {_('Schema Structure')}

    +

    + + A complete .idea schema file can contain multiple + elements organized in a specific structure: + +

    + + + {schemaExample} + +
    + + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/specifications/syntax-overview.tsx b/packages/www/plugins/docs/views/specifications/syntax-overview.tsx new file mode 100644 index 0000000..773370d --- /dev/null +++ b/packages/www/plugins/docs/views/specifications/syntax-overview.tsx @@ -0,0 +1,278 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, Nav, SS } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const examples = [` +// JavaScript object +{ foo: "bar", bar: "foo" } + +// JavaScript array +[ "foo", "bar" ] +[ "foo", "bar" ] + +// Nested structure +{ + user: { + name: "John", + age: 30, + active: true + }, + tags: ["admin", "user"] +}`, + + //------------------------------------------------------------------// + + `// Object structure +{ foo "bar" bar "foo" } + +// Array structure +[ "foo" "bar" ] + +// Nested structure +{ + user { + name "John" + age 30 + active true + } + tags ["admin" "user"] +}`, + + //------------------------------------------------------------------// + + `// Strings - always use double quotes +name "John Doe" +description "A comprehensive user management system" + +// Numbers - no quotes needed +age 30 +price 99.99 +count -5 + +// Booleans - no quotes needed +active true +verified false + +// Arrays - space-separated values +tags ["admin" "user" "moderator"] +numbers [1 2 3 4 5] +mixed ["text" 123 true] + +// Objects - nested key-value pairs +profile { + firstName "John" + lastName "Doe" + settings { + theme "dark" + notifications true + } +}`, + + //------------------------------------------------------------------// + + `// This is a single-line comment +model User { + id String @id // Inline comment + name String @required + // Another comment + email String @unique +} + +/* + Multi-line comments are also supported + for longer explanations +*/` +]; + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Syntax Overview'); + const description = _( + 'The .idea file format uses a simplified syntax that eliminates ' + + 'the need for traditional separators like commas (,) and ' + + 'colons (:) found in JSON or JavaScript. The parser can ' + + 'logically determine separations, making the syntax cleaner ' + + 'and more readable.' + ); + return ( + <> + {title} + + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Syntax Overview Content */} +
    +

    {_('Syntax Overview')}

    +

    + + The .idea file format uses a simplified syntax that + eliminates the need for traditional separators like + commas (,) and colons (:) found in JSON or + JavaScript. The parser can logically determine separations, + making the syntax cleaner and more readable. + +

    +
    + + {/* Key Syntax Rules Content */} +
    +

    {_('Key Syntax Rules')}

    +
      +
    • + {_('No Separators Required:')} + + The parser intelligently determines where values begin + and end + +
    • +
    • + {_('Double Quotes Only:')} + + All strings must use double quotes (") - single quotes + are not supported + +
    • +
    • + {_('Context Awareness:')} + + The parser understands context and can differentiate + between keys, values, and nested structures + +
    • +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Examples Content */} +
    +

    {_('Syntax Comparison')}

    +

    + Traditional JavaScript/JSON: +

    + + {examples[0]} + + +

    + Equivalent .idea syntax: +

    + + {examples[1]} + +
    + + {/* Horizontal Rule */} +
    + + {/* Data Types Representations Content */} +
    +

    {_('Data Types Representations')}

    + + {examples[2]} + +
    + + {/* Horizontal Rule */} +
    + +
    +

    {_('Comments')}

    +

    + + Comments in .idea files use the standard // syntax: + +

    + + {examples[3]} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/transformers/api-reference.tsx b/packages/www/plugins/docs/views/transformers/api-reference.tsx new file mode 100644 index 0000000..d32031d --- /dev/null +++ b/packages/www/plugins/docs/views/transformers/api-reference.tsx @@ -0,0 +1,315 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +import { Table, Thead, Trow, Tcol } from 'frui/element/Table'; +import clsx from 'clsx'; +//local +import { H1, H2, P, C, Nav } from '../../components/index.js'; +import Layout from '../../components/Layout.js'; + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx( + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500' +); + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('API Reference'); + const description = _( + 'Detailed documentation for all components and interfaces in the ' + + 'idea-transformer library' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + + return ( + +
    + {_('API Reference')} +
    + +
    + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* API Refernce Section Content */} +
    +

    {_('API Reference')}

    +

    + + The API reference provides detailed documentation for all + components and interfaces available in the idea-transformer + library. This section covers the main classes and their + methods for schema processing and plugin execution. + +

    +
    + + {/* Horizontal Rule */} +
    + + {/* Core Components Content */} +
    +

    {_('Core Components')}

    +

    + + The core components form the foundation of the transformation + system, providing the main classes and interfaces you'll + use to process schemas and execute plugins. + +

    + + + + Component + Description + Documentation + + + + Transformer + + + + Main class for loading and transforming schema files + + + + + {_('View Docs')} + + + + + + {_('Terminal')} + + + Command-line interface for schema processing + + + + {_('View Docs')} + + + +
    + +

    {_('Key Features')}

    +

    + + The idea-transformer library offers several key features + that make schema processing and code generation efficient + and reliable. These features work together to provide a + comprehensive transformation solution. + +

    +
    + + {/* Horizontal Rule */} +
    + + {/* Schema Loading Section Content */} +
    +

    {_('Schema Loading and Processing')}

    +

    + + The transformer provides robust schema loading capabilities + that handle complex schema structures and dependencies. + This includes support for modular schemas and intelligent + merging strategies. + +

    + +
      +
    • + + Support for both .idea and .json schema + files + +
    • +
    • + + Automatic dependency resolution with use directives + +
    • +
    • + + Intelligent schema merging based on mutability rules + +
    • +
    • + + Comprehensive error handling and validation + +
    • +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Plugin System Section Content */} +
    +

    {_('Plugin System')}

    +

    + + The plugin system enables extensible code generation + through a type-safe and flexible architecture. Plugins + can access the complete schema context and generate any + type of output. + +

    + +
      +
    • + + Type-safe plugin development with PluginProps and + PluginWithCLIProps + +
    • +
    • + + Access to complete schema configuration and transformation + context + +
    • +
    • + + CLI integration for interactive plugins + +
    • +
    • + + Flexible plugin configuration system + +
    • +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Command-Line Interface Section Content */} +
    +

    {_('Command-Line Interface')}

    +

    + + The CLI provides convenient command-line access for + integrating schema processing into build pipelines and + development workflows. It supports various configuration + options and batch processing capabilities. + +

    + +
      +
    • + + Simple CLI for processing schemas in build pipelines + +
    • +
    • + + Configurable working directories and file extensions + +
    • +
    • + + Integration with npm scripts and build tools + +
    • +
    • + + Support for batch processing multiple schemas + +
    • +
    +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + } + > + + + ); +} diff --git a/packages/www/plugins/docs/views/transformers/api-references/terminal.tsx b/packages/www/plugins/docs/views/transformers/api-references/terminal.tsx new file mode 100644 index 0000000..548e0e2 --- /dev/null +++ b/packages/www/plugins/docs/views/transformers/api-references/terminal.tsx @@ -0,0 +1,1300 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +import { Table, Thead, Trow, Tcol } from 'frui/element/Table'; +import clsx from 'clsx'; +//local +import { H1, H2, P, C, Nav } from '../../../components/index.js'; +import Code from '../../../components/Code.js'; +import Layout from '../../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const basicExample = + `import Terminal from '@stackpress/idea-transformer/Terminal'; + +const terminal = await Terminal.load(['transform', '--input', './schema.idea']); +await terminal.run();`; + +//--------------------------------------------------------------------// + +const loadExample = + `import Terminal from '@stackpress/idea-transformer/Terminal'; + +// Load with command-line arguments +const args = ['transform', '--input', './schema.idea']; +const terminal = await Terminal.load(args); + +// Load with custom options +const terminal = await Terminal.load(args, { + cwd: '/custom/working/directory', + extname: '.schema', + brand: '[MY-TOOL]' +});`; + +//--------------------------------------------------------------------// + +const runExample = + `const terminal = await Terminal.load(['transform', '--input', './schema.idea']); +await terminal.run();`; + +//--------------------------------------------------------------------// + +const basicCommandExecutionExample = + `import Terminal from '@stackpress/idea-transformer/Terminal'; + +// Process a schema file +const args = ['transform', '--input', './schema.idea']; +const terminal = await Terminal.load(args); +await terminal.run();`; + +//--------------------------------------------------------------------// + +const shortFlagExample = + `// Using the short flag alias +const args = ['transform', '--i', './schema.idea']; +const terminal = await Terminal.load(args); +await terminal.run();` + +//--------------------------------------------------------------------// + +const customWorkingDirectoryExample = + `// Set custom working directory +const terminal = await Terminal.load(['transform', '--i', './schema.idea'], { + cwd: '/path/to/project' +}); +await terminal.run();`; + +//--------------------------------------------------------------------// + +const customFileExtensionExample = + `// Use custom file extension +const terminal = await Terminal.load(['transform', '--i', './schema.custom'], { + extname: '.custom' +}); +await terminal.run();`; + +//--------------------------------------------------------------------// + +const customBrandExample = + `// Use custom terminal brand +const terminal = await Terminal.load(['transform', '--i', './schema.idea'], { + brand: '[MY-SCHEMA-TOOL]' +}); +await terminal.run();`; + +//--------------------------------------------------------------------// + +const directCommandLineExample = + `## Basic usage +node cli.js transform --input ./schema.idea + +## Using short flag +node cli.js transform --i ./schema.idea + +## With custom working directory +cd /path/to/project && node cli.js transform --i ./schema.idea`; + +//--------------------------------------------------------------------// + +const cliScriptExample = + `#!/usr/bin/env node +import Terminal from '@stackpress/idea-transformer/Terminal'; + +async function main() { + try { + const args = process.argv.slice(2); + const terminal = await Terminal.load(args, { + cwd: process.cwd(), + brand: '[SCHEMA-CLI]' + }); + await terminal.run(); + } catch (error) { + console.error('CLI Error:', error.message); + process.exit(1); + } +} + +main();`; + +//--------------------------------------------------------------------// + +const packageJsonIntegrationExample = + `{ + "name": "my-schema-tool", + "bin": { + "schema": "./cli.js" + }, + "scripts": { + "build": "schema transform --i ./schema.idea", + "dev": "schema transform --i ./dev-schema.idea" + } +}`; + +//--------------------------------------------------------------------// + +const defaultPathExample = + `// Default file path construction +const defaultPath = \`\${terminal.cwd}/schema\${terminal.extname}\`; +// Example: "/current/directory/schema.idea"` + +//--------------------------------------------------------------------// + +const flagProcessingExample = + `// These are equivalent: +['transform', '--input', './schema.idea'] +['transform', '--i', './schema.idea'] + +// Uses default path: ./schema.idea +['transform']`; + +//--------------------------------------------------------------------// + +const missingSchemaFileExample = + `try { + const terminal = await Terminal.load(['transform', '--i', './nonexistent.idea']); + await terminal.run(); +} catch (error) { + console.error('File not found:', error.message); +}`; + +//--------------------------------------------------------------------// + +const invalidCommandExample = + `try { + const terminal = await Terminal.load(['invalid-command']); + await terminal.run(); +} catch (error) { + console.error('Unknown command:', error.message); +}`; + +//--------------------------------------------------------------------// + +const pluginErrorsExample = + `// If plugins fail during transformation +try { + const terminal = await Terminal.load(['transform', '--i', './schema.idea']); + await terminal.run(); +} catch (error) { + console.error('Transformation failed:', error.message); +}`; + +//--------------------------------------------------------------------// + +const customEventHandlersExample = + `import Terminal from '@stackpress/idea-transformer/Terminal'; + +const terminal = await Terminal.load(['transform', '--i', './schema.idea']); + +// Add custom event handler +terminal.on('custom-command', async (event) => { + console.log('Custom command executed'); + // Custom logic here +}); + +await terminal.run();`; + +//--------------------------------------------------------------------// + +const programmaticCLIExample = + `// Build CLI arguments programmatically +function buildCLIArgs(schemaFile: string, options: any = {}) { + const args = ['transform']; + + if (schemaFile) { + args.push('--input', schemaFile); + } + + return args; +} + +const args = buildCLIArgs('./my-schema.idea'); +const terminal = await Terminal.load(args); +await terminal.run();`; + +//--------------------------------------------------------------------// + +const batchProcessingExample = + `import { glob } from 'glob'; + +async function processAllSchemas(pattern: string) { + const schemaFiles = await glob(pattern); + + for (const schemaFile of schemaFiles) { + console.log(\`Processing \${schemaFile}...\`); + + const terminal = await Terminal.load(['transform', '--i', schemaFile]); + await terminal.run(); + + console.log(\`Completed \${schemaFile}\`); + } +} + +// Process all .idea files in a directory +await processAllSchemas('./schemas/**/*.idea');`; + +//--------------------------------------------------------------------// + +const environmentBasedConfigExample = + `const terminal = await Terminal.load(['transform', '--i', './schema.idea'], { + cwd: process.env.SCHEMA_CWD || process.cwd(), + extname: process.env.SCHEMA_EXT || '.idea', + brand: process.env.CLI_BRAND || '[IDEA]' +}); + +await terminal.run();`; + +//--------------------------------------------------------------------// + + +const webpackPluginExample = + `class SchemaTransformPlugin { + constructor(options = {}) { + this.options = options; + } + + apply(compiler) { + compiler.hooks.beforeCompile.tapAsync('SchemaTransformPlugin', async (params, callback) => { + try { + const terminal = await Terminal.load(['transform', '--i', this.options.schemaFile]); + await terminal.run(); + callback(); + } catch (error) { + callback(error); + } + }); + } +}`; + +//--------------------------------------------------------------------// + +const gulpTaskExample = + `import gulp from 'gulp'; +import Terminal from '@stackpress/idea-transformer/Terminal'; + +gulp.task('transform-schema', async () => { + const terminal = await Terminal.load(['transform', '--i', './schema.idea']); + await terminal.run(); +});`; + +//--------------------------------------------------------------------// + +const npmScriptsExample = + `{ + "scripts": { + "schema:build": "node -e \"import('./cli.js').then(m => m.default(['transform', '--i', './schema.idea']))\"", + "schema:dev": "node -e \"import('./cli.js').then(m => m.default(['transform', '--i', './dev-schema.idea']))\"", + "schema:watch": "nodemon --watch schema.idea --exec \"npm run schema:build\"" + } +}`; + +//--------------------------------------------------------------------// + +const unitTestingExample = + `import { expect } from 'chai'; +import Terminal from '@stackpress/idea-transformer/Terminal'; + +describe('Terminal Tests', () => { + it('should process schema file', async () => { + const terminal = await Terminal.load(['transform', '--i', './test-schema.idea'], { + cwd: './test-fixtures' + }); + + expect(terminal.cwd).to.include('test-fixtures'); + + // Run the terminal command + await terminal.run(); + + // Verify output files were created + // ... assertions here + }); + + it('should use default options', async () => { + const terminal = await Terminal.load(['transform']); + + expect(terminal.extname).to.equal('.idea'); + expect(terminal.cwd).to.be.a('string'); + }); +});`; + +//--------------------------------------------------------------------// + +const integrationTestingExample = + `import fs from 'fs'; +import path from 'path'; + +describe('Terminal Integration', () => { + it('should generate expected output files', async () => { + const outputDir = './test-output'; + const schemaFile = './test-schema.idea'; + + // Clean output directory + if (fs.existsSync(outputDir)) { + fs.rmSync(outputDir, { recursive: true }); + } + + // Run transformation + const terminal = await Terminal.load(['transform', '--i', schemaFile]); + await terminal.run(); + + // Verify expected files were created + const expectedFiles = ['types.ts', 'enums.ts', 'models.ts']; + for (const file of expectedFiles) { + const filePath = path.join(outputDir, file); + expect(fs.existsSync(filePath)).to.be.true; + } + }); +});`; + +//--------------------------------------------------------------------// + +const errorHandlingBestPracticeExample = + `// Always wrap terminal execution in try-catch +async function safeTransform(schemaFile: string) { + try { + const terminal = await Terminal.load(['transform', '--i', schemaFile]); + await terminal.run(); + console.log(\`✅ Successfully processed \${schemaFile}\`); + } catch (error) { + console.error(\`❌ Failed to process \${schemaFile}:\`, error.message); + throw error; + } +}`; + +//--------------------------------------------------------------------// + +const configurationManagementExample = + `// Use configuration objects for reusable settings +const defaultConfig = { + cwd: process.cwd(), + extname: '.idea', + brand: '[SCHEMA-TOOL]' +}; + +async function createTerminal(args: string[], config = defaultConfig) { + return await Terminal.load(args, config); +}`; + +//--------------------------------------------------------------------// + +const loggingAndDebuggingExample = + `// Add logging for better debugging +const terminal = await Terminal.load(['transform', '--i', './schema.idea'], { + cwd: process.cwd() +}); + +console.log(\`Working directory: \${terminal.cwd}\`); +console.log(\`File extension: \${terminal.extname}\`); + +await terminal.run();`; + +//--------------------------------------------------------------------// + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx( + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500' +); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Terminal'); + const description = _( + 'A command-line interface for processing schema files and executing ' + + 'transformations through terminal commands' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + + return ( + +
    + {_('API Reference')} +
    + + +
    + {_('On this page')} +
    + +
    + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Overview Section */} +
    +

    {_('Terminal')}

    +

    + + A command-line interface for processing schema files and + executing transformations through terminal commands. The + Terminal class provides a comprehensive CLI interface for + the idea-transformer library, enabling developers to process + schema files and execute transformations from the command + line. + +

    + + + {basicExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Overview Section */} +
    +

    {_('Overview')}

    +

    + + The Terminal class provides a command-line interface for + processing schema files and executing transformations. This + section outlines the core capabilities and features of the + Terminal class, which extends the base Terminal functionality + to provide schema-specific command-line operations. + +

    + +

    + + The Terminal class (exported as Terminal) extends the base + Terminal class from stackpress to provide command-line + functionality for the idea-transformer library. It handles: + +

    + +
      +
    • {_('Command-line argument parsing')}
    • +
    • {_('Schema file resolution')}
    • +
    • {_('Transformation execution')}
    • +
    • {_('Error reporting and logging')}
    • +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Loading a Terminal Instance Section */} +
    +

    {_('Loading a Terminal Instance')}

    +

    + + The load method creates a new Terminal instance from + command-line arguments and optional configuration. This is + the primary way to create a terminal instance for processing + schema files from the command line. + +

    + +

    + + The following example shows how to create a new Terminal + instance from command-line arguments. + +

    + + + {loadExample} + + +

    {_('Parameters')}

    + + + + Parameter + Type + Description + + + args + string[] + + + Command-line arguments array + + + + + options + TerminalOptions + + + Optional configuration for terminal behavior + + + +
    + +

    {_('Returns')}

    +

    + + A promise that resolves to a new Terminal instance + configured with the specified arguments and options. + +

    +
    + + {/* Horizontal Rule */} +
    + + {/* Properties Section */} +
    +

    {_('Properties')}

    +

    + + The properties section describes the instance variables + available on Terminal objects. These properties provide + access to configuration details and runtime information + needed for command-line operations. + +

    + +

    + + The following properties are available when instantiating + a Terminal. + +

    + + + + Property + Type + Description + + + cwd + string + + + Current working directory for file operations + + + + + extname + string + + + Default file extension for schema files ' + + '(default: \'.idea\') + + + +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Running Terminal Commands Section */} +
    +

    {_('Running Terminal Commands')}

    +

    + + The run method executes the configured terminal command and + processes the specified schema file. This method handles the + complete workflow from command parsing to schema + transformation execution. + +

    + +

    + + The Terminal automatically sets up event handlers for + processing commands. The main command supported is transform. + +

    + + + {runExample} + + +

    {_('Command Structure')}

    +

    + + The terminal expects commands in the following format: + +

    + + transform --input <schema-file> [--i <schema-file>] + + +

    {_('Flags')}

    + + + + Flag + Alias + Description + + + --input + --i + + + Path to the schema file to process + + + +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Usage Examples Section */} +
    +

    {_('Usage Examples')}

    +

    + + This section provides practical examples of how to use the + Terminal class in various scenarios. These examples demonstrate + common patterns and use cases for command-line schema processing. + +

    + +

    {_('Basic Command Execution')}

    +

    + + Basic command execution demonstrates the fundamental workflow + for processing schema files through the Terminal interface. + This example shows the simplest way to transform a schema file + using command-line arguments. + +

    + + + {basicCommandExecutionExample} + + +

    {_('Using Short Flag Syntax')}

    +

    + + Short flag syntax provides convenient aliases for common + command-line options. This example shows how to use abbreviated + flags to make command-line usage more efficient. + +

    + + + {shortFlagExample} + + +

    {_('Custom Working Directory')}

    +

    + + Custom working directory configuration allows you to specify + where the Terminal should operate. This is useful when + processing schema files from different locations or when + integrating with build systems. + +

    + + + {customWorkingDirectoryExample} + + +

    {_('Custom File Extension')}

    +

    + + Custom file extension support enables the Terminal to work + with schema files that use non-standard extensions. This + flexibility allows integration with different naming + conventions and file organization strategies. + +

    + + + {customFileExtensionExample} + + +

    {_('Custom Brand/Label')}

    +

    + + Custom brand configuration allows you to customize the + Terminal's display name and branding. This is useful when + building custom CLI tools based on the idea-transformer + library. + +

    + + + {customBrandExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Command-Line Integration Section */} +
    +

    {_('Command-Line Integration')}

    +

    + + This section demonstrates how to integrate the Terminal class + with actual command-line environments and build systems. + These examples show practical applications for creating CLI + tools and automating schema processing. + +

    + +

    {_('Direct Command-Line Usage')}

    +

    + + Direct command-line usage shows how to invoke the Terminal + functionality from shell commands. This section provides + examples of the actual command syntax and available options. + +

    + + + {directCommandLineExample} + + +

    {_('CLI Script Example')}

    +

    + + CLI script examples demonstrate how to create executable + scripts that use the Terminal class. This pattern is useful + for creating standalone CLI tools and integrating with package + managers. + +

    + + + {cliScriptExample} + + +

    {_('Package.json Integration')}

    +

    + + Package.json integration shows how to configure npm scripts + and binary commands using the Terminal class. This enables + seamless integration with Node.js project workflows and package + distribution. + +

    + + + {packageJsonIntegrationExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Default Behavior Section */} +
    +

    {_('Default Behavior')}

    +

    + + This section explains the default behavior and conventions + used by the Terminal class. Understanding these defaults helps + developers predict how the Terminal will behave in different + scenarios and configure it appropriately. + +

    + +

    {_('File Path Resolution')}

    +

    + + File path resolution describes how the Terminal determines + which schema file to process when no explicit path is provided. + This automatic resolution simplifies common use cases while + maintaining flexibility. + +

    + +

    + + When no input file is specified, the terminal uses a default + path: + +

    + + + {defaultPathExample} + + +

    {_('Flag Processing')}

    +

    + + Flag processing explains how the Terminal parses and + prioritizes command-line flags. Understanding this order + of precedence helps developers use the most appropriate + flag syntax for their needs. + +

    + +

    + + The terminal processes the following flags in order of + preference: + +

    + +
      +
    1. + --input (full flag name) +
    2. +
    3. + --i (short alias) +
    4. +
    5. + Default file path if no flags provided +
    6. +
    + + + {flagProcessingExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Error Handling Section */} +
    +

    {_('Error Handling')}

    +

    + + This section covers common error conditions that can occur + when using the Terminal class. Understanding these error + scenarios helps developers implement proper error handling + and provide better user experiences. + +

    + +

    {_('Missing Schema File')}

    +

    + + Missing schema file errors occur when the specified schema + file doesn't exist or isn't accessible. This section shows + how these errors are reported and how to handle them + appropriately in CLI applications. + +

    + + + {missingSchemaFileExample} + + +

    {_('Invalid Command')}

    +

    + + Invalid command errors occur when unsupported commands are + passed to the Terminal. This section explains how the + Terminal handles unknown commands and provides guidance + for error recovery. + +

    + + + {invalidCommandExample} + + +

    {_('Plugin Errors')}

    +

    + + Plugin errors can occur during the transformation process + when plugins fail to execute properly. This section covers + how to handle and debug plugin-related issues in CLI + environments. + +

    + + + {pluginErrorsExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Advanced Usage Section */} +
    +

    {_('Advanced Usage')}

    +

    + + This section covers advanced patterns and techniques for + using the Terminal class in complex scenarios. These + examples demonstrate sophisticated use cases and integration + patterns for power users. + +

    + +

    {_('Custom Event Handlers')}

    +

    + + Custom event handlers allow you to extend the Terminal's + functionality with additional commands and behaviors. This + pattern enables building specialized CLI tools with custom + functionality. + +

    + + + {customEventHandlersExample} + + +

    {_('Programmatic CLI Building')}

    +

    + + Programmatic CLI building demonstrates how to construct + command-line arguments dynamically in code. This approach is + useful for building tools that generate CLI commands based on + configuration or user input. + +

    + + + {programmaticCLIExample} + + +

    {_('Batch Processing')}

    +

    + + Batch processing shows how to use the Terminal class to + process multiple schema files in sequence. This pattern is + essential for build systems and automation tools that need to + handle multiple schemas. + +

    + + + {batchProcessingExample} + + +

    {_('Environment-Based Configuration')}

    +

    + + Environment-based configuration demonstrates how to use + environment variables to configure Terminal behavior. This + approach enables flexible deployment and configuration + management across different environments. + +

    + + + {environmentBasedConfigExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Integration with Build Tools Section */} +
    +

    {_('Integration with Build Tools')}

    +

    + + This section demonstrates how to integrate the Terminal class + with popular build tools and development workflows. These + examples show practical applications for automating schema + processing in development and deployment pipelines. + +

    + +

    {_('Webpack Plugin')}

    +

    + + Webpack plugin integration shows how to incorporate schema + transformation into Webpack build processes. This enables + automatic schema processing as part of the application build + pipeline. + +

    + + + {webpackPluginExample} + + +

    {_('Gulp Task')}

    +

    + + Gulp task integration demonstrates how to create Gulp + tasks that use the Terminal class for schema processing. + This pattern is useful for projects that use Gulp as their + primary build tool. + +

    + + + {gulpTaskExample} + + +

    {_('NPM Scripts')}

    +

    + + NPM scripts integration shows how to configure package.json + scripts that use the Terminal class. This approach enables + easy schema processing through standard npm commands and + supports development workflows. + +

    + + + {npmScriptsExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Testing Section */} +
    +

    {_('Testing')}

    +

    + + This section covers testing strategies and patterns for + applications that use the Terminal class. These examples + demonstrate how to write effective tests for CLI functionality + and ensure reliable schema processing. + +

    + +

    {_('Unit Testing')}

    +

    + + Unit testing examples show how to test Terminal functionality + in isolation. These tests verify that the Terminal class + behaves correctly with different command-line arguments + and configuration options. + +

    + + + {unitTestingExample} + + +

    {_('Integration Testing')}

    +

    + + Integration testing demonstrates how to test the complete + workflow from command-line input to generated output files. + These tests ensure that the entire transformation pipeline + works correctly in realistic scenarios. + +

    + + + {integrationTestingExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Best Practices Section */} +
    +

    {_('Best Practices')}

    +

    + + This section outlines recommended approaches for using the + Terminal class effectively. Following these practices helps + ensure reliable, maintainable, and user-friendly CLI + applications. + +

    + +

    {_('Error Handling')}

    +

    + + Error handling best practices ensure that CLI applications + provide clear feedback when issues occur. This section + demonstrates patterns for implementing robust error handling + and user-friendly error messages. + +

    + + + {errorHandlingBestPracticeExample} + + +

    {_('Configuration Management')}

    +

    + + Configuration management best practices help maintain clean, + reusable configuration patterns. This section provides + guidance on organizing configuration options and providing + sensible defaults. + +

    + + + {configurationManagementExample} + + +

    {_('Logging and Debugging')}

    +

    + + Logging and debugging practices help developers troubleshoot + issues and understand Terminal behavior. This section + demonstrates effective logging strategies and debugging + techniques for CLI applications. + +

    + + + {loggingAndDebuggingExample} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + } + > + + + ); +} diff --git a/packages/www/plugins/docs/views/transformers/api-references/transformer.tsx b/packages/www/plugins/docs/views/transformers/api-references/transformer.tsx new file mode 100644 index 0000000..b90355c --- /dev/null +++ b/packages/www/plugins/docs/views/transformers/api-references/transformer.tsx @@ -0,0 +1,1074 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +import { Table, Thead, Trow, Tcol } from 'frui/element/Table'; +import clsx from 'clsx'; +//local +import { H1, H2, P, C, Nav, SS } from '../../../components/index.js'; +import Code from '../../../components/Code.js'; +import Layout from '../../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const basicExample = + `import Transformer from '@stackpress/idea-transformer'; + +const transformer = await Transformer.load('./schema.idea'); +const schema = await transformer.schema(); +await transformer.transform();`; + +//--------------------------------------------------------------------// + +const loadExample = + `import Transformer from '@stackpress/idea-transformer'; + +// Load with default options +const transformer = await Transformer.load('./schema.idea'); + +// Load with custom options +const transformer = await Transformer.load('./schema.idea', { + cwd: '/custom/working/directory', + fs: customFileSystem +});`; + +//--------------------------------------------------------------------// + +const schemaExample = + `const transformer = await Transformer.load('./schema.idea'); +const schema = await transformer.schema(); + +console.log(schema.model); // Access model definitions +console.log(schema.enum); // Access enum definitions +console.log(schema.type); // Access type definitions +console.log(schema.prop); // Access prop definitions +console.log(schema.plugin); // Access plugin configurations`; + +//--------------------------------------------------------------------// + +const transformExample = + `const transformer = await Transformer.load('./schema.idea'); + +// Transform with no additional context +await transformer.transform(); + +// Transform with additional context +await transformer.transform({ + outputDir: './generated', + debug: true +});`; + +//--------------------------------------------------------------------// + +const pluginContextExample = + `{ + transformer: Transformer, // The transformer instance + config: PluginConfig, // Plugin-specific configuration + schema: SchemaConfig, // Complete processed schema + cwd: string, // Current working directory + ...extras // Any additional context passed to transform() +}` + +//--------------------------------------------------------------------// + +const basicSchemaLoadingExample = + `import Transformer from '@stackpress/idea-transformer'; + +const transformer = await Transformer.load('./schema.idea'); +const schema = await transformer.schema(); + +// Access different parts of the schema +console.log('Models:', Object.keys(schema.model || {})); +console.log('Enums:', Object.keys(schema.enum || {})); +console.log('Types:', Object.keys(schema.type || {}));`; + +//--------------------------------------------------------------------// + +const multipleSchemaFilesExample = + `// main.idea +/* +use "./shared/types.idea" +use "./shared/enums.idea" + +model User { + id String @id + profile Profile // From shared/types.idea + role UserRole // From shared/enums.idea +} +*/ + +const transformer = await Transformer.load('./main.idea'); +const schema = await transformer.schema(); + +// The schema now includes definitions from all imported files +console.log(schema.type?.Profile); // Available from shared/types.idea +console.log(schema.enum?.UserRole); // Available from shared/enums.idea`; + +//--------------------------------------------------------------------// + +const pluginDevelopmentExample = + `// schema.idea +/* +plugin "./plugins/generate-types.js" { + output "./generated/types.ts" + format "typescript" +} +*/ + +// plugins/generate-types.js +export default function generateTypes({ transformer, config, schema, cwd }) { + const outputPath = config.output; + const format = config.format; + + // Generate TypeScript types based on schema + let content = ''; + + if (schema.model) { + for (const [name, model] of Object.entries(schema.model)) { + content += \`export interface \${name} {\n\`; + for (const column of model.columns) { + const optional = column.required ? '' : '?'; + content += \` \${column.name}\${optional}: \${column.type};\n\`; + } + content += '}\n\n'; + } + } + + // Write generated content to file + await writeFile(path.resolve(cwd, outputPath), content); +} + +// Execute the transformation +const transformer = await Transformer.load('./schema.idea'); +await transformer.transform({ + timestamp: new Date().toISOString() +});`; + +//--------------------------------------------------------------------// + +const errorHandlingExample = + `import { Exception } from '@stackpress/idea-parser'; + +try { + const transformer = await Transformer.load('./schema.idea'); + const schema = await transformer.schema(); + await transformer.transform(); +} catch (error) { + if (error instanceof Exception) { + console.error('Schema processing error:', error.message); + console.error('Error code:', error.code); + } else { + console.error('Unexpected error:', error); + } +}`; + +//--------------------------------------------------------------------// + +const customFileSystemExample = + `import { NodeFS } from '@stackpress/lib'; + +// Using custom file system +const customFS = new NodeFS(); +const transformer = await Transformer.load('./schema.idea', { + fs: customFS, + cwd: '/custom/working/directory' +});`; + +//--------------------------------------------------------------------// + +const fileNotFoundExample = + `// Throws: "Input file /path/to/nonexistent.idea does not exist" +const transformer = await Transformer.load('./nonexistent.idea'); +await transformer.schema(); // Error thrown here`; + +//--------------------------------------------------------------------// + +const noPluginsExample = + `// If schema has no plugins defined +const transformer = await Transformer.load('./schema-without-plugins.idea'); +await transformer.transform(); // Throws: "No plugins defined in schema file"`; + +//--------------------------------------------------------------------// + +const invalidPluginExample = + `// If plugin file doesn't export a function +const transformer = await Transformer.load('./schema.idea'); +await transformer.transform(); // Plugin is silently skipped if not a function`; + +//--------------------------------------------------------------------// + +const schemaOrganizationExample = + `// Organize schemas hierarchically +// shared/base.idea - Common types and enums +// modules/user.idea - User-specific models +// main.idea - Main schema that imports others + +use "./shared/base.idea" +use "./modules/user.idea" + +// Additional models specific to this schema +model Application { + id String @id + users User[] +}`; + +//--------------------------------------------------------------------// + +const pluginDevelopmentBestPracticeExample = + `// Always validate plugin configuration +export default async function myPlugin({ config, schema, transformer, cwd }) { + // Validate required configuration + if (!config.output) { + throw new Error('Plugin requires output configuration'); + } + + // Use transformer's file loader for consistent path resolution + const outputPath = await transformer.loader.absolute(config.output); + + // Process schema safely + const models = schema.model || {}; + const enums = schema.enum || {}; + + // Generate output... +}`; + +//--------------------------------------------------------------------// + +const errorRecoveryExample = + `// Implement graceful error handling +async function processSchema(schemaPath) { + try { + const transformer = await Transformer.load(schemaPath); + const schema = await transformer.schema(); + await transformer.transform(); + return { success: true, schema }; + } catch (error) { + console.error(\`Failed to process \${schemaPath}:\`, error.message); + return { success: false, error: error.message }; + } +}`; + +//--------------------------------------------------------------------// + +const buildSystemIntegrationExample = + `// Integration with build tools +import Transformer from '@stackpress/idea-transformer'; + +export async function buildSchemas(inputDir, outputDir) { + const schemaFiles = await glob(\`\${inputDir}/**/*.idea\`); + + for (const schemaFile of schemaFiles) { + const transformer = await Transformer.load(schemaFile); + await transformer.transform({ outputDir }); + } +}`; + +//--------------------------------------------------------------------// + +const testingExample = + `// Testing schema transformations +import { expect } from 'chai'; + +describe('Schema Transformation', () => { + it('should process schema correctly', async () => { + const transformer = await Transformer.load('./test-schema.idea'); + const schema = await transformer.schema(); + + expect(schema.model).to.have.property('User'); + expect(schema.model.User.columns).to.have.length.greaterThan(0); + }); +});`; + +//--------------------------------------------------------------------// + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx( + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500' +); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Transformer'); + const description = _( + 'A class for loading, processing, and transforming schema files ' + + 'with plugin support and schema merging capabilities' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + + return ( + +
    + {_('API Reference')} +
    + + +
    + {_('On this page')} +
    + +
    + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Transformer API Reference Section Content */} +
    +

    {_('Transformer API Reference')}

    +

    + + A class for loading, processing, and transforming schema + files with plugin support and schema merging capabilities. + The Transformer class serves as the core component of the + idea-transformer library, providing comprehensive functionality + for schema processing, plugin execution, and file management. + +

    + + + {basicExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Overview Section Content */} +
    +

    {_('Overview')}

    +

    + + The Transformer class provides a comprehensive solution for + processing schema files and executing transformations. This + section outlines the core capabilities and responsibilities of + the Transformer class within the idea-transformer ecosystem. + +

    + +

    + + The Transformer class is the core component of the + idea-transformer library. It handles: + +

    + +
      +
    • + + Loading schema files (both .idea and .json + formats) + +
    • +
    • + + Processing and merging schema configurations from + multiple files + +
    • +
    • + + Executing plugins defined in the schema + +
    • +
    • + + Managing file dependencies and imports + +
    • +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Loading a Transformer Section Content */} +
    +

    {_('Loading a Transformer')}

    +

    + + The load method creates a new Transformer instance configured + with the specified input file and options. This is the primary + way to create a transformer and begin working with schema files. + +

    + +

    + + The following example shows how to create a new Transformer + instance. + +

    + + + {loadExample} + + +

    {_('Parameters')}

    + + + + Parameter + Type + Description + + + input + string + + + Path to the schema file to load + + + + + options + LoaderOptions + + + Optional configuration for the file loader + + + +
    + +

    {_('Returns')}

    +

    + + A promise that resolves to a new Transformer instance + configured with the specified input file and options. + +

    +
    + + {/* Horizontal Rule */} +
    + + {/* Properties Section Content */} +
    +

    {_('Properties')}

    +

    + + The properties section describes the instance variables + available on Transformer objects. These properties provide + access to the underlying file system operations and + configuration details needed for schema processing. + +

    + +

    + + The following properties are available when instantiating + a Transformer. + +

    + + + + Property + Type + Description + + + loader + FileLoader + + + File system loader for handling file operations + + + + + input + string + + + Absolute path to the input schema file + + + +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Methods Section Content */} +
    +

    {_('Methods')}

    +

    + + The methods section covers the instance methods available + on Transformer objects. These methods provide the core + functionality for loading schema configurations, processing + dependencies, and executing plugin transformations. + +

    + +

    {_('Loading Schema Configuration')}

    +

    + + The schema method loads and processes the complete schema + configuration, including all dependencies and imports. This + method handles the complex process of merging multiple + schema files and resolving all references. + +

    + +

    + + The following example shows how to load and process the + schema configuration. + +

    + + + {schemaExample} + + +

    {_('Returns')}

    +

    + + A promise that resolves to a SchemaConfig object containing + all processed schema definitions. + +

    + +

    {_('Features')}

    +
      +
    • + + File Format Support: Automatically detects and + handles both .idea and .json schema files + +
    • +
    • + + Dependency Resolution: Processes use directives + to import and merge external schema files + +
    • +
    • + + Schema Merging: Intelligently merges child schemas + into parent schemas based on mutability rules + +
    • +
    • + + Caching: Caches the processed schema to avoid + redundant processing + +
    • +
    + +

    {_('Schema Merging Rules')}

    +

    + + When processing use directives, the transformer applies + these merging rules: + +

    + +
      +
    1. + Props and Enums: + + Simple merge where parent takes precedence + +
    2. +
    3. + Types and Models: +
        +
      • + + If parent doesn't exist or is immutable: child is added + +
      • +
      • + + If parent is mutable: attributes and columns are merged + +
      • +
      • + + Child columns are prepended to parent columns + +
      • +
      • + + Parent attributes take precedence over child attributes + +
      • +
      +
    4. +
    + +

    {_('Transforming with Plugins')}

    +

    + + The transform method executes all plugins defined in the + schema configuration. This method coordinates the plugin + execution process, providing each plugin with the necessary + context and handling any errors that occur during + transformation. + +

    + +

    + + The following example shows how to execute all plugins + defined in the schema. + +

    + + + {transformExample} + + +

    {_('Parameters')}

    + + + + Parameter + Type + Description + + + extras + T + + + Optional additional context to pass to plugins + + + +
    + +

    {_('Returns')}

    +

    + + A promise that resolves when all plugins have been executed. + +

    + +

    {_('Plugin Execution Process')}

    +
      +
    1. + + Validation: Ensures plugins are defined in the + schema + +
    2. +
    3. + + Module Resolution: Resolves plugin file paths + relative to the schema file + +
    4. +
    5. + + Dynamic Import: Loads plugin modules dynamically + +
    6. +
    7. + + Context Injection: Passes context including + transformer, schema, config, and extras + +
    8. +
    9. + + Execution: Calls each plugin function with the + injected context + +
    10. +
    + +

    {_('Plugin Context')}

    +

    + + Each plugin receives a context object with the following + properties: + +

    + + + {pluginContextExample[0]} + +
    + + {/* Horizontal Rule */} +
    + + {/* Usage Examples Section Content */} +
    +

    {_('Usage Examples')}

    +

    + + This section provides practical examples of how to use the + Transformer class in various scenarios. These examples + demonstrate common patterns and best practices for working + with schema files, plugins, and transformations. + +

    + +

    {_('Basic Schema Loading')}

    +

    + + Basic schema loading demonstrates the fundamental workflow + for loading and accessing schema configurations. This + example shows how to create a transformer instance and + retrieve different parts of the processed schema. + +

    + + + {basicSchemaLoadingExample} + + +

    {_('Working with Multiple Schema Files')}

    +

    + + Working with multiple schema files shows how the Transformer + handles complex schema hierarchies with imports and + dependencies. This example demonstrates how the use + directive enables modular schema organization. + +

    + + + {multipleSchemaFilesExample} + + +

    {_('Plugin Development and Execution')}

    +

    + + Plugin development and execution demonstrates how to create + and use plugins with the Transformer. This example shows + both the schema configuration and plugin implementation, + illustrating the complete plugin workflow. + +

    + + + {pluginDevelopmentExample} + + +

    {_('Error Handling')}

    +

    + + Error handling examples show how to properly catch and + handle different types of errors that can occur during + schema processing and transformation. This includes both + expected errors from the idea-parser and unexpected + runtime errors. + +

    + + + {errorHandlingExample} + + +

    {_('Custom File System')}

    +

    + + Custom file system usage demonstrates how to configure the + Transformer to work with different file system + implementations. This is useful for testing, custom + storage backends, or specialized deployment scenarios. + +

    + + + {customFileSystemExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Error Scenarios Section Content */} +
    +

    {_('Error Scenarios')}

    +

    + + This section covers common error conditions that can occur + when using the Transformer class. Understanding these + scenarios helps developers implement proper error handling + and debugging strategies. + +

    + +

    {_('File Not Found')}

    +

    + + File not found errors occur when the specified schema file + doesn't exist or isn't accessible. This section shows how + these errors are reported and how to handle them + appropriately. + +

    + + + {fileNotFoundExample} + + +

    {_('No Plugins Defined')}

    +

    + + No plugins defined errors occur when attempting to execute + transformations on schemas that don't have any plugin + configurations. This section explains when this error + occurs and how to handle it. + +

    + + + {noPluginsExample} + + +

    {_('Invalid Plugin Module')}

    +

    + + Invalid plugin module scenarios occur when plugin files + exist but don't export the expected function interface. + This section covers how the Transformer handles these + situations and what developers should expect. + +

    + + + {invalidPluginExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Best Practices Section Content */} +
    +

    {_('Best Practices')}

    +

    + + This section outlines recommended approaches for using the + Transformer class effectively. Following these practices + helps ensure reliable, maintainable, and efficient schema + processing workflows. + +

    + +

    {_('Schema Organization')}

    +

    + + Schema organization best practices help maintain clean, + modular, and reusable schema files. This section provides + guidance on structuring schema hierarchies and managing + dependencies effectively. + +

    + + + {schemaOrganizationExample} + + +

    {_('Plugin Development')}

    +

    + + Plugin development best practices ensure that plugins are + robust, reliable, and integrate well with the Transformer + ecosystem. This section covers validation, error handling, + and proper use of the plugin context. + +

    + + + {pluginDevelopmentBestPracticeExample} + + +

    {_('Error Recovery')}

    +

    + + Error recovery strategies help build resilient applications + that can handle schema processing failures gracefully. + This section demonstrates patterns for implementing robust + error handling and recovery mechanisms. + +

    + + + {errorRecoveryExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Integration with Other Tools Section Content */} +
    +

    {_('Integration with Other Tools')}

    +

    + + This section demonstrates how to integrate the Transformer + class with other development tools and workflows. These + examples show practical applications in build systems, + testing frameworks, and development environments. + +

    + +

    {_('Build Systems')}

    +

    + + Build system integration shows how to incorporate schema + transformation into automated build processes. This + enables continuous generation of code, documentation, + and other artifacts from schema definitions. + +

    + + + {buildSystemIntegrationExample} + + +

    {_('Testing')}

    +

    + + Testing integration demonstrates how to write tests for + schema transformations and validate that schemas are + processed correctly. This is essential for maintaining + schema quality and catching regressions. + +

    + + + {testingExample} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + } + > + + + ); +} diff --git a/packages/www/plugins/docs/views/transformers/architecture.tsx b/packages/www/plugins/docs/views/transformers/architecture.tsx new file mode 100644 index 0000000..8598929 --- /dev/null +++ b/packages/www/plugins/docs/views/transformers/architecture.tsx @@ -0,0 +1,114 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, Nav } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//code example +//--------------------------------------------------------------------// + +const architectureDiagram = +` +┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ +│ Schema File │───▶│ Transformer │───▶│ Plugins │ +│ (.idea/.json) │ │ │ │ │ +└─────────────────┘ └─────────────────┘ └─────────────────┘ + │ │ + ▼ ▼ + ┌─────────────────┐ ┌─────────────────┐ + │ Schema Config │ │ Generated Files │ + │ │ │ │ + └─────────────────┘ └─────────────────┘ +` + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Architecture'); + const description = _( + 'The idea-transformer follows a clear architectural pattern that ' + + 'separates concerns between schema loading, processing, and output ' + + 'generation. This design enables flexible plugin development and ' + + 'maintainable code generation workflows.' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Architecture Section Content */} +
    +

    {_('Architecture')}

    +

    + + The idea-transformer follows a clear architectural pattern + that separates concerns between schema loading, processing, + and output generation. This design enables flexible plugin + development and maintainable code generation workflows. + +

    + + {architectureDiagram} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/transformers/best-practices.tsx b/packages/www/plugins/docs/views/transformers/best-practices.tsx new file mode 100644 index 0000000..79c4d1d --- /dev/null +++ b/packages/www/plugins/docs/views/transformers/best-practices.tsx @@ -0,0 +1,181 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//docs +import { H1, P, C, Nav } from '../../components/index.js'; +import Layout from '../../components/Layout.js'; + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Best Practices'); + const description = _( + 'Best practices for maintainable, scalable, and reliable schema ' + + 'processing workflows' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + return ( +
    + {/* Best Practices Section Content */} +
    +

    {_('Best Practices')}

    +

    + + Following best practices ensures maintainable, scalable, and + reliable schema processing workflows. These guidelines help you + avoid common pitfalls and optimize your development experience. + +

    +
    + + {/* Horizontal Rule */} +
    + + {/* Schema Organization Section Content */} +
    +

    {_('Schema Organization')}

    +

    + + Organize your schemas for maintainability and clarity to + support team collaboration and long-term project success. + Proper organization makes schemas easier to understand + and modify. + +

    + +
      +
    • + {_('Use ')} {_('use')} + {_(' directives to split large schemas into manageable files')} +
    • +
    • + {_('Organize shared types and enums in separate files')} +
    • +
    • + {_('Follow consistent naming conventions across schemas')} +
    • +
    • + {_('Document complex relationships and business rules')} +
    • +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Plugin Development Section Content */} +
    +

    {_('Plugin Development')}

    +

    + + Follow these guidelines when developing plugins to ensure + reliability, maintainability, and type safety. Good plugin + development practices lead to more robust code generation. + +

    + +
      +
    • + {_('Always validate plugin configuration')} +
    • +
    • + {_('Use TypeScript for type safety')} +
    • +
    • + {_('Handle errors gracefully with meaningful messages')} +
    • +
    • + {_('Use the transformer\'s file loader for consistent path ' + + 'resolution')} +
    • +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Build Integration Section Content */} +
    +

    {_('Build Integration')}

    +

    + + Integrate schema processing effectively into your + workflow to maximize productivity and maintain consistency + across environments. Proper build integration ensures + reliable code generation. + +

    + +
      +
    • + {_('Add schema generation to your build process')} +
    • +
    • + {_('Use watch mode during development')} +
    • +
    • + {_('Version control generated files when appropriate')} +
    • +
    • + {_('Document the generation process for team members')} +
    • +
    +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/views/transformers/common-use-cases.tsx b/packages/www/plugins/docs/views/transformers/common-use-cases.tsx new file mode 100644 index 0000000..5ece968 --- /dev/null +++ b/packages/www/plugins/docs/views/transformers/common-use-cases.tsx @@ -0,0 +1,213 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, C, Nav } from '../../components/index.js'; +import Layout from '../../components/Layout.js'; + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Common Use Cases'); + const description = _( + 'Various use cases for code generation and schema processing with ' + + 'the idea-transformer library' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Common Use Cases Section Content */} +
    +

    {_('Common Use Cases')}

    +

    + + The idea-transformer library supports a wide variety of + use cases for code generation and schema processing. + These use cases demonstrate the flexibility and power + of the transformation system. + +

    +
    + + {/* Horizontal Rule */} +
    + + {/* Code Generation Section Content */} +
    +

    {_('Code Generation')}

    +

    + + Generate various code artifacts from your schema + definitions to maintain consistency across your + application. This use case covers the most common + code generation scenarios. + +

    + +
      +
    • + {_('Generate TypeScript interfaces from schema models')} +
    • +
    • + {_('Create enum definitions from schema enums')} +
    • +
    • + {_('Build API client libraries from schema definitions')} +
    • +
    • + {_('Generate database migration files')} +
    • +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Documentation Section Content */} +
    +

    {_('Documentation')}

    +

    + + Create comprehensive documentation from your schemas to + improve developer experience and API usability. This use + case focuses on generating human-readable documentation. + +

    + +
      +
    • + {_('Create API documentation from schema')} +
    • +
    • + {_('Generate schema reference guides')} +
    • +
    • + {_('Build interactive schema explorers')} +
    • +
    • + {_('Create validation rule documentation')} +
    • +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Validation Section Content */} +
    +

    {_('Validation')}

    +

    + + Build validation systems from your schema definitions to + ensure data integrity across your application. This use + case covers various validation library integrations. + +

    + +
      +
    • + {_('Generate validation schemas (')} + {_('Joi')}{_(', ')} + {_('Yup')}{_(', ')} + {_('Zod')}{_(')')} +
    • +
    • + {_('Create form validation rules')} +
    • +
    • + {_('Build API request/response validators')} +
    • +
    • + {_('Generate test fixtures and mock data')} +
    • +
    +
    + + {/* Horizontal Rule */} +
    + + {/* Build Integration Section Content */} +
    +

    {_('Build Integration')}

    +

    + + Integrate schema processing into your build pipeline for + automated code generation and consistent development work + flows. This use case covers various build system integrations. + +

    + +
      +
    • + {_('Integrate with webpack, rollup, or other bundlers')} +
    • +
    • + {_('Add to npm scripts for automated generation')} +
    • +
    • + {_('Use in CI/CD pipelines for consistent builds')} +
    • +
    • + {_('Create watch mode for development workflows')} +
    • +
    +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/views/transformers/error-handling.tsx b/packages/www/plugins/docs/views/transformers/error-handling.tsx new file mode 100644 index 0000000..9e256b2 --- /dev/null +++ b/packages/www/plugins/docs/views/transformers/error-handling.tsx @@ -0,0 +1,120 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, Nav } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//code example +//--------------------------------------------------------------------// + +const errorHandlingExample = + `import { Exception } from '@stackpress/idea-parser'; + +try { + const transformer = await Transformer.load('./schema.idea'); + await transformer.transform(); +} catch (error) { + if (error instanceof Exception) { + console.error('Schema error:', error.message); + console.error('Error code:', error.code); + } else { + console.error('Unexpected error:', error); + } +}`; + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Error Handling'); + const description = _( + 'Comprehensive error handling for the idea-transformer library' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Error Handling Section Content */} +
    +

    {_('Error Handling')}

    +

    + + The idea-transformer library provides comprehensive error + handling to help you identify and resolve issues during + schema processing. This section covers error types and + handling strategies. + +

    + +

    + + The library provides comprehensive error handling with + detailed error messages: + +

    + + + {errorHandlingExample} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/views/transformers/examples.tsx b/packages/www/plugins/docs/views/transformers/examples.tsx new file mode 100644 index 0000000..08e5a97 --- /dev/null +++ b/packages/www/plugins/docs/views/transformers/examples.tsx @@ -0,0 +1,212 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, Nav } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const schemaExample = + `// schema.idea +model User { + id String @id + name String @required + email String @required @unique + role UserRole + profile Profile? +} + +enum UserRole { + ADMIN "admin" + USER "user" +} + +type Profile { + bio String + avatar String? +} + +plugin "./generate-types.js" { + output "./generated/types.ts" +}`; + +//--------------------------------------------------------------------// + +const pluginExample = + `// generate-types.js +export default async function generateTypes({ schema, config, transformer }) { + let content = ''; + + // Generate enums + if (schema.enum) { + for (const [name, enumDef] of Object.entries(schema.enum)) { + content += \`export enum \${name} {\\n\`; + for (const [key, value] of Object.entries(enumDef)) { + content += \` \${key} = "\${value}",\\n\`; + } + content += '}\\n\\n'; + } + } + + // Generate interfaces + if (schema.model) { + for (const [name, model] of Object.entries(schema.model)) { + content += \`export interface \${name} {\\n\`; + for (const column of model.columns) { + const optional = column.required ? '' : '?'; + content += \` \${column.name}\${optional}: \${mapType(column.type)};\\n\`; + } + content += '}\\n\\n'; + } + } + + const outputPath = await transformer.loader.absolute(config.output); + await writeFile(outputPath, content); +}`; + +//--------------------------------------------------------------------// + +const cliExample = + `{ + "scripts": { + "generate": "idea transform --input ./schema.idea", + "build": "npm run generate && tsc", + "dev": "npm run generate && npm run build -- --watch" + } +}`; + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Examples'); + const description = _( + 'Practical examples of using the idea-transformer library for ' + + 'common code generation tasks' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + return ( +
    + {/* Examples Section Content */} +
    +

    {_('Examples')}

    +

    + + This section provides practical examples of using the + idea-transformer library for common code generation tasks. + These examples demonstrate real-world usage patterns and + best practices. + +

    +
    + + {/* Horizontal Rule */} +
    + + {/* TypeScript Interface Generation Section Content */} +
    +

    {_('TypeScript Interface Generation')}

    +

    + + This example shows how to create a plugin that generates + TypeScript interfaces from schema models. The example includes + both the schema definition and the plugin implementation. + +

    +
    + + {/* Horizontal Rule */} +
    + + {/* Schema Definition Section Content */} +
    +

    {_('Schema Definition')}

    + + {schemaExample} + + +

    {_('Plugin Implementation')}

    + + {pluginExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* CLI Integration Section Content */} +
    +

    {_('CLI Integration')}

    +

    + + This example demonstrates how to integrate the idea-transformer + CLI into your npm scripts for automated code generation during + the build process. + +

    + + {cliExample} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/transformers/introduction.tsx b/packages/www/plugins/docs/views/transformers/introduction.tsx new file mode 100644 index 0000000..51b9f76 --- /dev/null +++ b/packages/www/plugins/docs/views/transformers/introduction.tsx @@ -0,0 +1,171 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, H3, P, C, Nav } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const installationExample = `npm install @stackpress/idea-transformer`; + +//--------------------------------------------------------------------// + +const basicUsageExample = + `import Transformer from '@stackpress/idea-transformer'; + +// Load and process a schema +const transformer = await Transformer.load('./schema.idea'); +const schema = await transformer.schema(); +await transformer.transform();`; + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Introduction'); + const description = _( + 'Get started with the idea-transformer library' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Overview Section Content */} +
    +

    {_('Overview')}

    +

    + + The idea-transformer library provides a complete solution for + processing schema files and generating code through a flexible + plugin system. This library serves as the core transformation + engine that bridges schema definitions with code generation. + +

    + +

    + + The idea-transformer library provides a complete solution for: + +

    +
    + + {/* Horizontal Rule */} +
    + + {/* Features List Section Content */} +
    +
      +
    • + {_('Schema Processing:')} + + Load and parse .idea schema files with support for + 'imports and merging + +
    • +
    • + {_('Plugin System:')} + + Execute transformation plugins that generate code, + documentation, or other outputs + +
    • +
    • + {_('CLI Integration:')} + + Command-line interface for processing schemas in + build pipelines + +
    • +
    • + {_('Type Safety:')} + + Full TypeScript support with comprehensive type + definitions + +
    • +
    +
    + + {/* Quick Start Section Content */} +
    +

    {_('Quick Start')}

    +

    + + Get started with the idea-transformer library in just a few + steps. This section shows you how to install the library and + perform basic schema transformation operations. + +

    + +

    {_('Installation')}

    + + {installationExample} + + +

    {_('Basic Usage')}

    + + {basicUsageExample} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} diff --git a/packages/www/plugins/docs/views/transformers/usage-patterns.tsx b/packages/www/plugins/docs/views/transformers/usage-patterns.tsx new file mode 100644 index 0000000..5b48c01 --- /dev/null +++ b/packages/www/plugins/docs/views/transformers/usage-patterns.tsx @@ -0,0 +1,180 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage, Translate } from 'r22n'; +//local +import { H1, P, Nav } from '../../components/index.js'; +import Code from '../../components/Code.js'; +import Layout from '../../components/Layout.js'; + +//code examples +//--------------------------------------------------------------------// + +const basicTransformationExample = + `import Transformer from '@stackpress/idea-transformer'; + +// Load schema and execute plugins +const transformer = await Transformer.load('./schema.idea'); +await transformer.transform();` + +//--------------------------------------------------------------------// + +const cliUsageExample = + `# Process schema file +node cli.js transform --input ./schema.idea + +# Using short flag +node cli.js transform --i ./schema.idea` + +//--------------------------------------------------------------------// + +const pluginDevelopmentExample = + `import type { PluginProps } from '@stackpress/idea-transformer/types'; + +export default async function myPlugin(props: PluginProps<{}>) { + const { config, schema, transformer, cwd } = props; + + // Process schema and generate output + const content = generateFromSchema(schema); + const outputPath = await transformer.loader.absolute(config.output); + await writeFile(outputPath, content); +}` + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Usage Patterns'); + const description = _( + 'Common usage patterns for integrating the idea-transformer library ' + + 'into different development workflows' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Usage Patterns Section Content */} +
    +

    {_('Usage Patterns')}

    +

    + + This section demonstrates common usage patterns for the + idea-transformer library. These patterns show how to integrate + the transformer into different development workflows and use + cases. + +

    +
    + + {/* Horizontal Rule */} +
    + + {/* Basic Schema Transformation Section Content */} +
    +

    {_('Basic Schema Transformation')}

    +

    + + The most common usage pattern involves loading a schema file + and executing all configured plugins. This pattern is suitable + for most build processes and automated workflows. + +

    + + {basicTransformationExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* CLI Usage Section Content */} +
    +

    {_('CLI Usage')}

    +

    + + The command-line interface provides a simple way to process + schemas from build scripts or CI/CD pipelines. This pattern is + ideal for integrating schema processing into existing build + workflows. + +

    + + {cliUsageExample} + +
    + + {/* Horizontal Rule */} +
    + + {/* Plugin Development Section Content */} +
    +

    {_('Plugin Development')}

    +

    + + Creating custom plugins allows you to extend the transformer + with domain-specific code generation. This pattern shows the + basic structure for developing type-safe plugins. + +

    + + {pluginDevelopmentExample} + +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + + + + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/views/tutorials/api-client-plugin.tsx b/packages/www/plugins/docs/views/tutorials/api-client-plugin.tsx new file mode 100644 index 0000000..144280c --- /dev/null +++ b/packages/www/plugins/docs/views/tutorials/api-client-plugin.tsx @@ -0,0 +1,209 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage } from 'r22n'; +import clsx from 'clsx'; +//local +import { Nav } from '../../components/index.js'; +import Layout from '../../components/Layout.js'; +//components +import { + AdvancedFeatures, + BestPractices, + Implementation, + Introduction, + Overview, + PluginStructure, + Prerequisites, + SchemaConfiguration, + Troubleshooting, + UsageExamples +} from '../../components/api-client-plugin/index.js'; + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx( + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500' +); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('API Client Generator Plugin Tutorial'); + const description = _( + 'A comprehensive guide to creating a plugin that generates REST and ' + + ' GraphQL API clients from .idea schema files' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + + return ( + +
    + {_('On this page')} +
    + +
    + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Page Contents Section */} + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + } + > + + + ); +} diff --git a/packages/www/plugins/docs/views/tutorials/graphql-schema-plugin.tsx b/packages/www/plugins/docs/views/tutorials/graphql-schema-plugin.tsx new file mode 100644 index 0000000..f146822 --- /dev/null +++ b/packages/www/plugins/docs/views/tutorials/graphql-schema-plugin.tsx @@ -0,0 +1,216 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage } from 'r22n'; +import clsx from 'clsx'; +//local +import Layout from '../../components/Layout.js'; +import { Nav } from '../../components/index.js'; +//components +import { + AdvancedFeatures, + BestPractices, + Conclusion, + Implementation, + Introduction, + Overview, + PluginStructure, + Prerequisites, + SchemaConfiguration, + Troubleshooting, + UsageExamples +} from '../../components/graphql-schema-plugin/index.js'; + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx( + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500' +); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('GraphQL Schema Generator Plugin Tutorial'); + const description = _( + 'A comprehensive guide to creating a plugin that generates GraphQL type definitions from .idea schema files' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + + return ( + +
    + {_('On this page')} +
    + +
    + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Page Section */} + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + //props + const { data, session, request, response } = props; + return ( + } + > + + + ); +} diff --git a/packages/www/plugins/docs/views/tutorials/html-form-plugin.tsx b/packages/www/plugins/docs/views/tutorials/html-form-plugin.tsx new file mode 100644 index 0000000..b0f309e --- /dev/null +++ b/packages/www/plugins/docs/views/tutorials/html-form-plugin.tsx @@ -0,0 +1,223 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage } from 'r22n'; +import clsx from 'clsx'; +//local +import { Nav } from '../../components/index.js'; +import Layout from '../../components/Layout.js'; +//components +import { + CreatePluginStructure, + ErrorHandlingAndBestPractices, + GenerateCompleteHtmlDocument, + GeneratedOutput, + ImplementFormElementGeneration, + ImplementFormLayoutAndStyling, + Introduction, + Overview, + Prerequisites, + UnderstandingSchemaStructure, + UsageInSchema +} from '../../components/html-form-plugin/index.js'; + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx( + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500' +); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('HTML Form Plugin Tutorial'); + const description = _( + 'A comprehensive guide to creating a plugin that generates HTML' + + 'forms from processed .idea schema definitions' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + + return ( + +
    + {_('On this page')} +
    + +
    + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Page Section */} + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + } + > + + + ); +} diff --git a/packages/www/plugins/docs/views/tutorials/markdown-documentation-plugin.tsx b/packages/www/plugins/docs/views/tutorials/markdown-documentation-plugin.tsx new file mode 100644 index 0000000..69dbefe --- /dev/null +++ b/packages/www/plugins/docs/views/tutorials/markdown-documentation-plugin.tsx @@ -0,0 +1,262 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage } from 'r22n'; +import clsx from 'clsx'; +//local +import { Nav } from '../../components/index.js'; +import Layout from '../../components/Layout.js'; +//components +import { + AdvancedFeatures, + Conclusion, + CreatePluginStructure, + ErrorHandlingAndBestPractices, + GenerateModelsDocumentation, + GenerateTypesEnumsProps, + GeneratedOutput, + ImplementDocumentationGeneration, + Introduction, + Overview, + Prerequisites, + UnderstandingSchemaStructure, + UsageInSchema, + UtilityFunctions +} from '../../components/markdown-documentation-plugin/index.js'; + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx( + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500' +); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Markdown Documentation Plugin Tutorial'); + const description = _( + 'A comprehensive guide to creating a plugin that generates markdown documentation from schema definitions' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + + return ( + +
    + {_('On this page')} +
    + +
    + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Page Section */} + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + {/* Horizontal Rule */} + + + {/* Horizontal Rule */} +
    + + {/* Horizontal Rule */} + +
    + + {/* Horizontal Rule */} + + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + //props + const { data, session, request, response } = props; + return ( + } + > + + + ); +} diff --git a/packages/www/plugins/docs/views/tutorials/mysql-table-plugin.tsx b/packages/www/plugins/docs/views/tutorials/mysql-table-plugin.tsx new file mode 100644 index 0000000..06ff3f5 --- /dev/null +++ b/packages/www/plugins/docs/views/tutorials/mysql-table-plugin.tsx @@ -0,0 +1,225 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage } from 'r22n'; +import clsx from 'clsx'; +//local +import { Nav } from '../../components/index.js'; +import Layout from '../../components/Layout.js'; +//components +import { + BestPractices, + Conclusion, + CreatePluginStructure, + GenerateSqlStatements, + GeneratedOutput, + ImplementTypeMapping, + Introduction, + Overview, + Prerequisites, + UnderstandingSchemaStructure, + UsageInSchema +} from '../../components/mysql-table-plugin/index.js'; + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx( + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500' +); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('MySQL Tables Plugin'); + const description = _( + 'A guide to creating a plugin that generates MySQL tables from' + + ' schema definitions' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + + return ( + +
    + {_('On this page')} +
    + +
    + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Page Section */} + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + } + > + + + ); +} \ No newline at end of file diff --git a/packages/www/plugins/docs/views/tutorials/openapi-specification-plugin.tsx b/packages/www/plugins/docs/views/tutorials/openapi-specification-plugin.tsx new file mode 100644 index 0000000..c6cf41c --- /dev/null +++ b/packages/www/plugins/docs/views/tutorials/openapi-specification-plugin.tsx @@ -0,0 +1,200 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage } from 'r22n'; +import clsx from 'clsx'; +//local +import { Nav } from '../../components/index.js'; +import Layout from '../../components/Layout.js'; +//components +import { + AdvancedFeatures, + BasicImplementation, + BestPractices, + ConfigurationOptions, + Conclusion, + Introduction, + Overview, + SchemaProcessing, + Troubleshooting, + UsageExamples +} from '../../components/openapi-specification-plugin/index.js'; + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx( + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500' +); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('OpenAPI Specification Generator Plugin Tutorial'); + const description = _( + 'A comprehensive guide to creating a plugin that generates OpenAPI' + + ' 3.0 specifications from .idea schema files' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + + return ( + +
    + {_('On this page')} +
    + +
    + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Page Contents Section */} + + + {/* Horizontal Rule */} +
    + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + } + > + + + ); +} diff --git a/packages/www/plugins/docs/views/tutorials/test-data-plugin.tsx b/packages/www/plugins/docs/views/tutorials/test-data-plugin.tsx new file mode 100644 index 0000000..cb63cdb --- /dev/null +++ b/packages/www/plugins/docs/views/tutorials/test-data-plugin.tsx @@ -0,0 +1,175 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage } from 'r22n'; +import clsx from 'clsx'; +//local +import { Nav } from '../../components/index.js'; +import Layout from '../../components/Layout.js'; +import { + Conclusion, + CorePluginFunction, + GenerationFunctions, + Overview, + PluginStructure, + Prerequisites, + SchemaConfiguration +} from '../../components/test-data-plugin/index.js'; + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx( + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500' +); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Test Data Generator Plugin Tutorial'); + const description = _( + 'A guide to creating a plugin that generates mock data from .idea files' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + + return ( + +
    + {_('On this page')} +
    + +
    + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Page Contents Section */} + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + } + > + + + ); +} diff --git a/packages/www/plugins/docs/views/tutorials/tsmorph-plugin-guide.tsx b/packages/www/plugins/docs/views/tutorials/tsmorph-plugin-guide.tsx new file mode 100644 index 0000000..cfa4483 --- /dev/null +++ b/packages/www/plugins/docs/views/tutorials/tsmorph-plugin-guide.tsx @@ -0,0 +1,223 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage } from 'r22n'; +import clsx from 'clsx'; +//local +import { Nav } from '../../components/index.js'; +import Layout from '../../components/Layout.js'; +import { + AdvanceTsMorphPlugin, + BestPractices, + CreateFirstPlugin, + Installation, + Introduction, + References, + SettingUpProject, + TestingYourPlugin, + Troubleshooting, + UnderstandingTsMorphBasics +} from '../../components/ts-morph-plugin-guide/index.js'; + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx( + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500' +); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('TSMorph Plugin Guide'); + const description = _( + 'A guide to creating powerful code generation plugins using TSMorph' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + + return ( + +
    + {_('On this page')} +
    + +
    + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Page Content Section */} + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + } + > + + + ); +} diff --git a/packages/www/plugins/docs/views/tutorials/typescript-interface-plugin.tsx b/packages/www/plugins/docs/views/tutorials/typescript-interface-plugin.tsx new file mode 100644 index 0000000..5830762 --- /dev/null +++ b/packages/www/plugins/docs/views/tutorials/typescript-interface-plugin.tsx @@ -0,0 +1,219 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage } from 'r22n'; +import clsx from 'clsx'; +//local +import { Nav } from '../../components/index.js'; +import Layout from '../../components/Layout.js'; +//components +import { + AdvancedFeatures, + BestPractices, + Implementation, + Introduction, + Overview, + PluginStructure, + Prerequisites, + SchemaConfiguration, + Troubleshooting, + UsageExamples, +} from '../../components/typescript-interface-plugin/index.js'; + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx( + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500' +); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('TypeScript Interface Generator Plugin Tutorial'); + const description = _( + 'A comprehensive guide to creating a plugin that generates' + + ' TypeScript interfaces from .idea schema files' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + return ( + +
    + {_('On this page')} +
    + +
    + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Page Section */} + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + //props + const { data, session, request, response } = props; + return ( + } + > + + + ); +} diff --git a/packages/www/plugins/docs/views/tutorials/validation-plugin.tsx b/packages/www/plugins/docs/views/tutorials/validation-plugin.tsx new file mode 100644 index 0000000..7d25174 --- /dev/null +++ b/packages/www/plugins/docs/views/tutorials/validation-plugin.tsx @@ -0,0 +1,221 @@ +//modules +import type { + ServerConfigProps, + ServerPageProps +} from 'stackpress/view/client'; +import { useLanguage } from 'r22n'; +import clsx from 'clsx'; +//local +import { Nav } from '../../components/index.js'; +import Layout from '../../components/Layout.js'; +//components +import { + AdvancedFeatures, + BestPractices, + Implementation, + Introduction, + Overview, + PluginStructure, + Prerequisites, + SchemaConfiguration, + Troubleshooting, + UsageExamples +} from '../../components/validation-plugin/index.js'; + +//styles +//--------------------------------------------------------------------// + +const anchorStyles = clsx( + 'cursor-pointer', + 'hover:text-blue-700', + 'text-blue-500' +); + +//--------------------------------------------------------------------// + +export function Head(props: ServerPageProps) { + //props + const { request, styles = [] } = props; + //hooks + const { _ } = useLanguage(); + //variables + const title = _('Validation Schema Generator Plugin Tutorial'); + const description = _( + 'A comprehensive guide to creating a plugin that generates ' + + 'Zod validation schemas from .idea schema files' + ); + return ( + <> + {title} + + + + + + + + + + + + {styles.map((href, index) => ( + + ))} + + ) +} + +export function Right() { + //hooks + const { _ } = useLanguage(); + return ( + +
    + {_('On this page')} +
    + +
    + ); +} + +export function Body() { + //hooks + const { _ } = useLanguage(); + + return ( +
    + {/* Page Contents Section */} + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + + + {/* Horizontal Rule */} +
    + + {/* Page Navigation */} +
    + ); +} + +export default function Page(props: ServerPageProps) { + const { data, session, request, response } = props; + return ( + } + > + + + ); +} diff --git a/packages/www/public/favicon.ico b/packages/www/public/favicon.ico new file mode 100644 index 0000000..e93fedb Binary files /dev/null and b/packages/www/public/favicon.ico differ diff --git a/packages/www/public/icon.png b/packages/www/public/icon.png new file mode 100644 index 0000000..063b4e7 Binary files /dev/null and b/packages/www/public/icon.png differ diff --git a/packages/www/public/search-list.json b/packages/www/public/search-list.json new file mode 100644 index 0000000..c20e611 --- /dev/null +++ b/packages/www/public/search-list.json @@ -0,0 +1,853 @@ +[ + { + "title": "Introduction", + "description": "The .idea file format is a declarative schema definition language designed to simplify application development by providing a single source of truth for data structures, relationships, and code generation.", + "url": "/docs/introduction/" + }, + { + "title": "What is idea?", + "description": "The .idea file format is a declarative schema definition language designed to simplify application development by providing a single source of truth for data structures, relationships, and code generation.", + "url": "/docs/introduction/" + }, + { + "title": "Getting Started", + "description": "The following is a guide to get you started with Idea.", + "url": "/docs/getting-started/" + }, + { + "title": "Specification", + "description": "The specification section provides a comprehensive overview of the .idea file format, including its syntax, data types, and structure.", + "url": "/docs/specifications/syntax-overview/" + }, + { + "title": "Syntax Overview - Specification", + "description": "The specification section provides a comprehensive overview of the .idea file format, including its syntax, data types, and structure.", + "url": "/docs/specifications/syntax-overview/" + }, + { + "title": "Data Types - Specification", + "description": "The .idea format supports four primary data types that form the building blocks of your application schema.", + "url": "/docs/specifications/data-types/" + }, + { + "title": "(Enums) Data Types - Specification", + "description": "The .idea format supports four primary data types that form the building blocks of your application schema.", + "url": "/docs/specifications/data-types/#enums" + }, + { + "title": "(Props) Data Types - Specification", + "description": "Props are reusable property configurations that define common field behaviors, validation rules, and UI components. They promote consistency and reduce duplication across your schema.", + "url": "/docs/specifications/data-types/#props-1" + }, + { + "title": "(Type) Data Types - Specification", + "description": "The .idea format supports four primary data types that form the building blocks of your application schema.", + "url": "/docs/specifications/data-types/#type" + }, + { + "title": "(Models) Data Types - Specification", + "description": "Models represent the core entities in your application, typically corresponding to database tables or API resources. They define the structure, relationships, and behavior of your data.", + "url": "/docs/specifications/data-types/#models" + }, + { + "title": "Schema Elements - Specification", + "description": "Schema elements are the building blocks of your application schema.", + "url": "/docs/specifications/schema-elements/" + }, + { + "title": "Schema Structure - Specification", + "description": "A complete .idea schema file can contain multiple elements organized in a specific structure.", + "url": "/docs/specifications/schema-structure/" + }, + { + "title": "Schema Directives - Specification", + "description": "Schema directives are special declarations that control how the schema is processed and what outputs are generated.", + "url": "/docs/specifications/schema-structure/" + }, + { + "title": "(Use) Schema Directives - Specification", + "description": "Schema directives are special declarations that control how the schema is processed and what outputs are generated.", + "url": "/docs/specifications/schema-directives#use" + }, + { + "title": "(Plugin) Schema Directives - Specification", + "description": "Schema directives are special declarations that control how the schema is processed and what outputs are generated.", + "url": "/docs/specifications/schema-directives#plugin" + }, + { + "title": "Processing Flow - Specification", + "description": "The .idea file format follows a structured processing flow:", + "url": "/docs/specifications/processing-flow/" + }, + { + "title": "Plugin System - Specification", + "description": "The plugin system enables extensible code generation from your schema definitions.", + "url": "/docs/specifications/plugin-system/" + }, + { + "title": "Complete Example - Specification", + "description": "Complete examples of how to use the .idea file format to generate various outputs like TypeScript interfaces, database schemas, API documentation, and more.", + "url": "/docs/specifications/complete-examples/" + }, + { + "title": "Best Practices - Specification", + "description": "Best practices for using the .idea file format to generate various outputs like TypeScript interfaces, database schemas, API documentation, and more.", + "url": "/docs/specifications/best-practices/" + }, + { + "title": "Error Handling - Specification", + "description": "Error handling is a crucial aspect of any application. The .idea file format provides a way to handle errors in a structured way.", + "url": "/docs/specifications/error-handling/" + }, + { + "title": "Installation - Parser", + "description": "A TypeScript library for parsing .idea schema files into Abstract Syntax Trees (AST) and converting them to readable JSON configurations. This library is designed to help developers work with schema definitions in a structured and type-safe manner.", + "url": "/docs/parser/installation/" + }, + { + "title": "Core Concepts - Parser", + "description": "Learn the core concepts of the Idea Parser library including schema structure, processing flow, and key components.", + "url": "/docs/parser/core-concepts/" + }, + { + "title": "API Reference - Parser", + "description": "Complete API reference for the Idea Parser library, including detailed documentation for all classes, methods, and interfaces.", + "url": "/docs/parser/api-reference/" + }, + { + "title": "Examples - Parser", + "description": "Practical examples showing how to use the Idea Parser library for parsing schema files and working with individual components.", + "url": "/docs/parser/examples/" + }, + { + "title": "Best Practices - Parser", + "description": "Best practices and guidelines for using the Idea Parser library effectively, including error handling, type safety, and common pitfalls to avoid.", + "url": "/docs/parser/best-practices/" + }, + { + "title": "Lexer API", + "description": "The Lexer class implements the Parser interface and provides tokenization and parsing utilities for schema code. It manages a dictionary of token definitions and handles the parsing process by matching patterns against the input code.", + "url": "/docs/parser/api-references/lexer/" + }, + { + "title": "Compiler API", + "description": "Compiler class documentation for the Idea Parser library, including methods for compiling AST tokens into structured JSON configurations.", + "url": "/docs/parser/api-references/compiler/" + }, + { + "title": "AST API", + "description": "AST (Abstract Syntax Tree) representation for the Idea Parser library, including node types and traversal methods.", + "url": "/docs/parser/api-references/ast/" + }, + { + "title": "Tokens API", + "description": "Tokens representation for the Idea Parser library, including token types and utilities.", + "url": "/docs/parser/api-references/tokens/" + }, + { + "title": "Exception Handling API", + "description": "Exception handling representation for the Idea Parser library, including error types and utilities.", + "url": "/docs/parser/api-references/exception-handling/" + }, + { + "title": "Transformers", + "description": "Introduction to the concept of transformers in the Idea Parser library, including their purpose and usage.", + "url": "/docs/transformers/introduction/" + }, + { + "title": "API Reference - Transformers", + "description": "Complete API reference for the transformers in the Idea Parser library, including detailed documentation for all classes, methods, and interfaces.", + "url": "/docs/transformers/api-reference/" + }, + { + "title": "Transformers API", + "description": "Complete API reference for the transformers in the Idea Parser library, including detailed documentation for all classes, methods, and interfaces.", + "url": "/docs/transformers/api-references/transformer/" + }, + { + "title": "Terminal API", + "description": "Complete API reference for the terminal in the Idea Parser library, including detailed documentation for all classes, methods, and interfaces.", + "url": "/docs/transformers/api-references/terminal/" + }, + { + "title": "Architecture - Transformers", + "description": "Learn about the architecture of transformers in the Idea Parser library, including their components and interactions.", + "url": "/docs/transformers/architecture/" + }, + { + "title": "Usage Patterns - Transformers", + "description": "Learn about the usage patterns of transformers in the Idea Parser library, including common scenarios and best practices.", + "url": "/docs/transformers/usage-patterns/" + }, + { + "title": "Common Use Cases - Transformers", + "description": "Explore common use cases for transformers in the Idea Parser library, including practical examples and scenarios.", + "url": "/docs/transformers/common-use-cases/" + }, + { + "title": "Examples - Transformers", + "description": "Explore practical examples of using transformers in the Idea Parser library, including code snippets and use case demonstrations.", + "url": "/docs/transformers/examples/" + }, + { + "title": "Error Handling - Transformers", + "description": "Explore error handling strategies for transformers in the Idea Parser library, including best practices and common pitfalls.", + "url": "/docs/transformers/error-handling/" + }, + { + "title": "Best Practices - Transformers", + "description": "Explore best practices for using transformers in the Idea Parser library, including tips and guidelines for effective implementation.", + "url": "/docs/transformers/best-practices/" + }, + { + "title": "Plugin", + "description": "The plugin system enables extensible code generation from your schema definitions. Plugins can be developed to generate code in various programming languages, frameworks, or for specific use cases.", + "url": "/docs/plugin-development/plugin-development-guide" + }, + { + "title": "Plugin Examples", + "description": "Explore examples of plugins developed for the Idea Parser library, showcasing various use cases and implementations.", + "url": "/docs/plugin-development/plugin-examples" + }, + { + "title": "Plugin Configuration", + "description": "Learn how to configure and customize plugins in the Idea Parser library, including setup instructions and configuration options.", + "url": "/docs/plugin-development/plugin-configuration" + }, + { + "title": "Error Handling - Plugin", + "description": "Learn about error handling strategies for plugins in the Idea Parser library, including best practices and common pitfalls.", + "url": "/docs/plugin-development/error-handling" + }, + { + "title": "Best Practices - Plugin", + "description": "Learn about best practices for developing plugins in the Idea Parser library, including tips and guidelines for effective implementation.", + "url": "/docs/plugin-development/best-practices" + }, + { + "title": "Available Tutorials - Plugin", + "description": "Explore available tutorials for developing plugins in the Idea Parser library, including step-by-step guides and practical examples.", + "url": "/docs/plugin-development/available-tutorials" + }, + { + "title": "Advanced Tutorials - Plugin", + "description": "Explore advanced tutorials for developing plugins in the Idea Parser library, including step-by-step guides and practical examples.", + "url": "/docs/plugin-development/advanced-tutorials" + }, + { + "title": "Getting Started - Plugin", + "description": "Explore advanced tutorials for developing plugins in the Idea Parser library, including step-by-step guides and practical examples.", + "url": "/docs/plugin-development/getting-started" + }, + + { + "title": "Markdown Documentation Plugin Guide", + "description": "A comprehensive guide to developing a plugin for generating markdown documentation from your Idea schema files.", + "url": "/docs/tutorials/markdown-documentation-plugin" + }, + { + "title": "TypeScript Interface Plugin Guide", + "description": "Learn how to create a plugin that generates TypeScript interfaces from your Idea schema definitions.", + "url": "/docs/tutorials/typescript-interface-plugin" + }, + { + "title": "GraphQL Schema Plugin Guide", + "description": "A step-by-step guide to building a plugin that converts Idea schemas into GraphQL schema definitions.", + "url": "/docs/tutorials/graphql-schema-plugin" + }, + { + "title": "Validation Plugin Guide", + "description": "Create validation logic plugins for your Idea schemas, including custom validators and error handling.", + "url": "/docs/tutorials/validation-plugin" + }, + { + "title": "API Client Plugin Guide", + "description": "Build plugins that generate API client code from your Idea schema models and endpoints.", + "url": "/docs/tutorials/api-client-plugin" + }, + { + "title": "HTML Form Plugin Guide", + "description": "Generate HTML forms and form validation logic from your Idea schema field definitions.", + "url": "/docs/tutorials/html-form-plugin" + }, + { + "title": "Test Data Plugin Guide", + "description": "Create plugins that generate mock data and test fixtures based on your Idea schema structures.", + "url": "/docs/tutorials/test-data-plugin" + }, + { + "title": "OpenAPI Specification Plugin Guide", + "description": "Convert your Idea schemas into OpenAPI (Swagger) specifications for API documentation and testing.", + "url": "/docs/tutorials/openapi-specification-plugin" + }, + { + "title": "API Client Plugin - Introduction", + "description": "Introduction to building API client plugins for the Idea Parser library.", + "url": "/docs/tutorials/api-client-plugin#introduction" + }, + { + "title": "API Client Plugin - Overview", + "description": "Overview of API client plugin development concepts and features.", + "url": "/docs/tutorials/api-client-plugin#overview" + }, + { + "title": "API Client Plugin - Prerequisites", + "description": "Prerequisites and requirements for building API client plugins.", + "url": "/docs/tutorials/api-client-plugin#prerequisites" + }, + { + "title": "API Client Plugin - Plugin Structure", + "description": "Understanding the structure and organization of API client plugins.", + "url": "/docs/tutorials/api-client-plugin#plugin-structure" + }, + { + "title": "API Client Plugin - Schema Configuration", + "description": "Configuring schemas for API client plugin development.", + "url": "/docs/tutorials/api-client-plugin#schema-configuration" + }, + { + "title": "API Client Plugin - Implementation", + "description": "Implementation guide for API client plugin functionality.", + "url": "/docs/tutorials/api-client-plugin#implementation" + }, + { + "title": "API Client Plugin - Advanced Features", + "description": "Advanced features and techniques for API client plugins.", + "url": "/docs/tutorials/api-client-plugin#advanced-features" + }, + { + "title": "API Client Plugin - Usage Examples", + "description": "Practical examples of using API client plugins.", + "url": "/docs/tutorials/api-client-plugin#usage-examples" + }, + { + "title": "API Client Plugin - Troubleshooting", + "description": "Troubleshooting common issues with API client plugins.", + "url": "/docs/tutorials/api-client-plugin#troubleshooting" + }, + { + "title": "API Client Plugin - Best Practices", + "description": "Best practices for developing API client plugins.", + "url": "/docs/tutorials/api-client-plugin#best-practices" + }, + { + "title": "GraphQL Schema Plugin - Introduction", + "description": "Introduction to building GraphQL schema plugins for the Idea Parser library.", + "url": "/docs/tutorials/graphql-schema-plugin#introduction" + }, + { + "title": "GraphQL Schema Plugin - Overview", + "description": "Overview of GraphQL schema plugin development concepts and features.", + "url": "/docs/tutorials/graphql-schema-plugin#overview" + }, + { + "title": "GraphQL Schema Plugin - Prerequisites", + "description": "Prerequisites and requirements for building GraphQL schema plugins.", + "url": "/docs/tutorials/graphql-schema-plugin#prerequisites" + }, + { + "title": "GraphQL Schema Plugin - Plugin Structure", + "description": "Understanding the structure and organization of GraphQL schema plugins.", + "url": "/docs/tutorials/graphql-schema-plugin#plugin-structure" + }, + { + "title": "GraphQL Schema Plugin - Schema Configuration", + "description": "Configuring schemas for GraphQL schema plugin development.", + "url": "/docs/tutorials/graphql-schema-plugin#schema-configuration" + }, + { + "title": "GraphQL Schema Plugin - Implementation", + "description": "Implementation guide for GraphQL schema plugin functionality.", + "url": "/docs/tutorials/graphql-schema-plugin#implementation" + }, + { + "title": "GraphQL Schema Plugin - Advanced Features", + "description": "Advanced features and techniques for GraphQL schema plugins.", + "url": "/docs/tutorials/graphql-schema-plugin#advanced-features" + }, + { + "title": "GraphQL Schema Plugin - Usage Examples", + "description": "Practical examples of using GraphQL schema plugins.", + "url": "/docs/tutorials/graphql-schema-plugin#usage-examples" + }, + { + "title": "GraphQL Schema Plugin - Troubleshooting", + "description": "Troubleshooting common issues with GraphQL schema plugins.", + "url": "/docs/tutorials/graphql-schema-plugin#troubleshooting" + }, + { + "title": "GraphQL Schema Plugin - Best Practices", + "description": "Best practices for developing GraphQL schema plugins.", + "url": "/docs/tutorials/graphql-schema-plugin#best-practices" + }, + { + "title": "GraphQL Schema Plugin - Conclusion", + "description": "Conclusion and next steps for GraphQL schema plugin development.", + "url": "/docs/tutorials/graphql-schema-plugin#conclusion" + }, + { + "title": "HTML Form Plugin - Introduction", + "description": "Introduction to building HTML form plugins for the Idea Parser library.", + "url": "/docs/tutorials/html-form-plugin#introduction" + }, + { + "title": "HTML Form Plugin - Overview", + "description": "Overview of HTML form plugin development concepts and features.", + "url": "/docs/tutorials/html-form-plugin#overview" + }, + { + "title": "HTML Form Plugin - Prerequisites", + "description": "Prerequisites and requirements for building HTML form plugins.", + "url": "/docs/tutorials/html-form-plugin#prerequisites" + }, + { + "title": "HTML Form Plugin - Understanding Schema Structure", + "description": "Understanding schema structure for HTML form plugin development.", + "url": "/docs/tutorials/html-form-plugin#understanding-schema-structure" + }, + { + "title": "HTML Form Plugin - Create Plugin Structure", + "description": "Creating the plugin structure for HTML form plugins.", + "url": "/docs/tutorials/html-form-plugin#create-plugin-structure" + }, + { + "title": "HTML Form Plugin - Implement Form Element Generation", + "description": "Implementation guide for form element generation in HTML form plugins.", + "url": "/docs/tutorials/html-form-plugin#implement-form-element-generation" + }, + { + "title": "HTML Form Plugin - Implement Form Layout and Styling", + "description": "Implementation guide for form layout and styling in HTML form plugins.", + "url": "/docs/tutorials/html-form-plugin#implement-form-layout-styling" + }, + { + "title": "HTML Form Plugin - Generate Complete HTML Document", + "description": "Generating complete HTML documents with HTML form plugins.", + "url": "/docs/tutorials/html-form-plugin#generate-complete-html-document" + }, + { + "title": "HTML Form Plugin - Usage in Schema", + "description": "Using HTML form plugins in schema definitions.", + "url": "/docs/tutorials/html-form-plugin#usage-in-schema" + }, + { + "title": "HTML Form Plugin - Generated Output", + "description": "Understanding the generated output from HTML form plugins.", + "url": "/docs/tutorials/html-form-plugin#generated-output" + }, + { + "title": "HTML Form Plugin - Error Handling and Best Practices", + "description": "Error handling and best practices for HTML form plugins.", + "url": "/docs/tutorials/html-form-plugin#error-handling-best-practices" + }, + { + "title": "Markdown Documentation Plugin - Introduction", + "description": "Introduction to building markdown documentation plugins for the Idea Parser library.", + "url": "/docs/tutorials/markdown-documentation-plugin#introduction" + }, + { + "title": "Markdown Documentation Plugin - Overview", + "description": "Overview of markdown documentation plugin development concepts and features.", + "url": "/docs/tutorials/markdown-documentation-plugin#overview" + }, + { + "title": "Markdown Documentation Plugin - Prerequisites", + "description": "Prerequisites and requirements for building markdown documentation plugins.", + "url": "/docs/tutorials/markdown-documentation-plugin#prerequisites" + }, + { + "title": "Markdown Documentation Plugin - Understanding Schema Structure", + "description": "Understanding schema structure for markdown documentation plugin development.", + "url": "/docs/tutorials/markdown-documentation-plugin#understanding-schema-structure" + }, + { + "title": "Markdown Documentation Plugin - Create Plugin Structure", + "description": "Creating the plugin structure for markdown documentation plugins.", + "url": "/docs/tutorials/markdown-documentation-plugin#create-plugin-structure" + }, + { + "title": "Markdown Documentation Plugin - Utility Functions", + "description": "Utility functions for markdown documentation plugin development.", + "url": "/docs/tutorials/markdown-documentation-plugin#utility-functions" + }, + { + "title": "Markdown Documentation Plugin - Generate Types, Enums & Props", + "description": "Generating documentation for types, enums, and props in markdown format.", + "url": "/docs/tutorials/markdown-documentation-plugin#generate-types-enums-props" + }, + { + "title": "Markdown Documentation Plugin - Generate Models Documentation", + "description": "Generating documentation for models in markdown format.", + "url": "/docs/tutorials/markdown-documentation-plugin#generate-models-documentation" + }, + { + "title": "Markdown Documentation Plugin - Implement Documentation Generation", + "description": "Implementation guide for documentation generation in markdown plugins.", + "url": "/docs/tutorials/markdown-documentation-plugin#implement-documentation-generation" + }, + { + "title": "Markdown Documentation Plugin - Advanced Features", + "description": "Advanced features and techniques for markdown documentation plugins.", + "url": "/docs/tutorials/markdown-documentation-plugin#advanced-features" + }, + { + "title": "Markdown Documentation Plugin - Usage in Schema", + "description": "Using markdown documentation plugins in schema definitions.", + "url": "/docs/tutorials/markdown-documentation-plugin#usage-in-schema" + }, + { + "title": "Markdown Documentation Plugin - Generated Output", + "description": "Understanding the generated output from markdown documentation plugins.", + "url": "/docs/tutorials/markdown-documentation-plugin#generated-output" + }, + { + "title": "Markdown Documentation Plugin - Error Handling and Best Practices", + "description": "Error handling and best practices for markdown documentation plugins.", + "url": "/docs/tutorials/markdown-documentation-plugin#error-handling-best-practices" + }, + { + "title": "Markdown Documentation Plugin - Conclusion", + "description": "Conclusion and next steps for markdown documentation plugin development.", + "url": "/docs/tutorials/markdown-documentation-plugin#conclusion" + }, + { + "title": "MySQL Table Plugin - Introduction", + "description": "Introduction to building MySQL table plugins for the Idea Parser library.", + "url": "/docs/tutorials/mysql-table-plugin#introduction" + }, + { + "title": "MySQL Table Plugin - Overview", + "description": "Overview of MySQL table plugin development concepts and features.", + "url": "/docs/tutorials/mysql-table-plugin#overview" + }, + { + "title": "MySQL Table Plugin - Prerequisites", + "description": "Prerequisites and requirements for building MySQL table plugins.", + "url": "/docs/tutorials/mysql-table-plugin#prerequisites" + }, + { + "title": "MySQL Table Plugin - Understanding Schema Structure", + "description": "Understanding schema structure for MySQL table plugin development.", + "url": "/docs/tutorials/mysql-table-plugin#understanding-schema-structure" + }, + { + "title": "MySQL Table Plugin - Create Plugin Structure", + "description": "Creating the plugin structure for MySQL table plugins.", + "url": "/docs/tutorials/mysql-table-plugin#create-plugin-structure" + }, + { + "title": "MySQL Table Plugin - Implement Type Mapping", + "description": "Implementation guide for type mapping in MySQL table plugins.", + "url": "/docs/tutorials/mysql-table-plugin#implement-type-mapping" + }, + { + "title": "MySQL Table Plugin - Generate SQL Statements", + "description": "Generating SQL statements with MySQL table plugins.", + "url": "/docs/tutorials/mysql-table-plugin#generate-sql-statements" + }, + { + "title": "MySQL Table Plugin - Usage in Schema", + "description": "Using MySQL table plugins in schema definitions.", + "url": "/docs/tutorials/mysql-table-plugin#usage-in-schema" + }, + { + "title": "MySQL Table Plugin - Generated Output", + "description": "Understanding the generated output from MySQL table plugins.", + "url": "/docs/tutorials/mysql-table-plugin#generated-output" + }, + { + "title": "MySQL Table Plugin - Best Practices", + "description": "Best practices for developing MySQL table plugins.", + "url": "/docs/tutorials/mysql-table-plugin#best-practices" + }, + { + "title": "MySQL Table Plugin - Conclusion", + "description": "Conclusion and next steps for MySQL table plugin development.", + "url": "/docs/tutorials/mysql-table-plugin#conclusion" + }, + { + "title": "OpenAPI Specification Plugin - Introduction", + "description": "Introduction to building OpenAPI specification plugins for the Idea Parser library.", + "url": "/docs/tutorials/openapi-specification-plugin#introduction" + }, + { + "title": "OpenAPI Specification Plugin - Overview", + "description": "Overview of OpenAPI specification plugin development concepts and features.", + "url": "/docs/tutorials/openapi-specification-plugin#overview" + }, + { + "title": "OpenAPI Specification Plugin - Configuration Options", + "description": "Configuration options for OpenAPI specification plugins.", + "url": "/docs/tutorials/openapi-specification-plugin#configuration-options" + }, + { + "title": "OpenAPI Specification Plugin - Schema Processing", + "description": "Schema processing techniques for OpenAPI specification plugins.", + "url": "/docs/tutorials/openapi-specification-plugin#schema-processing" + }, + { + "title": "OpenAPI Specification Plugin - Basic Implementation", + "description": "Basic implementation guide for OpenAPI specification plugins.", + "url": "/docs/tutorials/openapi-specification-plugin#basic-implementation" + }, + { + "title": "OpenAPI Specification Plugin - Advanced Features", + "description": "Advanced features and techniques for OpenAPI specification plugins.", + "url": "/docs/tutorials/openapi-specification-plugin#advanced-features" + }, + { + "title": "OpenAPI Specification Plugin - Usage Examples", + "description": "Practical examples of using OpenAPI specification plugins.", + "url": "/docs/tutorials/openapi-specification-plugin#usage-examples" + }, + { + "title": "OpenAPI Specification Plugin - Troubleshooting", + "description": "Troubleshooting common issues with OpenAPI specification plugins.", + "url": "/docs/tutorials/openapi-specification-plugin#troubleshooting" + }, + { + "title": "OpenAPI Specification Plugin - Best Practices", + "description": "Best practices for developing OpenAPI specification plugins.", + "url": "/docs/tutorials/openapi-specification-plugin#best-practices" + }, + { + "title": "OpenAPI Specification Plugin - Conclusion", + "description": "Conclusion and next steps for OpenAPI specification plugin development.", + "url": "/docs/tutorials/openapi-specification-plugin#conclusion" + }, + { + "title": "Test Data Plugin - Overview", + "description": "Overview of test data plugin development concepts and features.", + "url": "/docs/tutorials/test-data-plugin#overview" + }, + { + "title": "Test Data Plugin - Prerequisites", + "description": "Prerequisites and requirements for building test data plugins.", + "url": "/docs/tutorials/test-data-plugin#prerequisites" + }, + { + "title": "Test Data Plugin - Plugin Structure", + "description": "Understanding the structure and organization of test data plugins.", + "url": "/docs/tutorials/test-data-plugin#plugin-structure" + }, + { + "title": "Test Data Plugin - Schema Configuration", + "description": "Configuring schemas for test data plugin development.", + "url": "/docs/tutorials/test-data-plugin#schema-configuration" + }, + { + "title": "Test Data Plugin - Core Plugin Function", + "description": "Core functionality implementation for test data plugins.", + "url": "/docs/tutorials/test-data-plugin#core-plugin-function" + }, + { + "title": "Test Data Plugin - Generation Functions", + "description": "Data generation functions for test data plugins.", + "url": "/docs/tutorials/test-data-plugin#generation-functions" + }, + { + "title": "Test Data Plugin - Conclusion", + "description": "Conclusion and next steps for test data plugin development.", + "url": "/docs/tutorials/test-data-plugin#conclusion" + }, + { + "title": "TS Morph Plugin Guide", + "description": "A comprehensive guide to developing a plugin using TS Morph for the Idea Parser library, including setup instructions, code examples, and best practices.", + "url": "/docs/tutorials/tsmorph-plugin-guide" + }, + { + "title": "TS Morph Plugin Guide - Introduction", + "description": "Introduction to building plugins with TS Morph for the Idea Parser library.", + "url": "/docs/tutorials/tsmorph-plugin-guide#introduction" + }, + { + "title": "TS Morph Plugin Guide - Installation", + "description": "Installation guide for TS Morph plugin development.", + "url": "/docs/tutorials/tsmorph-plugin-guide#installation" + }, + { + "title": "TS Morph Plugin Guide - Setting Up The Project", + "description": "Setting up your project for TS Morph plugin development.", + "url": "/docs/tutorials/tsmorph-plugin-guide#setting-up-project" + }, + { + "title": "TS Morph Plugin Guide - Understanding TS Morph Basics", + "description": "Understanding the basics of TS Morph for plugin development.", + "url": "/docs/tutorials/tsmorph-plugin-guide#understanding-ts-morph-basics" + }, + { + "title": "TS Morph Plugin Guide - Creating Your First Plugin", + "description": "Step-by-step guide to creating your first TS Morph plugin.", + "url": "/docs/tutorials/tsmorph-plugin-guide#creating-first-plugin" + }, + { + "title": "TS Morph Plugin Guide - Advanced TS Morph Features", + "description": "Advanced features and techniques for TS Morph plugins.", + "url": "/docs/tutorials/tsmorph-plugin-guide#advanced-ts-morph-features" + }, + { + "title": "TS Morph Plugin Guide - Testing Your Plugin", + "description": "Testing strategies and techniques for TS Morph plugins.", + "url": "/docs/tutorials/tsmorph-plugin-guide#testing-your-plugin" + }, + { + "title": "TS Morph Plugin Guide - Best Practices", + "description": "Best practices for developing TS Morph plugins.", + "url": "/docs/tutorials/tsmorph-plugin-guide#best-practices" + }, + { + "title": "TS Morph Plugin Guide - Troubleshooting", + "description": "Troubleshooting common issues with TS Morph plugins.", + "url": "/docs/tutorials/tsmorph-plugin-guide#troubleshooting" + }, + { + "title": "TS Morph Plugin Guide - References", + "description": "References and additional resources for TS Morph plugin development.", + "url": "/docs/tutorials/tsmorph-plugin-guide#references" + }, + { + "title": "MySQL Tables Plugin Guide", + "description": "A comprehensive guide to developing MySQL table plugins for the Idea Parser library.", + "url": "/docs/tutorials/mysql-table-plugin" + }, + { + "title": "MySQL Tables Plugin Guide - Prerequisites", + "description": "Prerequisites and requirements for building MySQL table plugins.", + "url": "/docs/tutorials/mysql-table-plugin#prerequisites" + }, + { + "title": "MySQL Tables Plugin Guide - Understanding Schema Structure", + "description": "Understanding schema structure for MySQL table plugin development.", + "url": "/docs/tutorials/mysql-table-plugin#understanding-schema" + }, + { + "title": "TypeScript Interface Plugin - Introduction", + "description": "Introduction to building TypeScript interface plugins for the Idea Parser library.", + "url": "/docs/tutorials/typescript-interface-plugin#introduction" + }, + { + "title": "TypeScript Interface Plugin - Overview", + "description": "Overview of TypeScript interface plugin development concepts and features.", + "url": "/docs/tutorials/typescript-interface-plugin#overview" + }, + { + "title": "TypeScript Interface Plugin - Prerequisites", + "description": "Prerequisites and requirements for building TypeScript interface plugins.", + "url": "/docs/tutorials/typescript-interface-plugin#prerequisites" + }, + { + "title": "TypeScript Interface Plugin - Plugin Structure", + "description": "Understanding the structure and organization of TypeScript interface plugins.", + "url": "/docs/tutorials/typescript-interface-plugin#plugin-structure" + }, + { + "title": "TypeScript Interface Plugin - Schema Configuration", + "description": "Configuring schemas for TypeScript interface plugin development.", + "url": "/docs/tutorials/typescript-interface-plugin#schema-configuration" + }, + { + "title": "TypeScript Interface Plugin - Implementation", + "description": "Implementation guide for TypeScript interface plugin functionality.", + "url": "/docs/tutorials/typescript-interface-plugin#implementation" + }, + { + "title": "TypeScript Interface Plugin - Advanced Features", + "description": "Advanced features and techniques for TypeScript interface plugins.", + "url": "/docs/tutorials/typescript-interface-plugin#advanced-features" + }, + { + "title": "TypeScript Interface Plugin - Usage Examples", + "description": "Practical examples of using TypeScript interface plugins.", + "url": "/docs/tutorials/typescript-interface-plugin#usage-examples" + }, + { + "title": "TypeScript Interface Plugin - Troubleshooting", + "description": "Troubleshooting common issues with TypeScript interface plugins.", + "url": "/docs/tutorials/typescript-interface-plugin#troubleshooting" + }, + { + "title": "TypeScript Interface Plugin - Best Practices", + "description": "Best practices for developing TypeScript interface plugins.", + "url": "/docs/tutorials/typescript-interface-plugin#best-practices" + }, + { + "title": "Validation Plugin - Introduction", + "description": "Introduction to building validation plugins for the Idea Parser library.", + "url": "/docs/tutorials/validation-plugin#introduction" + }, + { + "title": "Validation Plugin - Overview", + "description": "Overview of validation plugin development concepts and features.", + "url": "/docs/tutorials/validation-plugin#overview" + }, + { + "title": "Validation Plugin - Prerequisites", + "description": "Prerequisites and requirements for building validation plugins.", + "url": "/docs/tutorials/validation-plugin#prerequisites" + }, + { + "title": "Validation Plugin - Plugin Structure", + "description": "Understanding the structure and organization of validation plugins.", + "url": "/docs/tutorials/validation-plugin#plugin-structure" + }, + { + "title": "Validation Plugin - Schema Configuration", + "description": "Configuring schemas for validation plugin development.", + "url": "/docs/tutorials/validation-plugin#schema-configuration" + }, + { + "title": "Validation Plugin - Implementation", + "description": "Implementation guide for validation plugin functionality.", + "url": "/docs/tutorials/validation-plugin#implementation" + }, + { + "title": "Validation Plugin - Advanced Features", + "description": "Advanced features and techniques for validation plugins.", + "url": "/docs/tutorials/validation-plugin#advanced-features" + }, + { + "title": "Validation Plugin - Usage Examples", + "description": "Practical examples of using validation plugins.", + "url": "/docs/tutorials/validation-plugin#usage-examples" + }, + { + "title": "Validation Plugin - Troubleshooting", + "description": "Troubleshooting common issues with validation plugins.", + "url": "/docs/tutorials/validation-plugin#troubleshooting" + }, + { + "title": "Validation Plugin - Best Practices", + "description": "Best practices for developing validation plugins.", + "url": "/docs/tutorials/validation-plugin#best-practices" + }, + { + "title": "Specifications - Data Types - Enums", + "description": "Detailed specification for enum data types in the Idea schema format.", + "url": "/docs/specifications/data-types#enums-component" + }, + { + "title": "Specifications - Data Types - Models", + "description": "Detailed specification for model data types in the Idea schema format.", + "url": "/docs/specifications/data-types#models-component" + }, + { + "title": "Specifications - Data Types - Props", + "description": "Detailed specification for prop data types in the Idea schema format.", + "url": "/docs/specifications/data-types#props-component" + }, + { + "title": "Specifications - Data Types - Type", + "description": "Detailed specification for type data types in the Idea schema format.", + "url": "/docs/specifications/data-types#type-component" + }, + { + "title": "Specifications - Schema Directives - Plugin", + "description": "Detailed specification for plugin schema directives in the Idea format.", + "url": "/docs/specifications/schema-directives#plugin-component" + }, + { + "title": "Specifications - Schema Directives - Use", + "description": "Detailed specification for use schema directives in the Idea format.", + "url": "/docs/specifications/schema-directives#use-component" + } +] \ No newline at end of file diff --git a/packages/www/public/styles/global.css b/packages/www/public/styles/global.css new file mode 100644 index 0000000..fd2c15d --- /dev/null +++ b/packages/www/public/styles/global.css @@ -0,0 +1,452 @@ +@import url("https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.2.0/css/all.min.css"); +@import url('https://fonts.googleapis.com/css2?family=Open+Sans:ital,wght@0,300..800;1,300..800&display=swap'); + +/* Default Theme +---------------------------------*/ +:root { + --primary: #1474FC !important; + --secondary: #F43980 !important; + --black: #000000 !important; + --white: #FFFFFF !important; + --info: #1474FC !important; + --error: #DC3545 !important; + --warning: #FF7B07 !important; + --success: #28A745 !important; + --muted: #666666 !important; + --bg0: #EFEFEF !important; + --bg1: #CFCFCF !important; + --bg2: #AFAFAF !important; + --bg3: #BABABA !important; + --bg4: #9F9F9F !important; + --bd0: #EFEFEF !important; + --bd1: #CFCFCF !important; + --bd2: #AFAFAF !important; + --bd3: #BABABA !important; + --bd4: #9F9F9F !important; + --bgi: #333333 !important; + --tx0: #000000 !important; + --tx1: #333333 !important; + --txi: #CFCFCF !important; + /* This fixes FOUC */ + display: none; +} + +.dark { + --muted: #999999 !important; + --bg0: #121212 !important; + --bg1: #222222 !important; + --bg2: #323232 !important; + --bg3: #424242 !important; + --bg4: #525252 !important; + --bd0: #121212 !important; + --bd1: #222222 !important; + --bd2: #323232 !important; + --bd3: #424242 !important; + --bd4: #525252 !important; + --bgi: #DBDBDB !important; + --tx0: #FFFFFF !important; + --tx1: #CFCFCF !important; + --txi: #222222 !important; +} + +/* Reset (normalize.css) +---------------------------------*/ + +html, body, #root { + font-family: "Open Sans", Arial, sans-serif; + font-size: 14px; + height: 100%; + margin: 0; + padding: 0; + overflow: hidden; + position: relative; + width: 100%; +} + +/* +1. Prevent padding and border from affecting element width. (https://github.com/mozdevs/cssremedy/issues/4) +2. Allow adding a border to an element by just adding a border-width. (https://github.com/tailwindcss/tailwindcss/pull/116) +2. [UnoCSS]: allow to override the default border color with css var `--un-default-border-color` +*/ + +*, +::before, +::after { + box-sizing: border-box; /* 1 */ + border-width: 0; /* 2 */ + border-style: solid; /* 2 */ + border-color: var(--un-default-border-color, #e5e7eb); /* 2 */ +} + +::before, +::after { + --un-content: ''; +} + +/* +1. Use a consistent sensible line-height in all browsers. +2. Prevent adjustments of font size after orientation changes in iOS. +3. Use a more readable tab size. +4. Use the user's configured `sans` font-family by default. +5. Use the user's configured `sans` font-feature-settings by default. +6. Use the user's configured `sans` font-variation-settings by default. +7. Disable tap highlights on iOS. +*/ + +html, +:host { + line-height: 1.5; /* 1 */ + -webkit-text-size-adjust: 100%; /* 2 */ + -moz-tab-size: 4; /* 3 */ + tab-size: 4; /* 3 */ + font-family: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji"; /* 4 */ + font-feature-settings: normal; /* 5 */ + font-variation-settings: normal; /* 6 */ + -webkit-tap-highlight-color: transparent; /* 7 */ +} + +/* +1. Remove the margin in all browsers. +2. Inherit line-height from `html` so users can set them as a class directly on the `html` element. +*/ + +body { + margin: 0; /* 1 */ + line-height: inherit; /* 2 */ +} + +/* +1. Add the correct height in Firefox. +2. Correct the inheritance of border color in Firefox. (https://bugzilla.mozilla.org/show_bug.cgi?id=190655) +3. Ensure horizontal rules are visible by default. +*/ + +hr { + height: 0; /* 1 */ + color: inherit; /* 2 */ + border-top-width: 1px; /* 3 */ +} + +/* +Add the correct text decoration in Chrome, Edge, and Safari. +*/ + +abbr:where([title]) { + text-decoration: underline dotted; +} + +/* +Remove the default font size and weight for headings. +*/ + +h1, +h2, +h3, +h4, +h5, +h6 { + font-size: inherit; + font-weight: inherit; +} + +/* +Reset links to optimize for opt-in styling instead of opt-out. +*/ + +a { + color: inherit; + text-decoration: inherit; +} + +/* +Add the correct font weight in Edge and Safari. +*/ + +b, +strong { + font-weight: bolder; +} + +/* +1. Use the user's configured `mono` font-family by default. +2. Use the user's configured `mono` font-feature-settings by default. +3. Use the user's configured `mono` font-variation-settings by default. +4. Correct the odd `em` font sizing in all browsers. +*/ + +code, +kbd, +samp, +pre { + font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace; /* 1 */ + font-feature-settings: normal; /* 2 */ + font-variation-settings: normal; /* 3 */ + font-size: 1em; /* 4 */ +} + +/* +Add the correct font size in all browsers. +*/ + +small { + font-size: 80%; +} + +/* +Prevent `sub` and `sup` elements from affecting the line height in all browsers. +*/ + +sub, +sup { + font-size: 75%; + line-height: 0; + position: relative; + vertical-align: baseline; +} + +sub { + bottom: -0.25em; +} + +sup { + top: -0.5em; +} + +/* +1. Remove text indentation from table contents in Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=999088, https://bugs.webkit.org/show_bug.cgi?id=201297) +2. Correct table border color inheritance in all Chrome and Safari. (https://bugs.chromium.org/p/chromium/issues/detail?id=935729, https://bugs.webkit.org/show_bug.cgi?id=195016) +3. Remove gaps between table borders by default. +*/ + +table { + text-indent: 0; /* 1 */ + border-color: inherit; /* 2 */ + border-collapse: collapse; /* 3 */ +} + +/* +1. Change the font styles in all browsers. +2. Remove the margin in Firefox and Safari. +3. Remove default padding in all browsers. +*/ + +button, +input, +optgroup, +select, +textarea { + font-family: inherit; /* 1 */ + font-feature-settings: inherit; /* 1 */ + font-variation-settings: inherit; /* 1 */ + font-size: 100%; /* 1 */ + font-weight: inherit; /* 1 */ + line-height: inherit; /* 1 */ + color: inherit; /* 1 */ + margin: 0; /* 2 */ + padding: 0; /* 3 */ +} + +/* +Remove the inheritance of text transform in Edge and Firefox. +*/ + +button, +select { + text-transform: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Remove default button styles. +*/ + +button, +[type='button'], +[type='reset'], +[type='submit'] { + -webkit-appearance: button; /* 1 */ + background-color: transparent; /* 2 */ + background-image: none; /* 2 */ +} + +/* +Use the modern Firefox focus style for all focusable elements. +*/ + +:-moz-focusring { + outline: auto; +} + +/* +Remove the additional `:invalid` styles in Firefox. (https://github.com/mozilla/gecko-dev/blob/2f9eacd9d3d995c937b4251a5557d95d494c9be1/layout/style/res/forms.css#L728-L737) +*/ + +:-moz-ui-invalid { + box-shadow: none; +} + +/* +Add the correct vertical alignment in Chrome and Firefox. +*/ + +progress { + vertical-align: baseline; +} + +/* +Correct the cursor style of increment and decrement buttons in Safari. +*/ + +::-webkit-inner-spin-button, +::-webkit-outer-spin-button { + height: auto; +} + +/* +1. Correct the odd appearance in Chrome and Safari. +2. Correct the outline style in Safari. +*/ + +[type='search'] { + -webkit-appearance: textfield; /* 1 */ + outline-offset: -2px; /* 2 */ +} + +/* +Remove the inner padding in Chrome and Safari on macOS. +*/ + +::-webkit-search-decoration { + -webkit-appearance: none; +} + +/* +1. Correct the inability to style clickable types in iOS and Safari. +2. Change font properties to `inherit` in Safari. +*/ + +::-webkit-file-upload-button { + -webkit-appearance: button; /* 1 */ + font: inherit; /* 2 */ +} + +/* +Add the correct display in Chrome and Safari. +*/ + +summary { + display: list-item; +} + +/* +Removes the default spacing for appropriate elements. +*/ + +blockquote, +dl, +dd, +h1, +h2, +h3, +h4, +h5, +h6, +hr, +figure, +p, +pre { + margin: 0; +} + +fieldset { + margin: 0; + padding: 0; +} + +legend { + padding: 0; +} + +ol, +ul, +menu { + list-style: none; + margin: 0; + padding: 0; +} + +dialog { + padding: 0; +} + +/* +Prevent resizing textareas horizontally by default. +*/ + +textarea { + resize: vertical; +} + +/* +1. Reset the default placeholder opacity in Firefox. (https://github.com/tailwindlabs/tailwindcss/issues/3300) +2. Set the default placeholder color to the user's configured gray 400 color. +*/ + +input::placeholder, +textarea::placeholder { + opacity: 1; /* 1 */ + color: #9ca3af; /* 2 */ +} + +/* +Set the default cursor for buttons. +*/ + +button, +[role="button"] { + cursor: pointer; +} + +/* +Make sure disabled buttons don't get the pointer cursor. +*/ + +:disabled { + cursor: default; +} + +/* +1. Make replaced elements `display: block` by default. (https://github.com/mozdevs/cssremedy/issues/14) +2. Add `vertical-align: middle` to align replaced elements more sensibly by default. (https://github.com/jensimmons/cssremedy/issues/14#issuecomment-634934210) + This can trigger a poorly considered lint error in some tools but is included by design. +*/ + +img, +svg, +video, +canvas, +audio, +iframe, +embed, +object { + display: block; /* 1 */ + vertical-align: middle; /* 2 */ +} + +/* +Constrain images and videos to the parent width and preserve their intrinsic aspect ratio. (https://github.com/mozdevs/cssremedy/issues/14) +*/ + +img, +video { + max-width: 100%; + height: auto; +} + +/* +Make elements with the HTML hidden attribute stay hidden by default. +*/ + +[hidden]:where(:not([hidden="until-found"])) { + display: none; +} \ No newline at end of file diff --git a/packages/www/tsconfig.json b/packages/www/tsconfig.json new file mode 100644 index 0000000..bb8e4a8 --- /dev/null +++ b/packages/www/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "stackpress/tsconfig/esm", + "compilerOptions": { + "module": "nodenext", + "moduleResolution": "nodenext", + "outDir": ".build", + }, + "include": [ + "config/**/*.ts", + "plugins/**/*.ts", + "plugins/**/*.tsx", + "scripts/**/*.ts" +, "archives/api.tsx" ], + "exclude": [ "dist", "node_modules", "tests" ] +} \ No newline at end of file diff --git a/packages/www/uno.config.ts b/packages/www/uno.config.ts new file mode 100644 index 0000000..84edf95 --- /dev/null +++ b/packages/www/uno.config.ts @@ -0,0 +1,19 @@ +import { defineConfig, presetWind3 } from 'unocss'; +import presetStackpress from 'stackpress/unocss'; + +export default defineConfig({ + content: { + pipeline: { + include: [ + // include js/ts files + 'plugins/**/*.{js,ts,tsx}' + ], + // exclude files + // exclude: [] + }, + }, + presets: [ + presetWind3(), + presetStackpress() + ] +}) \ No newline at end of file diff --git a/packages/www/yarn.lock b/packages/www/yarn.lock new file mode 100644 index 0000000..0d654c8 --- /dev/null +++ b/packages/www/yarn.lock @@ -0,0 +1,3511 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@ampproject/remapping@^2.2.0", "@ampproject/remapping@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" + integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + +"@antfu/install-pkg@^1.0.0": + version "1.0.0" + resolved "https://registry.yarnpkg.com/@antfu/install-pkg/-/install-pkg-1.0.0.tgz#2912a150fc8b35ec912f583f90074ee98f64d66a" + integrity sha512-xvX6P/lo1B3ej0OsaErAjqgFYzYVcJpamjLAFLYh9vRJngBrMoUG7aVnrGTeqM7yxbyTD5p3F2+0/QUEh8Vzhw== + dependencies: + package-manager-detector "^0.2.8" + tinyexec "^0.3.2" + +"@antfu/utils@^8.1.0": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@antfu/utils/-/utils-8.1.1.tgz#95b1947d292a9a2efffba2081796dcaa05ecedfb" + integrity sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ== + +"@babel/code-frame@^7.26.2": + version "7.26.2" + resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" + integrity sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ== + dependencies: + "@babel/helper-validator-identifier" "^7.25.9" + js-tokens "^4.0.0" + picocolors "^1.0.0" + +"@babel/compat-data@^7.26.8": + version "7.26.8" + resolved "https://registry.yarnpkg.com/@babel/compat-data/-/compat-data-7.26.8.tgz#821c1d35641c355284d4a870b8a4a7b0c141e367" + integrity sha512-oH5UPLMWR3L2wEFLnFJ1TZXqHufiTKAiLfqw5zkhS4dKXLJ10yVztfil/twG8EDTA4F/tvVNw9nOl4ZMslB8rQ== + +"@babel/core@^7.23.9", "@babel/core@^7.26.10": + version "7.26.10" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.26.10.tgz#5c876f83c8c4dcb233ee4b670c0606f2ac3000f9" + integrity sha512-vMqyb7XCDMPvJFFOaT9kxtiRh42GwlZEg1/uIgtZshS5a/8OaduUfCi7kynKgc3Tw/6Uo2D+db9qBttghhmxwQ== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.26.2" + "@babel/generator" "^7.26.10" + "@babel/helper-compilation-targets" "^7.26.5" + "@babel/helper-module-transforms" "^7.26.0" + "@babel/helpers" "^7.26.10" + "@babel/parser" "^7.26.10" + "@babel/template" "^7.26.9" + "@babel/traverse" "^7.26.10" + "@babel/types" "^7.26.10" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + +"@babel/generator@^7.26.10", "@babel/generator@^7.27.0": + version "7.27.0" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.27.0.tgz#764382b5392e5b9aff93cadb190d0745866cbc2c" + integrity sha512-VybsKvpiN1gU1sdMZIp7FcqphVVKEwcuj02x73uvcHE0PTihx1nlBcowYWhDwjpoAXRv43+gDzyggGnn1XZhVw== + dependencies: + "@babel/parser" "^7.27.0" + "@babel/types" "^7.27.0" + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + jsesc "^3.0.2" + +"@babel/helper-compilation-targets@^7.26.5": + version "7.27.0" + resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.0.tgz#de0c753b1cd1d9ab55d473c5a5cf7170f0a81880" + integrity sha512-LVk7fbXml0H2xH34dFzKQ7TDZ2G4/rVTOrq9V+icbbadjbVxxeFeDsNHv2SrZeWoA+6ZiTyWYWtScEIW07EAcA== + dependencies: + "@babel/compat-data" "^7.26.8" + "@babel/helper-validator-option" "^7.25.9" + browserslist "^4.24.0" + lru-cache "^5.1.1" + semver "^6.3.1" + +"@babel/helper-module-imports@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz#e7f8d20602ebdbf9ebbea0a0751fb0f2a4141715" + integrity sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw== + dependencies: + "@babel/traverse" "^7.25.9" + "@babel/types" "^7.25.9" + +"@babel/helper-module-transforms@^7.26.0": + version "7.26.0" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz#8ce54ec9d592695e58d84cd884b7b5c6a2fdeeae" + integrity sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw== + dependencies: + "@babel/helper-module-imports" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + "@babel/traverse" "^7.25.9" + +"@babel/helper-plugin-utils@^7.25.9": + version "7.26.5" + resolved "https://registry.yarnpkg.com/@babel/helper-plugin-utils/-/helper-plugin-utils-7.26.5.tgz#18580d00c9934117ad719392c4f6585c9333cc35" + integrity sha512-RS+jZcRdZdRFzMyr+wcsaqOmld1/EqTghfaBGQQd/WnRdzdlvSZ//kF7U8VQTxf1ynZ4cjUcYgjVGx13ewNPMg== + +"@babel/helper-string-parser@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz#1aabb72ee72ed35789b4bbcad3ca2862ce614e8c" + integrity sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA== + +"@babel/helper-validator-identifier@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz#24b64e2c3ec7cd3b3c547729b8d16871f22cbdc7" + integrity sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ== + +"@babel/helper-validator-option@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz#86e45bd8a49ab7e03f276577f96179653d41da72" + integrity sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw== + +"@babel/helpers@^7.26.10": + version "7.27.0" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.27.0.tgz#53d156098defa8243eab0f32fa17589075a1b808" + integrity sha512-U5eyP/CTFPuNE3qk+WZMxFkp/4zUzdceQlfzf7DdGdhp+Fezd7HD+i8Y24ZuTMKX3wQBld449jijbGq6OdGNQg== + dependencies: + "@babel/template" "^7.27.0" + "@babel/types" "^7.27.0" + +"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.23.9", "@babel/parser@^7.26.10", "@babel/parser@^7.27.0": + version "7.27.0" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.0.tgz#3d7d6ee268e41d2600091cbd4e145ffee85a44ec" + integrity sha512-iaepho73/2Pz7w2eMS0Q5f83+0RKI7i4xmiYeBmDzfRVbQtTOG7Ts0S4HzJVsTMGI9keU8rNfuZr8DKfSt7Yyg== + dependencies: + "@babel/types" "^7.27.0" + +"@babel/plugin-transform-react-jsx-self@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz#c0b6cae9c1b73967f7f9eb2fca9536ba2fad2858" + integrity sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/plugin-transform-react-jsx-source@^7.25.9": + version "7.25.9" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz#4c6b8daa520b5f155b5fb55547d7c9fa91417503" + integrity sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg== + dependencies: + "@babel/helper-plugin-utils" "^7.25.9" + +"@babel/runtime@^7.3.1": + version "7.27.0" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.27.0.tgz#fbee7cf97c709518ecc1f590984481d5460d4762" + integrity sha512-VtPOkrdPHZsKc/clNqyi9WUA8TINkZ4cGk63UUE3u4pmB2k+ZMQRDuIOagv8UVd6j7k0T3+RRIb7beKTebNbcw== + dependencies: + regenerator-runtime "^0.14.0" + +"@babel/template@^7.26.9", "@babel/template@^7.27.0": + version "7.27.0" + resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.0.tgz#b253e5406cc1df1c57dcd18f11760c2dbf40c0b4" + integrity sha512-2ncevenBqXI6qRMukPlXwHKHchC7RyMuu4xv5JBXRfOGVcTy1mXCD12qrp7Jsoxll1EV3+9sE4GugBVRjT2jFA== + dependencies: + "@babel/code-frame" "^7.26.2" + "@babel/parser" "^7.27.0" + "@babel/types" "^7.27.0" + +"@babel/traverse@^7.25.9", "@babel/traverse@^7.26.10": + version "7.27.0" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.27.0.tgz#11d7e644779e166c0442f9a07274d02cd91d4a70" + integrity sha512-19lYZFzYVQkkHkl4Cy4WrAVcqBkgvV2YM2TU3xG6DIwO7O3ecbDPfW3yM3bjAGcqcQHi+CCtjMR3dIEHxsd6bA== + dependencies: + "@babel/code-frame" "^7.26.2" + "@babel/generator" "^7.27.0" + "@babel/parser" "^7.27.0" + "@babel/template" "^7.27.0" + "@babel/types" "^7.27.0" + debug "^4.3.1" + globals "^11.1.0" + +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.25.9", "@babel/types@^7.26.10", "@babel/types@^7.27.0": + version "7.27.0" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.27.0.tgz#ef9acb6b06c3173f6632d993ecb6d4ae470b4559" + integrity sha512-H45s8fVLYjbhFH62dIJ3WtmJ6RSPt/3DRO0ZcT2SUiYiQyz3BLVb9ADEnLl91m74aQPS3AzzeajZHYOalWe3bg== + dependencies: + "@babel/helper-string-parser" "^7.25.9" + "@babel/helper-validator-identifier" "^7.25.9" + +"@codemirror/autocomplete@^6.0.0": + version "6.18.6" + resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.18.6.tgz#de26e864a1ec8192a1b241eb86addbb612964ddb" + integrity sha512-PHHBXFomUs5DF+9tCOM/UoW6XQ4R44lLNNhRaW9PKPTU0D7lIjRg3ElxaJnTwsl/oHiR93WSXDBrekhoUGCPtg== + dependencies: + "@codemirror/language" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.17.0" + "@lezer/common" "^1.0.0" + +"@codemirror/commands@^6.0.0": + version "6.8.1" + resolved "https://registry.yarnpkg.com/@codemirror/commands/-/commands-6.8.1.tgz#639f5559d2f33f2582a2429c58cb0c1b925c7a30" + integrity sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw== + dependencies: + "@codemirror/language" "^6.0.0" + "@codemirror/state" "^6.4.0" + "@codemirror/view" "^6.27.0" + "@lezer/common" "^1.1.0" + +"@codemirror/language@^6.0.0": + version "6.11.0" + resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-6.11.0.tgz#5ae90972601497f4575f30811519d720bf7232c9" + integrity sha512-A7+f++LodNNc1wGgoRDTt78cOwWm9KVezApgjOMp1W4hM0898nsqBXwF+sbePE7ZRcjN7Sa1Z5m2oN27XkmEjQ== + dependencies: + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.23.0" + "@lezer/common" "^1.1.0" + "@lezer/highlight" "^1.0.0" + "@lezer/lr" "^1.0.0" + style-mod "^4.0.0" + +"@codemirror/lint@^6.0.0": + version "6.8.5" + resolved "https://registry.yarnpkg.com/@codemirror/lint/-/lint-6.8.5.tgz#9edaa808e764e28e07665b015951934c8ec3a418" + integrity sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA== + dependencies: + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.35.0" + crelt "^1.0.5" + +"@codemirror/search@^6.0.0": + version "6.5.10" + resolved "https://registry.yarnpkg.com/@codemirror/search/-/search-6.5.10.tgz#7367bfc88094d078b91c752bc74140fb565b55ee" + integrity sha512-RMdPdmsrUf53pb2VwflKGHEe1XVM07hI7vV2ntgw1dmqhimpatSJKva4VA9h4TLUDOD4EIF02201oZurpnEFsg== + dependencies: + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.0.0" + crelt "^1.0.5" + +"@codemirror/state@^6.0.0", "@codemirror/state@^6.4.0", "@codemirror/state@^6.5.0": + version "6.5.2" + resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.5.2.tgz#8eca3a64212a83367dc85475b7d78d5c9b7076c6" + integrity sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA== + dependencies: + "@marijn/find-cluster-break" "^1.0.0" + +"@codemirror/view@^6.0.0", "@codemirror/view@^6.17.0", "@codemirror/view@^6.23.0", "@codemirror/view@^6.27.0", "@codemirror/view@^6.35.0": + version "6.36.5" + resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.36.5.tgz#bb99b971322b9a3f8c7013f0ef6c4a511c0d750a" + integrity sha512-cd+FZEUlu3GQCYnguYm3EkhJ8KJVisqqUsCOKedBoAt/d9c76JUUap6U0UrpElln5k6VyrEOYliMuDAKIeDQLg== + dependencies: + "@codemirror/state" "^6.5.0" + style-mod "^4.1.0" + w3c-keyname "^2.2.4" + +"@cspotcode/source-map-support@^0.8.0": + version "0.8.1" + resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" + integrity sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw== + dependencies: + "@jridgewell/trace-mapping" "0.3.9" + +"@esbuild/aix-ppc64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.3.tgz#014180d9a149cffd95aaeead37179433f5ea5437" + integrity sha512-W8bFfPA8DowP8l//sxjJLSLkD8iEjMc7cBVyP+u4cEv9sM7mdUCkgsj+t0n/BWPFtv7WWCN5Yzj0N6FJNUUqBQ== + +"@esbuild/android-arm64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.3.tgz#649e47e04ddb24a27dc05c395724bc5f4c55cbfe" + integrity sha512-XelR6MzjlZuBM4f5z2IQHK6LkK34Cvv6Rj2EntER3lwCBFdg6h2lKbtRjpTTsdEjD/WSe1q8UyPBXP1x3i/wYQ== + +"@esbuild/android-arm@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.3.tgz#8a0f719c8dc28a4a6567ef7328c36ea85f568ff4" + integrity sha512-PuwVXbnP87Tcff5I9ngV0lmiSu40xw1At6i3GsU77U7cjDDB4s0X2cyFuBiDa1SBk9DnvWwnGvVaGBqoFWPb7A== + +"@esbuild/android-x64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.3.tgz#e2ab182d1fd06da9bef0784a13c28a7602d78009" + integrity sha512-ogtTpYHT/g1GWS/zKM0cc/tIebFjm1F9Aw1boQ2Y0eUQ+J89d0jFY//s9ei9jVIlkYi8AfOjiixcLJSGNSOAdQ== + +"@esbuild/darwin-arm64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.3.tgz#c7f3166fcece4d158a73dcfe71b2672ca0b1668b" + integrity sha512-eESK5yfPNTqpAmDfFWNsOhmIOaQA59tAcF/EfYvo5/QWQCzXn5iUSOnqt3ra3UdzBv073ykTtmeLJZGt3HhA+w== + +"@esbuild/darwin-x64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.3.tgz#d8c5342ec1a4bf4b1915643dfe031ba4b173a87a" + integrity sha512-Kd8glo7sIZtwOLcPbW0yLpKmBNWMANZhrC1r6K++uDR2zyzb6AeOYtI6udbtabmQpFaxJ8uduXMAo1gs5ozz8A== + +"@esbuild/freebsd-arm64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.3.tgz#9f7d789e2eb7747d4868817417cc968ffa84f35b" + integrity sha512-EJiyS70BYybOBpJth3M0KLOus0n+RRMKTYzhYhFeMwp7e/RaajXvP+BWlmEXNk6uk+KAu46j/kaQzr6au+JcIw== + +"@esbuild/freebsd-x64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.3.tgz#8ad35c51d084184a8e9e76bb4356e95350a64709" + integrity sha512-Q+wSjaLpGxYf7zC0kL0nDlhsfuFkoN+EXrx2KSB33RhinWzejOd6AvgmP5JbkgXKmjhmpfgKZq24pneodYqE8Q== + +"@esbuild/linux-arm64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.3.tgz#3af0da3d9186092a9edd4e28fa342f57d9e3cd30" + integrity sha512-xCUgnNYhRD5bb1C1nqrDV1PfkwgbswTTBRbAd8aH5PhYzikdf/ddtsYyMXFfGSsb/6t6QaPSzxtbfAZr9uox4A== + +"@esbuild/linux-arm@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.3.tgz#e91cafa95e4474b3ae3d54da12e006b782e57225" + integrity sha512-dUOVmAUzuHy2ZOKIHIKHCm58HKzFqd+puLaS424h6I85GlSDRZIA5ycBixb3mFgM0Jdh+ZOSB6KptX30DD8YOQ== + +"@esbuild/linux-ia32@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.3.tgz#81025732d85b68ee510161b94acdf7e3007ea177" + integrity sha512-yplPOpczHOO4jTYKmuYuANI3WhvIPSVANGcNUeMlxH4twz/TeXuzEP41tGKNGWJjuMhotpGabeFYGAOU2ummBw== + +"@esbuild/linux-loong64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.3.tgz#3c744e4c8d5e1148cbe60a71a11b58ed8ee5deb8" + integrity sha512-P4BLP5/fjyihmXCELRGrLd793q/lBtKMQl8ARGpDxgzgIKJDRJ/u4r1A/HgpBpKpKZelGct2PGI4T+axcedf6g== + +"@esbuild/linux-mips64el@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.3.tgz#1dfe2a5d63702db9034cc6b10b3087cc0424ec26" + integrity sha512-eRAOV2ODpu6P5divMEMa26RRqb2yUoYsuQQOuFUexUoQndm4MdpXXDBbUoKIc0iPa4aCO7gIhtnYomkn2x+bag== + +"@esbuild/linux-ppc64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.3.tgz#2e85d9764c04a1ebb346dc0813ea05952c9a5c56" + integrity sha512-ZC4jV2p7VbzTlnl8nZKLcBkfzIf4Yad1SJM4ZMKYnJqZFD4rTI+pBG65u8ev4jk3/MPwY9DvGn50wi3uhdaghg== + +"@esbuild/linux-riscv64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.3.tgz#a9ea3334556b09f85ccbfead58c803d305092415" + integrity sha512-LDDODcFzNtECTrUUbVCs6j9/bDVqy7DDRsuIXJg6so+mFksgwG7ZVnTruYi5V+z3eE5y+BJZw7VvUadkbfg7QA== + +"@esbuild/linux-s390x@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.3.tgz#f6a7cb67969222b200974de58f105dfe8e99448d" + integrity sha512-s+w/NOY2k0yC2p9SLen+ymflgcpRkvwwa02fqmAwhBRI3SC12uiS10edHHXlVWwfAagYSY5UpmT/zISXPMW3tQ== + +"@esbuild/linux-x64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.3.tgz#a237d3578ecdd184a3066b1f425e314ade0f8033" + integrity sha512-nQHDz4pXjSDC6UfOE1Fw9Q8d6GCAd9KdvMZpfVGWSJztYCarRgSDfOVBY5xwhQXseiyxapkiSJi/5/ja8mRFFA== + +"@esbuild/netbsd-arm64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.3.tgz#4c15c68d8149614ddb6a56f9c85ae62ccca08259" + integrity sha512-1QaLtOWq0mzK6tzzp0jRN3eccmN3hezey7mhLnzC6oNlJoUJz4nym5ZD7mDnS/LZQgkrhEbEiTn515lPeLpgWA== + +"@esbuild/netbsd-x64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.3.tgz#12f6856f8c54c2d7d0a8a64a9711c01a743878d5" + integrity sha512-i5Hm68HXHdgv8wkrt+10Bc50zM0/eonPb/a/OFVfB6Qvpiirco5gBA5bz7S2SHuU+Y4LWn/zehzNX14Sp4r27g== + +"@esbuild/openbsd-arm64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.3.tgz#ca078dad4a34df192c60233b058db2ca3d94bc5c" + integrity sha512-zGAVApJEYTbOC6H/3QBr2mq3upG/LBEXr85/pTtKiv2IXcgKV0RT0QA/hSXZqSvLEpXeIxah7LczB4lkiYhTAQ== + +"@esbuild/openbsd-x64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.3.tgz#c9178adb60e140e03a881d0791248489c79f95b2" + integrity sha512-fpqctI45NnCIDKBH5AXQBsD0NDPbEFczK98hk/aa6HJxbl+UtLkJV2+Bvy5hLSLk3LHmqt0NTkKNso1A9y1a4w== + +"@esbuild/sunos-x64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.3.tgz#03765eb6d4214ff27e5230af779e80790d1ee09f" + integrity sha512-ROJhm7d8bk9dMCUZjkS8fgzsPAZEjtRJqCAmVgB0gMrvG7hfmPmz9k1rwO4jSiblFjYmNvbECL9uhaPzONMfgA== + +"@esbuild/win32-arm64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.3.tgz#f1c867bd1730a9b8dfc461785ec6462e349411ea" + integrity sha512-YWcow8peiHpNBiIXHwaswPnAXLsLVygFwCB3A7Bh5jRkIBFWHGmNQ48AlX4xDvQNoMZlPYzjVOQDYEzWCqufMQ== + +"@esbuild/win32-ia32@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.3.tgz#77491f59ef6c9ddf41df70670d5678beb3acc322" + integrity sha512-qspTZOIGoXVS4DpNqUYUs9UxVb04khS1Degaw/MnfMe7goQ3lTfQ13Vw4qY/Nj0979BGvMRpAYbs/BAxEvU8ew== + +"@esbuild/win32-x64@0.25.3": + version "0.25.3" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.3.tgz#b17a2171f9074df9e91bfb07ef99a892ac06412a" + integrity sha512-ICgUR+kPimx0vvRzf+N/7L7tVSQeE3BYY+NhHRHXS1kBuPO7z2+7ea2HbhDyZdTephgvNvKrlDDKUexuCVBVvg== + +"@iconify/types@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@iconify/types/-/types-2.0.0.tgz#ab0e9ea681d6c8a1214f30cd741fe3a20cc57f57" + integrity sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg== + +"@iconify/utils@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@iconify/utils/-/utils-2.3.0.tgz#1bbbf8c477ebe9a7cacaea78b1b7e8937f9cbfba" + integrity sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA== + dependencies: + "@antfu/install-pkg" "^1.0.0" + "@antfu/utils" "^8.1.0" + "@iconify/types" "^2.0.0" + debug "^4.4.0" + globals "^15.14.0" + kolorist "^1.8.0" + local-pkg "^1.0.0" + mlly "^1.7.4" + +"@inquirer/checkbox@^4.0.2": + version "4.1.5" + resolved "https://registry.yarnpkg.com/@inquirer/checkbox/-/checkbox-4.1.5.tgz#891bb32ca98eb6ee2889f71d79722705e2241161" + integrity sha512-swPczVU+at65xa5uPfNP9u3qx/alNwiaykiI/ExpsmMSQW55trmZcwhYWzw/7fj+n6Q8z1eENvR7vFfq9oPSAQ== + dependencies: + "@inquirer/core" "^10.1.10" + "@inquirer/figures" "^1.0.11" + "@inquirer/type" "^3.0.6" + ansi-escapes "^4.3.2" + yoctocolors-cjs "^2.1.2" + +"@inquirer/confirm@^5.0.2": + version "5.1.9" + resolved "https://registry.yarnpkg.com/@inquirer/confirm/-/confirm-5.1.9.tgz#c858b6a3decb458241ec36ca9a9117477338076a" + integrity sha512-NgQCnHqFTjF7Ys2fsqK2WtnA8X1kHyInyG+nMIuHowVTIgIuS10T4AznI/PvbqSpJqjCUqNBlKGh1v3bwLFL4w== + dependencies: + "@inquirer/core" "^10.1.10" + "@inquirer/type" "^3.0.6" + +"@inquirer/core@^10.1.10": + version "10.1.10" + resolved "https://registry.yarnpkg.com/@inquirer/core/-/core-10.1.10.tgz#222a374e3768536a1eb0adf7516c436d5f4a291d" + integrity sha512-roDaKeY1PYY0aCqhRmXihrHjoSW2A00pV3Ke5fTpMCkzcGF64R8e0lw3dK+eLEHwS4vB5RnW1wuQmvzoRul8Mw== + dependencies: + "@inquirer/figures" "^1.0.11" + "@inquirer/type" "^3.0.6" + ansi-escapes "^4.3.2" + cli-width "^4.1.0" + mute-stream "^2.0.0" + signal-exit "^4.1.0" + wrap-ansi "^6.2.0" + yoctocolors-cjs "^2.1.2" + +"@inquirer/editor@^4.1.0": + version "4.2.10" + resolved "https://registry.yarnpkg.com/@inquirer/editor/-/editor-4.2.10.tgz#45e399313ee857857248bd539b8e832aa0fb60b3" + integrity sha512-5GVWJ+qeI6BzR6TIInLP9SXhWCEcvgFQYmcRG6d6RIlhFjM5TyG18paTGBgRYyEouvCmzeco47x9zX9tQEofkw== + dependencies: + "@inquirer/core" "^10.1.10" + "@inquirer/type" "^3.0.6" + external-editor "^3.1.0" + +"@inquirer/expand@^4.0.2": + version "4.0.12" + resolved "https://registry.yarnpkg.com/@inquirer/expand/-/expand-4.0.12.tgz#1e4554f509a435f966e2b91395a503d77df35c17" + integrity sha512-jV8QoZE1fC0vPe6TnsOfig+qwu7Iza1pkXoUJ3SroRagrt2hxiL+RbM432YAihNR7m7XnU0HWl/WQ35RIGmXHw== + dependencies: + "@inquirer/core" "^10.1.10" + "@inquirer/type" "^3.0.6" + yoctocolors-cjs "^2.1.2" + +"@inquirer/figures@^1.0.11": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@inquirer/figures/-/figures-1.0.11.tgz#4744e6db95288fea1dead779554859710a959a21" + integrity sha512-eOg92lvrn/aRUqbxRyvpEWnrvRuTYRifixHkYVpJiygTgVSBIHDqLh0SrMQXkafvULg3ck11V7xvR+zcgvpHFw== + +"@inquirer/input@^4.0.2": + version "4.1.9" + resolved "https://registry.yarnpkg.com/@inquirer/input/-/input-4.1.9.tgz#e93888d48c89bdb7f8e10bdd94572b636375749a" + integrity sha512-mshNG24Ij5KqsQtOZMgj5TwEjIf+F2HOESk6bjMwGWgcH5UBe8UoljwzNFHqdMbGYbgAf6v2wU/X9CAdKJzgOA== + dependencies: + "@inquirer/core" "^10.1.10" + "@inquirer/type" "^3.0.6" + +"@inquirer/number@^3.0.2": + version "3.0.12" + resolved "https://registry.yarnpkg.com/@inquirer/number/-/number-3.0.12.tgz#e027d27425ee2a81a7ccb9fdc750129edd291067" + integrity sha512-7HRFHxbPCA4e4jMxTQglHJwP+v/kpFsCf2szzfBHy98Wlc3L08HL76UDiA87TOdX5fwj2HMOLWqRWv9Pnn+Z5Q== + dependencies: + "@inquirer/core" "^10.1.10" + "@inquirer/type" "^3.0.6" + +"@inquirer/password@^4.0.2": + version "4.0.12" + resolved "https://registry.yarnpkg.com/@inquirer/password/-/password-4.0.12.tgz#f1a663bc5cf88699643cf6c83626a1ae77e580b5" + integrity sha512-FlOB0zvuELPEbnBYiPaOdJIaDzb2PmJ7ghi/SVwIHDDSQ2K4opGBkF+5kXOg6ucrtSUQdLhVVY5tycH0j0l+0g== + dependencies: + "@inquirer/core" "^10.1.10" + "@inquirer/type" "^3.0.6" + ansi-escapes "^4.3.2" + +"@inquirer/prompts@7.1.0": + version "7.1.0" + resolved "https://registry.yarnpkg.com/@inquirer/prompts/-/prompts-7.1.0.tgz#a55ee589c0eed0ca2ee0fbc7fc63f42f4c31a24e" + integrity sha512-5U/XiVRH2pp1X6gpNAjWOglMf38/Ys522ncEHIKT1voRUvSj/DQnR22OVxHnwu5S+rCFaUiPQ57JOtMFQayqYA== + dependencies: + "@inquirer/checkbox" "^4.0.2" + "@inquirer/confirm" "^5.0.2" + "@inquirer/editor" "^4.1.0" + "@inquirer/expand" "^4.0.2" + "@inquirer/input" "^4.0.2" + "@inquirer/number" "^3.0.2" + "@inquirer/password" "^4.0.2" + "@inquirer/rawlist" "^4.0.2" + "@inquirer/search" "^3.0.2" + "@inquirer/select" "^4.0.2" + +"@inquirer/rawlist@^4.0.2": + version "4.0.12" + resolved "https://registry.yarnpkg.com/@inquirer/rawlist/-/rawlist-4.0.12.tgz#97b9540199590d2b197836ba3a5658addd406479" + integrity sha512-wNPJZy8Oc7RyGISPxp9/MpTOqX8lr0r+lCCWm7hQra+MDtYRgINv1hxw7R+vKP71Bu/3LszabxOodfV/uTfsaA== + dependencies: + "@inquirer/core" "^10.1.10" + "@inquirer/type" "^3.0.6" + yoctocolors-cjs "^2.1.2" + +"@inquirer/search@^3.0.2": + version "3.0.12" + resolved "https://registry.yarnpkg.com/@inquirer/search/-/search-3.0.12.tgz#e86f91ea598ccb39caf9a17762b839a9b950e16d" + integrity sha512-H/kDJA3kNlnNIjB8YsaXoQI0Qccgf0Na14K1h8ExWhNmUg2E941dyFPrZeugihEa9AZNW5NdsD/NcvUME83OPQ== + dependencies: + "@inquirer/core" "^10.1.10" + "@inquirer/figures" "^1.0.11" + "@inquirer/type" "^3.0.6" + yoctocolors-cjs "^2.1.2" + +"@inquirer/select@^4.0.2": + version "4.1.1" + resolved "https://registry.yarnpkg.com/@inquirer/select/-/select-4.1.1.tgz#0496b913514149171cf6351f0acb6d4243a39fdf" + integrity sha512-IUXzzTKVdiVNMA+2yUvPxWsSgOG4kfX93jOM4Zb5FgujeInotv5SPIJVeXQ+fO4xu7tW8VowFhdG5JRmmCyQ1Q== + dependencies: + "@inquirer/core" "^10.1.10" + "@inquirer/figures" "^1.0.11" + "@inquirer/type" "^3.0.6" + ansi-escapes "^4.3.2" + yoctocolors-cjs "^2.1.2" + +"@inquirer/type@^3.0.6": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-3.0.6.tgz#2500e435fc2014c5250eec3279f42b70b64089bd" + integrity sha512-/mKVCtVpyBu3IDarv0G+59KC4stsD5mDsGpYh+GKs1NZT88Jh52+cuoA1AtLk2Q0r/quNl+1cSUyLRHBFeD0XA== + +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@istanbuljs/load-nyc-config@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz#fd3db1d59ecf7cf121e80650bb86712f9b55eced" + integrity sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ== + dependencies: + camelcase "^5.3.1" + find-up "^4.1.0" + get-package-type "^0.1.0" + js-yaml "^3.13.1" + resolve-from "^5.0.0" + +"@istanbuljs/schema@^0.1.2", "@istanbuljs/schema@^0.1.3": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.8" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142" + integrity sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.5.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + +"@jridgewell/trace-mapping@0.3.9": + version "0.3.9" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" + integrity sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ== + dependencies: + "@jridgewell/resolve-uri" "^3.0.3" + "@jridgewell/sourcemap-codec" "^1.4.10" + +"@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@lezer/common@^1.0.0", "@lezer/common@^1.1.0": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@lezer/common/-/common-1.2.3.tgz#138fcddab157d83da557554851017c6c1e5667fd" + integrity sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA== + +"@lezer/highlight@^1.0.0": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@lezer/highlight/-/highlight-1.2.1.tgz#596fa8f9aeb58a608be0a563e960c373cbf23f8b" + integrity sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA== + dependencies: + "@lezer/common" "^1.0.0" + +"@lezer/lr@^1.0.0": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@lezer/lr/-/lr-1.4.2.tgz#931ea3dea8e9de84e90781001dae30dea9ff1727" + integrity sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA== + dependencies: + "@lezer/common" "^1.0.0" + +"@marijn/find-cluster-break@^1.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz#775374306116d51c0c500b8c4face0f9a04752d8" + integrity sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g== + +"@noble/hashes@^1.1.5": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.8.0.tgz#cee43d801fcef9644b11b8194857695acd5f815a" + integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@paralleldrive/cuid2@2.2.2": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz#7f91364d53b89e2c9cb9e02e8dd0f129e834455f" + integrity sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA== + dependencies: + "@noble/hashes" "^1.1.5" + +"@peculiar/asn1-schema@^2.3.13", "@peculiar/asn1-schema@^2.3.8": + version "2.3.15" + resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-2.3.15.tgz#e926bfdeed51945a06f38be703499e7d8341a5d3" + integrity sha512-QPeD8UA8axQREpgR5UTAfu2mqQmm97oUqahDtNdBcfj3qAnoXzFdQW+aNf/tD2WVXF8Fhmftxoj0eMIT++gX2w== + dependencies: + asn1js "^3.0.5" + pvtsutils "^1.3.6" + tslib "^2.8.1" + +"@peculiar/json-schema@^1.1.12": + version "1.1.12" + resolved "https://registry.yarnpkg.com/@peculiar/json-schema/-/json-schema-1.1.12.tgz#fe61e85259e3b5ba5ad566cb62ca75b3d3cd5339" + integrity sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w== + dependencies: + tslib "^2.0.0" + +"@peculiar/webcrypto@^1.4.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@peculiar/webcrypto/-/webcrypto-1.5.0.tgz#9e57174c02c1291051c553600347e12b81469e10" + integrity sha512-BRs5XUAwiyCDQMsVA9IDvDa7UBR9gAvPHgugOeGng3YN6vJ9JYonyDc0lNczErgtCWtucjR5N7VtaonboD/ezg== + dependencies: + "@peculiar/asn1-schema" "^2.3.8" + "@peculiar/json-schema" "^1.1.12" + pvtsutils "^1.3.5" + tslib "^2.6.2" + webcrypto-core "^1.8.0" + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + +"@polka/url@^1.0.0-next.24": + version "1.0.0-next.29" + resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.29.tgz#5a40109a1ab5f84d6fd8fc928b19f367cbe7e7b1" + integrity sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww== + +"@rollup/rollup-android-arm-eabi@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.40.0.tgz#d964ee8ce4d18acf9358f96adc408689b6e27fe3" + integrity sha512-+Fbls/diZ0RDerhE8kyC6hjADCXA1K4yVNlH0EYfd2XjyH0UGgzaQ8MlT0pCXAThfxv3QUAczHaL+qSv1E4/Cg== + +"@rollup/rollup-android-arm64@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.40.0.tgz#9b5e130ecc32a5fc1e96c09ff371743ee71a62d3" + integrity sha512-PPA6aEEsTPRz+/4xxAmaoWDqh67N7wFbgFUJGMnanCFs0TV99M0M8QhhaSCks+n6EbQoFvLQgYOGXxlMGQe/6w== + +"@rollup/rollup-darwin-arm64@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.40.0.tgz#ef439182c739b20b3c4398cfc03e3c1249ac8903" + integrity sha512-GwYOcOakYHdfnjjKwqpTGgn5a6cUX7+Ra2HeNj/GdXvO2VJOOXCiYYlRFU4CubFM67EhbmzLOmACKEfvp3J1kQ== + +"@rollup/rollup-darwin-x64@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.40.0.tgz#d7380c1531ab0420ca3be16f17018ef72dd3d504" + integrity sha512-CoLEGJ+2eheqD9KBSxmma6ld01czS52Iw0e2qMZNpPDlf7Z9mj8xmMemxEucinev4LgHalDPczMyxzbq+Q+EtA== + +"@rollup/rollup-freebsd-arm64@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.40.0.tgz#cbcbd7248823c6b430ce543c59906dd3c6df0936" + integrity sha512-r7yGiS4HN/kibvESzmrOB/PxKMhPTlz+FcGvoUIKYoTyGd5toHp48g1uZy1o1xQvybwwpqpe010JrcGG2s5nkg== + +"@rollup/rollup-freebsd-x64@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.40.0.tgz#96bf6ff875bab5219c3472c95fa6eb992586a93b" + integrity sha512-mVDxzlf0oLzV3oZOr0SMJ0lSDd3xC4CmnWJ8Val8isp9jRGl5Dq//LLDSPFrasS7pSm6m5xAcKaw3sHXhBjoRw== + +"@rollup/rollup-linux-arm-gnueabihf@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.40.0.tgz#d80cd62ce6d40f8e611008d8dbf03b5e6bbf009c" + integrity sha512-y/qUMOpJxBMy8xCXD++jeu8t7kzjlOCkoxxajL58G62PJGBZVl/Gwpm7JK9+YvlB701rcQTzjUZ1JgUoPTnoQA== + +"@rollup/rollup-linux-arm-musleabihf@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.40.0.tgz#75440cfc1e8d0f87a239b4c31dfeaf4719b656b7" + integrity sha512-GoCsPibtVdJFPv/BOIvBKO/XmwZLwaNWdyD8TKlXuqp0veo2sHE+A/vpMQ5iSArRUz/uaoj4h5S6Pn0+PdhRjg== + +"@rollup/rollup-linux-arm64-gnu@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.40.0.tgz#ac527485ecbb619247fb08253ec8c551a0712e7c" + integrity sha512-L5ZLphTjjAD9leJzSLI7rr8fNqJMlGDKlazW2tX4IUF9P7R5TMQPElpH82Q7eNIDQnQlAyiNVfRPfP2vM5Avvg== + +"@rollup/rollup-linux-arm64-musl@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.40.0.tgz#74d2b5cb11cf714cd7d1682e7c8b39140e908552" + integrity sha512-ATZvCRGCDtv1Y4gpDIXsS+wfFeFuLwVxyUBSLawjgXK2tRE6fnsQEkE4csQQYWlBlsFztRzCnBvWVfcae/1qxQ== + +"@rollup/rollup-linux-loongarch64-gnu@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.40.0.tgz#a0a310e51da0b5fea0e944b0abd4be899819aef6" + integrity sha512-wG9e2XtIhd++QugU5MD9i7OnpaVb08ji3P1y/hNbxrQ3sYEelKJOq1UJ5dXczeo6Hj2rfDEL5GdtkMSVLa/AOg== + +"@rollup/rollup-linux-powerpc64le-gnu@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.40.0.tgz#4077e2862b0ac9f61916d6b474d988171bd43b83" + integrity sha512-vgXfWmj0f3jAUvC7TZSU/m/cOE558ILWDzS7jBhiCAFpY2WEBn5jqgbqvmzlMjtp8KlLcBlXVD2mkTSEQE6Ixw== + +"@rollup/rollup-linux-riscv64-gnu@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.40.0.tgz#5812a1a7a2f9581cbe12597307cc7ba3321cf2f3" + integrity sha512-uJkYTugqtPZBS3Z136arevt/FsKTF/J9dEMTX/cwR7lsAW4bShzI2R0pJVw+hcBTWF4dxVckYh72Hk3/hWNKvA== + +"@rollup/rollup-linux-riscv64-musl@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.40.0.tgz#973aaaf4adef4531375c36616de4e01647f90039" + integrity sha512-rKmSj6EXQRnhSkE22+WvrqOqRtk733x3p5sWpZilhmjnkHkpeCgWsFFo0dGnUGeA+OZjRl3+VYq+HyCOEuwcxQ== + +"@rollup/rollup-linux-s390x-gnu@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.40.0.tgz#9bad59e907ba5bfcf3e9dbd0247dfe583112f70b" + integrity sha512-SpnYlAfKPOoVsQqmTFJ0usx0z84bzGOS9anAC0AZ3rdSo3snecihbhFTlJZ8XMwzqAcodjFU4+/SM311dqE5Sw== + +"@rollup/rollup-linux-x64-gnu@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.40.0.tgz#68b045a720bd9b4d905f462b997590c2190a6de0" + integrity sha512-RcDGMtqF9EFN8i2RYN2W+64CdHruJ5rPqrlYw+cgM3uOVPSsnAQps7cpjXe9be/yDp8UC7VLoCoKC8J3Kn2FkQ== + +"@rollup/rollup-linux-x64-musl@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.40.0.tgz#8e703e2c2ad19ba7b2cb3d8c3a4ad11d4ee3a282" + integrity sha512-HZvjpiUmSNx5zFgwtQAV1GaGazT2RWvqeDi0hV+AtC8unqqDSsaFjPxfsO6qPtKRRg25SisACWnJ37Yio8ttaw== + +"@rollup/rollup-win32-arm64-msvc@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.40.0.tgz#c5bee19fa670ff5da5f066be6a58b4568e9c650b" + integrity sha512-UtZQQI5k/b8d7d3i9AZmA/t+Q4tk3hOC0tMOMSq2GlMYOfxbesxG4mJSeDp0EHs30N9bsfwUvs3zF4v/RzOeTQ== + +"@rollup/rollup-win32-ia32-msvc@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.40.0.tgz#846e02c17044bd922f6f483a3b4d36aac6e2b921" + integrity sha512-+m03kvI2f5syIqHXCZLPVYplP8pQch9JHyXKZ3AGMKlg8dCyr2PKHjwRLiW53LTrN/Nc3EqHOKxUxzoSPdKddA== + +"@rollup/rollup-win32-x64-msvc@4.40.0": + version "4.40.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.40.0.tgz#fd92d31a2931483c25677b9c6698106490cbbc76" + integrity sha512-lpPE1cLfP5oPzVjKMx10pgBmKELQnFJXHgvtHCtuJWOv8MxqdEIMNtgHgBFf7Ea2/7EuVwa9fodWUfXAlXZLZQ== + +"@stackpress/idea-parser@0.6.1": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@stackpress/idea-parser/-/idea-parser-0.6.1.tgz#0591e353e7403851f47356f835542e13ff490565" + integrity sha512-djf3JY4BOHBqT+VAMvLDHpT55thbdxnM3IHTuHr77JiJIsJqzue4IaKEQeWSDwEvHD2DPhAbT16Q/k0w91lzzw== + dependencies: + "@stackpress/lib" "0.6.1" + +"@stackpress/idea-transformer@0.6.1": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@stackpress/idea-transformer/-/idea-transformer-0.6.1.tgz#76daa1380036f9a3b7e80546ff567196d2b16c15" + integrity sha512-FGKlShUsoXZTi5IwI6sRR894jviGI0wNkKMduA5BuSZpPM2PfZSvH4F2vmUD0bKokxDVRUsm7wYFPnQRLgYMzQ== + dependencies: + "@stackpress/idea-parser" "0.6.1" + "@stackpress/lib" "0.6.1" + +"@stackpress/ingest@0.6.1": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@stackpress/ingest/-/ingest-0.6.1.tgz#20ba2a33a1d4a1573ed49774f887db2b0086fb35" + integrity sha512-i69p2fDHhEDQkWNfBiNp5pf74Gp0MQz6PkgrH0Nzf2I6L2d/5e25gQNeAAt9Qet9FPk0K0MlSgg46iMpXtQ4mQ== + dependencies: + "@stackpress/lib" "0.6.1" + "@whatwg-node/server" "0.6.7" + +"@stackpress/inquire@0.6.1": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@stackpress/inquire/-/inquire-0.6.1.tgz#ab8c5842fdcbdce6cd7c5d8bdefc207511f36312" + integrity sha512-SjbNrRuVVwNboMO5Bv6swZpK49z41sB1U2iYKKO2RrsLZPMdvpEZtjL7JxIDW37fm1Gh4PXkVTuYgvZ5qma2zQ== + dependencies: + "@stackpress/lib" "0.6.1" + +"@stackpress/lib@0.6.1": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@stackpress/lib/-/lib-0.6.1.tgz#56b65e66daaeb1e4a2a67cb8d743cd784bc8ed14" + integrity sha512-wAbMqAkO+nHFXwy2/ze++RuKtMgidKTa/FyrEcTrz36nTfeKmj7+1iXfvjrimLHljitUy2LZ42DUBFnrvlUKgg== + dependencies: + "@inquirer/prompts" "7.1.0" + +"@ts-morph/common@~0.26.0": + version "0.26.1" + resolved "https://registry.yarnpkg.com/@ts-morph/common/-/common-0.26.1.tgz#a346188e59d2befe4c71f66a7d626d81b1abe2a8" + integrity sha512-Sn28TGl/4cFpcM+jwsH1wLncYq3FtN/BIpem+HOygfBWPT5pAeS5dB4VFVzV8FbnOKHpDLZmvAl4AjPEev5idA== + dependencies: + fast-glob "^3.3.2" + minimatch "^9.0.4" + path-browserify "^1.0.1" + +"@tsconfig/node10@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" + integrity sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw== + +"@tsconfig/node12@^1.0.7": + version "1.0.11" + resolved "https://registry.yarnpkg.com/@tsconfig/node12/-/node12-1.0.11.tgz#ee3def1f27d9ed66dac6e46a295cffb0152e058d" + integrity sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag== + +"@tsconfig/node14@^1.0.0": + version "1.0.3" + resolved "https://registry.yarnpkg.com/@tsconfig/node14/-/node14-1.0.3.tgz#e4386316284f00b98435bf40f72f75a09dabf6c1" + integrity sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow== + +"@tsconfig/node16@^1.0.2": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" + integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== + +"@types/babel__core@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.27.0" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.27.0.tgz#b5819294c51179957afaec341442f9341e4108a9" + integrity sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*": + version "7.20.7" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.20.7.tgz#968cdc2366ec3da159f61166428ee40f370e56c2" + integrity sha512-dkO5fhS7+/oos4ciWxyEyjWe48zmG6wbCheo/G2ZnHx4fs3EU6YC6UM8rk56gAjNJ9P3MTH2jo5jb92/K6wbng== + dependencies: + "@babel/types" "^7.20.7" + +"@types/chai@5.2.1": + version "5.2.1" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-5.2.1.tgz#85687a58b27eac736ec0e87e5cb98f21e57a0bb1" + integrity sha512-iu1JLYmGmITRzUgNiLMZD3WCoFzpYtueuyAgHTXqgwSRAMIlFTnZqG6/xenkpUGRJEzSfklUTI4GNSzks/dc0w== + dependencies: + "@types/deep-eql" "*" + +"@types/deep-eql@*": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/deep-eql/-/deep-eql-4.0.2.tgz#334311971d3a07121e7eb91b684a605e7eea9cbd" + integrity sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw== + +"@types/estree@1.0.7": + version "1.0.7" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.7.tgz#4158d3105276773d5b7695cd4834b1722e4f37a8" + integrity sha512-w28IoSUCJpidD/TGviZwwMJckNESJZXFu7NBZ5YJ4mEUnNraUn9Pm8HSZm/jDF1pDWYKspWE7oVphigUPRakIQ== + +"@types/hast@^2.0.0": + version "2.3.10" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.10.tgz#5c9d9e0b304bbb8879b857225c5ebab2d81d7643" + integrity sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw== + dependencies: + "@types/unist" "^2" + +"@types/mocha@10.0.10": + version "10.0.10" + resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.10.tgz#91f62905e8d23cbd66225312f239454a23bebfa0" + integrity sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q== + +"@types/node@22.14.1": + version "22.14.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.14.1.tgz#53b54585cec81c21eee3697521e31312d6ca1e6f" + integrity sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw== + dependencies: + undici-types "~6.21.0" + +"@types/react-dom@19.1.2": + version "19.1.2" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.1.2.tgz#bd1fe3b8c28a3a2e942f85314dcfb71f531a242f" + integrity sha512-XGJkWF41Qq305SKWEILa1O8vzhb3aOo3ogBlSmiqNko/WmRb6QIaweuZCXjKygVDXpzXb5wyxKTSOsmkuqj+Qw== + +"@types/react-syntax-highlighter@15.5.13": + version "15.5.13" + resolved "https://registry.yarnpkg.com/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.13.tgz#c5baf62a3219b3bf28d39cfea55d0a49a263d1f2" + integrity sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA== + dependencies: + "@types/react" "*" + +"@types/react@*", "@types/react@19.1.2": + version "19.1.2" + resolved "https://registry.yarnpkg.com/@types/react/-/react-19.1.2.tgz#11df86f66f188f212c90ecb537327ec68bfd593f" + integrity sha512-oxLPMytKchWGbnQM9O7D67uPa9paTNxO7jVoNMXgkkErULBPhPARCfkKL9ytcIJJRGjbsVwW4ugJzyFFvm/Tiw== + dependencies: + csstype "^3.0.2" + +"@types/unist@^2": + version "2.0.11" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.11.tgz#11af57b127e32487774841f7a4e54eab166d03c4" + integrity sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA== + +"@unocss/astro@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/astro/-/astro-66.0.0.tgz#6564ef14c9d7c1346769c222c6e525d7d8995c98" + integrity sha512-GBhXT6JPqXjDXoJZTXhySk83NgOt0UigChqrUUdG4x7Z+DVYkDBION8vZUJjw0OdIaxNQ4euGWu4GDsMF6gQQg== + dependencies: + "@unocss/core" "66.0.0" + "@unocss/reset" "66.0.0" + "@unocss/vite" "66.0.0" + +"@unocss/cli@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/cli/-/cli-66.0.0.tgz#4cd4b6e14a6743354fe532f6dc390bab30e04e35" + integrity sha512-KVQiskoOjVkLVpNaG6WpLa4grPplrZROYZJVIUYSTqZyZRFNSvjttHcsCwpoWUEUdEombPtVZl8FrXePjY5IiQ== + dependencies: + "@ampproject/remapping" "^2.3.0" + "@unocss/config" "66.0.0" + "@unocss/core" "66.0.0" + "@unocss/preset-uno" "66.0.0" + cac "^6.7.14" + chokidar "^3.6.0" + colorette "^2.0.20" + consola "^3.4.0" + magic-string "^0.30.17" + pathe "^2.0.3" + perfect-debounce "^1.0.0" + tinyglobby "^0.2.10" + unplugin-utils "^0.2.4" + +"@unocss/config@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/config/-/config-66.0.0.tgz#16ff6da705cd7b97813d62a887adbf354ee423c8" + integrity sha512-nFRGop/guBa4jLkrgXjaRDm5JPz4x3YpP10m5IQkHpHwlnHUVn1L9smyPl04ohYWhYn9ZcAHgR28Ih2jwta8hw== + dependencies: + "@unocss/core" "66.0.0" + unconfig "~7.0.0" + +"@unocss/core@66.0.0", "@unocss/core@^66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/core/-/core-66.0.0.tgz#2a316f4e0e17bd3f77788479401ca84eaf52e847" + integrity sha512-PdVbSMHNDDkr++9nkqzsZRAkaU84gxMTEgYbqI7dt2p1DXp/5tomVtmMsr2/whXGYKRiUc0xZ3p4Pzraz8TcXA== + +"@unocss/extractor-arbitrary-variants@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/extractor-arbitrary-variants/-/extractor-arbitrary-variants-66.0.0.tgz#8bd37b36cc4e568db809d7d460f65ff3f4830b30" + integrity sha512-vlkOIOuwBfaFBJcN6o7+obXjigjOlzVFN/jT6pG1WXbQDTRZ021jeF3i9INdb9D/0cQHSeDvNgi1TJ5oUxfiow== + dependencies: + "@unocss/core" "66.0.0" + +"@unocss/inspector@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/inspector/-/inspector-66.0.0.tgz#98d9e4bf83abb4a4b119eea89c464aef066439ec" + integrity sha512-mkIxieVm0kMOKw+E4ABpIerihYMdjgq9A92RD5h2+W/ebpxTEw5lTTK1xcMLiAlmOrVYMQKjpgPeu3vQmDyGZQ== + dependencies: + "@unocss/core" "66.0.0" + "@unocss/rule-utils" "66.0.0" + colorette "^2.0.20" + gzip-size "^6.0.0" + sirv "^3.0.0" + vue-flow-layout "^0.1.1" + +"@unocss/postcss@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/postcss/-/postcss-66.0.0.tgz#686a74de9de91809d02ae715b60b1470d2705826" + integrity sha512-6bi+ujzh8I1PJwtmHX71LH8z/H9+vPxeYD4XgFihyU1k4Y6MVhjr7giGjLX4yP27IP+NsVyotD22V7by/dBVEA== + dependencies: + "@unocss/config" "66.0.0" + "@unocss/core" "66.0.0" + "@unocss/rule-utils" "66.0.0" + css-tree "^3.1.0" + postcss "^8.5.2" + tinyglobby "^0.2.10" + +"@unocss/preset-attributify@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/preset-attributify/-/preset-attributify-66.0.0.tgz#e319503c7ffb5a482cafb09744d33424db97167e" + integrity sha512-eYsOgmcDoiIgGAepIwRX+DKGYxc/wm0r4JnDuZdz29AB+A6oY/FGHS1BVt4rq9ny4B5PofP4p6Rty+vwD9rigw== + dependencies: + "@unocss/core" "66.0.0" + +"@unocss/preset-icons@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/preset-icons/-/preset-icons-66.0.0.tgz#97d9e9e110a343e2c5b6de37070019ac05de1221" + integrity sha512-6ObwTvEGuPBbKWRoMMiDioHtwwQTFI5oojFLJ32Y8tW6TdXvBLkO88d7qpgQxEjgVt4nJrqF1WEfR4niRgBm0Q== + dependencies: + "@iconify/utils" "^2.3.0" + "@unocss/core" "66.0.0" + ofetch "^1.4.1" + +"@unocss/preset-mini@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/preset-mini/-/preset-mini-66.0.0.tgz#8b1b5ee36aaa8d1226ff34179622d4433a872130" + integrity sha512-d62eACnuKtR0dwCFOQXgvw5VLh5YSyK56xCzpHkh0j0GstgfDLfKTys0T/XVAAvdSvAy/8A8vhSNJ4PlIc9V2A== + dependencies: + "@unocss/core" "66.0.0" + "@unocss/extractor-arbitrary-variants" "66.0.0" + "@unocss/rule-utils" "66.0.0" + +"@unocss/preset-tagify@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/preset-tagify/-/preset-tagify-66.0.0.tgz#8629c466ffdcdf771e79d19cca92f8a4b13bfb3f" + integrity sha512-GGYGyWxaevh0jN0NoATVO1Qe7DFXM3ykLxchlXmG6/zy963pZxItg/njrKnxE9la4seCdxpFH7wQBa68imwwdA== + dependencies: + "@unocss/core" "66.0.0" + +"@unocss/preset-typography@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/preset-typography/-/preset-typography-66.0.0.tgz#85c62a0fa57e538f23ab9f56e68a8ac3bc4ed116" + integrity sha512-apjckP5nPU5mtaHTCzz5u/dK9KJWwJ2kOFCVk0+a/KhUWmnqnzmjRYZlEuWxxr5QxTdCW+9cIoRDSA0lYZS5tg== + dependencies: + "@unocss/core" "66.0.0" + "@unocss/preset-mini" "66.0.0" + "@unocss/rule-utils" "66.0.0" + +"@unocss/preset-uno@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/preset-uno/-/preset-uno-66.0.0.tgz#37633290c6594de40a40fc158504fa22c02c6ab7" + integrity sha512-qgoZ/hzTI32bQvcyjcwvv1X/dbPlmQNehzgjUaL7QFT0q0/CN/SRpysfzoQ8DLl2se9T+YCOS9POx3KrpIiYSQ== + dependencies: + "@unocss/core" "66.0.0" + "@unocss/preset-wind3" "66.0.0" + +"@unocss/preset-web-fonts@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/preset-web-fonts/-/preset-web-fonts-66.0.0.tgz#39c936ad69f6777df1077ffff40d6694cf9368e9" + integrity sha512-9MzfDc6AJILN4Kq7Z91FfFbizBOYgw3lJd2UwqIs3PDYWG5iH5Zv5zhx6jelZVqEW5uWcIARYEEg2m4stZO1ZA== + dependencies: + "@unocss/core" "66.0.0" + ofetch "^1.4.1" + +"@unocss/preset-wind3@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/preset-wind3/-/preset-wind3-66.0.0.tgz#3f17da21cea683d75d4adefbd4f9c95172eeb1bb" + integrity sha512-WAGRmpi1sb2skvYn9DBQUvhfqrJ+VmQmn5ZGsT2ewvsk7HFCvVLAMzZeKrrTQepeNBRhg6HzFDDi8yg6yB5c9g== + dependencies: + "@unocss/core" "66.0.0" + "@unocss/preset-mini" "66.0.0" + "@unocss/rule-utils" "66.0.0" + +"@unocss/preset-wind@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/preset-wind/-/preset-wind-66.0.0.tgz#eeb22cd66a32dc896c6263dc0eeb8be0c6c9b090" + integrity sha512-FtvGpHnGC7FiyKJavPnn5y9lsaoWRhXlujCqlT5Bw63kKhMNr0ogKySBpenUhJOhWhVM0OQXn2nZ3GZRxW2qpw== + dependencies: + "@unocss/core" "66.0.0" + "@unocss/preset-wind3" "66.0.0" + +"@unocss/reset@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/reset/-/reset-66.0.0.tgz#8e3301206ab315d3287fb133be6f03e60a3ebdd4" + integrity sha512-YLFz/5yT7mFJC8JSmIUA5+bS3CBCJbtztOw+8rWzjQr/BEVSGuihWUUpI2Df6VVxXIXxKanZR6mIl59yvf+GEA== + +"@unocss/rule-utils@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/rule-utils/-/rule-utils-66.0.0.tgz#5fd1c7bd2372e9f3724ed6858263a703a9ae064a" + integrity sha512-UJ51YHbwxYTGyj35ugsPlOT4gaa7tCbXdywZ3m5Nn0JgywwIqGmBFyiN9ZjHBHfJuDxmmPd6lxojoBscih/WMQ== + dependencies: + "@unocss/core" "^66.0.0" + magic-string "^0.30.17" + +"@unocss/transformer-attributify-jsx@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/transformer-attributify-jsx/-/transformer-attributify-jsx-66.0.0.tgz#f93168db7fd7efbccfa75cd3ea5f3457d1aee8eb" + integrity sha512-jS7szFXXC6RjTv9wo0NACskf618w981bkbyQ5izRO7Ha47sNpHhHDpaltnG7SR9qV4cCtGalOw4onVMHsRKwRg== + dependencies: + "@unocss/core" "66.0.0" + +"@unocss/transformer-compile-class@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/transformer-compile-class/-/transformer-compile-class-66.0.0.tgz#baa303da481e6df25d963436c4536479b620025b" + integrity sha512-ytUIE0nAcHRMACuTXkHp8auZ483DXrOZw99jk3FJ+aFjpD/pVSFmX14AWJ7bqPFObxb4SLFs6KhQma30ESC22A== + dependencies: + "@unocss/core" "66.0.0" + +"@unocss/transformer-directives@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/transformer-directives/-/transformer-directives-66.0.0.tgz#7cfff36c2b196937a54f107a76803aeb7236d0d8" + integrity sha512-utcg7m2Foi7uHrU5WHadNuJ0a3qWG8tZNkQMi+m0DQpX6KWfuDtDn0zDZ1X+z5lmiB3WGSJERRrsvZbj1q50Mw== + dependencies: + "@unocss/core" "66.0.0" + "@unocss/rule-utils" "66.0.0" + css-tree "^3.1.0" + +"@unocss/transformer-variant-group@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/transformer-variant-group/-/transformer-variant-group-66.0.0.tgz#255ae998dd75c379df6af09f0b9f10a5dc0a5ad1" + integrity sha512-1BLjNWtAnR1JAcQGw0TS+nGrVoB9aznzvVZRoTx23dtRr3btvgKPHb8LrD48eD/p8Dtw9j3WfuxMDKXKegKDLg== + dependencies: + "@unocss/core" "66.0.0" + +"@unocss/vite@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/vite/-/vite-66.0.0.tgz#e0e4e50288d8b5ef6e53af85ae35149ce2a60b73" + integrity sha512-IVcPX8xL+2edyXKt4tp9yu5A6gcbPVCsspfcL0XgziCr01kS+4qSoZ90F3IUs3hXc/AyO5eCpRtGFMPLpOjXQg== + dependencies: + "@ampproject/remapping" "^2.3.0" + "@unocss/config" "66.0.0" + "@unocss/core" "66.0.0" + "@unocss/inspector" "66.0.0" + chokidar "^3.6.0" + magic-string "^0.30.17" + tinyglobby "^0.2.10" + unplugin-utils "^0.2.4" + +"@vitejs/plugin-react@4.4.1": + version "4.4.1" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-4.4.1.tgz#d7d1e9c9616d7536b0953637edfee7c6cbe2fe0f" + integrity sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w== + dependencies: + "@babel/core" "^7.26.10" + "@babel/plugin-transform-react-jsx-self" "^7.25.9" + "@babel/plugin-transform-react-jsx-source" "^7.25.9" + "@types/babel__core" "^7.20.5" + react-refresh "^0.17.0" + +"@whatwg-node/events@^0.0.3": + version "0.0.3" + resolved "https://registry.yarnpkg.com/@whatwg-node/events/-/events-0.0.3.tgz#13a65dd4f5893f55280f766e29ae48074927acad" + integrity sha512-IqnKIDWfXBJkvy/k6tzskWTc2NK3LcqHlb+KHGCrjOCH4jfQckRX0NAiIcC/vIqQkzLYw2r2CTSwAxcrtcD6lA== + +"@whatwg-node/fetch@^0.8.1": + version "0.8.8" + resolved "https://registry.yarnpkg.com/@whatwg-node/fetch/-/fetch-0.8.8.tgz#48c6ad0c6b7951a73e812f09dd22d75e9fa18cae" + integrity sha512-CdcjGC2vdKhc13KKxgsc6/616BQ7ooDIgPeTuAiE8qfCnS0mGzcfCOoZXypQSz73nxI+GWc7ZReIAVhxoE1KCg== + dependencies: + "@peculiar/webcrypto" "^1.4.0" + "@whatwg-node/node-fetch" "^0.3.6" + busboy "^1.6.0" + urlpattern-polyfill "^8.0.0" + web-streams-polyfill "^3.2.1" + +"@whatwg-node/node-fetch@^0.3.6": + version "0.3.6" + resolved "https://registry.yarnpkg.com/@whatwg-node/node-fetch/-/node-fetch-0.3.6.tgz#e28816955f359916e2d830b68a64493124faa6d0" + integrity sha512-w9wKgDO4C95qnXZRwZTfCmLWqyRnooGjcIwG0wADWjw9/HN0p7dtvtgSvItZtUyNteEvgTrd8QojNEqV6DAGTA== + dependencies: + "@whatwg-node/events" "^0.0.3" + busboy "^1.6.0" + fast-querystring "^1.1.1" + fast-url-parser "^1.1.3" + tslib "^2.3.1" + +"@whatwg-node/server@0.6.7": + version "0.6.7" + resolved "https://registry.yarnpkg.com/@whatwg-node/server/-/server-0.6.7.tgz#14f5d0aca49308759d64fc7faa3cbfc20162a1ee" + integrity sha512-M4zHWdJ6M1IdcxnZBdDmiUh1bHQ4gPYRxzkH0gh8Qf6MpWJmX6I/MNftqem3GNn+qn1y47qqlGSed7T7nzsRFw== + dependencies: + "@whatwg-node/fetch" "^0.8.1" + tslib "^2.3.1" + +acorn-walk@^8.1.1: + version "8.3.4" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" + integrity sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g== + dependencies: + acorn "^8.11.0" + +acorn@^8.11.0, acorn@^8.14.0, acorn@^8.4.1: + version "8.14.1" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.1.tgz#721d5dc10f7d5b5609a891773d47731796935dfb" + integrity sha512-OvQ/2pUDKmgfCg++xsTX1wGxfTaszcHVcTctW4UJB4hibJx2HXxxO5UmVgyjMa+ZDsiaf5wWLXYpRWMmBI0QHg== + +aggregate-error@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" + integrity sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA== + dependencies: + clean-stack "^2.0.0" + indent-string "^4.0.0" + +ansi-escapes@^4.3.2: + version "4.3.2" + resolved "https://registry.yarnpkg.com/ansi-escapes/-/ansi-escapes-4.3.2.tgz#6b2291d1db7d98b6521d5f1efa42d0f3a9feb65e" + integrity sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ== + dependencies: + type-fest "^0.21.3" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-regex@^6.0.1: + version "6.1.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.1.0.tgz#95ec409c69619d6cb1b8b34f14b660ef28ebd654" + integrity sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + +anymatch@~3.1.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" + integrity sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw== + dependencies: + normalize-path "^3.0.0" + picomatch "^2.0.4" + +append-transform@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/append-transform/-/append-transform-2.0.0.tgz#99d9d29c7b38391e6f428d28ce136551f0b77e12" + integrity sha512-7yeyCEurROLQJFv5Xj4lEGTy0borxepjFv1g22oAdqFu//SrAlDl1O1Nxx15SH1RoliUml6p8dwJW9jvZughhg== + dependencies: + default-require-extensions "^3.0.0" + +archy@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/archy/-/archy-1.0.0.tgz#f9c8c13757cc1dd7bc379ac77b2c62a5c2868c40" + integrity sha512-Xg+9RwCg/0p32teKdGMPTPnVXKD0w3DfHnFTficozsAgsvq2XenPJq/MYpzzQ/v8zrOyJn6Ds39VA4JIDwFfqw== + +arg@^4.1.0: + version "4.1.3" + resolved "https://registry.yarnpkg.com/arg/-/arg-4.1.3.tgz#269fc7ad5b8e42cb63c896d5666017261c144089" + integrity sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA== + +argparse@^1.0.7: + version "1.0.10" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-1.0.10.tgz#bcd6791ea5ae09725e17e5ad988134cd40b3d911" + integrity sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg== + dependencies: + sprintf-js "~1.0.2" + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +asn1js@^3.0.5: + version "3.0.6" + resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-3.0.6.tgz#53e002ebe00c5f7fd77c1c047c3557d7c04dce25" + integrity sha512-UOCGPYbl0tv8+006qks/dTgV9ajs97X2p0FAbyS2iyCRrmLSRolDaHdp+v/CLgnzHc3fVB+CwYiUmei7ndFcgA== + dependencies: + pvtsutils "^1.3.6" + pvutils "^1.1.3" + tslib "^2.8.1" + +assertion-error@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" + integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +binary-extensions@^2.0.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/binary-extensions/-/binary-extensions-2.3.0.tgz#f6e14a97858d327252200242d4ccfe522c445522" + integrity sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.3, braces@~3.0.2: + version "3.0.3" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" + integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== + dependencies: + fill-range "^7.1.1" + +browser-stdout@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/browser-stdout/-/browser-stdout-1.3.1.tgz#baa559ee14ced73452229bad7326467c61fabd60" + integrity sha512-qhAVI1+Av2X7qelOfAIYwXONood6XlZE/fXaBSmW/T5SzLAmCgzi+eiWE7fUvbHaeNBQH13UftjpXxsfLkMpgw== + +browserslist@^4.24.0: + version "4.24.4" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.24.4.tgz#c6b2865a3f08bcb860a0e827389003b9fe686e4b" + integrity sha512-KDi1Ny1gSePi1vm0q4oxSF8b4DR44GF4BbmS2YdhPLOEqd8pDviZOGH/GsmRwoWJ2+5Lr085X7naowMwKHDG1A== + dependencies: + caniuse-lite "^1.0.30001688" + electron-to-chromium "^1.5.73" + node-releases "^2.0.19" + update-browserslist-db "^1.1.1" + +busboy@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" + integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== + dependencies: + streamsearch "^1.1.0" + +cac@^6.7.14: + version "6.7.14" + resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" + integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== + +caching-transform@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-4.0.0.tgz#00d297a4206d71e2163c39eaffa8157ac0651f0f" + integrity sha512-kpqOvwXnjjN44D89K5ccQC+RUrsy7jB/XLlRrx0D7/2HNcTPqzsb6XgYoErwko6QsV184CA2YgS1fxDiiDZMWA== + dependencies: + hasha "^5.0.0" + make-dir "^3.0.0" + package-hash "^4.0.0" + write-file-atomic "^3.0.0" + +camelcase@^5.0.0, camelcase@^5.3.1: + version "5.3.1" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-5.3.1.tgz#e3c9b31569e106811df242f715725a1f4c494320" + integrity sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg== + +camelcase@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/camelcase/-/camelcase-6.3.0.tgz#5685b95eb209ac9c0c177467778c9c84df58ba9a" + integrity sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA== + +caniuse-lite@^1.0.30001688: + version "1.0.30001715" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001715.tgz#bd325a37ad366e3fe90827d74062807a34fbaeb2" + integrity sha512-7ptkFGMm2OAOgvZpwgA4yjQ5SQbrNVGdRjzH0pBdy1Fasvcr+KAeECmbCAECzTuDuoX0FCY8KzUxjf9+9kfZEw== + +chai@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/chai/-/chai-5.2.0.tgz#1358ee106763624114addf84ab02697e411c9c05" + integrity sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw== + dependencies: + assertion-error "^2.0.1" + check-error "^2.1.1" + deep-eql "^5.0.1" + loupe "^3.1.0" + pathval "^2.0.0" + +chalk@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +character-entities-legacy@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" + integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== + +character-entities@^1.0.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" + integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== + +character-reference-invalid@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" + integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== + +chardet@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" + integrity sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA== + +check-error@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc" + integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw== + +chokidar@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" + integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== + dependencies: + anymatch "~3.1.2" + braces "~3.0.2" + glob-parent "~5.1.2" + is-binary-path "~2.1.0" + is-glob "~4.0.1" + normalize-path "~3.0.0" + readdirp "~3.6.0" + optionalDependencies: + fsevents "~2.3.2" + +chokidar@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + dependencies: + readdirp "^4.0.1" + +clean-stack@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" + integrity sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A== + +cli-width@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/cli-width/-/cli-width-4.1.0.tgz#42daac41d3c254ef38ad8ac037672130173691c5" + integrity sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ== + +cliui@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-6.0.0.tgz#511d702c0c4e41ca156d7d0e96021f23e13225b1" + integrity sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.0" + wrap-ansi "^6.2.0" + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +clsx@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" + integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== + +code-block-writer@^13.0.3: + version "13.0.3" + resolved "https://registry.yarnpkg.com/code-block-writer/-/code-block-writer-13.0.3.tgz#90f8a84763a5012da7af61319dd638655ae90b5b" + integrity sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg== + +codemirror@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-6.0.1.tgz#62b91142d45904547ee3e0e0e4c1a79158035a29" + integrity sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg== + dependencies: + "@codemirror/autocomplete" "^6.0.0" + "@codemirror/commands" "^6.0.0" + "@codemirror/language" "^6.0.0" + "@codemirror/lint" "^6.0.0" + "@codemirror/search" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +colorette@^2.0.20: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + +comma-separated-tokens@^1.0.0: + version "1.0.8" + resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" + integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== + +commondir@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" + integrity sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +confbox@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.1.8.tgz#820d73d3b3c82d9bd910652c5d4d599ef8ff8b06" + integrity sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w== + +confbox@^0.2.1: + version "0.2.2" + resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.2.2.tgz#8652f53961c74d9e081784beed78555974a9c110" + integrity sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ== + +consola@^3.4.0: + version "3.4.2" + resolved "https://registry.yarnpkg.com/consola/-/consola-3.4.2.tgz#5af110145397bb67afdab77013fdc34cae590ea7" + integrity sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA== + +convert-source-map@^1.7.0: + version "1.9.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" + integrity sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +cookie@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-1.0.2.tgz#27360701532116bd3f1f9416929d176afe1e4610" + integrity sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA== + +create-require@^1.1.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" + integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== + +crelt@^1.0.5: + version "1.0.6" + resolved "https://registry.yarnpkg.com/crelt/-/crelt-1.0.6.tgz#7cc898ea74e190fb6ef9dae57f8f81cf7302df72" + integrity sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g== + +cross-spawn@^7.0.0, cross-spawn@^7.0.3, cross-spawn@^7.0.6: + version "7.0.6" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" + integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +css-tree@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-3.1.0.tgz#7aabc035f4e66b5c86f54570d55e05b1346eb0fd" + integrity sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w== + dependencies: + mdn-data "2.12.2" + source-map-js "^1.0.1" + +csstype@^3.0.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== + +debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.5, debug@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" + integrity sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA== + dependencies: + ms "^2.1.3" + +decamelize@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" + integrity sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA== + +decamelize@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-4.0.0.tgz#aa472d7bf660eb15f3494efd531cab7f2a709837" + integrity sha512-9iE1PgSik9HeIIw2JO94IidnE3eBoQrFJ3w7sFuzSX4DpmZ3v5sZpUiV5Swcf6mQEF+Y0ru8Neo+p+nyh2J+hQ== + +deep-eql@^5.0.1: + version "5.0.2" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341" + integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q== + +default-require-extensions@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/default-require-extensions/-/default-require-extensions-3.0.1.tgz#bfae00feeaeada68c2ae256c62540f60b80625bd" + integrity sha512-eXTJmRbm2TIt9MgWTsOH1wEuhew6XGZcMeGKCtLedIg/NCsg1iBePXkceTdK4Fii7pzmN9tGsZhKzZ4h7O/fxw== + dependencies: + strip-bom "^4.0.0" + +defu@^6.1.4: + version "6.1.4" + resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479" + integrity sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg== + +destr@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/destr/-/destr-2.0.5.tgz#7d112ff1b925fb8d2079fac5bdb4a90973b51fdb" + integrity sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA== + +diff@^4.0.1: + version "4.0.2" + resolved "https://registry.yarnpkg.com/diff/-/diff-4.0.2.tgz#60f3aecb89d5fae520c11aa19efc2bb982aade7d" + integrity sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A== + +diff@^5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" + integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== + +dotenv-cli@8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/dotenv-cli/-/dotenv-cli-8.0.0.tgz#cea1519f5a06c7372a1428fca4605fcf3d50e1cf" + integrity sha512-aLqYbK7xKOiTMIRf1lDPbI+Y+Ip/wo5k3eyp6ePysVaSqbyxjyK3dK35BTxG+rmd7djf5q2UPs4noPNH+cj0Qw== + dependencies: + cross-spawn "^7.0.6" + dotenv "^16.3.0" + dotenv-expand "^10.0.0" + minimist "^1.2.6" + +dotenv-expand@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-10.0.0.tgz#12605d00fb0af6d0a592e6558585784032e4ef37" + integrity sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A== + +dotenv@^16.3.0: + version "16.5.0" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.5.0.tgz#092b49f25f808f020050051d1ff258e404c78692" + integrity sha512-m/C+AwOAr9/W1UOIZUo232ejMNnJAJtYQjUbHoNTBNTJSvqzzDh7vnrei3o3r3m9blf6ZoDkvcw0VmozNRFJxg== + +duplexer@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + +electron-to-chromium@^1.5.73: + version "1.5.140" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.140.tgz#91d9279fe72963f22c5784cc7f3461b5fed34786" + integrity sha512-o82Rj+ONp4Ip7Cl1r7lrqx/pXhbp/lh9DpKcMNscFJdh8ebyRofnc7Sh01B4jx403RI0oqTBvlZ7OBIZLMr2+Q== + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +es6-error@^4.0.1: + version "4.1.1" + resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" + integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== + +esbuild@^0.25.0, esbuild@~0.25.0: + version "0.25.3" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.3.tgz#371f7cb41283e5b2191a96047a7a89562965a285" + integrity sha512-qKA6Pvai73+M2FtftpNKRxJ78GIjmFXFxd/1DVBqGo/qNhLSfv+G12n9pNoWdytJC8U00TrViOwpjT0zgqQS8Q== + optionalDependencies: + "@esbuild/aix-ppc64" "0.25.3" + "@esbuild/android-arm" "0.25.3" + "@esbuild/android-arm64" "0.25.3" + "@esbuild/android-x64" "0.25.3" + "@esbuild/darwin-arm64" "0.25.3" + "@esbuild/darwin-x64" "0.25.3" + "@esbuild/freebsd-arm64" "0.25.3" + "@esbuild/freebsd-x64" "0.25.3" + "@esbuild/linux-arm" "0.25.3" + "@esbuild/linux-arm64" "0.25.3" + "@esbuild/linux-ia32" "0.25.3" + "@esbuild/linux-loong64" "0.25.3" + "@esbuild/linux-mips64el" "0.25.3" + "@esbuild/linux-ppc64" "0.25.3" + "@esbuild/linux-riscv64" "0.25.3" + "@esbuild/linux-s390x" "0.25.3" + "@esbuild/linux-x64" "0.25.3" + "@esbuild/netbsd-arm64" "0.25.3" + "@esbuild/netbsd-x64" "0.25.3" + "@esbuild/openbsd-arm64" "0.25.3" + "@esbuild/openbsd-x64" "0.25.3" + "@esbuild/sunos-x64" "0.25.3" + "@esbuild/win32-arm64" "0.25.3" + "@esbuild/win32-ia32" "0.25.3" + "@esbuild/win32-x64" "0.25.3" + +escalade@^3.1.1, escalade@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +esprima@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" + integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== + +exsolve@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/exsolve/-/exsolve-1.0.5.tgz#1f5b6b4fe82ad6b28a173ccb955a635d77859dcf" + integrity sha512-pz5dvkYYKQ1AHVrgOzBKWeP4u4FRb3a6DNK2ucr0OoNwYIU4QWsJ+NM36LLzORT+z845MzKHHhpXiUF5nvQoJg== + +external-editor@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" + integrity sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew== + dependencies: + chardet "^0.7.0" + iconv-lite "^0.4.24" + tmp "^0.0.33" + +fast-decode-uri-component@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz#46f8b6c22b30ff7a81357d4f59abfae938202543" + integrity sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg== + +fast-glob@3.3.3, fast-glob@^3.3.2: + version "3.3.3" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.8" + +fast-querystring@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/fast-querystring/-/fast-querystring-1.1.2.tgz#a6d24937b4fc6f791b4ee31dcb6f53aeafb89f53" + integrity sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg== + dependencies: + fast-decode-uri-component "^1.0.1" + +fast-url-parser@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" + integrity sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ== + dependencies: + punycode "^1.3.2" + +fastq@^1.6.0: + version "1.19.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" + integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== + dependencies: + reusify "^1.0.4" + +fault@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.4.tgz#eafcfc0a6d214fc94601e170df29954a4f842f13" + integrity sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA== + dependencies: + format "^0.2.0" + +fdir@^6.4.3, fdir@^6.4.4: + version "6.4.4" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.4.tgz#1cfcf86f875a883e19a8fab53622cfe992e8d2f9" + integrity sha512-1NZP+GK4GfuAv3PqKvxQRDMjdSRZjnkq7KfhlNrCNNlZ0ygQFpebfrnfnq/W7fpUnAv9aGWmY1zKx7FYL3gwhg== + +fill-range@^7.1.1: + version "7.1.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" + integrity sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg== + dependencies: + to-regex-range "^5.0.1" + +find-cache-dir@^3.2.0: + version "3.3.2" + resolved "https://registry.yarnpkg.com/find-cache-dir/-/find-cache-dir-3.3.2.tgz#b30c5b6eff0730731aea9bbd9dbecbd80256d64b" + integrity sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig== + dependencies: + commondir "^1.0.1" + make-dir "^3.0.2" + pkg-dir "^4.1.0" + +find-up@^4.0.0, find-up@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-4.1.0.tgz#97afe7d6cdc0bc5928584b7c8d7b16e8a9aa5d19" + integrity sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw== + dependencies: + locate-path "^5.0.0" + path-exists "^4.0.0" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat@^5.0.2: + version "5.0.2" + resolved "https://registry.yarnpkg.com/flat/-/flat-5.0.2.tgz#8ca6fe332069ffa9d324c327198c598259ceb241" + integrity sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ== + +foreground-child@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-2.0.0.tgz#71b32800c9f15aa8f2f83f4a6bd9bff35d861a53" + integrity sha512-dCIq9FpEcyQyXKCkyzmlPTFNgrCzPudOe+mhvJU5zAtlBnGVy2yKxtfsxK2tQBThwq225jcvBjpw1Gr40uzZCA== + dependencies: + cross-spawn "^7.0.0" + signal-exit "^3.0.2" + +foreground-child@^3.1.0, foreground-child@^3.3.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" + integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== + dependencies: + cross-spawn "^7.0.6" + signal-exit "^4.0.1" + +format@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" + integrity sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww== + +fromentries@^1.2.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.3.2.tgz#e4bca6808816bf8f93b52750f1127f5a6fd86e3a" + integrity sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg== + +frui@0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/frui/-/frui-0.1.8.tgz#b04f534f0b6b0f942054388031b8fc3b8418f144" + integrity sha512-gz09LCW8xTeN4eMHI+zYOm3yByWq+NNVZ9naL1G0mSaEj2po3pnQFK5EZzNq+gJDzDcBnf0/BNrRAJMG9xBKIA== + dependencies: + codemirror "6.0.1" + inputmask "5.0.9" + markdown-to-jsx "7.7.4" + moment "2.30.1" + react-syntax-highlighter "15.6.1" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2, fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +gensync@^1.0.0-beta.2: + version "1.0.0-beta.2" + resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" + integrity sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg== + +get-caller-file@^2.0.1, get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-package-type@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/get-package-type/-/get-package-type-0.1.0.tgz#8de2d803cff44df3bc6c456e6668b36c3926e11a" + integrity sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q== + +get-tsconfig@^4.7.5: + version "4.10.0" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.10.0.tgz#403a682b373a823612475a4c2928c7326fc0f6bb" + integrity sha512-kGzZ3LWWQcGIAmg6iWvXn0ei6WDtV26wzHRMwDSzmAbcXrTEXxHy6IehI6/4eT6VRKyMP1eF1VqwrVUmE/LR7A== + dependencies: + resolve-pkg-maps "^1.0.0" + +glob-parent@^5.1.2, glob-parent@~5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob@^10.4.5: + version "10.4.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + +glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^11.1.0: + version "11.12.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" + integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== + +globals@^15.14.0: + version "15.15.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-15.15.0.tgz#7c4761299d41c32b075715a4ce1ede7897ff72a8" + integrity sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg== + +graceful-fs@^4.1.15: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +gzip-size@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" + integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== + dependencies: + duplexer "^0.1.2" + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +hasha@^5.0.0: + version "5.2.2" + resolved "https://registry.yarnpkg.com/hasha/-/hasha-5.2.2.tgz#a48477989b3b327aea3c04f53096d816d97522a1" + integrity sha512-Hrp5vIK/xr5SkeN2onO32H0MgNZ0f17HRNH39WfL0SYUNOTZ5Lz1TJ8Pajo/87dYGEFlLMm7mIc/k/s6Bvz9HQ== + dependencies: + is-stream "^2.0.0" + type-fest "^0.8.0" + +hast-util-parse-selector@^2.0.0: + version "2.2.5" + resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz#d57c23f4da16ae3c63b3b6ca4616683313499c3a" + integrity sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ== + +hastscript@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-6.0.0.tgz#e8768d7eac56c3fdeac8a92830d58e811e5bf640" + integrity sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w== + dependencies: + "@types/hast" "^2.0.0" + comma-separated-tokens "^1.0.0" + hast-util-parse-selector "^2.0.0" + property-information "^5.0.0" + space-separated-tokens "^1.0.0" + +he@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" + integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== + +highlight.js@^10.4.1, highlight.js@~10.7.0: + version "10.7.3" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" + integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== + +highlightjs-vue@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/highlightjs-vue/-/highlightjs-vue-1.0.0.tgz#fdfe97fbea6354e70ee44e3a955875e114db086d" + integrity sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA== + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +iconv-lite@^0.4.24: + version "0.4.24" + resolved "https://registry.yarnpkg.com/iconv-lite/-/iconv-lite-0.4.24.tgz#2022b4b25fbddc21d2f524974a474aafe733908b" + integrity sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA== + dependencies: + safer-buffer ">= 2.1.2 < 3" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +indent-string@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/indent-string/-/indent-string-4.0.0.tgz#624f8f4497d619b2d9768531d58f4122854d7251" + integrity sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +inputmask@5.0.9: + version "5.0.9" + resolved "https://registry.yarnpkg.com/inputmask/-/inputmask-5.0.9.tgz#7bf4e83f5e199c88c0edf28545dc23fa208ef4be" + integrity sha512-s0lUfqcEbel+EQXtehXqwCJGShutgieOaIImFKC/r4reYNvX3foyrChl6LOEvaEgxEbesePIrw1Zi2jhZaDZbQ== + +is-alphabetical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" + integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== + +is-alphanumerical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" + integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== + dependencies: + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + +is-binary-path@~2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" + integrity sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw== + dependencies: + binary-extensions "^2.0.0" + +is-decimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" + integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.1, is-glob@~4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-hexadecimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" + integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-plain-obj@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/is-plain-obj/-/is-plain-obj-2.1.0.tgz#45e42e37fccf1f40da8e5f76ee21515840c09287" + integrity sha512-YWnfyRwxL/+SsrWYfOpUtz5b3YD+nyfkHvjbcanzk8zgyO4ASD67uVMRt8k5bM4lLMDnXfriRhOpemw+NfT1eA== + +is-stream@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-2.0.1.tgz#fac1e3d53b97ad5a9d0ae9cef2389f5810a5c077" + integrity sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg== + +is-typedarray@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/is-typedarray/-/is-typedarray-1.0.0.tgz#e479c80858df0c1b11ddda6940f96011fcda4a9a" + integrity sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA== + +is-unicode-supported@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz#3f26c76a809593b52bfa2ecb5710ed2779b522a7" + integrity sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw== + +is-windows@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-windows/-/is-windows-1.0.2.tgz#d1850eb9791ecd18e6182ce12a30f396634bb19d" + integrity sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +istanbul-lib-coverage@^3.0.0, istanbul-lib-coverage@^3.2.0: + version "3.2.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== + +istanbul-lib-hook@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-hook/-/istanbul-lib-hook-3.0.0.tgz#8f84c9434888cc6b1d0a9d7092a76d239ebf0cc6" + integrity sha512-Pt/uge1Q9s+5VAZ+pCo16TYMWPBIl+oaNIjgLQxcX0itS6ueeaA+pEfThZpH8WxhFgCiEb8sAJY6MdUKgiIWaQ== + dependencies: + append-transform "^2.0.0" + +istanbul-lib-instrument@^6.0.2: + version "6.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz#fa15401df6c15874bcb2105f773325d78c666765" + integrity sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q== + dependencies: + "@babel/core" "^7.23.9" + "@babel/parser" "^7.23.9" + "@istanbuljs/schema" "^0.1.3" + istanbul-lib-coverage "^3.2.0" + semver "^7.5.4" + +istanbul-lib-processinfo@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/istanbul-lib-processinfo/-/istanbul-lib-processinfo-2.0.3.tgz#366d454cd0dcb7eb6e0e419378e60072c8626169" + integrity sha512-NkwHbo3E00oybX6NGJi6ar0B29vxyvNwoC7eJ4G4Yq28UfY758Hgn/heV8VRFhevPED4LXfFz0DQ8z/0kw9zMg== + dependencies: + archy "^1.0.0" + cross-spawn "^7.0.3" + istanbul-lib-coverage "^3.2.0" + p-map "^3.0.0" + rimraf "^3.0.0" + uuid "^8.3.2" + +istanbul-lib-report@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.0: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.0.2: + version "3.1.7" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.7.tgz#daed12b9e1dca518e15c056e1e537e741280fa0b" + integrity sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + +jiti@^2.4.2: + version "2.4.2" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.4.2.tgz#d19b7732ebb6116b06e2038da74a55366faef560" + integrity sha512-rg9zJN+G4n2nfJl5MW3BMygZX56zKPNVEYYqq7adpmMh4Jn2QNEwhvQlFy6jPVdcod7txZtKHWnyZiA3a0zP7A== + +jose@6.0.10: + version "6.0.10" + resolved "https://registry.yarnpkg.com/jose/-/jose-6.0.10.tgz#52d96e1a671b4c02e13b71e0d35abea2e774712b" + integrity sha512-skIAxZqcMkOrSwjJvplIPYrlXGpxTPnro2/QWTDCxAdWQrSTV5/KqspMWmi5WAx5+ULswASJiZ0a+1B/Lxt9cw== + +js-tokens@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" + integrity sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ== + +js-yaml@^3.13.1: + version "3.14.1" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-3.14.1.tgz#dae812fdb3825fa306609a8717383c50c36a0537" + integrity sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g== + dependencies: + argparse "^1.0.7" + esprima "^4.0.0" + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +jsesc@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsesc/-/jsesc-3.1.0.tgz#74d335a234f67ed19907fdadfac7ccf9d409825d" + integrity sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA== + +json5@^2.2.3: + version "2.2.3" + resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" + integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== + +kolorist@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/kolorist/-/kolorist-1.8.0.tgz#edddbbbc7894bc13302cdf740af6374d4a04743c" + integrity sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ== + +local-pkg@^1.0.0: + version "1.1.1" + resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-1.1.1.tgz#f5fe74a97a3bd3c165788ee08ca9fbe998dc58dd" + integrity sha512-WunYko2W1NcdfAFpuLUoucsgULmgDBRkdxHxWQ7mK0cQqwPiy8E1enjuRBrhLtZkB5iScJ1XIPdhVEFK8aOLSg== + dependencies: + mlly "^1.7.4" + pkg-types "^2.0.1" + quansync "^0.2.8" + +locate-path@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" + integrity sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g== + dependencies: + p-locate "^4.1.0" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.flattendeep@^4.4.0: + version "4.4.0" + resolved "https://registry.yarnpkg.com/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz#fb030917f86a3134e5bc9bec0d69e0013ddfedb2" + integrity sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ== + +log-symbols@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/log-symbols/-/log-symbols-4.1.0.tgz#3fbdbb95b4683ac9fc785111e792e558d4abd503" + integrity sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg== + dependencies: + chalk "^4.1.0" + is-unicode-supported "^0.1.0" + +loupe@^3.1.0: + version "3.1.3" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.1.3.tgz#042a8f7986d77f3d0f98ef7990a2b2fef18b0fd2" + integrity sha512-kkIp7XSkP78ZxJEsSxW3712C6teJVoeHHwgo9zJ380de7IYyJ2ISlxojcH2pC5OFLewESmnRi/+XCDIEEVyoug== + +lowlight@^1.17.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.20.0.tgz#ddb197d33462ad0d93bf19d17b6c301aa3941888" + integrity sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw== + dependencies: + fault "^1.0.0" + highlight.js "~10.7.0" + +lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + +lru-cache@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" + integrity sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w== + dependencies: + yallist "^3.0.2" + +magic-string@^0.30.17: + version "0.30.17" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.17.tgz#450a449673d2460e5bbcfba9a61916a1714c7453" + integrity sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + +make-dir@^3.0.0, make-dir@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + +make-error@^1.1.1: + version "1.3.6" + resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" + integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== + +markdown-to-jsx@7.7.4: + version "7.7.4" + resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-7.7.4.tgz#507d17c15af72ddf970fca84a95f0243244fcfa9" + integrity sha512-1bSfXyBKi+EYS3YY+e0Csuxf8oZ3decdfhOav/Z7Wrk89tjudyL5FOmwZQUoy0/qVXGUl+6Q3s2SWtpDEWITfQ== + +mdn-data@2.12.2: + version "2.12.2" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.12.2.tgz#9ae6c41a9e65adf61318b32bff7b64fbfb13f8cf" + integrity sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA== + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + +minimatch@^3.0.4, minimatch@^3.1.1: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimatch@^5.1.6: + version "5.1.6" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.6.tgz#1cfcb8cf5522ea69952cd2af95ae09477f122a96" + integrity sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^9.0.4: + version "9.0.5" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.5.tgz#d74f9dd6b57d83d8e98cfb82133b03978bc929e5" + integrity sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow== + dependencies: + brace-expansion "^2.0.1" + +minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + +mlly@^1.7.4: + version "1.7.4" + resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.7.4.tgz#3d7295ea2358ec7a271eaa5d000a0f84febe100f" + integrity sha512-qmdSIPC4bDJXgZTCR7XosJiNKySV7O215tsPtDN9iEO/7q/76b/ijtgRu/+epFXSJhijtTCCGp3DWS549P3xKw== + dependencies: + acorn "^8.14.0" + pathe "^2.0.1" + pkg-types "^1.3.0" + ufo "^1.5.4" + +mocha@11.2.2: + version "11.2.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-11.2.2.tgz#2dfefc9652de746389f5286888034239b6486231" + integrity sha512-VlSBxrPYHK4YNOEbFdkCxHQbZMoNzBkoPprqtZRW6311EUF/DlSxoycE2e/2NtRk4WKkIXzyrXDTrlikJMWgbw== + dependencies: + browser-stdout "^1.3.1" + chokidar "^4.0.1" + debug "^4.3.5" + diff "^5.2.0" + escape-string-regexp "^4.0.0" + find-up "^5.0.0" + glob "^10.4.5" + he "^1.2.0" + js-yaml "^4.1.0" + log-symbols "^4.1.0" + minimatch "^5.1.6" + ms "^2.1.3" + picocolors "^1.1.1" + serialize-javascript "^6.0.2" + strip-json-comments "^3.1.1" + supports-color "^8.1.1" + workerpool "^6.5.1" + yargs "^17.7.2" + yargs-parser "^21.1.1" + yargs-unparser "^2.0.0" + +moment@2.30.1: + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== + +mrmime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-2.0.1.tgz#bc3e87f7987853a54c9850eeb1f1078cd44adddc" + integrity sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ== + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +mustache@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64" + integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ== + +mute-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-2.0.0.tgz#a5446fc0c512b71c83c44d908d5c7b7b4c493b2b" + integrity sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA== + +nanoid@3.3.8: + version "3.3.8" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" + integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== + +nanoid@^3.3.8: + version "3.3.11" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" + integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== + +node-fetch-native@^1.6.4: + version "1.6.6" + resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.6.6.tgz#ae1d0e537af35c2c0b0de81cbff37eedd410aa37" + integrity sha512-8Mc2HhqPdlIfedsuZoc3yioPuzp6b+L5jRCRY1QzuWZh2EGJVQrGppC6V6cF0bLdbW0+O2YpqCA25aF/1lvipQ== + +node-preload@^0.2.1: + version "0.2.1" + resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz#c03043bb327f417a18fee7ab7ee57b408a144301" + integrity sha512-RM5oyBy45cLEoHqCeh+MNuFAxO0vTFBLskvQbOKnEE7YTTSN4tbN8QWDIPQ6L+WvKsB/qLEGpYe2ZZ9d4W9OIQ== + dependencies: + process-on-spawn "^1.0.0" + +node-releases@^2.0.19: + version "2.0.19" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" + integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== + +nodemailer@6.9.16: + version "6.9.16" + resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.9.16.tgz#3ebdf6c6f477c571c0facb0727b33892635e0b8b" + integrity sha512-psAuZdTIRN08HKVd/E8ObdV6NO7NTBY3KsC30F7M4H1OnmLCUNaS56FpYxyb26zWLSyYF9Ozch9KYHhHegsiOQ== + +normalize-path@^3.0.0, normalize-path@~3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" + integrity sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA== + +nyc@17.1.0: + version "17.1.0" + resolved "https://registry.yarnpkg.com/nyc/-/nyc-17.1.0.tgz#b6349a401a62ffeb912bd38ea9a018839fdb6eb1" + integrity sha512-U42vQ4czpKa0QdI1hu950XuNhYqgoM+ZF1HT+VuUHL9hPfDPVvNQyltmMqdE9bUHMVa+8yNbc3QKTj8zQhlVxQ== + dependencies: + "@istanbuljs/load-nyc-config" "^1.0.0" + "@istanbuljs/schema" "^0.1.2" + caching-transform "^4.0.0" + convert-source-map "^1.7.0" + decamelize "^1.2.0" + find-cache-dir "^3.2.0" + find-up "^4.1.0" + foreground-child "^3.3.0" + get-package-type "^0.1.0" + glob "^7.1.6" + istanbul-lib-coverage "^3.0.0" + istanbul-lib-hook "^3.0.0" + istanbul-lib-instrument "^6.0.2" + istanbul-lib-processinfo "^2.0.2" + istanbul-lib-report "^3.0.0" + istanbul-lib-source-maps "^4.0.0" + istanbul-reports "^3.0.2" + make-dir "^3.0.0" + node-preload "^0.2.1" + p-map "^3.0.0" + process-on-spawn "^1.0.0" + resolve-from "^5.0.0" + rimraf "^3.0.0" + signal-exit "^3.0.2" + spawn-wrap "^2.0.0" + test-exclude "^6.0.0" + yargs "^15.0.2" + +ofetch@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.4.1.tgz#b6bf6b0d75ba616cef6519dd8b6385a8bae480ec" + integrity sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw== + dependencies: + destr "^2.0.3" + node-fetch-native "^1.6.4" + ufo "^1.5.4" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +os-tmpdir@~1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" + integrity sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g== + +p-limit@^2.2.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-2.3.0.tgz#3dd33c647a214fdfffd835933eb086da0dc21db1" + integrity sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w== + dependencies: + p-try "^2.0.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-locate@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-4.1.0.tgz#a3428bb7088b3a60292f66919278b7c297ad4f07" + integrity sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A== + dependencies: + p-limit "^2.2.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +p-map@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/p-map/-/p-map-3.0.0.tgz#d704d9af8a2ba684e2600d9a215983d4141a979d" + integrity sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ== + dependencies: + aggregate-error "^3.0.0" + +p-try@^2.0.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/p-try/-/p-try-2.2.0.tgz#cb2868540e313d61de58fafbe35ce9004d5540e6" + integrity sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ== + +package-hash@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/package-hash/-/package-hash-4.0.0.tgz#3537f654665ec3cc38827387fc904c163c54f506" + integrity sha512-whdkPIooSu/bASggZ96BWVvZTRMOFxnyUG5PnTSGKoJE2gd5mbVNmR2Nj20QFzxYYgAXpoqC+AiXzl+UMRh7zQ== + dependencies: + graceful-fs "^4.1.15" + hasha "^5.0.0" + lodash.flattendeep "^4.4.0" + release-zalgo "^1.0.0" + +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + +package-manager-detector@^0.2.8: + version "0.2.11" + resolved "https://registry.yarnpkg.com/package-manager-detector/-/package-manager-detector-0.2.11.tgz#3af0b34f99d86d24af0a0620603d2e1180d05c9c" + integrity sha512-BEnLolu+yuz22S56CU1SUKq3XC3PkwD5wv4ikR4MfGvnRVcmzXR9DwSlW2fEamyTPyXHomBJRzgapeuBvRNzJQ== + dependencies: + quansync "^0.2.7" + +papaparse@5.5.1: + version "5.5.1" + resolved "https://registry.yarnpkg.com/papaparse/-/papaparse-5.5.1.tgz#4322da01e85d8e9e282c1e4387793a5978b5a0a1" + integrity sha512-EuEKUhyxrHVozD7g3/ztsJn6qaKse8RPfR6buNB2dMJvdtXNhcw8jccVi/LxNEY3HVrV6GO6Z4OoeCG9Iy9wpA== + +parse-entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" + integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ== + dependencies: + character-entities "^1.0.0" + character-entities-legacy "^1.0.0" + character-reference-invalid "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + is-hexadecimal "^1.0.0" + +path-browserify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" + integrity sha512-b7uo2UCUOYZcnF/3ID0lulOJi/bafxa1xPe7ZPsammBSpjSWQkjNxlt635YGS2MiR9GjvuXCtz2emr3jbsz98g== + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + +pathe@^2.0.1, pathe@^2.0.2, pathe@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" + integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== + +pathval@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.0.tgz#7e2550b422601d4f6b8e26f1301bc8f15a741a25" + integrity sha512-vE7JKRyES09KiunauX7nd2Q9/L7lhok4smP9RZTDeD4MVs72Dp2qNFVz39Nz5a0FVEW0BJR6C0DYrq6unoziZA== + +perfect-debounce@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz#9c2e8bc30b169cc984a58b7d5b28049839591d2a" + integrity sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA== + +picocolors@^1.0.0, picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +picomatch@^4.0.2: + version "4.0.2" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" + integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== + +pkg-dir@^4.1.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" + integrity sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ== + dependencies: + find-up "^4.0.0" + +pkg-types@^1.3.0: + version "1.3.1" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.3.1.tgz#bd7cc70881192777eef5326c19deb46e890917df" + integrity sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ== + dependencies: + confbox "^0.1.8" + mlly "^1.7.4" + pathe "^2.0.1" + +pkg-types@^2.0.1: + version "2.1.0" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-2.1.0.tgz#70c9e1b9c74b63fdde749876ee0aa007ea9edead" + integrity sha512-wmJwA+8ihJixSoHKxZJRBQG1oY8Yr9pGLzRmSsNms0iNWyHHAlZCa7mmKiFR10YPZuz/2k169JiS/inOjBCZ2A== + dependencies: + confbox "^0.2.1" + exsolve "^1.0.1" + pathe "^2.0.3" + +postcss@^8.5.2, postcss@^8.5.3: + version "8.5.3" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.3.tgz#1463b6f1c7fb16fe258736cba29a2de35237eafb" + integrity sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A== + dependencies: + nanoid "^3.3.8" + picocolors "^1.1.1" + source-map-js "^1.2.1" + +prettier@3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.5.3.tgz#4fc2ce0d657e7a02e602549f053b239cb7dfe1b5" + integrity sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw== + +prismjs@^1.27.0: + version "1.30.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.30.0.tgz#d9709969d9d4e16403f6f348c63553b19f0975a9" + integrity sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw== + +prismjs@~1.27.0: + version "1.27.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057" + integrity sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA== + +process-on-spawn@^1.0.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/process-on-spawn/-/process-on-spawn-1.1.0.tgz#9d5999ba87b3bf0a8acb05322d69f2f5aa4fb763" + integrity sha512-JOnOPQ/8TZgjs1JIH/m9ni7FfimjNa/PRx7y/Wb5qdItsnhO0jE4AT7fC0HjC28DUQWDr50dwSYZLdRMlqDq3Q== + dependencies: + fromentries "^1.2.0" + +property-information@^5.0.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.6.0.tgz#61675545fb23002f245c6540ec46077d4da3ed69" + integrity sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA== + dependencies: + xtend "^4.0.0" + +punycode@^1.3.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== + +pvtsutils@^1.3.5, pvtsutils@^1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.3.6.tgz#ec46e34db7422b9e4fdc5490578c1883657d6001" + integrity sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg== + dependencies: + tslib "^2.8.1" + +pvutils@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.3.tgz#f35fc1d27e7cd3dfbd39c0826d173e806a03f5a3" + integrity sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ== + +quansync@^0.2.7, quansync@^0.2.8: + version "0.2.10" + resolved "https://registry.yarnpkg.com/quansync/-/quansync-0.2.10.tgz#32053cf166fa36511aae95fc49796116f2dc20e1" + integrity sha512-t41VRkMYbkHyCYmOvx/6URnN80H7k4X0lLdBMGsz+maAwrJQYB1djpV6vHrQIBE0WBSGqhtEHrK9U3DWWH8v7A== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +r22n@1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/r22n/-/r22n-1.0.10.tgz#bab4b5888bcdb3f44d93ac076acfe6cec5ab102d" + integrity sha512-2jFDC6oCe5UhzL4s8iAMN+7FbAtaxK9SjzZ6HxYm8O7+zmxZsiSSqjZD7iFfsjJtJkPx760p7Nc6jTXjc+Yd2w== + +randombytes@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" + integrity sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ== + dependencies: + safe-buffer "^5.1.0" + +react-dom@19.1.0: + version "19.1.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.1.0.tgz#133558deca37fa1d682708df8904b25186793623" + integrity sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g== + dependencies: + scheduler "^0.26.0" + +react-refresh@^0.17.0: + version "0.17.0" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.17.0.tgz#b7e579c3657f23d04eccbe4ad2e58a8ed51e7e53" + integrity sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ== + +react-syntax-highlighter@15.6.1: + version "15.6.1" + resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-15.6.1.tgz#fa567cb0a9f96be7bbccf2c13a3c4b5657d9543e" + integrity sha512-OqJ2/vL7lEeV5zTJyG7kmARppUjiB9h9udl4qHQjjgEos66z00Ia0OckwYfRxCSFrW8RJIBnsBwQsHZbVPspqg== + dependencies: + "@babel/runtime" "^7.3.1" + highlight.js "^10.4.1" + highlightjs-vue "^1.0.0" + lowlight "^1.17.0" + prismjs "^1.27.0" + refractor "^3.6.0" + +react-toastify@11.0.5: + version "11.0.5" + resolved "https://registry.yarnpkg.com/react-toastify/-/react-toastify-11.0.5.tgz#ce4c42d10eeb433988ab2264d3e445c4e9d13313" + integrity sha512-EpqHBGvnSTtHYhCPLxML05NLY2ZX0JURbAdNYa6BUkk+amz4wbKBQvoKQAB0ardvSarUBuY4Q4s1sluAzZwkmA== + dependencies: + clsx "^2.1.1" + +react@19.1.0: + version "19.1.0" + resolved "https://registry.yarnpkg.com/react/-/react-19.1.0.tgz#926864b6c48da7627f004795d6cce50e90793b75" + integrity sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg== + +reactus@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/reactus/-/reactus-0.6.1.tgz#fea94424481052ba298e511ad8f7e6e53dbff084" + integrity sha512-+NP6BJYMYrk79NkIvgd094ghxHQ4zTDCVFvuSBZJRePYpXEHNkoqjIGl+2IUGGbO+gVGGqNTfALZEnJ13pvh7A== + dependencies: + "@stackpress/lib" "0.6.1" + +readdirp@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" + integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== + +readdirp@~3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" + integrity sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA== + dependencies: + picomatch "^2.2.1" + +refractor@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.6.0.tgz#ac318f5a0715ead790fcfb0c71f4dd83d977935a" + integrity sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA== + dependencies: + hastscript "^6.0.0" + parse-entities "^2.0.0" + prismjs "~1.27.0" + +regenerator-runtime@^0.14.0: + version "0.14.1" + resolved "https://registry.yarnpkg.com/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz#356ade10263f685dda125100cd862c1db895327f" + integrity sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw== + +release-zalgo@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" + integrity sha512-gUAyHVHPPC5wdqX/LG4LWtRYtgjxyX78oanFNTMMyFEfOqdC54s3eE82imuWKbOeqYht2CrNf64Qb8vgmmtZGA== + dependencies: + es6-error "^4.0.1" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +require-main-filename@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/require-main-filename/-/require-main-filename-2.0.0.tgz#d0b329ecc7cc0f61649f62215be69af54aa8989b" + integrity sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg== + +resolve-from@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-5.0.0.tgz#c35225843df8f776df21c57557bc087e9dfdfc69" + integrity sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw== + +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + +reusify@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== + +rimraf@^3.0.0: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +rollup@^4.34.9: + version "4.40.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.40.0.tgz#13742a615f423ccba457554f006873d5a4de1920" + integrity sha512-Noe455xmA96nnqH5piFtLobsGbCij7Tu+tb3c1vYjNbTkfzGqXqQXG3wJaYXkRZuQ0vEYN4bhwg7QnIrqB5B+w== + dependencies: + "@types/estree" "1.0.7" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.40.0" + "@rollup/rollup-android-arm64" "4.40.0" + "@rollup/rollup-darwin-arm64" "4.40.0" + "@rollup/rollup-darwin-x64" "4.40.0" + "@rollup/rollup-freebsd-arm64" "4.40.0" + "@rollup/rollup-freebsd-x64" "4.40.0" + "@rollup/rollup-linux-arm-gnueabihf" "4.40.0" + "@rollup/rollup-linux-arm-musleabihf" "4.40.0" + "@rollup/rollup-linux-arm64-gnu" "4.40.0" + "@rollup/rollup-linux-arm64-musl" "4.40.0" + "@rollup/rollup-linux-loongarch64-gnu" "4.40.0" + "@rollup/rollup-linux-powerpc64le-gnu" "4.40.0" + "@rollup/rollup-linux-riscv64-gnu" "4.40.0" + "@rollup/rollup-linux-riscv64-musl" "4.40.0" + "@rollup/rollup-linux-s390x-gnu" "4.40.0" + "@rollup/rollup-linux-x64-gnu" "4.40.0" + "@rollup/rollup-linux-x64-musl" "4.40.0" + "@rollup/rollup-win32-arm64-msvc" "4.40.0" + "@rollup/rollup-win32-ia32-msvc" "4.40.0" + "@rollup/rollup-win32-x64-msvc" "4.40.0" + fsevents "~2.3.2" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-buffer@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" + integrity sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ== + +"safer-buffer@>= 2.1.2 < 3": + version "2.1.2" + resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" + integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== + +scheduler@^0.26.0: + version "0.26.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.26.0.tgz#4ce8a8c2a2095f13ea11bf9a445be50c555d6337" + integrity sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA== + +semver@^6.0.0, semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.5.3, semver@^7.5.4: + version "7.7.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.7.1.tgz#abd5098d82b18c6c81f6074ff2647fd3e7220c9f" + integrity sha512-hlq8tAfn0m/61p4BVRcPzIGr6LKiMwo4VM6dGi6pt4qcRkmNzTcWq6eCEjEh+qXjkMDvPlOFFSGwQjoEa6gyMA== + +serialize-javascript@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== + dependencies: + randombytes "^2.1.0" + +set-blocking@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" + integrity sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw== + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +signal-exit@^3.0.2: + version "3.0.7" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.7.tgz#a9a1767f8af84155114eaabd73f99273c8f59ad9" + integrity sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ== + +signal-exit@^4.0.1, signal-exit@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +sirv@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-3.0.1.tgz#32a844794655b727f9e2867b777e0060fbe07bf3" + integrity sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A== + dependencies: + "@polka/url" "^1.0.0-next.24" + mrmime "^2.0.0" + totalist "^3.0.0" + +source-map-js@^1.0.1, source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + +source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +space-separated-tokens@^1.0.0: + version "1.1.5" + resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" + integrity sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA== + +spawn-wrap@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-2.0.0.tgz#103685b8b8f9b79771318827aa78650a610d457e" + integrity sha512-EeajNjfN9zMnULLwhZZQU3GWBoFNkbngTUPfaawT4RkMiviTxcX0qfhVbGey39mfctfDHkWtuecgQ8NJcyQWHg== + dependencies: + foreground-child "^2.0.0" + is-windows "^1.0.2" + make-dir "^3.0.0" + rimraf "^3.0.0" + signal-exit "^3.0.2" + which "^2.0.1" + +sprintf-js@~1.0.2: + version "1.0.3" + resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" + integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== + +stackpress@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/stackpress/-/stackpress-0.6.1.tgz#2609acfc3d063b20ca614b5bbaa9afd379dde79d" + integrity sha512-y0xUvvlXR2Tfkq4ZHy7R5KsNL3e7PjpEy563YGWVTm294AxwAO7jjNa0/tbfpuxFhKp+kxougz78nrSIVjJpeA== + dependencies: + "@paralleldrive/cuid2" "2.2.2" + "@stackpress/idea-transformer" "0.6.1" + "@stackpress/ingest" "0.6.1" + "@stackpress/inquire" "0.6.1" + "@stackpress/lib" "0.6.1" + jose "6.0.10" + mustache "4.2.0" + nanoid "3.3.8" + nodemailer "6.9.16" + papaparse "5.5.1" + r22n "1.0.10" + react-toastify "11.0.5" + reactus "0.6.1" + universal-cookie "8.0.1" + +streamsearch@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" + integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== + +"string-width-cjs@npm:string-width@^4.2.0": + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + +strip-bom@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-4.0.0.tgz#9c3505c1db45bcedca3d9cf7a16f5c5aa3901878" + integrity sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +style-mod@^4.0.0, style-mod@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.1.2.tgz#ca238a1ad4786520f7515a8539d5a63691d7bf67" + integrity sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw== + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-color@^8.1.1: + version "8.1.1" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-8.1.1.tgz#cd6fc17e28500cff56c1b86c0a7fd4a54a73005c" + integrity sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q== + dependencies: + has-flag "^4.0.0" + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +tinyexec@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-0.3.2.tgz#941794e657a85e496577995c6eef66f53f42b3d2" + integrity sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA== + +tinyglobby@^0.2.10, tinyglobby@^0.2.12: + version "0.2.13" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.13.tgz#a0e46515ce6cbcd65331537e57484af5a7b2ff7e" + integrity sha512-mEwzpUgrLySlveBwEVDMKk5B57bhLPYovRfPAXD5gA/98Opn0rCDj3GtLwFvCvH5RK9uPCExUROW5NjDwvqkxw== + dependencies: + fdir "^6.4.4" + picomatch "^4.0.2" + +tmp@^0.0.33: + version "0.0.33" + resolved "https://registry.yarnpkg.com/tmp/-/tmp-0.0.33.tgz#6d34335889768d21b2bcda0aa277ced3b1bfadf9" + integrity sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw== + dependencies: + os-tmpdir "~1.0.2" + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +totalist@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/totalist/-/totalist-3.0.1.tgz#ba3a3d600c915b1a97872348f79c127475f6acf8" + integrity sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ== + +ts-mocha@11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-11.1.0.tgz#d8336ec0146bd6f36cca2555f4cfc7df85bd1586" + integrity sha512-yT7FfzNRCu8ZKkYvAOiH01xNma/vLq6Vit7yINKYFNVP8e5UyrYXSOMIipERTpzVKJQ4Qcos5bQo1tNERNZevQ== + +ts-morph@25.0.1: + version "25.0.1" + resolved "https://registry.yarnpkg.com/ts-morph/-/ts-morph-25.0.1.tgz#7de0b60fcc6e86955c8766831bcd2c5d87ffbd4f" + integrity sha512-QJEiTdnz1YjrB3JFhd626gX4rKHDLSjSVMvGGG4v7ONc3RBwa0Eei98G9AT9uNFDMtV54JyuXsFeC+OH0n6bXQ== + dependencies: + "@ts-morph/common" "~0.26.0" + code-block-writer "^13.0.3" + +ts-node@10.9.2: + version "10.9.2" + resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" + integrity sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ== + dependencies: + "@cspotcode/source-map-support" "^0.8.0" + "@tsconfig/node10" "^1.0.7" + "@tsconfig/node12" "^1.0.7" + "@tsconfig/node14" "^1.0.0" + "@tsconfig/node16" "^1.0.2" + acorn "^8.4.1" + acorn-walk "^8.1.1" + arg "^4.1.0" + create-require "^1.1.0" + diff "^4.0.1" + make-error "^1.1.1" + v8-compile-cache-lib "^3.0.1" + yn "3.1.1" + +tslib@^2.0.0, tslib@^2.3.1, tslib@^2.6.2, tslib@^2.7.0, tslib@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + +tsx@4.19.3: + version "4.19.3" + resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.19.3.tgz#2bdbcb87089374d933596f8645615142ed727666" + integrity sha512-4H8vUNGNjQ4V2EOoGw005+c+dGuPSnhpPBPHBtsZdGZBk/iJb4kguGlPWaZTZ3q5nMtFOEsY0nRDlh9PJyd6SQ== + dependencies: + esbuild "~0.25.0" + get-tsconfig "^4.7.5" + optionalDependencies: + fsevents "~2.3.3" + +type-fest@^0.21.3: + version "0.21.3" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.21.3.tgz#d260a24b0198436e133fa26a524a6d65fa3b2e37" + integrity sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w== + +type-fest@^0.8.0: + version "0.8.1" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.8.1.tgz#09e249ebde851d3b1e48d27c105444667f17b83d" + integrity sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA== + +typedarray-to-buffer@^3.1.5: + version "3.1.5" + resolved "https://registry.yarnpkg.com/typedarray-to-buffer/-/typedarray-to-buffer-3.1.5.tgz#a97ee7a9ff42691b9f783ff1bc5112fe3fca9080" + integrity sha512-zdu8XMNEDepKKR+XYOXAVPtWui0ly0NtohUscw+UmaHiAWT8hrV1rr//H6V+0DvJ3OQ19S979M0laLfX8rm82Q== + dependencies: + is-typedarray "^1.0.0" + +typescript@5.8.3: + version "5.8.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e" + integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== + +ufo@^1.5.4: + version "1.6.1" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.6.1.tgz#ac2db1d54614d1b22c1d603e3aef44a85d8f146b" + integrity sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA== + +unconfig@~7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/unconfig/-/unconfig-7.0.0.tgz#0c917fbbeb9ac49341b4bc56b155351646dd6ff2" + integrity sha512-G5CJSoG6ZTxgzCJblEfgpdRK2tos9+UdD2WtecDUVfImzQ0hFjwpH5RVvGMhP4pRpC9ML7NrC4qBsBl0Ttj35A== + dependencies: + "@antfu/utils" "^8.1.0" + defu "^6.1.4" + jiti "^2.4.2" + +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== + +universal-cookie@8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/universal-cookie/-/universal-cookie-8.0.1.tgz#19263fcda6889978a081c610a90fc395eeaeec64" + integrity sha512-B6ks9FLLnP1UbPPcveOidfvB9pHjP+wekP2uRYB9YDfKVpvcjKgy1W5Zj+cEXJ9KTPnqOKGfVDQBmn8/YCQfRg== + dependencies: + cookie "^1.0.2" + +unocss@66.0.0: + version "66.0.0" + resolved "https://registry.yarnpkg.com/unocss/-/unocss-66.0.0.tgz#4f6842b54fc1a1a1c7d86d925b972ba035e03c4f" + integrity sha512-SHstiv1s7zGPSjzOsADzlwRhQM+6817+OqQE3Fv+N/nn2QLNx1bi3WXybFfz5tWkzBtyTZlwdPmeecsIs1yOCA== + dependencies: + "@unocss/astro" "66.0.0" + "@unocss/cli" "66.0.0" + "@unocss/core" "66.0.0" + "@unocss/postcss" "66.0.0" + "@unocss/preset-attributify" "66.0.0" + "@unocss/preset-icons" "66.0.0" + "@unocss/preset-mini" "66.0.0" + "@unocss/preset-tagify" "66.0.0" + "@unocss/preset-typography" "66.0.0" + "@unocss/preset-uno" "66.0.0" + "@unocss/preset-web-fonts" "66.0.0" + "@unocss/preset-wind" "66.0.0" + "@unocss/preset-wind3" "66.0.0" + "@unocss/transformer-attributify-jsx" "66.0.0" + "@unocss/transformer-compile-class" "66.0.0" + "@unocss/transformer-directives" "66.0.0" + "@unocss/transformer-variant-group" "66.0.0" + "@unocss/vite" "66.0.0" + +unplugin-utils@^0.2.4: + version "0.2.4" + resolved "https://registry.yarnpkg.com/unplugin-utils/-/unplugin-utils-0.2.4.tgz#56e4029a6906645a10644f8befc404b06d5d24d0" + integrity sha512-8U/MtpkPkkk3Atewj1+RcKIjb5WBimZ/WSLhhR3w6SsIj8XJuKTacSP8g+2JhfSGw0Cb125Y+2zA/IzJZDVbhA== + dependencies: + pathe "^2.0.2" + picomatch "^4.0.2" + +update-browserslist-db@^1.1.1: + version "1.1.3" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.3.tgz#348377dd245216f9e7060ff50b15a1b740b75420" + integrity sha512-UxhIZQ+QInVdunkDAaiazvvT/+fXL5Osr0JZlJulepYu6Jd7qJtDZjlur0emRlT71EN3ScPoE7gvsuIKKNavKw== + dependencies: + escalade "^3.2.0" + picocolors "^1.1.1" + +urlpattern-polyfill@^8.0.0: + version "8.0.2" + resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-8.0.2.tgz#99f096e35eff8bf4b5a2aa7d58a1523d6ebc7ce5" + integrity sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ== + +uuid@^8.3.2: + version "8.3.2" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" + integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== + +v8-compile-cache-lib@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" + integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== + +vite@6.3.2: + version "6.3.2" + resolved "https://registry.yarnpkg.com/vite/-/vite-6.3.2.tgz#4c1bb01b1cea853686a191657bbc14272a038f0a" + integrity sha512-ZSvGOXKGceizRQIZSz7TGJ0pS3QLlVY/9hwxVh17W3re67je1RKYzFHivZ/t0tubU78Vkyb9WnHPENSBCzbckg== + dependencies: + esbuild "^0.25.0" + fdir "^6.4.3" + picomatch "^4.0.2" + postcss "^8.5.3" + rollup "^4.34.9" + tinyglobby "^0.2.12" + optionalDependencies: + fsevents "~2.3.3" + +vue-flow-layout@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/vue-flow-layout/-/vue-flow-layout-0.1.1.tgz#4095d9e79b80e845f110d4d015de6faf2c71f735" + integrity sha512-JdgRRUVrN0Y2GosA0M68DEbKlXMqJ7FQgsK8CjQD2vxvNSqAU6PZEpi4cfcTVtfM2GVOMjHo7GKKLbXxOBqDqA== + +w3c-keyname@^2.2.4: + version "2.2.8" + resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz#7b17c8c6883d4e8b86ac8aba79d39e880f8869c5" + integrity sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ== + +web-streams-polyfill@^3.2.1: + version "3.3.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b" + integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw== + +webcrypto-core@^1.8.0: + version "1.8.1" + resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.8.1.tgz#09d5bd8a9c48e9fbcaf412e06b1ff1a57514ce86" + integrity sha512-P+x1MvlNCXlKbLSOY4cYrdreqPG5hbzkmawbcXLKN/mf6DZW0SdNNkZ+sjwsqVkI4A4Ko2sPZmkZtCKY58w83A== + dependencies: + "@peculiar/asn1-schema" "^2.3.13" + "@peculiar/json-schema" "^1.1.12" + asn1js "^3.0.5" + pvtsutils "^1.3.5" + tslib "^2.7.0" + +which-module@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" + integrity sha512-iBdZ57RDvnOR9AGBhML2vFZf7h8vmBjhoaZqODJBFWHVtKkDmKuHai3cx5PgVMrX5YDNp27AofYbAwctSS+vhQ== + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +workerpool@^6.5.1: + version "6.5.1" + resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" + integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== + +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^6.2.0: + version "6.2.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" + integrity sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +write-file-atomic@^3.0.0: + version "3.0.3" + resolved "https://registry.yarnpkg.com/write-file-atomic/-/write-file-atomic-3.0.3.tgz#56bd5c5a5c70481cd19c571bd39ab965a5de56e8" + integrity sha512-AvHcyZ5JnSfq3ioSyjrBkH9yW4m7Ayk8/9My/DD9onKeu/94fwrMocemO2QAJFAlnnDN+ZDS+ZjAR5ua1/PV/Q== + dependencies: + imurmurhash "^0.1.4" + is-typedarray "^1.0.0" + signal-exit "^3.0.2" + typedarray-to-buffer "^3.1.5" + +xtend@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + +y18n@^4.0.0: + version "4.0.3" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" + integrity sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^3.0.2: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" + integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== + +yargs-parser@^18.1.2: + version "18.1.3" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" + integrity sha512-o50j0JeToy/4K6OZcaQmW6lyXXKhq7csREXcDwk2omFPJEwUNOVtJKvmDr9EI1fAJZUyZcRF7kxGBWmRXudrCQ== + dependencies: + camelcase "^5.0.0" + decamelize "^1.2.0" + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs-unparser@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" + integrity sha512-7pRTIA9Qc1caZ0bZ6RYRGbHJthJWuakf+WmHK0rVeLkNrrGhfoabBNdue6kdINI6r4if7ocq9aD/n7xwKOdzOA== + dependencies: + camelcase "^6.0.0" + decamelize "^4.0.0" + flat "^5.0.2" + is-plain-obj "^2.1.0" + +yargs@^15.0.2: + version "15.4.1" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-15.4.1.tgz#0d87a16de01aee9d8bec2bfbf74f67851730f4f8" + integrity sha512-aePbxDmcYW++PaqBsJ+HYUFwCdv4LVvdnhBy78E57PIor8/OVvhMrADFFEDh8DHDFRv/O9i3lPhsENjO7QX0+A== + dependencies: + cliui "^6.0.0" + decamelize "^1.2.0" + find-up "^4.1.0" + get-caller-file "^2.0.1" + require-directory "^2.1.1" + require-main-filename "^2.0.0" + set-blocking "^2.0.0" + string-width "^4.2.0" + which-module "^2.0.0" + y18n "^4.0.0" + yargs-parser "^18.1.2" + +yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yn@3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50" + integrity sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q== + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +yoctocolors-cjs@^2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/yoctocolors-cjs/-/yoctocolors-cjs-2.1.2.tgz#f4b905a840a37506813a7acaa28febe97767a242" + integrity sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA== diff --git a/yarn.lock b/yarn.lock index 6778e18..d289583 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2,7 +2,7 @@ # yarn lockfile v1 -"@ampproject/remapping@^2.2.0": +"@ampproject/remapping@^2.2.0", "@ampproject/remapping@^2.3.0": version "2.3.0" resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.3.0.tgz#ed441b6fa600072520ce18b43d2c8cc8caecc7f4" integrity sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw== @@ -10,6 +10,19 @@ "@jridgewell/gen-mapping" "^0.3.5" "@jridgewell/trace-mapping" "^0.3.24" +"@antfu/install-pkg@^1.0.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@antfu/install-pkg/-/install-pkg-1.1.0.tgz#78fa036be1a6081b5a77a5cf59f50c7752b6ba26" + integrity sha512-MGQsmw10ZyI+EJo45CdSER4zEb+p31LpDAFp2Z3gkSd1yqVZGi0Ebx++YTEMonJy4oChEMLsxZ64j8FH6sSqtQ== + dependencies: + package-manager-detector "^1.3.0" + tinyexec "^1.0.1" + +"@antfu/utils@^8.1.0": + version "8.1.1" + resolved "https://registry.yarnpkg.com/@antfu/utils/-/utils-8.1.1.tgz#95b1947d292a9a2efffba2081796dcaa05ecedfb" + integrity sha512-Mex9nXf9vR6AhcXmMrlz/HVgYYZpVGJ6YlPgwl7UnaFpnshXs6EK/oa5Gpf3CzENMjkvEx2tQtntGnb7UtSTOQ== + "@babel/code-frame@^7.25.9", "@babel/code-frame@^7.26.2": version "7.26.2" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.26.2.tgz#4b5fab97d33338eff916235055f0ebc21e573a85" @@ -80,6 +93,27 @@ json5 "^2.2.3" semver "^6.3.1" +"@babel/core@^7.26.10": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/core/-/core-7.28.3.tgz#aceddde69c5d1def69b839d09efa3e3ff59c97cb" + integrity sha512-yDBHV9kQNcr2/sUr9jghVyz9C3Y5G2zUM2H2lo+9mKv4sFgbA8s8Z9t8D1jiTkGoO/NoIfKMyKWr4s6CN23ZwQ== + dependencies: + "@ampproject/remapping" "^2.2.0" + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.3" + "@babel/helper-compilation-targets" "^7.27.2" + "@babel/helper-module-transforms" "^7.28.3" + "@babel/helpers" "^7.28.3" + "@babel/parser" "^7.28.3" + "@babel/template" "^7.27.2" + "@babel/traverse" "^7.28.3" + "@babel/types" "^7.28.2" + convert-source-map "^2.0.0" + debug "^4.1.0" + gensync "^1.0.0-beta.2" + json5 "^2.2.3" + semver "^6.3.1" + "@babel/generator@^7.26.5": version "7.26.5" resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.26.5.tgz#e44d4ab3176bbcaf78a5725da5f1dc28802a9458" @@ -102,6 +136,17 @@ "@jridgewell/trace-mapping" "^0.3.25" jsesc "^3.0.2" +"@babel/generator@^7.28.3": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/generator/-/generator-7.28.3.tgz#9626c1741c650cbac39121694a0f2d7451b8ef3e" + integrity sha512-3lSpxGgvnmZznmBkCRnVREPUFJv2wrv9iAoFDvADJc0ypmdOxdUtcLeBgBJ6zE0PMeTKnxeQzyk0xTBq4Ep7zw== + dependencies: + "@babel/parser" "^7.28.3" + "@babel/types" "^7.28.2" + "@jridgewell/gen-mapping" "^0.3.12" + "@jridgewell/trace-mapping" "^0.3.28" + jsesc "^3.0.2" + "@babel/helper-annotate-as-pure@^7.27.1": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.1.tgz#4345d81a9a46a6486e24d069469f13e60445c05d" @@ -120,7 +165,7 @@ lru-cache "^5.1.1" semver "^6.3.1" -"@babel/helper-compilation-targets@^7.27.1": +"@babel/helper-compilation-targets@^7.27.1", "@babel/helper-compilation-targets@^7.27.2": version "7.27.2" resolved "https://registry.yarnpkg.com/@babel/helper-compilation-targets/-/helper-compilation-targets-7.27.2.tgz#46a0f6efab808d51d29ce96858dd10ce8732733d" integrity sha512-2+1thGUUWWjLTYTHZWK1n8Yga0ijBz1XAhUXcKy81rd5g6yh7hGqMp45v7cadSbEHc9G3OTv45SyneRN3ps4DQ== @@ -144,6 +189,11 @@ "@babel/traverse" "^7.27.1" semver "^6.3.1" +"@babel/helper-globals@^7.28.0": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@babel/helper-globals/-/helper-globals-7.28.0.tgz#b9430df2aa4e17bc28665eadeae8aa1d985e6674" + integrity sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw== + "@babel/helper-member-expression-to-functions@^7.27.1": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.27.1.tgz#ea1211276be93e798ce19037da6f06fbb994fa44" @@ -186,6 +236,15 @@ "@babel/helper-validator-identifier" "^7.27.1" "@babel/traverse" "^7.27.1" +"@babel/helper-module-transforms@^7.28.3": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/helper-module-transforms/-/helper-module-transforms-7.28.3.tgz#a2b37d3da3b2344fe085dab234426f2b9a2fa5f6" + integrity sha512-gytXUbs8k2sXS9PnQptz5o0QnpLL51SwASIORY6XaBKF88nsOT0Zw9szLqlSGQDP/4TljBAD5y98p2U1fqkdsw== + dependencies: + "@babel/helper-module-imports" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + "@babel/traverse" "^7.28.3" + "@babel/helper-optimise-call-expression@^7.27.1": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz#c65221b61a643f3e62705e5dd2b5f115e35f9200" @@ -261,6 +320,21 @@ "@babel/template" "^7.27.1" "@babel/types" "^7.27.1" +"@babel/helpers@^7.28.3": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/helpers/-/helpers-7.28.3.tgz#b83156c0a2232c133d1b535dd5d3452119c7e441" + integrity sha512-PTNtvUQihsAsDHMOP5pfobP8C6CM4JWXmP8DrEIt46c3r2bf87Ua1zoqevsMo9g+tWDwgWrFP5EIxuBx5RudAw== + dependencies: + "@babel/template" "^7.27.2" + "@babel/types" "^7.28.2" + +"@babel/parser@^7.1.0", "@babel/parser@^7.20.7", "@babel/parser@^7.28.3": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.28.3.tgz#d2d25b814621bca5fe9d172bc93792547e7a2a71" + integrity sha512-7+Ey1mAgYqFAx2h0RuoxcQT5+MlG3GTV0TQrgr7/ZliKsm/MNDxVVutlWaziMq7wJNAz8MTqz55XLpWvva6StA== + dependencies: + "@babel/types" "^7.28.2" + "@babel/parser@^7.14.7", "@babel/parser@^7.27.1", "@babel/parser@^7.27.2": version "7.27.2" resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.27.2.tgz#577518bedb17a2ce4212afd052e01f7df0941127" @@ -304,6 +378,20 @@ "@babel/helper-module-transforms" "^7.27.1" "@babel/helper-plugin-utils" "^7.27.1" +"@babel/plugin-transform-react-jsx-self@^7.25.9": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.27.1.tgz#af678d8506acf52c577cac73ff7fe6615c85fc92" + integrity sha512-6UzkCs+ejGdZ5mFFC/OCUrv028ab2fp1znZmCZjAOBKiBK2jXD1O+BPSfX8X2qjJ75fZBMSnQn3Rq2mrBJK2mw== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + +"@babel/plugin-transform-react-jsx-source@^7.25.9": + version "7.27.1" + resolved "https://registry.yarnpkg.com/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.27.1.tgz#dcfe2c24094bb757bf73960374e7c55e434f19f0" + integrity sha512-zbwoTsBruTeKB9hSq73ha66iFeJHuaFkUbwvqElnygoNbj/jHRsSeokowZFN3CZ64IvEqcmmkVe89OPXc7ldAw== + dependencies: + "@babel/helper-plugin-utils" "^7.27.1" + "@babel/plugin-transform-typescript@^7.27.1": version "7.27.1" resolved "https://registry.yarnpkg.com/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.27.1.tgz#d3bb65598bece03f773111e88cc4e8e5070f1140" @@ -326,6 +414,11 @@ "@babel/plugin-transform-modules-commonjs" "^7.27.1" "@babel/plugin-transform-typescript" "^7.27.1" +"@babel/runtime@^7.3.1": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/runtime/-/runtime-7.28.3.tgz#75c5034b55ba868121668be5d5bb31cc64e6e61a" + integrity sha512-9uIQ10o0WGdpP6GDhXcdOJPJuDgFtIDtN/9+ArJQ2NAfAmiuhTQdzkaTGR33v43GYS2UrSA0eX2pPPHoFVvpxA== + "@babel/template@^7.25.9": version "7.25.9" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.25.9.tgz#ecb62d81a8a6f5dc5fe8abfc3901fc52ddf15016" @@ -335,7 +428,7 @@ "@babel/parser" "^7.25.9" "@babel/types" "^7.25.9" -"@babel/template@^7.27.1": +"@babel/template@^7.27.1", "@babel/template@^7.27.2": version "7.27.2" resolved "https://registry.yarnpkg.com/@babel/template/-/template-7.27.2.tgz#fa78ceed3c4e7b63ebf6cb39e5852fca45f6809d" integrity sha512-LPDZ85aEJyYSd18/DkjNh4/y1ntkE5KwUHWTiqgRxruuZL2F1yuHligVHLvcHY2vMHXttKFpJn6LwfI7cw7ODw== @@ -370,6 +463,27 @@ debug "^4.3.1" globals "^11.1.0" +"@babel/traverse@^7.28.3": + version "7.28.3" + resolved "https://registry.yarnpkg.com/@babel/traverse/-/traverse-7.28.3.tgz#6911a10795d2cce43ec6a28cffc440cca2593434" + integrity sha512-7w4kZYHneL3A6NP2nxzHvT3HCZ7puDZZjFMqDpBPECub79sTtSO5CGXDkKrTQq8ksAwfD/XI2MRFX23njdDaIQ== + dependencies: + "@babel/code-frame" "^7.27.1" + "@babel/generator" "^7.28.3" + "@babel/helper-globals" "^7.28.0" + "@babel/parser" "^7.28.3" + "@babel/template" "^7.27.2" + "@babel/types" "^7.28.2" + debug "^4.3.1" + +"@babel/types@^7.0.0", "@babel/types@^7.20.7", "@babel/types@^7.28.2": + version "7.28.2" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.28.2.tgz#da9db0856a9a88e0a13b019881d7513588cf712b" + integrity sha512-ruv7Ae4J5dUYULmeXw1gmb7rYRz57OWCPM57pHojnLq/3Z1CK2lNSLTCVjxVk1F/TZHwOZZrOWi0ur95BbLxNQ== + dependencies: + "@babel/helper-string-parser" "^7.27.1" + "@babel/helper-validator-identifier" "^7.27.1" + "@babel/types@^7.25.9", "@babel/types@^7.26.5", "@babel/types@^7.26.7": version "7.26.7" resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.26.7.tgz#5e2b89c0768e874d4d061961f3a5a153d71dc17a" @@ -386,6 +500,73 @@ "@babel/helper-string-parser" "^7.27.1" "@babel/helper-validator-identifier" "^7.27.1" +"@codemirror/autocomplete@^6.0.0": + version "6.18.6" + resolved "https://registry.yarnpkg.com/@codemirror/autocomplete/-/autocomplete-6.18.6.tgz#de26e864a1ec8192a1b241eb86addbb612964ddb" + integrity sha512-PHHBXFomUs5DF+9tCOM/UoW6XQ4R44lLNNhRaW9PKPTU0D7lIjRg3ElxaJnTwsl/oHiR93WSXDBrekhoUGCPtg== + dependencies: + "@codemirror/language" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.17.0" + "@lezer/common" "^1.0.0" + +"@codemirror/commands@^6.0.0": + version "6.8.1" + resolved "https://registry.yarnpkg.com/@codemirror/commands/-/commands-6.8.1.tgz#639f5559d2f33f2582a2429c58cb0c1b925c7a30" + integrity sha512-KlGVYufHMQzxbdQONiLyGQDUW0itrLZwq3CcY7xpv9ZLRHqzkBSoteocBHtMCoY7/Ci4xhzSrToIeLg7FxHuaw== + dependencies: + "@codemirror/language" "^6.0.0" + "@codemirror/state" "^6.4.0" + "@codemirror/view" "^6.27.0" + "@lezer/common" "^1.1.0" + +"@codemirror/language@^6.0.0": + version "6.11.3" + resolved "https://registry.yarnpkg.com/@codemirror/language/-/language-6.11.3.tgz#8e6632df566a7ed13a1bd307f9837765bb1abfdd" + integrity sha512-9HBM2XnwDj7fnu0551HkGdrUrrqmYq/WC5iv6nbY2WdicXdGbhR/gfbZOH73Aqj4351alY1+aoG9rCNfiwS1RA== + dependencies: + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.23.0" + "@lezer/common" "^1.1.0" + "@lezer/highlight" "^1.0.0" + "@lezer/lr" "^1.0.0" + style-mod "^4.0.0" + +"@codemirror/lint@^6.0.0": + version "6.8.5" + resolved "https://registry.yarnpkg.com/@codemirror/lint/-/lint-6.8.5.tgz#9edaa808e764e28e07665b015951934c8ec3a418" + integrity sha512-s3n3KisH7dx3vsoeGMxsbRAgKe4O1vbrnKBClm99PU0fWxmxsx5rR2PfqQgIt+2MMJBHbiJ5rfIdLYfB9NNvsA== + dependencies: + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.35.0" + crelt "^1.0.5" + +"@codemirror/search@^6.0.0": + version "6.5.11" + resolved "https://registry.yarnpkg.com/@codemirror/search/-/search-6.5.11.tgz#a324ffee36e032b7f67aa31c4fb9f3e6f9f3ed63" + integrity sha512-KmWepDE6jUdL6n8cAAqIpRmLPBZ5ZKnicE8oGU/s3QrAVID+0VhLFrzUucVKHG5035/BSykhExDL/Xm7dHthiA== + dependencies: + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.0.0" + crelt "^1.0.5" + +"@codemirror/state@^6.0.0", "@codemirror/state@^6.4.0", "@codemirror/state@^6.5.0": + version "6.5.2" + resolved "https://registry.yarnpkg.com/@codemirror/state/-/state-6.5.2.tgz#8eca3a64212a83367dc85475b7d78d5c9b7076c6" + integrity sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA== + dependencies: + "@marijn/find-cluster-break" "^1.0.0" + +"@codemirror/view@^6.0.0", "@codemirror/view@^6.17.0", "@codemirror/view@^6.23.0", "@codemirror/view@^6.27.0", "@codemirror/view@^6.35.0": + version "6.38.1" + resolved "https://registry.yarnpkg.com/@codemirror/view/-/view-6.38.1.tgz#74214434351719ec0710431363a85f7a01e80a73" + integrity sha512-RmTOkE7hRU3OVREqFVITWHz6ocgBjv08GoePscAakgVQfciA3SGCEk7mb9IzwW61cKKmlTpHXG6DUE5Ubx+MGQ== + dependencies: + "@codemirror/state" "^6.5.0" + crelt "^1.0.6" + style-mod "^4.1.0" + w3c-keyname "^2.2.4" + "@cspotcode/source-map-support@^0.8.0": version "0.8.1" resolved "https://registry.yarnpkg.com/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz#00629c35a688e05a88b1cda684fb9d5e73f000a1" @@ -393,131 +574,309 @@ dependencies: "@jridgewell/trace-mapping" "0.3.9" +"@emnapi/core@^1.4.3", "@emnapi/core@^1.4.5": + version "1.4.5" + resolved "https://registry.yarnpkg.com/@emnapi/core/-/core-1.4.5.tgz#bfbb0cbbbb9f96ec4e2c4fd917b7bbe5495ceccb" + integrity sha512-XsLw1dEOpkSX/WucdqUhPWP7hDxSvZiY+fsUC14h+FtQ2Ifni4znbBt8punRX+Uj2JG/uDb8nEHVKvrVlvdZ5Q== + dependencies: + "@emnapi/wasi-threads" "1.0.4" + tslib "^2.4.0" + +"@emnapi/runtime@^1.4.3", "@emnapi/runtime@^1.4.5": + version "1.4.5" + resolved "https://registry.yarnpkg.com/@emnapi/runtime/-/runtime-1.4.5.tgz#c67710d0661070f38418b6474584f159de38aba9" + integrity sha512-++LApOtY0pEEz1zrd9vy1/zXVaVJJ/EbAF3u0fXIzPJEDtnITsBGbbK0EkM72amhl/R5b+5xx0Y/QhcVOpuulg== + dependencies: + tslib "^2.4.0" + +"@emnapi/wasi-threads@1.0.4": + version "1.0.4" + resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.0.4.tgz#703fc094d969e273b1b71c292523b2f792862bf4" + integrity sha512-PJR+bOmMOPH8AtcTGAyYNiuJ3/Fcoj2XN/gBEWzDIKh254XO+mM9XoXHk5GNEhodxeMznbg7BlRojVbKN+gC6g== + dependencies: + tslib "^2.4.0" + +"@emnapi/wasi-threads@^1.0.4": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@emnapi/wasi-threads/-/wasi-threads-1.1.0.tgz#60b2102fddc9ccb78607e4a3cf8403ea69be41bf" + integrity sha512-WI0DdZ8xFSbgMjR1sFsKABJ/C5OnRrjT06JXbZKexJGrDuPTzZdDYfFlsgcCXCyf+suG5QU2e/y1Wo2V/OapLQ== + dependencies: + tslib "^2.4.0" + "@esbuild/aix-ppc64@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.2.tgz#b87036f644f572efb2b3c75746c97d1d2d87ace8" integrity sha512-wCIboOL2yXZym2cgm6mlA742s9QeJ8DjGVaL39dLN4rRwrOgOyYSnOaFPhKZGLb2ngj4EyfAFjsNJwPXZvseag== +"@esbuild/aix-ppc64@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.25.9.tgz#bef96351f16520055c947aba28802eede3c9e9a9" + integrity sha512-OaGtL73Jck6pBKjNIe24BnFE6agGl+6KxDtTfHhy1HmhthfKouEcOhqpSL64K4/0WCtbKFLOdzD/44cJ4k9opA== + "@esbuild/android-arm64@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.2.tgz#5ca7dc20a18f18960ad8d5e6ef5cf7b0a256e196" integrity sha512-5ZAX5xOmTligeBaeNEPnPaeEuah53Id2tX4c2CVP3JaROTH+j4fnfHCkr1PjXMd78hMst+TlkfKcW/DlTq0i4w== +"@esbuild/android-arm64@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.25.9.tgz#d2e70be7d51a529425422091e0dcb90374c1546c" + integrity sha512-IDrddSmpSv51ftWslJMvl3Q2ZT98fUSL2/rlUXuVqRXHCs5EUF1/f+jbjF5+NG9UffUDMCiTyh8iec7u8RlTLg== + "@esbuild/android-arm@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.2.tgz#3c49f607b7082cde70c6ce0c011c362c57a194ee" integrity sha512-NQhH7jFstVY5x8CKbcfa166GoV0EFkaPkCKBQkdPJFvo5u+nGXLEH/ooniLb3QI8Fk58YAx7nsPLozUWfCBOJA== +"@esbuild/android-arm@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.25.9.tgz#d2a753fe2a4c73b79437d0ba1480e2d760097419" + integrity sha512-5WNI1DaMtxQ7t7B6xa572XMXpHAaI/9Hnhk8lcxF4zVN4xstUgTlvuGDorBguKEnZO70qwEcLpfifMLoxiPqHQ== + "@esbuild/android-x64@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.2.tgz#8a00147780016aff59e04f1036e7cb1b683859e2" integrity sha512-Ffcx+nnma8Sge4jzddPHCZVRvIfQ0kMsUsCMcJRHkGJ1cDmhe4SsrYIjLUKn1xpHZybmOqCWwB0zQvsjdEHtkg== +"@esbuild/android-x64@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.25.9.tgz#5278836e3c7ae75761626962f902a0d55352e683" + integrity sha512-I853iMZ1hWZdNllhVZKm34f4wErd4lMyeV7BLzEExGEIZYsOzqDWDf+y082izYUE8gtJnYHdeDpN/6tUdwvfiw== + "@esbuild/darwin-arm64@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.2.tgz#486efe7599a8d90a27780f2bb0318d9a85c6c423" integrity sha512-MpM6LUVTXAzOvN4KbjzU/q5smzryuoNjlriAIx+06RpecwCkL9JpenNzpKd2YMzLJFOdPqBpuub6eVRP5IgiSA== +"@esbuild/darwin-arm64@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.25.9.tgz#f1513eaf9ec8fa15dcaf4c341b0f005d3e8b47ae" + integrity sha512-XIpIDMAjOELi/9PB30vEbVMs3GV1v2zkkPnuyRRURbhqjyzIINwj+nbQATh4H9GxUgH1kFsEyQMxwiLFKUS6Rg== + "@esbuild/darwin-x64@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.2.tgz#95ee222aacf668c7a4f3d7ee87b3240a51baf374" integrity sha512-5eRPrTX7wFyuWe8FqEFPG2cU0+butQQVNcT4sVipqjLYQjjh8a8+vUTfgBKM88ObB85ahsnTwF7PSIt6PG+QkA== +"@esbuild/darwin-x64@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.25.9.tgz#e27dbc3b507b3a1cea3b9280a04b8b6b725f82be" + integrity sha512-jhHfBzjYTA1IQu8VyrjCX4ApJDnH+ez+IYVEoJHeqJm9VhG9Dh2BYaJritkYK3vMaXrf7Ogr/0MQ8/MeIefsPQ== + "@esbuild/freebsd-arm64@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.2.tgz#67efceda8554b6fc6a43476feba068fb37fa2ef6" integrity sha512-mLwm4vXKiQ2UTSX4+ImyiPdiHjiZhIaE9QvC7sw0tZ6HoNMjYAqQpGyui5VRIi5sGd+uWq940gdCbY3VLvsO1w== +"@esbuild/freebsd-arm64@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.25.9.tgz#364e3e5b7a1fd45d92be08c6cc5d890ca75908ca" + integrity sha512-z93DmbnY6fX9+KdD4Ue/H6sYs+bhFQJNCPZsi4XWJoYblUqT06MQUdBCpcSfuiN72AbqeBFu5LVQTjfXDE2A6Q== + "@esbuild/freebsd-x64@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.2.tgz#88a9d7ecdd3adadbfe5227c2122d24816959b809" integrity sha512-6qyyn6TjayJSwGpm8J9QYYGQcRgc90nmfdUb0O7pp1s4lTY+9D0H9O02v5JqGApUyiHOtkz6+1hZNvNtEhbwRQ== +"@esbuild/freebsd-x64@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.25.9.tgz#7c869b45faeb3df668e19ace07335a0711ec56ab" + integrity sha512-mrKX6H/vOyo5v71YfXWJxLVxgy1kyt1MQaD8wZJgJfG4gq4DpQGpgTB74e5yBeQdyMTbgxp0YtNj7NuHN0PoZg== + "@esbuild/linux-arm64@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.2.tgz#87be1099b2bbe61282333b084737d46bc8308058" integrity sha512-gq/sjLsOyMT19I8obBISvhoYiZIAaGF8JpeXu1u8yPv8BE5HlWYobmlsfijFIZ9hIVGYkbdFhEqC0NvM4kNO0g== +"@esbuild/linux-arm64@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.25.9.tgz#48d42861758c940b61abea43ba9a29b186d6cb8b" + integrity sha512-BlB7bIcLT3G26urh5Dmse7fiLmLXnRlopw4s8DalgZ8ef79Jj4aUcYbk90g8iCa2467HX8SAIidbL7gsqXHdRw== + "@esbuild/linux-arm@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.2.tgz#72a285b0fe64496e191fcad222185d7bf9f816f6" integrity sha512-UHBRgJcmjJv5oeQF8EpTRZs/1knq6loLxTsjc3nxO9eXAPDLcWW55flrMVc97qFPbmZP31ta1AZVUKQzKTzb0g== +"@esbuild/linux-arm@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.25.9.tgz#6ce4b9cabf148274101701d112b89dc67cc52f37" + integrity sha512-HBU2Xv78SMgaydBmdor38lg8YDnFKSARg1Q6AT0/y2ezUAKiZvc211RDFHlEZRFNRVhcMamiToo7bDx3VEOYQw== + "@esbuild/linux-ia32@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.2.tgz#337a87a4c4dd48a832baed5cbb022be20809d737" integrity sha512-bBYCv9obgW2cBP+2ZWfjYTU+f5cxRoGGQ5SeDbYdFCAZpYWrfjjfYwvUpP8MlKbP0nwZ5gyOU/0aUzZ5HWPuvQ== +"@esbuild/linux-ia32@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.25.9.tgz#207e54899b79cac9c26c323fc1caa32e3143f1c4" + integrity sha512-e7S3MOJPZGp2QW6AK6+Ly81rC7oOSerQ+P8L0ta4FhVi+/j/v2yZzx5CqqDaWjtPFfYz21Vi1S0auHrap3Ma3A== + "@esbuild/linux-loong64@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.2.tgz#1b81aa77103d6b8a8cfa7c094ed3d25c7579ba2a" integrity sha512-SHNGiKtvnU2dBlM5D8CXRFdd+6etgZ9dXfaPCeJtz+37PIUlixvlIhI23L5khKXs3DIzAn9V8v+qb1TRKrgT5w== +"@esbuild/linux-loong64@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.25.9.tgz#0ba48a127159a8f6abb5827f21198b999ffd1fc0" + integrity sha512-Sbe10Bnn0oUAB2AalYztvGcK+o6YFFA/9829PhOCUS9vkJElXGdphz0A3DbMdP8gmKkqPmPcMJmJOrI3VYB1JQ== + "@esbuild/linux-mips64el@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.2.tgz#afbe380b6992e7459bf7c2c3b9556633b2e47f30" integrity sha512-hDDRlzE6rPeoj+5fsADqdUZl1OzqDYow4TB4Y/3PlKBD0ph1e6uPHzIQcv2Z65u2K0kpeByIyAjCmjn1hJgG0Q== +"@esbuild/linux-mips64el@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.25.9.tgz#a4d4cc693d185f66a6afde94f772b38ce5d64eb5" + integrity sha512-YcM5br0mVyZw2jcQeLIkhWtKPeVfAerES5PvOzaDxVtIyZ2NUBZKNLjC5z3/fUlDgT6w89VsxP2qzNipOaaDyA== + "@esbuild/linux-ppc64@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.2.tgz#6bf8695cab8a2b135cca1aa555226dc932d52067" integrity sha512-tsHu2RRSWzipmUi9UBDEzc0nLc4HtpZEI5Ba+Omms5456x5WaNuiG3u7xh5AO6sipnJ9r4cRWQB2tUjPyIkc6g== +"@esbuild/linux-ppc64@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.25.9.tgz#0f5805c1c6d6435a1dafdc043cb07a19050357db" + integrity sha512-++0HQvasdo20JytyDpFvQtNrEsAgNG2CY1CLMwGXfFTKGBGQT3bOeLSYE2l1fYdvML5KUuwn9Z8L1EWe2tzs1w== + "@esbuild/linux-riscv64@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.2.tgz#43c2d67a1a39199fb06ba978aebb44992d7becc3" integrity sha512-k4LtpgV7NJQOml/10uPU0s4SAXGnowi5qBSjaLWMojNCUICNu7TshqHLAEbkBdAszL5TabfvQ48kK84hyFzjnw== +"@esbuild/linux-riscv64@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.25.9.tgz#6776edece0f8fca79f3386398b5183ff2a827547" + integrity sha512-uNIBa279Y3fkjV+2cUjx36xkx7eSjb8IvnL01eXUKXez/CBHNRw5ekCGMPM0BcmqBxBcdgUWuUXmVWwm4CH9kg== + "@esbuild/linux-s390x@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.2.tgz#419e25737ec815c6dce2cd20d026e347cbb7a602" integrity sha512-GRa4IshOdvKY7M/rDpRR3gkiTNp34M0eLTaC1a08gNrh4u488aPhuZOCpkF6+2wl3zAN7L7XIpOFBhnaE3/Q8Q== +"@esbuild/linux-s390x@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.25.9.tgz#3f6f29ef036938447c2218d309dc875225861830" + integrity sha512-Mfiphvp3MjC/lctb+7D287Xw1DGzqJPb/J2aHHcHxflUo+8tmN/6d4k6I2yFR7BVo5/g7x2Monq4+Yew0EHRIA== + "@esbuild/linux-x64@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.2.tgz#22451f6edbba84abe754a8cbd8528ff6e28d9bcb" integrity sha512-QInHERlqpTTZ4FRB0fROQWXcYRD64lAoiegezDunLpalZMjcUcld3YzZmVJ2H/Cp0wJRZ8Xtjtj0cEHhYc/uUg== +"@esbuild/linux-x64@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.25.9.tgz#831fe0b0e1a80a8b8391224ea2377d5520e1527f" + integrity sha512-iSwByxzRe48YVkmpbgoxVzn76BXjlYFXC7NvLYq+b+kDjyyk30J0JY47DIn8z1MO3K0oSl9fZoRmZPQI4Hklzg== + "@esbuild/netbsd-arm64@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.2.tgz#744affd3b8d8236b08c5210d828b0698a62c58ac" integrity sha512-talAIBoY5M8vHc6EeI2WW9d/CkiO9MQJ0IOWX8hrLhxGbro/vBXJvaQXefW2cP0z0nQVTdQ/eNyGFV1GSKrxfw== +"@esbuild/netbsd-arm64@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-arm64/-/netbsd-arm64-0.25.9.tgz#06f99d7eebe035fbbe43de01c9d7e98d2a0aa548" + integrity sha512-9jNJl6FqaUG+COdQMjSCGW4QiMHH88xWbvZ+kRVblZsWrkXlABuGdFJ1E9L7HK+T0Yqd4akKNa/lO0+jDxQD4Q== + "@esbuild/netbsd-x64@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.2.tgz#dbbe7521fd6d7352f34328d676af923fc0f8a78f" integrity sha512-voZT9Z+tpOxrvfKFyfDYPc4DO4rk06qamv1a/fkuzHpiVBMOhpjK+vBmWM8J1eiB3OLSMFYNaOaBNLXGChf5tg== +"@esbuild/netbsd-x64@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.25.9.tgz#db99858e6bed6e73911f92a88e4edd3a8c429a52" + integrity sha512-RLLdkflmqRG8KanPGOU7Rpg829ZHu8nFy5Pqdi9U01VYtG9Y0zOG6Vr2z4/S+/3zIyOxiK6cCeYNWOFR9QP87g== + "@esbuild/openbsd-arm64@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.2.tgz#f9caf987e3e0570500832b487ce3039ca648ce9f" integrity sha512-dcXYOC6NXOqcykeDlwId9kB6OkPUxOEqU+rkrYVqJbK2hagWOMrsTGsMr8+rW02M+d5Op5NNlgMmjzecaRf7Tg== +"@esbuild/openbsd-arm64@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-arm64/-/openbsd-arm64-0.25.9.tgz#afb886c867e36f9d86bb21e878e1185f5d5a0935" + integrity sha512-YaFBlPGeDasft5IIM+CQAhJAqS3St3nJzDEgsgFixcfZeyGPCd6eJBWzke5piZuZ7CtL656eOSYKk4Ls2C0FRQ== + "@esbuild/openbsd-x64@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.2.tgz#d2bb6a0f8ffea7b394bb43dfccbb07cabd89f768" integrity sha512-t/TkWwahkH0Tsgoq1Ju7QfgGhArkGLkF1uYz8nQS/PPFlXbP5YgRpqQR3ARRiC2iXoLTWFxc6DJMSK10dVXluw== +"@esbuild/openbsd-x64@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.25.9.tgz#30855c9f8381fac6a0ef5b5f31ac6e7108a66ecf" + integrity sha512-1MkgTCuvMGWuqVtAvkpkXFmtL8XhWy+j4jaSO2wxfJtilVCi0ZE37b8uOdMItIHz4I6z1bWWtEX4CJwcKYLcuA== + +"@esbuild/openharmony-arm64@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/openharmony-arm64/-/openharmony-arm64-0.25.9.tgz#2f2144af31e67adc2a8e3705c20c2bd97bd88314" + integrity sha512-4Xd0xNiMVXKh6Fa7HEJQbrpP3m3DDn43jKxMjxLLRjWnRsfxjORYJlXPO4JNcXtOyfajXorRKY9NkOpTHptErg== + "@esbuild/sunos-x64@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.2.tgz#49b437ed63fe333b92137b7a0c65a65852031afb" integrity sha512-cfZH1co2+imVdWCjd+D1gf9NjkchVhhdpgb1q5y6Hcv9TP6Zi9ZG/beI3ig8TvwT9lH9dlxLq5MQBBgwuj4xvA== +"@esbuild/sunos-x64@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.25.9.tgz#69b99a9b5bd226c9eb9c6a73f990fddd497d732e" + integrity sha512-WjH4s6hzo00nNezhp3wFIAfmGZ8U7KtrJNlFMRKxiI9mxEK1scOMAaa9i4crUtu+tBr+0IN6JCuAcSBJZfnphw== + "@esbuild/win32-arm64@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.2.tgz#081424168463c7d6c7fb78f631aede0c104373cf" integrity sha512-7Loyjh+D/Nx/sOTzV8vfbB3GJuHdOQyrOryFdZvPHLf42Tk9ivBU5Aedi7iyX+x6rbn2Mh68T4qq1SDqJBQO5Q== +"@esbuild/win32-arm64@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.25.9.tgz#d789330a712af916c88325f4ffe465f885719c6b" + integrity sha512-mGFrVJHmZiRqmP8xFOc6b84/7xa5y5YvR1x8djzXpJBSv/UsNK6aqec+6JDjConTgvvQefdGhFDAs2DLAds6gQ== + "@esbuild/win32-ia32@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.2.tgz#3f9e87143ddd003133d21384944a6c6cadf9693f" integrity sha512-WRJgsz9un0nqZJ4MfhabxaD9Ft8KioqU3JMinOTvobbX6MOSUigSBlogP8QB3uxpJDsFS6yN+3FDBdqE5lg9kg== +"@esbuild/win32-ia32@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.25.9.tgz#52fc735406bd49688253e74e4e837ac2ba0789e3" + integrity sha512-b33gLVU2k11nVx1OhX3C8QQP6UHQK4ZtN56oFWvVXvz2VkDoe6fbG8TOgHFxEvqeqohmRnIHe5A1+HADk4OQww== + "@esbuild/win32-x64@0.25.2": version "0.25.2" resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.2.tgz#839f72c2decd378f86b8f525e1979a97b920c67d" integrity sha512-kM3HKb16VIXZyIeVrM1ygYmZBKybX8N4p754bw390wGO3Tf2j4L2/WYL+4suWujpgf6GBYs3jv7TyUivdd05JA== +"@esbuild/win32-x64@0.25.9": + version "0.25.9" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.25.9.tgz#585624dc829cfb6e7c0aa6c3ca7d7e6daa87e34f" + integrity sha512-PPOl1mi6lpLNQxnGoyAfschAodRFYXJ+9fs6WHXz7CSWKbOqiMZsubC+BQsVKuul+3vKLuwTHsS2c2y9EoKwxQ== + +"@iconify/types@^2.0.0": + version "2.0.0" + resolved "https://registry.yarnpkg.com/@iconify/types/-/types-2.0.0.tgz#ab0e9ea681d6c8a1214f30cd741fe3a20cc57f57" + integrity sha512-+wluvCrRhXrhyOmRDJ3q8mux9JkKy5SJ/v8ol2tu4FVjyYvtEzkc/3pK15ET6RKg4b4w4BmTk1+gsCUhf21Ykg== + +"@iconify/utils@^2.3.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@iconify/utils/-/utils-2.3.0.tgz#1bbbf8c477ebe9a7cacaea78b1b7e8937f9cbfba" + integrity sha512-GmQ78prtwYW6EtzXRU1rY+KwOKfz32PD7iJh6Iyqw68GiKuoZ2A6pRtzWONz5VQJbp50mEjXh/7NkumtrAgRKA== + dependencies: + "@antfu/install-pkg" "^1.0.0" + "@antfu/utils" "^8.1.0" + "@iconify/types" "^2.0.0" + debug "^4.4.0" + globals "^15.14.0" + kolorist "^1.8.0" + local-pkg "^1.0.0" + mlly "^1.7.4" + "@inquirer/checkbox@^4.0.2": version "4.1.1" resolved "https://registry.yarnpkg.com/@inquirer/checkbox/-/checkbox-4.1.1.tgz#5f2c0ce74a75e3872f8e170fd209655972ce7802" @@ -650,6 +1009,25 @@ resolved "https://registry.yarnpkg.com/@inquirer/type/-/type-3.0.4.tgz#fa5f9e91a0abf3c9e93d3e1990ecb891d8195cf2" integrity sha512-2MNFrDY8jkFYc9Il9DgLsHhMzuHnOYM1+CUYVWbzu9oT0hC7V7EcYvdCKeoll/Fcci04A+ERZ9wcc7cQ8lTkIA== +"@isaacs/cliui@^8.0.2": + version "8.0.2" + resolved "https://registry.yarnpkg.com/@isaacs/cliui/-/cliui-8.0.2.tgz#b37667b7bc181c168782259bab42474fbf52b550" + integrity sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA== + dependencies: + string-width "^5.1.2" + string-width-cjs "npm:string-width@^4.2.0" + strip-ansi "^7.0.1" + strip-ansi-cjs "npm:strip-ansi@^6.0.1" + wrap-ansi "^8.1.0" + wrap-ansi-cjs "npm:wrap-ansi@^7.0.0" + +"@isaacs/fs-minipass@^4.0.0": + version "4.0.1" + resolved "https://registry.yarnpkg.com/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz#2d59ae3ab4b38fb4270bfa23d30f8e2e86c7fe32" + integrity sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w== + dependencies: + minipass "^7.0.4" + "@istanbuljs/esm-loader-hook@0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@istanbuljs/esm-loader-hook/-/esm-loader-hook-0.3.0.tgz#f63094877f7f74f3e6ccab375d95922728eb01d1" @@ -679,6 +1057,14 @@ resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== +"@jridgewell/gen-mapping@^0.3.12": + version "0.3.13" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz#6342a19f44347518c93e43b1ac69deb3c4656a1f" + integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" + "@jridgewell/gen-mapping@^0.3.5": version "0.3.8" resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz#4f0e06362e01362f823d348f1872b08f666d8142" @@ -688,6 +1074,14 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.24" +"@jridgewell/remapping@^2.3.4": + version "2.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/remapping/-/remapping-2.3.5.tgz#375c476d1972947851ba1e15ae8f123047445aa1" + integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + "@jridgewell/resolve-uri@^3.0.3", "@jridgewell/resolve-uri@^3.1.0": version "3.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" @@ -703,6 +1097,11 @@ resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== +"@jridgewell/sourcemap-codec@^1.5.0", "@jridgewell/sourcemap-codec@^1.5.5": + version "1.5.5" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz#6912b00d2c631c0d15ce1a7ab57cd657f2a8f8ba" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + "@jridgewell/trace-mapping@0.3.9": version "0.3.9" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz#6534fd5933a53ba7cbf3a17615e273a0d1273ff9" @@ -719,6 +1118,232 @@ "@jridgewell/resolve-uri" "^3.1.0" "@jridgewell/sourcemap-codec" "^1.4.14" +"@jridgewell/trace-mapping@^0.3.28": + version "0.3.30" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.30.tgz#4a76c4daeee5df09f5d3940e087442fb36ce2b99" + integrity sha512-GQ7Nw5G2lTu/BtHTKfXhKHok2WGetd4XYcVKGx00SjAk8GMwgJM3zr6zORiPGuOE+/vkc90KtTosSSvaCjKb2Q== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@lezer/common@^1.0.0", "@lezer/common@^1.1.0": + version "1.2.3" + resolved "https://registry.yarnpkg.com/@lezer/common/-/common-1.2.3.tgz#138fcddab157d83da557554851017c6c1e5667fd" + integrity sha512-w7ojc8ejBqr2REPsWxJjrMFsA/ysDCFICn8zEOR9mrqzOu2amhITYuLD8ag6XZf0CFXDrhKqw7+tW8cX66NaDA== + +"@lezer/highlight@^1.0.0": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@lezer/highlight/-/highlight-1.2.1.tgz#596fa8f9aeb58a608be0a563e960c373cbf23f8b" + integrity sha512-Z5duk4RN/3zuVO7Jq0pGLJ3qynpxUVsh7IbUbGj88+uV2ApSAn6kWg2au3iJb+0Zi7kKtqffIESgNcRXWZWmSA== + dependencies: + "@lezer/common" "^1.0.0" + +"@lezer/lr@^1.0.0": + version "1.4.2" + resolved "https://registry.yarnpkg.com/@lezer/lr/-/lr-1.4.2.tgz#931ea3dea8e9de84e90781001dae30dea9ff1727" + integrity sha512-pu0K1jCIdnQ12aWNaAVU5bzi7Bd1w54J3ECgANPmYLtQKP0HBj2cE/5coBD66MT10xbtIuUr7tg0Shbsvk0mDA== + dependencies: + "@lezer/common" "^1.0.0" + +"@marijn/find-cluster-break@^1.0.0": + version "1.0.2" + resolved "https://registry.yarnpkg.com/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz#775374306116d51c0c500b8c4face0f9a04752d8" + integrity sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g== + +"@napi-rs/wasm-runtime@^0.2.12": + version "0.2.12" + resolved "https://registry.yarnpkg.com/@napi-rs/wasm-runtime/-/wasm-runtime-0.2.12.tgz#3e78a8b96e6c33a6c517e1894efbd5385a7cb6f2" + integrity sha512-ZVWUcfwY4E/yPitQJl481FjFo3K22D6qF0DuFH6Y/nbnE11GY5uguDxZMGXPQ8WQ0128MXQD7TnfHyK4oWoIJQ== + dependencies: + "@emnapi/core" "^1.4.3" + "@emnapi/runtime" "^1.4.3" + "@tybys/wasm-util" "^0.10.0" + +"@noble/hashes@^1.1.5": + version "1.8.0" + resolved "https://registry.yarnpkg.com/@noble/hashes/-/hashes-1.8.0.tgz#cee43d801fcef9644b11b8194857695acd5f815a" + integrity sha512-jCs9ldd7NwzpgXDIf6P3+NrHh9/sD6CQdxHyjQI+h/6rDNo88ypBxxz45UDuZHz9r3tNz7N/VInSVoVdtXEI4A== + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@paralleldrive/cuid2@2.2.2": + version "2.2.2" + resolved "https://registry.yarnpkg.com/@paralleldrive/cuid2/-/cuid2-2.2.2.tgz#7f91364d53b89e2c9cb9e02e8dd0f129e834455f" + integrity sha512-ZOBkgDwEdoYVlSeRbYYXs0S9MejQofiVYoTbKzy/6GQa39/q5tQU2IX46+shYnUkpEl3wc+J6wRlar7r2EK2xA== + dependencies: + "@noble/hashes" "^1.1.5" + +"@peculiar/asn1-schema@^2.3.13", "@peculiar/asn1-schema@^2.3.8": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@peculiar/asn1-schema/-/asn1-schema-2.4.0.tgz#e3aa7917d433b4c3fcfa1fcb57eac233b1c38787" + integrity sha512-umbembjIWOrPSOzEGG5vxFLkeM8kzIhLkgigtsOrfLKnuzxWxejAcUX+q/SoZCdemlODOcr5WiYa7+dIEzBXZQ== + dependencies: + asn1js "^3.0.6" + pvtsutils "^1.3.6" + tslib "^2.8.1" + +"@peculiar/json-schema@^1.1.12": + version "1.1.12" + resolved "https://registry.yarnpkg.com/@peculiar/json-schema/-/json-schema-1.1.12.tgz#fe61e85259e3b5ba5ad566cb62ca75b3d3cd5339" + integrity sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w== + dependencies: + tslib "^2.0.0" + +"@peculiar/webcrypto@^1.4.0": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@peculiar/webcrypto/-/webcrypto-1.5.0.tgz#9e57174c02c1291051c553600347e12b81469e10" + integrity sha512-BRs5XUAwiyCDQMsVA9IDvDa7UBR9gAvPHgugOeGng3YN6vJ9JYonyDc0lNczErgtCWtucjR5N7VtaonboD/ezg== + dependencies: + "@peculiar/asn1-schema" "^2.3.8" + "@peculiar/json-schema" "^1.1.12" + pvtsutils "^1.3.5" + tslib "^2.6.2" + webcrypto-core "^1.8.0" + +"@pkgjs/parseargs@^0.11.0": + version "0.11.0" + resolved "https://registry.yarnpkg.com/@pkgjs/parseargs/-/parseargs-0.11.0.tgz#a77ea742fab25775145434eb1d2328cf5013ac33" + integrity sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg== + +"@polka/url@^1.0.0-next.24": + version "1.0.0-next.29" + resolved "https://registry.yarnpkg.com/@polka/url/-/url-1.0.0-next.29.tgz#5a40109a1ab5f84d6fd8fc928b19f367cbe7e7b1" + integrity sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww== + +"@rollup/rollup-android-arm-eabi@4.49.0": + version "4.49.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.49.0.tgz#ba432433f5e7b419dba2be407d1d59fea6b8de48" + integrity sha512-rlKIeL854Ed0e09QGYFlmDNbka6I3EQFw7iZuugQjMb11KMpJCLPFL4ZPbMfaEhLADEL1yx0oujGkBQ7+qW3eA== + +"@rollup/rollup-android-arm64@4.49.0": + version "4.49.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.49.0.tgz#4e05c86e0fb9af6eaf52fc298dcdec577477e35c" + integrity sha512-cqPpZdKUSQYRtLLr6R4X3sD4jCBO1zUmeo3qrWBCqYIeH8Q3KRL4F3V7XJ2Rm8/RJOQBZuqzQGWPjjvFUcYa/w== + +"@rollup/rollup-darwin-arm64@4.49.0": + version "4.49.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.49.0.tgz#788fad425b4129875639e0c14b6441c5f3b69d46" + integrity sha512-99kMMSMQT7got6iYX3yyIiJfFndpojBmkHfTc1rIje8VbjhmqBXE+nb7ZZP3A5skLyujvT0eIUCUsxAe6NjWbw== + +"@rollup/rollup-darwin-x64@4.49.0": + version "4.49.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.49.0.tgz#d44e05bee55b781d7c2cf535d9f9169787c3599d" + integrity sha512-y8cXoD3wdWUDpjOLMKLx6l+NFz3NlkWKcBCBfttUn+VGSfgsQ5o/yDUGtzE9HvsodkP0+16N0P4Ty1VuhtRUGg== + +"@rollup/rollup-freebsd-arm64@4.49.0": + version "4.49.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.49.0.tgz#107786b4d604495224c3543bfd2cae33ddf76500" + integrity sha512-3mY5Pr7qv4GS4ZvWoSP8zha8YoiqrU+e0ViPvB549jvliBbdNLrg2ywPGkgLC3cmvN8ya3za+Q2xVyT6z+vZqA== + +"@rollup/rollup-freebsd-x64@4.49.0": + version "4.49.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.49.0.tgz#54e105c3da27f31084ca6913fed603627755abde" + integrity sha512-C9KzzOAQU5gU4kG8DTk+tjdKjpWhVWd5uVkinCwwFub2m7cDYLOdtXoMrExfeBmeRy9kBQMkiyJ+HULyF1yj9w== + +"@rollup/rollup-linux-arm-gnueabihf@4.49.0": + version "4.49.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.49.0.tgz#725c23e0766b5d9368180bc2c427a51e31d0e147" + integrity sha512-OVSQgEZDVLnTbMq5NBs6xkmz3AADByCWI4RdKSFNlDsYXdFtlxS59J+w+LippJe8KcmeSSM3ba+GlsM9+WwC1w== + +"@rollup/rollup-linux-arm-musleabihf@4.49.0": + version "4.49.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.49.0.tgz#6946b0d2f132f2baf5657945b81565d8abd51cc0" + integrity sha512-ZnfSFA7fDUHNa4P3VwAcfaBLakCbYaxCk0jUnS3dTou9P95kwoOLAMlT3WmEJDBCSrOEFFV0Y1HXiwfLYJuLlA== + +"@rollup/rollup-linux-arm64-gnu@4.49.0": + version "4.49.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.49.0.tgz#83510a6d03e748619241a17f5a879418a963c5ed" + integrity sha512-Z81u+gfrobVK2iV7GqZCBfEB1y6+I61AH466lNK+xy1jfqFLiQ9Qv716WUM5fxFrYxwC7ziVdZRU9qvGHkYIJg== + +"@rollup/rollup-linux-arm64-musl@4.49.0": + version "4.49.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.49.0.tgz#085b98d44c10908626dd40f26bf924433bbd8471" + integrity sha512-zoAwS0KCXSnTp9NH/h9aamBAIve0DXeYpll85shf9NJ0URjSTzzS+Z9evmolN+ICfD3v8skKUPyk2PO0uGdFqg== + +"@rollup/rollup-linux-loongarch64-gnu@4.49.0": + version "4.49.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.49.0.tgz#13e0a4808e9f7924f2cc8c133603f627c7a00543" + integrity sha512-2QyUyQQ1ZtwZGiq0nvODL+vLJBtciItC3/5cYN8ncDQcv5avrt2MbKt1XU/vFAJlLta5KujqyHdYtdag4YEjYQ== + +"@rollup/rollup-linux-ppc64-gnu@4.49.0": + version "4.49.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-ppc64-gnu/-/rollup-linux-ppc64-gnu-4.49.0.tgz#aeee4e47fc9ca5d6687e686fea4696202af6b2f4" + integrity sha512-k9aEmOWt+mrMuD3skjVJSSxHckJp+SiFzFG+v8JLXbc/xi9hv2icSkR3U7uQzqy+/QbbYY7iNB9eDTwrELo14g== + +"@rollup/rollup-linux-riscv64-gnu@4.49.0": + version "4.49.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.49.0.tgz#603e4591643f1d7851a96d096cf7fcd273f7b0e1" + integrity sha512-rDKRFFIWJ/zJn6uk2IdYLc09Z7zkE5IFIOWqpuU0o6ZpHcdniAyWkwSUWE/Z25N/wNDmFHHMzin84qW7Wzkjsw== + +"@rollup/rollup-linux-riscv64-musl@4.49.0": + version "4.49.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-musl/-/rollup-linux-riscv64-musl-4.49.0.tgz#f8fd9b01f1888e1816d5a398789d430511286c00" + integrity sha512-FkkhIY/hYFVnOzz1WeV3S9Bd1h0hda/gRqvZCMpHWDHdiIHn6pqsY3b5eSbvGccWHMQ1uUzgZTKS4oGpykf8Tw== + +"@rollup/rollup-linux-s390x-gnu@4.49.0": + version "4.49.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.49.0.tgz#37a1fd372d9b93d2b75b2f37c482ecf52f52849b" + integrity sha512-gRf5c+A7QiOG3UwLyOOtyJMD31JJhMjBvpfhAitPAoqZFcOeK3Kc1Veg1z/trmt+2P6F/biT02fU19GGTS529A== + +"@rollup/rollup-linux-x64-gnu@4.49.0": + version "4.49.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.49.0.tgz#131e66dbf7e71cb2a389acc45319bd4c990e093a" + integrity sha512-BR7+blScdLW1h/2hB/2oXM+dhTmpW3rQt1DeSiCP9mc2NMMkqVgjIN3DDsNpKmezffGC9R8XKVOLmBkRUcK/sA== + +"@rollup/rollup-linux-x64-musl@4.49.0": + version "4.49.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.49.0.tgz#b7245a5ea57db9679e8bf3032c25a5d2c5f54056" + integrity sha512-hDMOAe+6nX3V5ei1I7Au3wcr9h3ktKzDvF2ne5ovX8RZiAHEtX1A5SNNk4zt1Qt77CmnbqT+upb/umzoPMWiPg== + +"@rollup/rollup-win32-arm64-msvc@4.49.0": + version "4.49.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.49.0.tgz#768a128bb5da3c5472c3c56aec77507d28bc7209" + integrity sha512-wkNRzfiIGaElC9kXUT+HLx17z7D0jl+9tGYRKwd8r7cUqTL7GYAvgUY++U2hK6Ar7z5Z6IRRoWC8kQxpmM7TDA== + +"@rollup/rollup-win32-ia32-msvc@4.49.0": + version "4.49.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.49.0.tgz#ce3f3b2eebe585340631498666718f00983a6a62" + integrity sha512-gq5aW/SyNpjp71AAzroH37DtINDcX1Qw2iv9Chyz49ZgdOP3NV8QCyKZUrGsYX9Yyggj5soFiRCgsL3HwD8TdA== + +"@rollup/rollup-win32-x64-msvc@4.49.0": + version "4.49.0" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.49.0.tgz#c2a0e3b81262a7e9dd12ce18b350a97558dd50bc" + integrity sha512-gEtqFbzmZLFk2xKh7g0Rlo8xzho8KrEFEkzvHbfUGkrgXOpZ4XagQ6n+wIZFNh1nTb8UD16J4nFSFKXYgnbdBg== + +"@stackpress/ingest@0.6.1": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@stackpress/ingest/-/ingest-0.6.1.tgz#20ba2a33a1d4a1573ed49774f887db2b0086fb35" + integrity sha512-i69p2fDHhEDQkWNfBiNp5pf74Gp0MQz6PkgrH0Nzf2I6L2d/5e25gQNeAAt9Qet9FPk0K0MlSgg46iMpXtQ4mQ== + dependencies: + "@stackpress/lib" "0.6.1" + "@whatwg-node/server" "0.6.7" + +"@stackpress/inquire@0.6.1": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@stackpress/inquire/-/inquire-0.6.1.tgz#ab8c5842fdcbdce6cd7c5d8bdefc207511f36312" + integrity sha512-SjbNrRuVVwNboMO5Bv6swZpK49z41sB1U2iYKKO2RrsLZPMdvpEZtjL7JxIDW37fm1Gh4PXkVTuYgvZ5qma2zQ== + dependencies: + "@stackpress/lib" "0.6.1" + "@stackpress/lib@0.6.1": version "0.6.1" resolved "https://registry.yarnpkg.com/@stackpress/lib/-/lib-0.6.1.tgz#56b65e66daaeb1e4a2a67cb8d743cd784bc8ed14" @@ -726,6 +1351,116 @@ dependencies: "@inquirer/prompts" "7.1.0" +"@tailwindcss/node@4.1.12": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@tailwindcss/node/-/node-4.1.12.tgz#9099c7c9a6b719b2cae265fecbb37e08ed3fd2a2" + integrity sha512-3hm9brwvQkZFe++SBt+oLjo4OLDtkvlE8q2WalaD/7QWaeM7KEJbAiY/LJZUaCs7Xa8aUu4xy3uoyX4q54UVdQ== + dependencies: + "@jridgewell/remapping" "^2.3.4" + enhanced-resolve "^5.18.3" + jiti "^2.5.1" + lightningcss "1.30.1" + magic-string "^0.30.17" + source-map-js "^1.2.1" + tailwindcss "4.1.12" + +"@tailwindcss/oxide-android-arm64@4.1.12": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.12.tgz#27920fe61fa2743afe8a8ca296fa640b609d17d5" + integrity sha512-oNY5pq+1gc4T6QVTsZKwZaGpBb2N1H1fsc1GD4o7yinFySqIuRZ2E4NvGasWc6PhYJwGK2+5YT1f9Tp80zUQZQ== + +"@tailwindcss/oxide-darwin-arm64@4.1.12": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.12.tgz#e8bd4798f26ec1d012bf0683aeb77449f71505cd" + integrity sha512-cq1qmq2HEtDV9HvZlTtrj671mCdGB93bVY6J29mwCyaMYCP/JaUBXxrQQQm7Qn33AXXASPUb2HFZlWiiHWFytw== + +"@tailwindcss/oxide-darwin-x64@4.1.12": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.12.tgz#8ddb7e5ddfd9b049ec84a2bda99f2b04a86859f5" + integrity sha512-6UCsIeFUcBfpangqlXay9Ffty9XhFH1QuUFn0WV83W8lGdX8cD5/+2ONLluALJD5+yJ7k8mVtwy3zMZmzEfbLg== + +"@tailwindcss/oxide-freebsd-x64@4.1.12": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.12.tgz#da1c0b16b7a5f95a1e400f299a3ec94fb6fd40ac" + integrity sha512-JOH/f7j6+nYXIrHobRYCtoArJdMJh5zy5lr0FV0Qu47MID/vqJAY3r/OElPzx1C/wdT1uS7cPq+xdYYelny1ww== + +"@tailwindcss/oxide-linux-arm-gnueabihf@4.1.12": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.12.tgz#34e558aa6e869c6fe9867cb78ed7ba651b9fcaa4" + integrity sha512-v4Ghvi9AU1SYgGr3/j38PD8PEe6bRfTnNSUE3YCMIRrrNigCFtHZ2TCm8142X8fcSqHBZBceDx+JlFJEfNg5zQ== + +"@tailwindcss/oxide-linux-arm64-gnu@4.1.12": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.12.tgz#0a00a8146ab6215f81b2d385056c991441bf390e" + integrity sha512-YP5s1LmetL9UsvVAKusHSyPlzSRqYyRB0f+Kl/xcYQSPLEw/BvGfxzbH+ihUciePDjiXwHh+p+qbSP3SlJw+6g== + +"@tailwindcss/oxide-linux-arm64-musl@4.1.12": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.12.tgz#b138f494068884ae0d8c343dc1904b22f5e98dc6" + integrity sha512-V8pAM3s8gsrXcCv6kCHSuwyb/gPsd863iT+v1PGXC4fSL/OJqsKhfK//v8P+w9ThKIoqNbEnsZqNy+WDnwQqCA== + +"@tailwindcss/oxide-linux-x64-gnu@4.1.12": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.12.tgz#5b9d5f23b15cdb714639f5b9741c0df5d610f794" + integrity sha512-xYfqYLjvm2UQ3TZggTGrwxjYaLB62b1Wiysw/YE3Yqbh86sOMoTn0feF98PonP7LtjsWOWcXEbGqDL7zv0uW8Q== + +"@tailwindcss/oxide-linux-x64-musl@4.1.12": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.12.tgz#f68ec530d3ca6875ea9015bcd5dd0762ee5e2f5d" + integrity sha512-ha0pHPamN+fWZY7GCzz5rKunlv9L5R8kdh+YNvP5awe3LtuXb5nRi/H27GeL2U+TdhDOptU7T6Is7mdwh5Ar3A== + +"@tailwindcss/oxide-wasm32-wasi@4.1.12": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.12.tgz#9fd15a1ebde6076c42c445c5e305c31673ead965" + integrity sha512-4tSyu3dW+ktzdEpuk6g49KdEangu3eCYoqPhWNsZgUhyegEda3M9rG0/j1GV/JjVVsj+lG7jWAyrTlLzd/WEBg== + dependencies: + "@emnapi/core" "^1.4.5" + "@emnapi/runtime" "^1.4.5" + "@emnapi/wasi-threads" "^1.0.4" + "@napi-rs/wasm-runtime" "^0.2.12" + "@tybys/wasm-util" "^0.10.0" + tslib "^2.8.0" + +"@tailwindcss/oxide-win32-arm64-msvc@4.1.12": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.12.tgz#938bcc6a82e1120ea4fe2ce94be0a8cdf3ae92c7" + integrity sha512-iGLyD/cVP724+FGtMWslhcFyg4xyYyM+5F4hGvKA7eifPkXHRAUDFaimu53fpNg9X8dfP75pXx/zFt/jlNF+lg== + +"@tailwindcss/oxide-win32-x64-msvc@4.1.12": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.12.tgz#b1ee2ed0ef2c4095ddec3684a1987e2b3613af36" + integrity sha512-NKIh5rzw6CpEodv/++r0hGLlfgT/gFN+5WNdZtvh6wpU2BpGNgdjvj6H2oFc8nCM839QM1YOhjpgbAONUb4IxA== + +"@tailwindcss/oxide@4.1.12": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@tailwindcss/oxide/-/oxide-4.1.12.tgz#13a6f806aafa9c83629c9a04acd92031aef83f1c" + integrity sha512-gM5EoKHW/ukmlEtphNwaGx45fGoEmP10v51t9unv55voWh6WrOL19hfuIdo2FjxIaZzw776/BUQg7Pck++cIVw== + dependencies: + detect-libc "^2.0.4" + tar "^7.4.3" + optionalDependencies: + "@tailwindcss/oxide-android-arm64" "4.1.12" + "@tailwindcss/oxide-darwin-arm64" "4.1.12" + "@tailwindcss/oxide-darwin-x64" "4.1.12" + "@tailwindcss/oxide-freebsd-x64" "4.1.12" + "@tailwindcss/oxide-linux-arm-gnueabihf" "4.1.12" + "@tailwindcss/oxide-linux-arm64-gnu" "4.1.12" + "@tailwindcss/oxide-linux-arm64-musl" "4.1.12" + "@tailwindcss/oxide-linux-x64-gnu" "4.1.12" + "@tailwindcss/oxide-linux-x64-musl" "4.1.12" + "@tailwindcss/oxide-wasm32-wasi" "4.1.12" + "@tailwindcss/oxide-win32-arm64-msvc" "4.1.12" + "@tailwindcss/oxide-win32-x64-msvc" "4.1.12" + +"@tailwindcss/vite@^4.1.12": + version "4.1.12" + resolved "https://registry.yarnpkg.com/@tailwindcss/vite/-/vite-4.1.12.tgz#f2839180aa7ba938a5247114e32ee9d57215e7f8" + integrity sha512-4pt0AMFDx7gzIrAOIYgYP0KCBuKWqyW8ayrdiLEjoJTT4pKTjrzG/e4uzWtTLDziC+66R9wbUqZBccJalSE5vQ== + dependencies: + "@tailwindcss/node" "4.1.12" + "@tailwindcss/oxide" "4.1.12" + tailwindcss "4.1.12" + "@ts-morph/common@~0.25.0": version "0.25.0" resolved "https://registry.yarnpkg.com/@ts-morph/common/-/common-0.25.0.tgz#b76cbd517118acc8eadaf12b2fc2d47f42923452" @@ -735,6 +1470,15 @@ path-browserify "^1.0.1" tinyglobby "^0.2.9" +"@ts-morph/common@~0.26.0": + version "0.26.1" + resolved "https://registry.yarnpkg.com/@ts-morph/common/-/common-0.26.1.tgz#a346188e59d2befe4c71f66a7d626d81b1abe2a8" + integrity sha512-Sn28TGl/4cFpcM+jwsH1wLncYq3FtN/BIpem+HOygfBWPT5pAeS5dB4VFVzV8FbnOKHpDLZmvAl4AjPEev5idA== + dependencies: + fast-glob "^3.3.2" + minimatch "^9.0.4" + path-browserify "^1.0.1" + "@tsconfig/node10@^1.0.7": version "1.0.11" resolved "https://registry.yarnpkg.com/@tsconfig/node10/-/node10-1.0.11.tgz#6ee46400685f130e278128c7b38b7e031ff5b2f2" @@ -755,16 +1499,80 @@ resolved "https://registry.yarnpkg.com/@tsconfig/node16/-/node16-1.0.4.tgz#0b92dcc0cc1c81f6f306a381f28e31b1a56536e9" integrity sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA== +"@tybys/wasm-util@^0.10.0": + version "0.10.0" + resolved "https://registry.yarnpkg.com/@tybys/wasm-util/-/wasm-util-0.10.0.tgz#2fd3cd754b94b378734ce17058d0507c45c88369" + integrity sha512-VyyPYFlOMNylG45GoAe0xDoLwWuowvf92F9kySqzYh8vmYm7D2u4iUJKa1tOUpS70Ku13ASrOkS4ScXFsTaCNQ== + dependencies: + tslib "^2.4.0" + +"@types/babel__core@^7.20.5": + version "7.20.5" + resolved "https://registry.yarnpkg.com/@types/babel__core/-/babel__core-7.20.5.tgz#3df15f27ba85319caa07ba08d0721889bb39c017" + integrity sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA== + dependencies: + "@babel/parser" "^7.20.7" + "@babel/types" "^7.20.7" + "@types/babel__generator" "*" + "@types/babel__template" "*" + "@types/babel__traverse" "*" + +"@types/babel__generator@*": + version "7.27.0" + resolved "https://registry.yarnpkg.com/@types/babel__generator/-/babel__generator-7.27.0.tgz#b5819294c51179957afaec341442f9341e4108a9" + integrity sha512-ufFd2Xi92OAVPYsy+P4n7/U7e68fex0+Ee8gSG9KX7eo084CWiQ4sdxktvdl0bOPupXtVJPY19zk6EwWqUQ8lg== + dependencies: + "@babel/types" "^7.0.0" + +"@types/babel__template@*": + version "7.4.4" + resolved "https://registry.yarnpkg.com/@types/babel__template/-/babel__template-7.4.4.tgz#5672513701c1b2199bc6dad636a9d7491586766f" + integrity sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A== + dependencies: + "@babel/parser" "^7.1.0" + "@babel/types" "^7.0.0" + +"@types/babel__traverse@*": + version "7.28.0" + resolved "https://registry.yarnpkg.com/@types/babel__traverse/-/babel__traverse-7.28.0.tgz#07d713d6cce0d265c9849db0cbe62d3f61f36f74" + integrity sha512-8PvcXf70gTDZBgt9ptxJ8elBeBjcLOAcOtoO/mPJjtji1+CdGbHgm77om1GrsPxsiE+uXIpNSK64UYaIwQXd4Q== + dependencies: + "@babel/types" "^7.28.2" + "@types/chai@4.3.20": version "4.3.20" resolved "https://registry.yarnpkg.com/@types/chai/-/chai-4.3.20.tgz#cb291577ed342ca92600430841a00329ba05cecc" integrity sha512-/pC9HAB5I/xMlc5FP77qjCnI16ChlJfW0tGa0IUcFn38VJrTV6DeZ60NU5KZBtaOZqjdpwTWohz5HU1RrhiYxQ== +"@types/chai@5.2.1": + version "5.2.1" + resolved "https://registry.yarnpkg.com/@types/chai/-/chai-5.2.1.tgz#85687a58b27eac736ec0e87e5cb98f21e57a0bb1" + integrity sha512-iu1JLYmGmITRzUgNiLMZD3WCoFzpYtueuyAgHTXqgwSRAMIlFTnZqG6/xenkpUGRJEzSfklUTI4GNSzks/dc0w== + dependencies: + "@types/deep-eql" "*" + +"@types/deep-eql@*": + version "4.0.2" + resolved "https://registry.yarnpkg.com/@types/deep-eql/-/deep-eql-4.0.2.tgz#334311971d3a07121e7eb91b684a605e7eea9cbd" + integrity sha512-c9h9dVVMigMPc4bwTvC5dxqtqJZwQPePsWjPlpSOnojbor6pGqdk541lfA7AqFQr5pB1BRdq0juY9db81BwyFw== + "@types/deep-equal-in-any-order@1.0.3": version "1.0.3" resolved "https://registry.yarnpkg.com/@types/deep-equal-in-any-order/-/deep-equal-in-any-order-1.0.3.tgz#55baf558924d52adaec886f7f1930c05e69c4ca6" integrity sha512-jT0O3hAILDKeKbdWJ9FZLD0Xdfhz7hMvfyFlRWpirjiEVr8G+GZ4kVIzPIqM6x6Rpp93TNPgOAed4XmvcuV6Qg== +"@types/estree@1.0.8": + version "1.0.8" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.8.tgz#958b91c991b1867ced318bedea0e215ee050726e" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + +"@types/hast@^2.0.0": + version "2.3.10" + resolved "https://registry.yarnpkg.com/@types/hast/-/hast-2.3.10.tgz#5c9d9e0b304bbb8879b857225c5ebab2d81d7643" + integrity sha512-McWspRw8xx8J9HurkVBfYj0xKoE25tOFlHGdx4MJ5xORQrMGZNqJhVQWaIbm6Oyla5kYOXtDiopzKRJzEOkwJw== + dependencies: + "@types/unist" "^2" + "@types/json5@^0.0.29": version "0.0.29" resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" @@ -775,6 +1583,13 @@ resolved "https://registry.yarnpkg.com/@types/mocha/-/mocha-10.0.10.tgz#91f62905e8d23cbd66225312f239454a23bebfa0" integrity sha512-xPyYSz1cMPnJQhl0CLMH68j3gprKZaTjG3s5Vi+fDgx+uhG9NOXwbVt52eFS8ECyXhyKcjDLCBEqBExKuiZb7Q== +"@types/node@22.14.1": + version "22.14.1" + resolved "https://registry.yarnpkg.com/@types/node/-/node-22.14.1.tgz#53b54585cec81c21eee3697521e31312d6ca1e6f" + integrity sha512-u0HuPQwe/dHrItgHHpmw3N2fYCR6x4ivMNbPHRkBVP4CvN+kiRrKHWk3i8tXiO/joPwXLMYvF9TTF0eqgHIuOw== + dependencies: + undici-types "~6.21.0" + "@types/node@22.9.3": version "22.9.3" resolved "https://registry.yarnpkg.com/@types/node/-/node-22.9.3.tgz#08f3d64b3bc6d74b162d36f60213e8a6704ef2b4" @@ -782,6 +1597,291 @@ dependencies: undici-types "~6.19.8" +"@types/react-dom@19.1.2": + version "19.1.2" + resolved "https://registry.yarnpkg.com/@types/react-dom/-/react-dom-19.1.2.tgz#bd1fe3b8c28a3a2e942f85314dcfb71f531a242f" + integrity sha512-XGJkWF41Qq305SKWEILa1O8vzhb3aOo3ogBlSmiqNko/WmRb6QIaweuZCXjKygVDXpzXb5wyxKTSOsmkuqj+Qw== + +"@types/react-syntax-highlighter@15.5.13": + version "15.5.13" + resolved "https://registry.yarnpkg.com/@types/react-syntax-highlighter/-/react-syntax-highlighter-15.5.13.tgz#c5baf62a3219b3bf28d39cfea55d0a49a263d1f2" + integrity sha512-uLGJ87j6Sz8UaBAooU0T6lWJ0dBmjZgN1PZTrj05TNql2/XpC6+4HhMT5syIdFUUt+FASfCeLLv4kBygNU+8qA== + dependencies: + "@types/react" "*" + +"@types/react@*": + version "19.1.12" + resolved "https://registry.yarnpkg.com/@types/react/-/react-19.1.12.tgz#7bfaa76aabbb0b4fe0493c21a3a7a93d33e8937b" + integrity sha512-cMoR+FoAf/Jyq6+Df2/Z41jISvGZZ2eTlnsaJRptmZ76Caldwy1odD4xTr/gNV9VLj0AWgg/nmkevIyUfIIq5w== + dependencies: + csstype "^3.0.2" + +"@types/react@19.1.2": + version "19.1.2" + resolved "https://registry.yarnpkg.com/@types/react/-/react-19.1.2.tgz#11df86f66f188f212c90ecb537327ec68bfd593f" + integrity sha512-oxLPMytKchWGbnQM9O7D67uPa9paTNxO7jVoNMXgkkErULBPhPARCfkKL9ytcIJJRGjbsVwW4ugJzyFFvm/Tiw== + dependencies: + csstype "^3.0.2" + +"@types/unist@^2": + version "2.0.11" + resolved "https://registry.yarnpkg.com/@types/unist/-/unist-2.0.11.tgz#11af57b127e32487774841f7a4e54eab166d03c4" + integrity sha512-CmBKiL6NNo/OqgmMn95Fk9Whlp2mtvIv+KNpQKN2F4SjvrEesubTRWGYSg+BnWZOnlCaSTU1sMpsBOzgbYhnsA== + +"@unocss/astro@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/astro/-/astro-66.0.0.tgz#6564ef14c9d7c1346769c222c6e525d7d8995c98" + integrity sha512-GBhXT6JPqXjDXoJZTXhySk83NgOt0UigChqrUUdG4x7Z+DVYkDBION8vZUJjw0OdIaxNQ4euGWu4GDsMF6gQQg== + dependencies: + "@unocss/core" "66.0.0" + "@unocss/reset" "66.0.0" + "@unocss/vite" "66.0.0" + +"@unocss/cli@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/cli/-/cli-66.0.0.tgz#4cd4b6e14a6743354fe532f6dc390bab30e04e35" + integrity sha512-KVQiskoOjVkLVpNaG6WpLa4grPplrZROYZJVIUYSTqZyZRFNSvjttHcsCwpoWUEUdEombPtVZl8FrXePjY5IiQ== + dependencies: + "@ampproject/remapping" "^2.3.0" + "@unocss/config" "66.0.0" + "@unocss/core" "66.0.0" + "@unocss/preset-uno" "66.0.0" + cac "^6.7.14" + chokidar "^3.6.0" + colorette "^2.0.20" + consola "^3.4.0" + magic-string "^0.30.17" + pathe "^2.0.3" + perfect-debounce "^1.0.0" + tinyglobby "^0.2.10" + unplugin-utils "^0.2.4" + +"@unocss/config@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/config/-/config-66.0.0.tgz#16ff6da705cd7b97813d62a887adbf354ee423c8" + integrity sha512-nFRGop/guBa4jLkrgXjaRDm5JPz4x3YpP10m5IQkHpHwlnHUVn1L9smyPl04ohYWhYn9ZcAHgR28Ih2jwta8hw== + dependencies: + "@unocss/core" "66.0.0" + unconfig "~7.0.0" + +"@unocss/core@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/core/-/core-66.0.0.tgz#2a316f4e0e17bd3f77788479401ca84eaf52e847" + integrity sha512-PdVbSMHNDDkr++9nkqzsZRAkaU84gxMTEgYbqI7dt2p1DXp/5tomVtmMsr2/whXGYKRiUc0xZ3p4Pzraz8TcXA== + +"@unocss/core@^66.0.0": + version "66.4.2" + resolved "https://registry.yarnpkg.com/@unocss/core/-/core-66.4.2.tgz#4c4dac438a3b0e59025933ee36bf7728c6447fbb" + integrity sha512-cYgMQrLhB9nRekv5c+yPDDa+5dzlMkA2UMQRil0s5D9Lb5n7NsCMcr6+nfxkcSYVLy92SbwDV45c6T7vIxFTOA== + +"@unocss/extractor-arbitrary-variants@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/extractor-arbitrary-variants/-/extractor-arbitrary-variants-66.0.0.tgz#8bd37b36cc4e568db809d7d460f65ff3f4830b30" + integrity sha512-vlkOIOuwBfaFBJcN6o7+obXjigjOlzVFN/jT6pG1WXbQDTRZ021jeF3i9INdb9D/0cQHSeDvNgi1TJ5oUxfiow== + dependencies: + "@unocss/core" "66.0.0" + +"@unocss/inspector@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/inspector/-/inspector-66.0.0.tgz#98d9e4bf83abb4a4b119eea89c464aef066439ec" + integrity sha512-mkIxieVm0kMOKw+E4ABpIerihYMdjgq9A92RD5h2+W/ebpxTEw5lTTK1xcMLiAlmOrVYMQKjpgPeu3vQmDyGZQ== + dependencies: + "@unocss/core" "66.0.0" + "@unocss/rule-utils" "66.0.0" + colorette "^2.0.20" + gzip-size "^6.0.0" + sirv "^3.0.0" + vue-flow-layout "^0.1.1" + +"@unocss/postcss@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/postcss/-/postcss-66.0.0.tgz#686a74de9de91809d02ae715b60b1470d2705826" + integrity sha512-6bi+ujzh8I1PJwtmHX71LH8z/H9+vPxeYD4XgFihyU1k4Y6MVhjr7giGjLX4yP27IP+NsVyotD22V7by/dBVEA== + dependencies: + "@unocss/config" "66.0.0" + "@unocss/core" "66.0.0" + "@unocss/rule-utils" "66.0.0" + css-tree "^3.1.0" + postcss "^8.5.2" + tinyglobby "^0.2.10" + +"@unocss/preset-attributify@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/preset-attributify/-/preset-attributify-66.0.0.tgz#e319503c7ffb5a482cafb09744d33424db97167e" + integrity sha512-eYsOgmcDoiIgGAepIwRX+DKGYxc/wm0r4JnDuZdz29AB+A6oY/FGHS1BVt4rq9ny4B5PofP4p6Rty+vwD9rigw== + dependencies: + "@unocss/core" "66.0.0" + +"@unocss/preset-icons@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/preset-icons/-/preset-icons-66.0.0.tgz#97d9e9e110a343e2c5b6de37070019ac05de1221" + integrity sha512-6ObwTvEGuPBbKWRoMMiDioHtwwQTFI5oojFLJ32Y8tW6TdXvBLkO88d7qpgQxEjgVt4nJrqF1WEfR4niRgBm0Q== + dependencies: + "@iconify/utils" "^2.3.0" + "@unocss/core" "66.0.0" + ofetch "^1.4.1" + +"@unocss/preset-mini@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/preset-mini/-/preset-mini-66.0.0.tgz#8b1b5ee36aaa8d1226ff34179622d4433a872130" + integrity sha512-d62eACnuKtR0dwCFOQXgvw5VLh5YSyK56xCzpHkh0j0GstgfDLfKTys0T/XVAAvdSvAy/8A8vhSNJ4PlIc9V2A== + dependencies: + "@unocss/core" "66.0.0" + "@unocss/extractor-arbitrary-variants" "66.0.0" + "@unocss/rule-utils" "66.0.0" + +"@unocss/preset-tagify@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/preset-tagify/-/preset-tagify-66.0.0.tgz#8629c466ffdcdf771e79d19cca92f8a4b13bfb3f" + integrity sha512-GGYGyWxaevh0jN0NoATVO1Qe7DFXM3ykLxchlXmG6/zy963pZxItg/njrKnxE9la4seCdxpFH7wQBa68imwwdA== + dependencies: + "@unocss/core" "66.0.0" + +"@unocss/preset-typography@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/preset-typography/-/preset-typography-66.0.0.tgz#85c62a0fa57e538f23ab9f56e68a8ac3bc4ed116" + integrity sha512-apjckP5nPU5mtaHTCzz5u/dK9KJWwJ2kOFCVk0+a/KhUWmnqnzmjRYZlEuWxxr5QxTdCW+9cIoRDSA0lYZS5tg== + dependencies: + "@unocss/core" "66.0.0" + "@unocss/preset-mini" "66.0.0" + "@unocss/rule-utils" "66.0.0" + +"@unocss/preset-uno@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/preset-uno/-/preset-uno-66.0.0.tgz#37633290c6594de40a40fc158504fa22c02c6ab7" + integrity sha512-qgoZ/hzTI32bQvcyjcwvv1X/dbPlmQNehzgjUaL7QFT0q0/CN/SRpysfzoQ8DLl2se9T+YCOS9POx3KrpIiYSQ== + dependencies: + "@unocss/core" "66.0.0" + "@unocss/preset-wind3" "66.0.0" + +"@unocss/preset-web-fonts@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/preset-web-fonts/-/preset-web-fonts-66.0.0.tgz#39c936ad69f6777df1077ffff40d6694cf9368e9" + integrity sha512-9MzfDc6AJILN4Kq7Z91FfFbizBOYgw3lJd2UwqIs3PDYWG5iH5Zv5zhx6jelZVqEW5uWcIARYEEg2m4stZO1ZA== + dependencies: + "@unocss/core" "66.0.0" + ofetch "^1.4.1" + +"@unocss/preset-wind3@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/preset-wind3/-/preset-wind3-66.0.0.tgz#3f17da21cea683d75d4adefbd4f9c95172eeb1bb" + integrity sha512-WAGRmpi1sb2skvYn9DBQUvhfqrJ+VmQmn5ZGsT2ewvsk7HFCvVLAMzZeKrrTQepeNBRhg6HzFDDi8yg6yB5c9g== + dependencies: + "@unocss/core" "66.0.0" + "@unocss/preset-mini" "66.0.0" + "@unocss/rule-utils" "66.0.0" + +"@unocss/preset-wind@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/preset-wind/-/preset-wind-66.0.0.tgz#eeb22cd66a32dc896c6263dc0eeb8be0c6c9b090" + integrity sha512-FtvGpHnGC7FiyKJavPnn5y9lsaoWRhXlujCqlT5Bw63kKhMNr0ogKySBpenUhJOhWhVM0OQXn2nZ3GZRxW2qpw== + dependencies: + "@unocss/core" "66.0.0" + "@unocss/preset-wind3" "66.0.0" + +"@unocss/reset@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/reset/-/reset-66.0.0.tgz#8e3301206ab315d3287fb133be6f03e60a3ebdd4" + integrity sha512-YLFz/5yT7mFJC8JSmIUA5+bS3CBCJbtztOw+8rWzjQr/BEVSGuihWUUpI2Df6VVxXIXxKanZR6mIl59yvf+GEA== + +"@unocss/rule-utils@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/rule-utils/-/rule-utils-66.0.0.tgz#5fd1c7bd2372e9f3724ed6858263a703a9ae064a" + integrity sha512-UJ51YHbwxYTGyj35ugsPlOT4gaa7tCbXdywZ3m5Nn0JgywwIqGmBFyiN9ZjHBHfJuDxmmPd6lxojoBscih/WMQ== + dependencies: + "@unocss/core" "^66.0.0" + magic-string "^0.30.17" + +"@unocss/transformer-attributify-jsx@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/transformer-attributify-jsx/-/transformer-attributify-jsx-66.0.0.tgz#f93168db7fd7efbccfa75cd3ea5f3457d1aee8eb" + integrity sha512-jS7szFXXC6RjTv9wo0NACskf618w981bkbyQ5izRO7Ha47sNpHhHDpaltnG7SR9qV4cCtGalOw4onVMHsRKwRg== + dependencies: + "@unocss/core" "66.0.0" + +"@unocss/transformer-compile-class@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/transformer-compile-class/-/transformer-compile-class-66.0.0.tgz#baa303da481e6df25d963436c4536479b620025b" + integrity sha512-ytUIE0nAcHRMACuTXkHp8auZ483DXrOZw99jk3FJ+aFjpD/pVSFmX14AWJ7bqPFObxb4SLFs6KhQma30ESC22A== + dependencies: + "@unocss/core" "66.0.0" + +"@unocss/transformer-directives@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/transformer-directives/-/transformer-directives-66.0.0.tgz#7cfff36c2b196937a54f107a76803aeb7236d0d8" + integrity sha512-utcg7m2Foi7uHrU5WHadNuJ0a3qWG8tZNkQMi+m0DQpX6KWfuDtDn0zDZ1X+z5lmiB3WGSJERRrsvZbj1q50Mw== + dependencies: + "@unocss/core" "66.0.0" + "@unocss/rule-utils" "66.0.0" + css-tree "^3.1.0" + +"@unocss/transformer-variant-group@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/transformer-variant-group/-/transformer-variant-group-66.0.0.tgz#255ae998dd75c379df6af09f0b9f10a5dc0a5ad1" + integrity sha512-1BLjNWtAnR1JAcQGw0TS+nGrVoB9aznzvVZRoTx23dtRr3btvgKPHb8LrD48eD/p8Dtw9j3WfuxMDKXKegKDLg== + dependencies: + "@unocss/core" "66.0.0" + +"@unocss/vite@66.0.0": + version "66.0.0" + resolved "https://registry.yarnpkg.com/@unocss/vite/-/vite-66.0.0.tgz#e0e4e50288d8b5ef6e53af85ae35149ce2a60b73" + integrity sha512-IVcPX8xL+2edyXKt4tp9yu5A6gcbPVCsspfcL0XgziCr01kS+4qSoZ90F3IUs3hXc/AyO5eCpRtGFMPLpOjXQg== + dependencies: + "@ampproject/remapping" "^2.3.0" + "@unocss/config" "66.0.0" + "@unocss/core" "66.0.0" + "@unocss/inspector" "66.0.0" + chokidar "^3.6.0" + magic-string "^0.30.17" + tinyglobby "^0.2.10" + unplugin-utils "^0.2.4" + +"@vitejs/plugin-react@4.4.1": + version "4.4.1" + resolved "https://registry.yarnpkg.com/@vitejs/plugin-react/-/plugin-react-4.4.1.tgz#d7d1e9c9616d7536b0953637edfee7c6cbe2fe0f" + integrity sha512-IpEm5ZmeXAP/osiBXVVP5KjFMzbWOonMs0NaQQl+xYnUAcq4oHUBsF2+p4MgKWG4YMmFYJU8A6sxRPuowllm6w== + dependencies: + "@babel/core" "^7.26.10" + "@babel/plugin-transform-react-jsx-self" "^7.25.9" + "@babel/plugin-transform-react-jsx-source" "^7.25.9" + "@types/babel__core" "^7.20.5" + react-refresh "^0.17.0" + +"@whatwg-node/events@^0.0.3": + version "0.0.3" + resolved "https://registry.yarnpkg.com/@whatwg-node/events/-/events-0.0.3.tgz#13a65dd4f5893f55280f766e29ae48074927acad" + integrity sha512-IqnKIDWfXBJkvy/k6tzskWTc2NK3LcqHlb+KHGCrjOCH4jfQckRX0NAiIcC/vIqQkzLYw2r2CTSwAxcrtcD6lA== + +"@whatwg-node/fetch@^0.8.1": + version "0.8.8" + resolved "https://registry.yarnpkg.com/@whatwg-node/fetch/-/fetch-0.8.8.tgz#48c6ad0c6b7951a73e812f09dd22d75e9fa18cae" + integrity sha512-CdcjGC2vdKhc13KKxgsc6/616BQ7ooDIgPeTuAiE8qfCnS0mGzcfCOoZXypQSz73nxI+GWc7ZReIAVhxoE1KCg== + dependencies: + "@peculiar/webcrypto" "^1.4.0" + "@whatwg-node/node-fetch" "^0.3.6" + busboy "^1.6.0" + urlpattern-polyfill "^8.0.0" + web-streams-polyfill "^3.2.1" + +"@whatwg-node/node-fetch@^0.3.6": + version "0.3.6" + resolved "https://registry.yarnpkg.com/@whatwg-node/node-fetch/-/node-fetch-0.3.6.tgz#e28816955f359916e2d830b68a64493124faa6d0" + integrity sha512-w9wKgDO4C95qnXZRwZTfCmLWqyRnooGjcIwG0wADWjw9/HN0p7dtvtgSvItZtUyNteEvgTrd8QojNEqV6DAGTA== + dependencies: + "@whatwg-node/events" "^0.0.3" + busboy "^1.6.0" + fast-querystring "^1.1.1" + fast-url-parser "^1.1.3" + tslib "^2.3.1" + +"@whatwg-node/server@0.6.7": + version "0.6.7" + resolved "https://registry.yarnpkg.com/@whatwg-node/server/-/server-0.6.7.tgz#14f5d0aca49308759d64fc7faa3cbfc20162a1ee" + integrity sha512-M4zHWdJ6M1IdcxnZBdDmiUh1bHQ4gPYRxzkH0gh8Qf6MpWJmX6I/MNftqem3GNn+qn1y47qqlGSed7T7nzsRFw== + dependencies: + "@whatwg-node/fetch" "^0.8.1" + tslib "^2.3.1" + acorn-walk@^8.1.1: version "8.3.4" resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.4.tgz#794dd169c3977edf4ba4ea47583587c5866236b7" @@ -794,6 +1894,11 @@ acorn@^8.11.0, acorn@^8.4.1: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.14.0.tgz#063e2c70cac5fb4f6467f0b11152e04c682795b0" integrity sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA== +acorn@^8.15.0: + version "8.15.0" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.15.0.tgz#a360898bc415edaac46c8241f6383975b930b816" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== + aggregate-error@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/aggregate-error/-/aggregate-error-3.1.0.tgz#92670ff50f5359bdb7a3e0d40d0ec30c5737687a" @@ -819,6 +1924,11 @@ ansi-regex@^5.0.1: resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== +ansi-regex@^6.0.1: + version "6.2.0" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-6.2.0.tgz#2f302e7550431b1b7762705fffb52cf1ffa20447" + integrity sha512-TKY5pyBkHyADOPYlRT9Lx6F544mPl0vS5Ew7BJ45hA08Q+t3GjbueLliBWN3sMICk6+y7HdyxSzC4bWS8baBdg== + ansi-styles@^4.0.0, ansi-styles@^4.1.0: version "4.3.0" resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" @@ -826,6 +1936,11 @@ ansi-styles@^4.0.0, ansi-styles@^4.1.0: dependencies: color-convert "^2.0.1" +ansi-styles@^6.1.0: + version "6.2.1" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-6.2.1.tgz#0e62320cf99c21afff3b3012192546aacbfb05c5" + integrity sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug== + anymatch@~3.1.2: version "3.1.3" resolved "https://registry.yarnpkg.com/anymatch/-/anymatch-3.1.3.tgz#790c58b19ba1720a84205b57c618d5ad8524973e" @@ -868,11 +1983,25 @@ arrify@^1.0.0: resolved "https://registry.yarnpkg.com/arrify/-/arrify-1.0.1.tgz#898508da2226f380df904728456849c1501a4b0d" integrity sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA== +asn1js@^3.0.5, asn1js@^3.0.6: + version "3.0.6" + resolved "https://registry.yarnpkg.com/asn1js/-/asn1js-3.0.6.tgz#53e002ebe00c5f7fd77c1c047c3557d7c04dce25" + integrity sha512-UOCGPYbl0tv8+006qks/dTgV9ajs97X2p0FAbyS2iyCRrmLSRolDaHdp+v/CLgnzHc3fVB+CwYiUmei7ndFcgA== + dependencies: + pvtsutils "^1.3.6" + pvutils "^1.1.3" + tslib "^2.8.1" + assertion-error@^1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== +assertion-error@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-2.0.1.tgz#f641a196b335690b1070bf00b6e7593fec190bf7" + integrity sha512-Izi8RQcffqCeNVgFigKli1ssklIbpHnCYc6AknXGYoB6grJqyeby7jv12JUQgmTAnIDnbck1uxksT4dzN3PWBA== + babel-plugin-istanbul@^6.0.0: version "6.1.1" resolved "https://registry.yarnpkg.com/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz#fa88ec59232fd9b4e36dbbc540a8ec9a9b47da73" @@ -909,7 +2038,7 @@ brace-expansion@^2.0.1: dependencies: balanced-match "^1.0.0" -braces@~3.0.2: +braces@^3.0.3, braces@~3.0.2: version "3.0.3" resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.3.tgz#490332f40919452272d55a8480adc0c441358789" integrity sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA== @@ -936,6 +2065,18 @@ buffer-from@^1.0.0, buffer-from@^1.1.0: resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== +busboy@^1.6.0: + version "1.6.0" + resolved "https://registry.yarnpkg.com/busboy/-/busboy-1.6.0.tgz#966ea36a9502e43cdb9146962523b92f531f6893" + integrity sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA== + dependencies: + streamsearch "^1.1.0" + +cac@^6.7.14: + version "6.7.14" + resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" + integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== + caching-transform@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/caching-transform/-/caching-transform-4.0.0.tgz#00d297a4206d71e2163c39eaffa8157ac0651f0f" @@ -974,6 +2115,17 @@ chai@4.5.0: pathval "^1.1.1" type-detect "^4.1.0" +chai@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/chai/-/chai-5.2.0.tgz#1358ee106763624114addf84ab02697e411c9c05" + integrity sha512-mCuXncKXk5iCLhfhwTc0izo0gtEmpz5CtG2y8GiOINBlMVS6v8TMRc5TaLWKS6692m9+dVVfzgeVxR5UxWHTYw== + dependencies: + assertion-error "^2.0.1" + check-error "^2.1.1" + deep-eql "^5.0.1" + loupe "^3.1.0" + pathval "^2.0.0" + chalk@^4.1.0: version "4.1.2" resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" @@ -982,6 +2134,21 @@ chalk@^4.1.0: ansi-styles "^4.1.0" supports-color "^7.1.0" +character-entities-legacy@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-entities-legacy/-/character-entities-legacy-1.1.4.tgz#94bc1845dce70a5bb9d2ecc748725661293d8fc1" + integrity sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA== + +character-entities@^1.0.0: + version "1.2.4" + resolved "https://registry.yarnpkg.com/character-entities/-/character-entities-1.2.4.tgz#e12c3939b7eaf4e5b15e7ad4c5e28e1d48c5b16b" + integrity sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw== + +character-reference-invalid@^1.0.0: + version "1.1.4" + resolved "https://registry.yarnpkg.com/character-reference-invalid/-/character-reference-invalid-1.1.4.tgz#083329cda0eae272ab3dbbf37e9a382c13af1560" + integrity sha512-mKKUkUbhPpQlCOfIuZkvSEgktjPFIsZKRRbC6KWVEMvlzblj3i3asQv5ODsrwt0N3pHAEvjP8KTQPHkp0+6jOg== + chardet@^0.7.0: version "0.7.0" resolved "https://registry.yarnpkg.com/chardet/-/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e" @@ -994,7 +2161,12 @@ check-error@^1.0.3: dependencies: get-func-name "^2.0.2" -chokidar@^3.5.3: +check-error@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-2.1.1.tgz#87eb876ae71ee388fa0471fe423f494be1d96ccc" + integrity sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw== + +chokidar@^3.5.3, chokidar@^3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-3.6.0.tgz#197c6cc669ef2a8dc5e7b4d97ee4e092c3eb0d5b" integrity sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw== @@ -1009,6 +2181,18 @@ chokidar@^3.5.3: optionalDependencies: fsevents "~2.3.2" +chokidar@^4.0.1: + version "4.0.3" + resolved "https://registry.yarnpkg.com/chokidar/-/chokidar-4.0.3.tgz#7be37a4c03c9aee1ecfe862a4a23b2c70c205d30" + integrity sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA== + dependencies: + readdirp "^4.0.1" + +chownr@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/chownr/-/chownr-3.0.0.tgz#9855e64ecd240a9cc4267ce8a4aa5d24a1da15e4" + integrity sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g== + clean-stack@^2.0.0: version "2.2.0" resolved "https://registry.yarnpkg.com/clean-stack/-/clean-stack-2.2.0.tgz#ee8472dbb129e727b31e8a10a427dee9dfe4008b" @@ -1037,11 +2221,38 @@ cliui@^7.0.2: strip-ansi "^6.0.0" wrap-ansi "^7.0.0" +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +clsx@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/clsx/-/clsx-2.1.1.tgz#eed397c9fd8bd882bfb18deab7102049a2f32999" + integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== + code-block-writer@^13.0.3: version "13.0.3" resolved "https://registry.yarnpkg.com/code-block-writer/-/code-block-writer-13.0.3.tgz#90f8a84763a5012da7af61319dd638655ae90b5b" integrity sha512-Oofo0pq3IKnsFtuHqSF7TqBfr71aeyZDVJ0HpmqB7FBM2qEigL0iPONSCZSO9pE9dZTAxANe5XHG9Uy0YMv8cg== +codemirror@6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/codemirror/-/codemirror-6.0.1.tgz#62b91142d45904547ee3e0e0e4c1a79158035a29" + integrity sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg== + dependencies: + "@codemirror/autocomplete" "^6.0.0" + "@codemirror/commands" "^6.0.0" + "@codemirror/language" "^6.0.0" + "@codemirror/lint" "^6.0.0" + "@codemirror/search" "^6.0.0" + "@codemirror/state" "^6.0.0" + "@codemirror/view" "^6.0.0" + color-convert@^2.0.1: version "2.0.1" resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" @@ -1054,6 +2265,16 @@ color-name@~1.1.4: resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== +colorette@^2.0.20: + version "2.0.20" + resolved "https://registry.yarnpkg.com/colorette/-/colorette-2.0.20.tgz#9eb793e6833067f7235902fcd3b09917a000a95a" + integrity sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w== + +comma-separated-tokens@^1.0.0: + version "1.0.8" + resolved "https://registry.yarnpkg.com/comma-separated-tokens/-/comma-separated-tokens-1.0.8.tgz#632b80b6117867a158f1080ad498b2fbe7e3f5ea" + integrity sha512-GHuDRO12Sypu2cV70d1dkA2EUmXHgntrzbpvOB+Qy+49ypNfGgFQIC2fhhXbnyrJRynDCAARsT7Ou0M6hirpfw== + commondir@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/commondir/-/commondir-1.0.1.tgz#ddd800da0c66127393cca5950ea968a3aaf1253b" @@ -1064,6 +2285,21 @@ concat-map@0.0.1: resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== +confbox@^0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.1.8.tgz#820d73d3b3c82d9bd910652c5d4d599ef8ff8b06" + integrity sha512-RMtmw0iFkeR4YV+fUOSucriAQNb9g8zFR52MWCtl+cCZOFRNL6zeB395vPzFhEjjn4fMxXudmELnl/KF/WrK6w== + +confbox@^0.2.2: + version "0.2.2" + resolved "https://registry.yarnpkg.com/confbox/-/confbox-0.2.2.tgz#8652f53961c74d9e081784beed78555974a9c110" + integrity sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ== + +consola@^3.4.0: + version "3.4.2" + resolved "https://registry.yarnpkg.com/consola/-/consola-3.4.2.tgz#5af110145397bb67afdab77013fdc34cae590ea7" + integrity sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA== + convert-source-map@^1.7.0: version "1.9.0" resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-1.9.0.tgz#7faae62353fb4213366d0ca98358d22e8368b05f" @@ -1074,12 +2310,22 @@ convert-source-map@^2.0.0: resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== +cookie@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-1.0.2.tgz#27360701532116bd3f1f9416929d176afe1e4610" + integrity sha512-9Kr/j4O16ISv8zBBhJoi4bXOYNTkFLOqSL3UDB0njXxCXNezjeyVrJyGOWtgfs/q2km1gwBcfH8q1yEGoMYunA== + create-require@^1.1.0: version "1.1.1" resolved "https://registry.yarnpkg.com/create-require/-/create-require-1.1.1.tgz#c1d7e8f1e5f6cfc9ff65f9cd352d37348756c333" integrity sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ== -cross-spawn@^7.0.0, cross-spawn@^7.0.3: +crelt@^1.0.5, crelt@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/crelt/-/crelt-1.0.6.tgz#7cc898ea74e190fb6ef9dae57f8f81cf7302df72" + integrity sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g== + +cross-spawn@^7.0.0, cross-spawn@^7.0.3, cross-spawn@^7.0.6: version "7.0.6" resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.6.tgz#8a58fe78f00dcd70c370451759dfbfaf03e8ee9f" integrity sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA== @@ -1088,6 +2334,19 @@ cross-spawn@^7.0.0, cross-spawn@^7.0.3: shebang-command "^2.0.0" which "^2.0.1" +css-tree@^3.1.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/css-tree/-/css-tree-3.1.0.tgz#7aabc035f4e66b5c86f54570d55e05b1346eb0fd" + integrity sha512-0eW44TGN5SQXU1mWSkKwFstI/22X2bG1nYzZTYMAWjylYURhse752YgbE4Cx46AC+bAvI+/dYTPRk1LqSUnu6w== + dependencies: + mdn-data "2.12.2" + source-map-js "^1.0.1" + +csstype@^3.0.2: + version "3.1.3" + resolved "https://registry.yarnpkg.com/csstype/-/csstype-3.1.3.tgz#d80ff294d114fb0e6ac500fbf85b60137d7eff81" + integrity sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw== + debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.5: version "4.4.0" resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.0.tgz#2b3f2aea2ffeb776477460267377dc8710faba8a" @@ -1095,6 +2354,13 @@ debug@^4.1.0, debug@^4.1.1, debug@^4.3.1, debug@^4.3.5: dependencies: ms "^2.1.3" +debug@^4.4.0: + version "4.4.1" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.4.1.tgz#e5a8bc6cbc4c6cd3e64308b0693a3d4fa550189b" + integrity sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ== + dependencies: + ms "^2.1.3" + decamelize@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/decamelize/-/decamelize-1.2.0.tgz#f6534d15148269b20352e7bee26f501f9a191290" @@ -1112,6 +2378,11 @@ deep-eql@^4.1.3: dependencies: type-detect "^4.0.0" +deep-eql@^5.0.1: + version "5.0.2" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-5.0.2.tgz#4b756d8d770a9257300825d52a2c2cff99c3a341" + integrity sha512-h5k/5U50IJJFpzfL6nO9jaaumfjO/f2NjK/oYB2Djzm4p9L+3T9qWpZqZ2hAbLPuuYq9wrU08WQyBTL5GbPk5Q== + deep-equal-in-any-order@1.1.20: version "1.1.20" resolved "https://registry.yarnpkg.com/deep-equal-in-any-order/-/deep-equal-in-any-order-1.1.20.tgz#04328876a10864cc2af1325186a970aa5a845486" @@ -1127,6 +2398,21 @@ default-require-extensions@^3.0.0: dependencies: strip-bom "^4.0.0" +defu@^6.1.4: + version "6.1.4" + resolved "https://registry.yarnpkg.com/defu/-/defu-6.1.4.tgz#4e0c9cf9ff68fe5f3d7f2765cc1a012dfdcb0479" + integrity sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg== + +destr@^2.0.3: + version "2.0.5" + resolved "https://registry.yarnpkg.com/destr/-/destr-2.0.5.tgz#7d112ff1b925fb8d2079fac5bdb4a90973b51fdb" + integrity sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA== + +detect-libc@^2.0.3, detect-libc@^2.0.4: + version "2.0.4" + resolved "https://registry.yarnpkg.com/detect-libc/-/detect-libc-2.0.4.tgz#f04715b8ba815e53b4d8109655b6508a6865a7e8" + integrity sha512-3UDv+G9CsCKO1WKMGw9fwq/SWJYbI0c5Y7LU1AXYoDdbhE2AHQ6N6Nb34sG8Fj7T5APy8qXDCKuuIHd1BR0tVA== + diff@^3.1.0: version "3.5.0" resolved "https://registry.yarnpkg.com/diff/-/diff-3.5.0.tgz#800c0dd1e0a8bfbc95835c202ad220fe317e5a12" @@ -1142,6 +2428,36 @@ diff@^5.2.0: resolved "https://registry.yarnpkg.com/diff/-/diff-5.2.0.tgz#26ded047cd1179b78b9537d5ef725503ce1ae531" integrity sha512-uIFDxqpRZGZ6ThOk84hEfqWoHx2devRFvpTZcTHur85vImfaxUbTW9Ryh4CpCuDnToOP1CEtXKIgytHBPVff5A== +dotenv-cli@8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/dotenv-cli/-/dotenv-cli-8.0.0.tgz#cea1519f5a06c7372a1428fca4605fcf3d50e1cf" + integrity sha512-aLqYbK7xKOiTMIRf1lDPbI+Y+Ip/wo5k3eyp6ePysVaSqbyxjyK3dK35BTxG+rmd7djf5q2UPs4noPNH+cj0Qw== + dependencies: + cross-spawn "^7.0.6" + dotenv "^16.3.0" + dotenv-expand "^10.0.0" + minimist "^1.2.6" + +dotenv-expand@^10.0.0: + version "10.0.0" + resolved "https://registry.yarnpkg.com/dotenv-expand/-/dotenv-expand-10.0.0.tgz#12605d00fb0af6d0a592e6558585784032e4ef37" + integrity sha512-GopVGCpVS1UKH75VKHGuQFqS1Gusej0z4FyQkPdwjil2gNIv+LNsqBlboOzpJFZKVT95GkCyWJbBSdFEFUWI2A== + +dotenv@^16.3.0: + version "16.6.1" + resolved "https://registry.yarnpkg.com/dotenv/-/dotenv-16.6.1.tgz#773f0e69527a8315c7285d5ee73c4459d20a8020" + integrity sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow== + +duplexer@^0.1.2: + version "0.1.2" + resolved "https://registry.yarnpkg.com/duplexer/-/duplexer-0.1.2.tgz#3abe43aef3835f8ae077d136ddce0f276b0400e6" + integrity sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg== + +eastasianwidth@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/eastasianwidth/-/eastasianwidth-0.2.0.tgz#696ce2ec0aa0e6ea93a397ffcf24aa7840c827cb" + integrity sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA== + electron-to-chromium@^1.5.73: version "1.5.92" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.92.tgz#81e8ebe06f8e2a49fdba84bd10e9ad5b63efffe0" @@ -1152,11 +2468,56 @@ emoji-regex@^8.0.0: resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== +emoji-regex@^9.2.2: + version "9.2.2" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-9.2.2.tgz#840c8803b0d8047f4ff0cf963176b32d4ef3ed72" + integrity sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg== + +enhanced-resolve@^5.18.3: + version "5.18.3" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.18.3.tgz#9b5f4c5c076b8787c78fe540392ce76a88855b44" + integrity sha512-d4lC8xfavMeBjzGr2vECC3fsGXziXZQyJxD868h2M/mBI3PwAuODxAkLkq5HYuvrPYcUtiLzsTo8U3PgX3Ocww== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + es6-error@^4.0.1: version "4.1.1" resolved "https://registry.yarnpkg.com/es6-error/-/es6-error-4.1.1.tgz#9e3af407459deed47e9a91f9b885a84eb05c561d" integrity sha512-Um/+FxMr9CISWh0bi5Zv0iOD+4cFh5qLeks1qhAopKVAJw3drgKbKySikp7wGhDL0HPeaja0P5ULZrxLkniUVg== +esbuild@^0.25.0: + version "0.25.9" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.9.tgz#15ab8e39ae6cdc64c24ff8a2c0aef5b3fd9fa976" + integrity sha512-CRbODhYyQx3qp7ZEwzxOk4JBqmD/seJrzPa/cGjY1VtIn5E09Oi9/dB4JwctnfZ8Q8iT7rioVv5k/FNT/uf54g== + optionalDependencies: + "@esbuild/aix-ppc64" "0.25.9" + "@esbuild/android-arm" "0.25.9" + "@esbuild/android-arm64" "0.25.9" + "@esbuild/android-x64" "0.25.9" + "@esbuild/darwin-arm64" "0.25.9" + "@esbuild/darwin-x64" "0.25.9" + "@esbuild/freebsd-arm64" "0.25.9" + "@esbuild/freebsd-x64" "0.25.9" + "@esbuild/linux-arm" "0.25.9" + "@esbuild/linux-arm64" "0.25.9" + "@esbuild/linux-ia32" "0.25.9" + "@esbuild/linux-loong64" "0.25.9" + "@esbuild/linux-mips64el" "0.25.9" + "@esbuild/linux-ppc64" "0.25.9" + "@esbuild/linux-riscv64" "0.25.9" + "@esbuild/linux-s390x" "0.25.9" + "@esbuild/linux-x64" "0.25.9" + "@esbuild/netbsd-arm64" "0.25.9" + "@esbuild/netbsd-x64" "0.25.9" + "@esbuild/openbsd-arm64" "0.25.9" + "@esbuild/openbsd-x64" "0.25.9" + "@esbuild/openharmony-arm64" "0.25.9" + "@esbuild/sunos-x64" "0.25.9" + "@esbuild/win32-arm64" "0.25.9" + "@esbuild/win32-ia32" "0.25.9" + "@esbuild/win32-x64" "0.25.9" + esbuild@~0.25.0: version "0.25.2" resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.25.2.tgz#55a1d9ebcb3aa2f95e8bba9e900c1a5061bc168b" @@ -1203,6 +2564,11 @@ esprima@^4.0.0: resolved "https://registry.yarnpkg.com/esprima/-/esprima-4.0.1.tgz#13b04cdb3e6c5d19df91ab6987a8695619b0aa71" integrity sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A== +exsolve@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/exsolve/-/exsolve-1.0.7.tgz#3b74e4c7ca5c5f9a19c3626ca857309fa99f9e9e" + integrity sha512-VO5fQUzZtI6C+vx4w/4BWJpg3s/5l+6pRQEHzFRM8WFi4XffSP1Z+4qi7GbjWbvRQEbdIco5mIMq+zX4rPuLrw== + external-editor@^3.1.0: version "3.1.0" resolved "https://registry.yarnpkg.com/external-editor/-/external-editor-3.1.0.tgz#cb03f740befae03ea4d283caed2741a83f335495" @@ -1212,11 +2578,60 @@ external-editor@^3.1.0: iconv-lite "^0.4.24" tmp "^0.0.33" +fast-decode-uri-component@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/fast-decode-uri-component/-/fast-decode-uri-component-1.0.1.tgz#46f8b6c22b30ff7a81357d4f59abfae938202543" + integrity sha512-WKgKWg5eUxvRZGwW8FvfbaH7AXSh2cL+3j5fMGzUMCxWBJ3dV3a7Wz8y2f/uQ0e3B6WmodD3oS54jTQ9HVTIIg== + +fast-glob@3.3.3, fast-glob@^3.3.2: + version "3.3.3" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.3.tgz#d06d585ce8dba90a16b0505c543c3ccfb3aeb818" + integrity sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg== + dependencies: + "@nodelib/fs.stat" "^2.0.2" + "@nodelib/fs.walk" "^1.2.3" + glob-parent "^5.1.2" + merge2 "^1.3.0" + micromatch "^4.0.8" + +fast-querystring@^1.1.1: + version "1.1.2" + resolved "https://registry.yarnpkg.com/fast-querystring/-/fast-querystring-1.1.2.tgz#a6d24937b4fc6f791b4ee31dcb6f53aeafb89f53" + integrity sha512-g6KuKWmFXc0fID8WWH0jit4g0AGBoJhCkJMb1RmbsSEUNvQ+ZC8D6CUZ+GtF8nMzSPXnhiePyyqqipzNNEnHjg== + dependencies: + fast-decode-uri-component "^1.0.1" + +fast-url-parser@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/fast-url-parser/-/fast-url-parser-1.1.3.tgz#f4af3ea9f34d8a271cf58ad2b3759f431f0b318d" + integrity sha512-5jOCVXADYNuRkKFzNJ0dCCewsZiYo0dz8QNYljkOpFC6r2U4OBmKtvm/Tsuh4w1YYdDqDb31a8TVhBJ2OJKdqQ== + dependencies: + punycode "^1.3.2" + +fastq@^1.6.0: + version "1.19.1" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.19.1.tgz#d50eaba803c8846a883c16492821ebcd2cda55f5" + integrity sha512-GwLTyxkCXjXbxqIhTsMI2Nui8huMPtnxg7krajPJAjnEG/iiOS7i+zCtWGZR9G0NBKbXKh6X9m9UIsYX/N6vvQ== + dependencies: + reusify "^1.0.4" + +fault@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/fault/-/fault-1.0.4.tgz#eafcfc0a6d214fc94601e170df29954a4f842f13" + integrity sha512-CJ0HCB5tL5fYTEA7ToAq5+kTwd++Borf1/bifxd9iT70QcXr4MRrO3Llf8Ifs70q+SJcGHFtnIE/Nw6giCtECA== + dependencies: + format "^0.2.0" + fdir@^6.4.2: version "6.4.3" resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.4.3.tgz#011cdacf837eca9b811c89dbb902df714273db72" integrity sha512-PMXmW2y1hDDfTSRc9gaXIuCCRpuoz3Kaz8cUelp3smouvfT632ozg2vrT6lJsHKKOF59YLbOGfAWGUcKEfRMQw== +fdir@^6.4.3, fdir@^6.4.4: + version "6.5.0" + resolved "https://registry.yarnpkg.com/fdir/-/fdir-6.5.0.tgz#ed2ab967a331ade62f18d077dae192684d50d350" + integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== + fill-range@^7.1.1: version "7.1.1" resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.1.1.tgz#44265d3cac07e3ea7dc247516380643754a05292" @@ -1262,6 +2677,14 @@ foreground-child@^2.0.0: cross-spawn "^7.0.0" signal-exit "^3.0.2" +foreground-child@^3.1.0: + version "3.3.1" + resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.1.tgz#32e8e9ed1b68a3497befb9ac2b6adf92a638576f" + integrity sha512-gIXjKqtFuWEgzFRJA9WCQeSJLZDjgJUOMCMzxtvFq/37KojM1BFGufqsCy0r4qSQmYLsZYMeyRqzIWOMup03sw== + dependencies: + cross-spawn "^7.0.6" + signal-exit "^4.0.1" + foreground-child@^3.3.0: version "3.3.0" resolved "https://registry.yarnpkg.com/foreground-child/-/foreground-child-3.3.0.tgz#0ac8644c06e431439f8561db8ecf29a7b5519c77" @@ -1270,11 +2693,27 @@ foreground-child@^3.3.0: cross-spawn "^7.0.0" signal-exit "^4.0.1" +format@^0.2.0: + version "0.2.2" + resolved "https://registry.yarnpkg.com/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" + integrity sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww== + fromentries@^1.2.0: version "1.3.2" resolved "https://registry.yarnpkg.com/fromentries/-/fromentries-1.3.2.tgz#e4bca6808816bf8f93b52750f1127f5a6fd86e3a" integrity sha512-cHEpEQHUg0f8XdtZCc2ZAhrHzKzT0MrFUTcvx+hfxYu7rGMDc5SKoXFh+n4YigxsHXRzc6OrCshdR1bWH6HHyg== +frui@0.1.8: + version "0.1.8" + resolved "https://registry.yarnpkg.com/frui/-/frui-0.1.8.tgz#b04f534f0b6b0f942054388031b8fc3b8418f144" + integrity sha512-gz09LCW8xTeN4eMHI+zYOm3yByWq+NNVZ9naL1G0mSaEj2po3pnQFK5EZzNq+gJDzDcBnf0/BNrRAJMG9xBKIA== + dependencies: + codemirror "6.0.1" + inputmask "5.0.9" + markdown-to-jsx "7.7.4" + moment "2.30.1" + react-syntax-highlighter "15.6.1" + fs.realpath@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" @@ -1285,6 +2724,11 @@ fsevents@~2.3.2, fsevents@~2.3.3: resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== +fuse.js@^7.1.0: + version "7.1.0" + resolved "https://registry.yarnpkg.com/fuse.js/-/fuse.js-7.1.0.tgz#306228b4befeee11e05b027087c2744158527d09" + integrity sha512-trLf4SzuuUxfusZADLINj+dE8clK1frKdmqiJNb1Es75fmI5oY6X2mxLVUciLLjxqw/xr72Dhy+lER6dGd02FQ== + gensync@^1.0.0-beta.2: version "1.0.0-beta.2" resolved "https://registry.yarnpkg.com/gensync/-/gensync-1.0.0-beta.2.tgz#32a6ee76c3d7f52d46b2b1ae5d93fea8580a25e0" @@ -1312,13 +2756,25 @@ get-tsconfig@^4.7.5: dependencies: resolve-pkg-maps "^1.0.0" -glob-parent@~5.1.2: +glob-parent@^5.1.2, glob-parent@~5.1.2: version "5.1.2" resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== dependencies: is-glob "^4.0.1" +glob@^10.4.5: + version "10.4.5" + resolved "https://registry.yarnpkg.com/glob/-/glob-10.4.5.tgz#f4d9f0b90ffdbab09c9d77f5f29b4262517b0956" + integrity sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg== + dependencies: + foreground-child "^3.1.0" + jackspeak "^3.1.2" + minimatch "^9.0.4" + minipass "^7.1.2" + package-json-from-dist "^1.0.0" + path-scurry "^1.11.1" + glob@^7.1.3, glob@^7.1.4, glob@^7.1.6: version "7.2.3" resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" @@ -1347,11 +2803,23 @@ globals@^11.1.0: resolved "https://registry.yarnpkg.com/globals/-/globals-11.12.0.tgz#ab8795338868a0babd8525758018c2a7eb95c42e" integrity sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA== -graceful-fs@^4.1.15: +globals@^15.14.0: + version "15.15.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-15.15.0.tgz#7c4761299d41c32b075715a4ce1ede7897ff72a8" + integrity sha512-7ACyT3wmyp3I61S4fG682L0VA2RGD9otkqGJIwNUMF1SWUombIIk+af1unuDYgMm082aHYwD+mzJvv9Iu8dsgg== + +graceful-fs@^4.1.15, graceful-fs@^4.2.4: version "4.2.11" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== +gzip-size@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/gzip-size/-/gzip-size-6.0.0.tgz#065367fd50c239c0671cbcbad5be3e2eeb10e462" + integrity sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q== + dependencies: + duplexer "^0.1.2" + has-flag@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" @@ -1365,11 +2833,37 @@ hasha@^5.0.0: is-stream "^2.0.0" type-fest "^0.8.0" +hast-util-parse-selector@^2.0.0: + version "2.2.5" + resolved "https://registry.yarnpkg.com/hast-util-parse-selector/-/hast-util-parse-selector-2.2.5.tgz#d57c23f4da16ae3c63b3b6ca4616683313499c3a" + integrity sha512-7j6mrk/qqkSehsM92wQjdIgWM2/BW61u/53G6xmC8i1OmEdKLHbk419QKQUjz6LglWsfqoiHmyMRkP1BGjecNQ== + +hastscript@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/hastscript/-/hastscript-6.0.0.tgz#e8768d7eac56c3fdeac8a92830d58e811e5bf640" + integrity sha512-nDM6bvd7lIqDUiYEiu5Sl/+6ReP0BMk/2f4U/Rooccxkj0P5nm+acM5PrGJ/t5I8qPGiqZSE6hVAwZEdZIvP4w== + dependencies: + "@types/hast" "^2.0.0" + comma-separated-tokens "^1.0.0" + hast-util-parse-selector "^2.0.0" + property-information "^5.0.0" + space-separated-tokens "^1.0.0" + he@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== +highlight.js@^10.4.1, highlight.js@~10.7.0: + version "10.7.3" + resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" + integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== + +highlightjs-vue@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/highlightjs-vue/-/highlightjs-vue-1.0.0.tgz#fdfe97fbea6354e70ee44e3a955875e114db086d" + integrity sha512-PDEfEF102G23vHmPhLyPboFCD+BkMGu+GuJe2d9/eH4FsCwvgBpnc9n0pGE+ffKdph38s6foEZiEjdgHdzp+IA== + html-escaper@^2.0.0: version "2.0.2" resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" @@ -1405,6 +2899,24 @@ inherits@2: resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== +inputmask@5.0.9: + version "5.0.9" + resolved "https://registry.yarnpkg.com/inputmask/-/inputmask-5.0.9.tgz#7bf4e83f5e199c88c0edf28545dc23fa208ef4be" + integrity sha512-s0lUfqcEbel+EQXtehXqwCJGShutgieOaIImFKC/r4reYNvX3foyrChl6LOEvaEgxEbesePIrw1Zi2jhZaDZbQ== + +is-alphabetical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphabetical/-/is-alphabetical-1.0.4.tgz#9e7d6b94916be22153745d184c298cbf986a686d" + integrity sha512-DwzsA04LQ10FHTZuL0/grVDk4rFoVH1pjAToYwBrHSxcrBIGQuXrQMtD5U1b0U2XVgKZCTLLP8u2Qxqhy3l2Vg== + +is-alphanumerical@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-alphanumerical/-/is-alphanumerical-1.0.4.tgz#7eb9a2431f855f6b1ef1a78e326df515696c4dbf" + integrity sha512-UzoZUr+XfVz3t3v4KyGEniVL9BDRoQtY7tOyrRybkVNjDFWyo1yhXNGrrBTQxp3ib9BLAWs7k2YKBQsFRkZG9A== + dependencies: + is-alphabetical "^1.0.0" + is-decimal "^1.0.0" + is-binary-path@~2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/is-binary-path/-/is-binary-path-2.1.0.tgz#ea1f7f3b80f064236e83470f86c09c254fb45b09" @@ -1412,6 +2924,11 @@ is-binary-path@~2.1.0: dependencies: binary-extensions "^2.0.0" +is-decimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-decimal/-/is-decimal-1.0.4.tgz#65a3a5958a1c5b63a706e1b333d7cd9f630d3fa5" + integrity sha512-RGdriMmQQvZ2aqaQq3awNA6dCGtKpiDFcOzrTWrDAT2MiWrKQVPmxLGHl7Y2nNu6led0kEyoX0enY0qXYsv9zw== + is-extglob@^2.1.1: version "2.1.1" resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" @@ -1429,6 +2946,11 @@ is-glob@^4.0.1, is-glob@~4.0.1: dependencies: is-extglob "^2.1.1" +is-hexadecimal@^1.0.0: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-hexadecimal/-/is-hexadecimal-1.0.4.tgz#cc35c97588da4bd49a8eedd6bc4082d44dcb23a7" + integrity sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw== + is-number@^7.0.0: version "7.0.0" resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" @@ -1536,6 +3058,25 @@ istanbul-reports@^3.0.2: html-escaper "^2.0.0" istanbul-lib-report "^3.0.0" +jackspeak@^3.1.2: + version "3.4.3" + resolved "https://registry.yarnpkg.com/jackspeak/-/jackspeak-3.4.3.tgz#8833a9d89ab4acde6188942bd1c53b6390ed5a8a" + integrity sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw== + dependencies: + "@isaacs/cliui" "^8.0.2" + optionalDependencies: + "@pkgjs/parseargs" "^0.11.0" + +jiti@^2.4.2, jiti@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/jiti/-/jiti-2.5.1.tgz#bd099c1c2be1c59bbea4e5adcd127363446759d0" + integrity sha512-twQoecYPiVA5K/h6SxtORw/Bs3ar+mLUtoPSc7iMXzQzK8d7eJ/R09wmTwAjiamETn1cXYPGfNnu7DMoHgu12w== + +jose@6.0.10: + version "6.0.10" + resolved "https://registry.yarnpkg.com/jose/-/jose-6.0.10.tgz#52d96e1a671b4c02e13b71e0d35abea2e774712b" + integrity sha512-skIAxZqcMkOrSwjJvplIPYrlXGpxTPnro2/QWTDCxAdWQrSTV5/KqspMWmi5WAx5+ULswASJiZ0a+1B/Lxt9cw== + js-tokens@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/js-tokens/-/js-tokens-4.0.0.tgz#19203fb59991df98e3a287050d4647cdeaf32499" @@ -1573,6 +3114,88 @@ json5@^2.2.3: resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.3.tgz#78cd6f1a19bdc12b73db5ad0c61efd66c1e29283" integrity sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg== +kolorist@^1.8.0: + version "1.8.0" + resolved "https://registry.yarnpkg.com/kolorist/-/kolorist-1.8.0.tgz#edddbbbc7894bc13302cdf740af6374d4a04743c" + integrity sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ== + +lightningcss-darwin-arm64@1.30.1: + version "1.30.1" + resolved "https://registry.yarnpkg.com/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz#3d47ce5e221b9567c703950edf2529ca4a3700ae" + integrity sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ== + +lightningcss-darwin-x64@1.30.1: + version "1.30.1" + resolved "https://registry.yarnpkg.com/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz#e81105d3fd6330860c15fe860f64d39cff5fbd22" + integrity sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA== + +lightningcss-freebsd-x64@1.30.1: + version "1.30.1" + resolved "https://registry.yarnpkg.com/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz#a0e732031083ff9d625c5db021d09eb085af8be4" + integrity sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig== + +lightningcss-linux-arm-gnueabihf@1.30.1: + version "1.30.1" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz#1f5ecca6095528ddb649f9304ba2560c72474908" + integrity sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q== + +lightningcss-linux-arm64-gnu@1.30.1: + version "1.30.1" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz#eee7799726103bffff1e88993df726f6911ec009" + integrity sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw== + +lightningcss-linux-arm64-musl@1.30.1: + version "1.30.1" + resolved "https://registry.yarnpkg.com/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz#f2e4b53f42892feeef8f620cbb889f7c064a7dfe" + integrity sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ== + +lightningcss-linux-x64-gnu@1.30.1: + version "1.30.1" + resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz#2fc7096224bc000ebb97eea94aea248c5b0eb157" + integrity sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw== + +lightningcss-linux-x64-musl@1.30.1: + version "1.30.1" + resolved "https://registry.yarnpkg.com/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz#66dca2b159fd819ea832c44895d07e5b31d75f26" + integrity sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ== + +lightningcss-win32-arm64-msvc@1.30.1: + version "1.30.1" + resolved "https://registry.yarnpkg.com/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz#7d8110a19d7c2d22bfdf2f2bb8be68e7d1b69039" + integrity sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA== + +lightningcss-win32-x64-msvc@1.30.1: + version "1.30.1" + resolved "https://registry.yarnpkg.com/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz#fd7dd008ea98494b85d24b4bea016793f2e0e352" + integrity sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg== + +lightningcss@1.30.1: + version "1.30.1" + resolved "https://registry.yarnpkg.com/lightningcss/-/lightningcss-1.30.1.tgz#78e979c2d595bfcb90d2a8c0eb632fe6c5bfed5d" + integrity sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg== + dependencies: + detect-libc "^2.0.3" + optionalDependencies: + lightningcss-darwin-arm64 "1.30.1" + lightningcss-darwin-x64 "1.30.1" + lightningcss-freebsd-x64 "1.30.1" + lightningcss-linux-arm-gnueabihf "1.30.1" + lightningcss-linux-arm64-gnu "1.30.1" + lightningcss-linux-arm64-musl "1.30.1" + lightningcss-linux-x64-gnu "1.30.1" + lightningcss-linux-x64-musl "1.30.1" + lightningcss-win32-arm64-msvc "1.30.1" + lightningcss-win32-x64-msvc "1.30.1" + +local-pkg@^1.0.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-1.1.2.tgz#c03d208787126445303f8161619dc701afa4abb5" + integrity sha512-arhlxbFRmoQHl33a0Zkle/YWlmNwoyt6QNZEIJcqNbdrsix5Lvc4HyyI3EnwxTYlZYc32EbYrQ8SzEZ7dqgg9A== + dependencies: + mlly "^1.7.4" + pkg-types "^2.3.0" + quansync "^0.2.11" + locate-path@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-5.0.0.tgz#1afba396afd676a6d42504d0a67a3a7eb9f62aa0" @@ -1617,6 +3240,24 @@ loupe@^2.3.6: dependencies: get-func-name "^2.0.1" +loupe@^3.1.0: + version "3.2.1" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-3.2.1.tgz#0095cf56dc5b7a9a7c08ff5b1a8796ec8ad17e76" + integrity sha512-CdzqowRJCeLU72bHvWqwRBBlLcMEtIvGrlvef74kMnV2AolS9Y8xUv1I0U/MNAWMhBlKIoyuEgoJ0t/bbwHbLQ== + +lowlight@^1.17.0: + version "1.20.0" + resolved "https://registry.yarnpkg.com/lowlight/-/lowlight-1.20.0.tgz#ddb197d33462ad0d93bf19d17b6c301aa3941888" + integrity sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw== + dependencies: + fault "^1.0.0" + highlight.js "~10.7.0" + +lru-cache@^10.2.0: + version "10.4.3" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-10.4.3.tgz#410fc8a17b70e598013df257c2446b7f3383f119" + integrity sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ== + lru-cache@^5.1.1: version "5.1.1" resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-5.1.1.tgz#1da27e6710271947695daf6848e847f01d84b920" @@ -1624,6 +3265,13 @@ lru-cache@^5.1.1: dependencies: yallist "^3.0.2" +magic-string@^0.30.17: + version "0.30.18" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.18.tgz#905bfbbc6aa5692703a93db26a9edcaa0007d2bb" + integrity sha512-yi8swmWbO17qHhwIBNeeZxTceJMeBvWJaId6dyvTSOwTipqeHhMhOrz6513r1sOKnpvQ7zkhlG8tPrpilwTxHQ== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.5" + make-dir@^3.0.0, make-dir@^3.0.2: version "3.1.0" resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" @@ -1643,6 +3291,29 @@ make-error@^1.1.1: resolved "https://registry.yarnpkg.com/make-error/-/make-error-1.3.6.tgz#2eb2e37ea9b67c4891f684a1394799af484cf7a2" integrity sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw== +markdown-to-jsx@7.7.4: + version "7.7.4" + resolved "https://registry.yarnpkg.com/markdown-to-jsx/-/markdown-to-jsx-7.7.4.tgz#507d17c15af72ddf970fca84a95f0243244fcfa9" + integrity sha512-1bSfXyBKi+EYS3YY+e0Csuxf8oZ3decdfhOav/Z7Wrk89tjudyL5FOmwZQUoy0/qVXGUl+6Q3s2SWtpDEWITfQ== + +mdn-data@2.12.2: + version "2.12.2" + resolved "https://registry.yarnpkg.com/mdn-data/-/mdn-data-2.12.2.tgz#9ae6c41a9e65adf61318b32bff7b64fbfb13f8cf" + integrity sha512-IEn+pegP1aManZuckezWCO+XZQDplx1366JoVhTpMpBB1sPey/SbveZQUosKiKiGYjg1wH4pMlNgXbCiYgihQA== + +merge2@^1.3.0: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.8.tgz#d66fa18f3a47076789320b9b1af32bd86d9fa202" + integrity sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA== + dependencies: + braces "^3.0.3" + picomatch "^2.3.1" + minimatch@^3.0.4, minimatch@^3.1.1: version "3.1.2" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" @@ -1669,6 +3340,18 @@ minimist@^1.2.0, minimist@^1.2.6: resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== +"minipass@^5.0.0 || ^6.0.2 || ^7.0.0", minipass@^7.0.4, minipass@^7.1.2: + version "7.1.2" + resolved "https://registry.yarnpkg.com/minipass/-/minipass-7.1.2.tgz#93a9626ce5e5e66bd4db86849e7515e92340a707" + integrity sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw== + +minizlib@^3.0.1: + version "3.0.2" + resolved "https://registry.yarnpkg.com/minizlib/-/minizlib-3.0.2.tgz#f33d638eb279f664439aa38dc5f91607468cb574" + integrity sha512-oG62iEk+CYt5Xj2YqI5Xi9xWUeZhDI8jjQmC5oThVH5JGCTgIjr7ciJDzC7MBzYd//WvR1OTmP5Q38Q8ShQtVA== + dependencies: + minipass "^7.1.2" + mkdirp@^0.5.1: version "0.5.6" resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-0.5.6.tgz#7def03d2432dcae4ba1d611445c48396062255f6" @@ -1676,6 +3359,21 @@ mkdirp@^0.5.1: dependencies: minimist "^1.2.6" +mkdirp@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-3.0.1.tgz#e44e4c5607fb279c168241713cc6e0fea9adcb50" + integrity sha512-+NsyUUAZDmo6YVHzL/stxSu3t9YS1iljliy3BSDrXJ/dkn1KYdmtZODGGjLcc9XLgVVpH4KshHB8XmZgMhaBXg== + +mlly@^1.7.4: + version "1.8.0" + resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.8.0.tgz#e074612b938af8eba1eaf43299cbc89cb72d824e" + integrity sha512-l8D9ODSRWLe2KHJSifWGwBqpTZXIXTeo8mlKjY+E2HAakaTeNpqAyBZ8GSqLzHgw4XmHmC8whvpjJNMbFZN7/g== + dependencies: + acorn "^8.15.0" + pathe "^2.0.3" + pkg-types "^1.3.1" + ufo "^1.6.1" + mocha@10.8.2: version "10.8.2" resolved "https://registry.yarnpkg.com/mocha/-/mocha-10.8.2.tgz#8d8342d016ed411b12a429eb731b825f961afb96" @@ -1702,16 +3400,72 @@ mocha@10.8.2: yargs-parser "^20.2.9" yargs-unparser "^2.0.0" +mocha@11.2.2: + version "11.2.2" + resolved "https://registry.yarnpkg.com/mocha/-/mocha-11.2.2.tgz#2dfefc9652de746389f5286888034239b6486231" + integrity sha512-VlSBxrPYHK4YNOEbFdkCxHQbZMoNzBkoPprqtZRW6311EUF/DlSxoycE2e/2NtRk4WKkIXzyrXDTrlikJMWgbw== + dependencies: + browser-stdout "^1.3.1" + chokidar "^4.0.1" + debug "^4.3.5" + diff "^5.2.0" + escape-string-regexp "^4.0.0" + find-up "^5.0.0" + glob "^10.4.5" + he "^1.2.0" + js-yaml "^4.1.0" + log-symbols "^4.1.0" + minimatch "^5.1.6" + ms "^2.1.3" + picocolors "^1.1.1" + serialize-javascript "^6.0.2" + strip-json-comments "^3.1.1" + supports-color "^8.1.1" + workerpool "^6.5.1" + yargs "^17.7.2" + yargs-parser "^21.1.1" + yargs-unparser "^2.0.0" + +moment@2.30.1: + version "2.30.1" + resolved "https://registry.yarnpkg.com/moment/-/moment-2.30.1.tgz#f8c91c07b7a786e30c59926df530b4eac96974ae" + integrity sha512-uEmtNhbDOrWPFS+hdjFCBfy9f2YoyzRpwcl+DqpC6taX21FzsTLQVbMV/W7PzNSX6x/bhC1zA3c2UQ5NzH6how== + +mrmime@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/mrmime/-/mrmime-2.0.1.tgz#bc3e87f7987853a54c9850eeb1f1078cd44adddc" + integrity sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ== + ms@^2.1.3: version "2.1.3" resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== +mustache@4.2.0: + version "4.2.0" + resolved "https://registry.yarnpkg.com/mustache/-/mustache-4.2.0.tgz#e5892324d60a12ec9c2a73359edca52972bf6f64" + integrity sha512-71ippSywq5Yb7/tVYyGbkBggbU8H3u5Rz56fH60jGFgr8uHwxs+aSKeqmluIVzM0m0kB7xQjKS6qPfd0b2ZoqQ== + mute-stream@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/mute-stream/-/mute-stream-2.0.0.tgz#a5446fc0c512b71c83c44d908d5c7b7b4c493b2b" integrity sha512-WWdIxpyjEn+FhQJQQv9aQAYlHoNVdzIzUySNV1gHUPDSdZJ3yZn7pAAbQcV7B56Mvu881q9FZV+0Vx2xC44VWA== +nanoid@3.3.8: + version "3.3.8" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.8.tgz#b1be3030bee36aaff18bacb375e5cce521684baf" + integrity sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w== + +nanoid@^3.3.11: + version "3.3.11" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.11.tgz#4f4f112cefbe303202f2199838128936266d185b" + integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== + +node-fetch-native@^1.6.4: + version "1.6.7" + resolved "https://registry.yarnpkg.com/node-fetch-native/-/node-fetch-native-1.6.7.tgz#9d09ca63066cc48423211ed4caf5d70075d76a71" + integrity sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q== + node-preload@^0.2.1: version "0.2.1" resolved "https://registry.yarnpkg.com/node-preload/-/node-preload-0.2.1.tgz#c03043bb327f417a18fee7ab7ee57b408a144301" @@ -1724,6 +3478,11 @@ node-releases@^2.0.19: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.19.tgz#9e445a52950951ec4d177d843af370b411caf314" integrity sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw== +nodemailer@6.9.16: + version "6.9.16" + resolved "https://registry.yarnpkg.com/nodemailer/-/nodemailer-6.9.16.tgz#3ebdf6c6f477c571c0facb0727b33892635e0b8b" + integrity sha512-psAuZdTIRN08HKVd/E8ObdV6NO7NTBY3KsC30F7M4H1OnmLCUNaS56FpYxyb26zWLSyYF9Ozch9KYHhHegsiOQ== + normalize-path@^3.0.0, normalize-path@~3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/normalize-path/-/normalize-path-3.0.0.tgz#0dcd69ff23a1c9b11fd0978316644a0388216a65" @@ -1762,6 +3521,15 @@ nyc@17.1.0: test-exclude "^6.0.0" yargs "^15.0.2" +ofetch@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/ofetch/-/ofetch-1.4.1.tgz#b6bf6b0d75ba616cef6519dd8b6385a8bae480ec" + integrity sha512-QZj2DfGplQAr2oj9KzceK9Hwz6Whxazmn85yYeVuS3u9XTMOGMRx0kO95MQ+vLsj/S/NwBDMMLU5hpxvI6Tklw== + dependencies: + destr "^2.0.3" + node-fetch-native "^1.6.4" + ufo "^1.5.4" + once@^1.3.0: version "1.4.0" resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" @@ -1824,6 +3592,33 @@ package-hash@^4.0.0: lodash.flattendeep "^4.4.0" release-zalgo "^1.0.0" +package-json-from-dist@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz#4f1471a010827a86f94cfd9b0727e36d267de505" + integrity sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw== + +package-manager-detector@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/package-manager-detector/-/package-manager-detector-1.3.0.tgz#b42d641c448826e03c2b354272456a771ce453c0" + integrity sha512-ZsEbbZORsyHuO00lY1kV3/t72yp6Ysay6Pd17ZAlNGuGwmWDLCJxFpRs0IzfXfj1o4icJOkUEioexFHzyPurSQ== + +papaparse@5.5.1: + version "5.5.1" + resolved "https://registry.yarnpkg.com/papaparse/-/papaparse-5.5.1.tgz#4322da01e85d8e9e282c1e4387793a5978b5a0a1" + integrity sha512-EuEKUhyxrHVozD7g3/ztsJn6qaKse8RPfR6buNB2dMJvdtXNhcw8jccVi/LxNEY3HVrV6GO6Z4OoeCG9Iy9wpA== + +parse-entities@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/parse-entities/-/parse-entities-2.0.0.tgz#53c6eb5b9314a1f4ec99fa0fdf7ce01ecda0cbe8" + integrity sha512-kkywGpCcRYhqQIchaWqZ875wzpS/bMKhz5HnN3p7wveJTkTtyAB/AlnS0f8DFSqYW1T82t6yEAkEcB+A1I3MbQ== + dependencies: + character-entities "^1.0.0" + character-entities-legacy "^1.0.0" + character-reference-invalid "^1.0.0" + is-alphanumerical "^1.0.0" + is-decimal "^1.0.0" + is-hexadecimal "^1.0.0" + path-browserify@^1.0.1: version "1.0.1" resolved "https://registry.yarnpkg.com/path-browserify/-/path-browserify-1.0.1.tgz#d98454a9c3753d5790860f16f68867b9e46be1fd" @@ -1844,17 +3639,40 @@ path-key@^3.1.0: resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== +path-scurry@^1.11.1: + version "1.11.1" + resolved "https://registry.yarnpkg.com/path-scurry/-/path-scurry-1.11.1.tgz#7960a668888594a0720b12a911d1a742ab9f11d2" + integrity sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA== + dependencies: + lru-cache "^10.2.0" + minipass "^5.0.0 || ^6.0.2 || ^7.0.0" + +pathe@^2.0.1, pathe@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-2.0.3.tgz#3ecbec55421685b70a9da872b2cff3e1cbed1716" + integrity sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w== + pathval@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== +pathval@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-2.0.1.tgz#8855c5a2899af072d6ac05d11e46045ad0dc605d" + integrity sha512-//nshmD55c46FuFw26xV/xFAaB5HF9Xdap7HJBBnrKdAd6/GxDBaNA1870O79+9ueg61cZLSVc+OaFlfmObYVQ== + +perfect-debounce@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/perfect-debounce/-/perfect-debounce-1.0.0.tgz#9c2e8bc30b169cc984a58b7d5b28049839591d2a" + integrity sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA== + picocolors@^1.0.0, picocolors@^1.1.1: version "1.1.1" resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.1.tgz#3d321af3eab939b083c8f929a1d12cda81c26b6b" integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== -picomatch@^2.0.4, picomatch@^2.2.1: +picomatch@^2.0.4, picomatch@^2.2.1, picomatch@^2.3.1: version "2.3.1" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== @@ -1864,6 +3682,11 @@ picomatch@^4.0.2: resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.2.tgz#77c742931e8f3b8820946c76cd0c1f13730d1dab" integrity sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg== +picomatch@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-4.0.3.tgz#796c76136d1eead715db1e7bad785dedd695a042" + integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== + pkg-dir@^4.1.0: version "4.2.0" resolved "https://registry.yarnpkg.com/pkg-dir/-/pkg-dir-4.2.0.tgz#f099133df7ede422e81d1d8448270eeb3e4261f3" @@ -1871,6 +3694,48 @@ pkg-dir@^4.1.0: dependencies: find-up "^4.0.0" +pkg-types@^1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.3.1.tgz#bd7cc70881192777eef5326c19deb46e890917df" + integrity sha512-/Jm5M4RvtBFVkKWRu2BLUTNP8/M2a+UwuAX+ae4770q1qVGtfjG+WTCupoZixokjmHiry8uI+dlY8KXYV5HVVQ== + dependencies: + confbox "^0.1.8" + mlly "^1.7.4" + pathe "^2.0.1" + +pkg-types@^2.3.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-2.3.0.tgz#037f2c19bd5402966ff6810e32706558cb5b5726" + integrity sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig== + dependencies: + confbox "^0.2.2" + exsolve "^1.0.7" + pathe "^2.0.3" + +postcss@^8.5.2, postcss@^8.5.3: + version "8.5.6" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.5.6.tgz#2825006615a619b4f62a9e7426cc120b349a8f3c" + integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg== + dependencies: + nanoid "^3.3.11" + picocolors "^1.1.1" + source-map-js "^1.2.1" + +prettier@3.5.3: + version "3.5.3" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.5.3.tgz#4fc2ce0d657e7a02e602549f053b239cb7dfe1b5" + integrity sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw== + +prismjs@^1.27.0: + version "1.30.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.30.0.tgz#d9709969d9d4e16403f6f348c63553b19f0975a9" + integrity sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw== + +prismjs@~1.27.0: + version "1.27.0" + resolved "https://registry.yarnpkg.com/prismjs/-/prismjs-1.27.0.tgz#bb6ee3138a0b438a3653dd4d6ce0cc6510a45057" + integrity sha512-t13BGPUlFDR7wRB5kQDG4jjl7XeuH6jbJGt11JHPL96qwsEHNX2+68tFXqc1/k+/jALsbSWJKUOT/hcYAZ5LkA== + process-on-spawn@^1.0.0: version "1.1.0" resolved "https://registry.yarnpkg.com/process-on-spawn/-/process-on-spawn-1.1.0.tgz#9d5999ba87b3bf0a8acb05322d69f2f5aa4fb763" @@ -1878,6 +3743,45 @@ process-on-spawn@^1.0.0: dependencies: fromentries "^1.2.0" +property-information@^5.0.0: + version "5.6.0" + resolved "https://registry.yarnpkg.com/property-information/-/property-information-5.6.0.tgz#61675545fb23002f245c6540ec46077d4da3ed69" + integrity sha512-YUHSPk+A30YPv+0Qf8i9Mbfe/C0hdPXk1s1jPVToV8pk8BQtpw10ct89Eo7OWkutrwqvT0eicAxlOg3dOAu8JA== + dependencies: + xtend "^4.0.0" + +punycode@^1.3.2: + version "1.4.1" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-1.4.1.tgz#c0d5a63b2718800ad8e1eb0fa5269c84dd41845e" + integrity sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ== + +pvtsutils@^1.3.5, pvtsutils@^1.3.6: + version "1.3.6" + resolved "https://registry.yarnpkg.com/pvtsutils/-/pvtsutils-1.3.6.tgz#ec46e34db7422b9e4fdc5490578c1883657d6001" + integrity sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg== + dependencies: + tslib "^2.8.1" + +pvutils@^1.1.3: + version "1.1.3" + resolved "https://registry.yarnpkg.com/pvutils/-/pvutils-1.1.3.tgz#f35fc1d27e7cd3dfbd39c0826d173e806a03f5a3" + integrity sha512-pMpnA0qRdFp32b1sJl1wOJNxZLQ2cbQx+k6tjNtZ8CpvVhNqEPRgivZ2WOUev2YMajecdH7ctUPDvEe87nariQ== + +quansync@^0.2.11: + version "0.2.11" + resolved "https://registry.yarnpkg.com/quansync/-/quansync-0.2.11.tgz#f9c3adda2e1272e4f8cf3f1457b04cbdb4ee692a" + integrity sha512-AifT7QEbW9Nri4tAwR5M/uzpBuqfZf+zwaEM/QkzEjj7NBuFD2rBuy0K3dE+8wltbezDV7JMA0WfnCPYRSYbXA== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +r22n@1.0.10: + version "1.0.10" + resolved "https://registry.yarnpkg.com/r22n/-/r22n-1.0.10.tgz#bab4b5888bcdb3f44d93ac076acfe6cec5ab102d" + integrity sha512-2jFDC6oCe5UhzL4s8iAMN+7FbAtaxK9SjzZ6HxYm8O7+zmxZsiSSqjZD7iFfsjJtJkPx760p7Nc6jTXjc+Yd2w== + randombytes@^2.1.0: version "2.1.0" resolved "https://registry.yarnpkg.com/randombytes/-/randombytes-2.1.0.tgz#df6f84372f0270dc65cdf6291349ab7a473d4f2a" @@ -1885,6 +3789,54 @@ randombytes@^2.1.0: dependencies: safe-buffer "^5.1.0" +react-dom@19.1.0: + version "19.1.0" + resolved "https://registry.yarnpkg.com/react-dom/-/react-dom-19.1.0.tgz#133558deca37fa1d682708df8904b25186793623" + integrity sha512-Xs1hdnE+DyKgeHJeJznQmYMIBG3TKIHJJT95Q58nHLSrElKlGQqDTR2HQ9fx5CN/Gk6Vh/kupBTDLU11/nDk/g== + dependencies: + scheduler "^0.26.0" + +react-refresh@^0.17.0: + version "0.17.0" + resolved "https://registry.yarnpkg.com/react-refresh/-/react-refresh-0.17.0.tgz#b7e579c3657f23d04eccbe4ad2e58a8ed51e7e53" + integrity sha512-z6F7K9bV85EfseRCp2bzrpyQ0Gkw1uLoCel9XBVWPg/TjRj94SkJzUTGfOa4bs7iJvBWtQG0Wq7wnI0syw3EBQ== + +react-syntax-highlighter@15.6.1: + version "15.6.1" + resolved "https://registry.yarnpkg.com/react-syntax-highlighter/-/react-syntax-highlighter-15.6.1.tgz#fa567cb0a9f96be7bbccf2c13a3c4b5657d9543e" + integrity sha512-OqJ2/vL7lEeV5zTJyG7kmARppUjiB9h9udl4qHQjjgEos66z00Ia0OckwYfRxCSFrW8RJIBnsBwQsHZbVPspqg== + dependencies: + "@babel/runtime" "^7.3.1" + highlight.js "^10.4.1" + highlightjs-vue "^1.0.0" + lowlight "^1.17.0" + prismjs "^1.27.0" + refractor "^3.6.0" + +react-toastify@11.0.5, react-toastify@^11.0.5: + version "11.0.5" + resolved "https://registry.yarnpkg.com/react-toastify/-/react-toastify-11.0.5.tgz#ce4c42d10eeb433988ab2264d3e445c4e9d13313" + integrity sha512-EpqHBGvnSTtHYhCPLxML05NLY2ZX0JURbAdNYa6BUkk+amz4wbKBQvoKQAB0ardvSarUBuY4Q4s1sluAzZwkmA== + dependencies: + clsx "^2.1.1" + +react@19.1.0: + version "19.1.0" + resolved "https://registry.yarnpkg.com/react/-/react-19.1.0.tgz#926864b6c48da7627f004795d6cce50e90793b75" + integrity sha512-FS+XFBNvn3GTAWq26joslQgWNoFu08F4kl0J4CgdNKADkdSGXQyTCnKteIAJy96Br6YbpEU1LSzV5dYtjMkMDg== + +reactus@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/reactus/-/reactus-0.6.1.tgz#fea94424481052ba298e511ad8f7e6e53dbff084" + integrity sha512-+NP6BJYMYrk79NkIvgd094ghxHQ4zTDCVFvuSBZJRePYpXEHNkoqjIGl+2IUGGbO+gVGGqNTfALZEnJ13pvh7A== + dependencies: + "@stackpress/lib" "0.6.1" + +readdirp@^4.0.1: + version "4.1.2" + resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-4.1.2.tgz#eb85801435fbf2a7ee58f19e0921b068fc69948d" + integrity sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg== + readdirp@~3.6.0: version "3.6.0" resolved "https://registry.yarnpkg.com/readdirp/-/readdirp-3.6.0.tgz#74a370bd857116e245b29cc97340cd431a02a6c7" @@ -1892,6 +3844,15 @@ readdirp@~3.6.0: dependencies: picomatch "^2.2.1" +refractor@^3.6.0: + version "3.6.0" + resolved "https://registry.yarnpkg.com/refractor/-/refractor-3.6.0.tgz#ac318f5a0715ead790fcfb0c71f4dd83d977935a" + integrity sha512-MY9W41IOWxxk31o+YvFCNyNzdkc9M20NoZK5vq6jkv4I/uh2zkWcfudj0Q1fovjUQJrNewS9NMzeTtqPf+n5EA== + dependencies: + hastscript "^6.0.0" + parse-entities "^2.0.0" + prismjs "~1.27.0" + release-zalgo@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/release-zalgo/-/release-zalgo-1.0.0.tgz#09700b7e5074329739330e535c5a90fb67851730" @@ -1919,6 +3880,11 @@ resolve-pkg-maps@^1.0.0: resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== +reusify@^1.0.4: + version "1.1.0" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.1.0.tgz#0fe13b9522e1473f51b558ee796e08f11f9b489f" + integrity sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw== + rimraf@^3.0.0: version "3.0.2" resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" @@ -1926,6 +3892,42 @@ rimraf@^3.0.0: dependencies: glob "^7.1.3" +rollup@^4.34.9: + version "4.49.0" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.49.0.tgz#9751ad9d06a47a4496c3c5c238b27b1422c8b0eb" + integrity sha512-3IVq0cGJ6H7fKXXEdVt+RcYvRCt8beYY9K1760wGQwSAHZcS9eot1zDG5axUbcp/kWRi5zKIIDX8MoKv/TzvZA== + dependencies: + "@types/estree" "1.0.8" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.49.0" + "@rollup/rollup-android-arm64" "4.49.0" + "@rollup/rollup-darwin-arm64" "4.49.0" + "@rollup/rollup-darwin-x64" "4.49.0" + "@rollup/rollup-freebsd-arm64" "4.49.0" + "@rollup/rollup-freebsd-x64" "4.49.0" + "@rollup/rollup-linux-arm-gnueabihf" "4.49.0" + "@rollup/rollup-linux-arm-musleabihf" "4.49.0" + "@rollup/rollup-linux-arm64-gnu" "4.49.0" + "@rollup/rollup-linux-arm64-musl" "4.49.0" + "@rollup/rollup-linux-loongarch64-gnu" "4.49.0" + "@rollup/rollup-linux-ppc64-gnu" "4.49.0" + "@rollup/rollup-linux-riscv64-gnu" "4.49.0" + "@rollup/rollup-linux-riscv64-musl" "4.49.0" + "@rollup/rollup-linux-s390x-gnu" "4.49.0" + "@rollup/rollup-linux-x64-gnu" "4.49.0" + "@rollup/rollup-linux-x64-musl" "4.49.0" + "@rollup/rollup-win32-arm64-msvc" "4.49.0" + "@rollup/rollup-win32-ia32-msvc" "4.49.0" + "@rollup/rollup-win32-x64-msvc" "4.49.0" + fsevents "~2.3.2" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + safe-buffer@^5.1.0: version "5.2.1" resolved "https://registry.yarnpkg.com/safe-buffer/-/safe-buffer-5.2.1.tgz#1eaf9fa9bdb1fdd4ec75f58f9cdb4e6b7827eec6" @@ -1936,6 +3938,11 @@ safe-buffer@^5.1.0: resolved "https://registry.yarnpkg.com/safer-buffer/-/safer-buffer-2.1.2.tgz#44fa161b0187b9549dd84bb91802f9bd8385cd6a" integrity sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg== +scheduler@^0.26.0: + version "0.26.0" + resolved "https://registry.yarnpkg.com/scheduler/-/scheduler-0.26.0.tgz#4ce8a8c2a2095f13ea11bf9a445be50c555d6337" + integrity sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA== + semver@^6.0.0, semver@^6.3.0, semver@^6.3.1: version "6.3.1" resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" @@ -1980,6 +3987,15 @@ signal-exit@^4.0.1, signal-exit@^4.1.0: resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== +sirv@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/sirv/-/sirv-3.0.1.tgz#32a844794655b727f9e2867b777e0060fbe07bf3" + integrity sha512-FoqMu0NCGBLCcAkS1qA+XJIQTR6/JHfQXl+uGteNCQ76T91DMUjPa9xfmeqMY3z80nLSg9yQmNjK0Px6RWsH/A== + dependencies: + "@polka/url" "^1.0.0-next.24" + mrmime "^2.0.0" + totalist "^3.0.0" + sort-any@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/sort-any/-/sort-any-2.0.0.tgz#62a5409c9905c9483f03e41e17f46cc451aa7c55" @@ -1987,6 +4003,11 @@ sort-any@^2.0.0: dependencies: lodash "^4.17.21" +source-map-js@^1.0.1, source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.2.1.tgz#1ce5650fddd87abc099eda37dcff024c2667ae46" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + source-map-support@^0.5.6: version "0.5.21" resolved "https://registry.yarnpkg.com/source-map-support/-/source-map-support-0.5.21.tgz#04fe7c7f9e1ed2d662233c28cb2b35b9f63f6e4f" @@ -2000,6 +4021,11 @@ source-map@^0.6.0, source-map@^0.6.1: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== +space-separated-tokens@^1.0.0: + version "1.1.5" + resolved "https://registry.yarnpkg.com/space-separated-tokens/-/space-separated-tokens-1.1.5.tgz#85f32c3d10d9682007e917414ddc5c26d1aa6899" + integrity sha512-q/JSVd1Lptzhf5bkYm4ob4iWPjx0KiRe3sRFBNrVqbJkFaBm5vbbowy1mymoPNLRa52+oadOhJ+K49wsSeSjTA== + spawn-wrap@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/spawn-wrap/-/spawn-wrap-2.0.0.tgz#103685b8b8f9b79771318827aa78650a610d457e" @@ -2017,7 +4043,32 @@ sprintf-js@~1.0.2: resolved "https://registry.yarnpkg.com/sprintf-js/-/sprintf-js-1.0.3.tgz#04e6926f662895354f3dd015203633b857297e2c" integrity sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g== -string-width@^4.1.0, string-width@^4.2.0: +stackpress@0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/stackpress/-/stackpress-0.6.1.tgz#2609acfc3d063b20ca614b5bbaa9afd379dde79d" + integrity sha512-y0xUvvlXR2Tfkq4ZHy7R5KsNL3e7PjpEy563YGWVTm294AxwAO7jjNa0/tbfpuxFhKp+kxougz78nrSIVjJpeA== + dependencies: + "@paralleldrive/cuid2" "2.2.2" + "@stackpress/idea-transformer" "0.6.1" + "@stackpress/ingest" "0.6.1" + "@stackpress/inquire" "0.6.1" + "@stackpress/lib" "0.6.1" + jose "6.0.10" + mustache "4.2.0" + nanoid "3.3.8" + nodemailer "6.9.16" + papaparse "5.5.1" + r22n "1.0.10" + react-toastify "11.0.5" + reactus "0.6.1" + universal-cookie "8.0.1" + +streamsearch@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/streamsearch/-/streamsearch-1.1.0.tgz#404dd1e2247ca94af554e841a8ef0eaa238da764" + integrity sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg== + +"string-width-cjs@npm:string-width@^4.2.0": version "4.2.3" resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== @@ -2026,6 +4077,31 @@ string-width@^4.1.0, string-width@^4.2.0: is-fullwidth-code-point "^3.0.0" strip-ansi "^6.0.1" +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string-width@^5.0.1, string-width@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-5.1.2.tgz#14f8daec6d81e7221d2a357e668cab73bdbca794" + integrity sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA== + dependencies: + eastasianwidth "^0.2.0" + emoji-regex "^9.2.2" + strip-ansi "^7.0.1" + +"strip-ansi-cjs@npm:strip-ansi@^6.0.1": + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + strip-ansi@^6.0.0, strip-ansi@^6.0.1: version "6.0.1" resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" @@ -2033,6 +4109,13 @@ strip-ansi@^6.0.0, strip-ansi@^6.0.1: dependencies: ansi-regex "^5.0.1" +strip-ansi@^7.0.1: + version "7.1.0" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-7.1.0.tgz#d5b6568ca689d8561370b0707685d22434faff45" + integrity sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ== + dependencies: + ansi-regex "^6.0.1" + strip-bom@^3.0.0: version "3.0.0" resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" @@ -2048,6 +4131,11 @@ strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +style-mod@^4.0.0, style-mod@^4.1.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/style-mod/-/style-mod-4.1.2.tgz#ca238a1ad4786520f7515a8539d5a63691d7bf67" + integrity sha512-wnD1HyVqpJUI2+eKZ+eo1UwghftP6yuFheBqqe+bWCotBjC2K1YnteJILRMs3SM4V/0dLEW1SC27MWP5y+mwmw== + supports-color@^7.1.0: version "7.2.0" resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" @@ -2062,6 +4150,28 @@ supports-color@^8.1.1: dependencies: has-flag "^4.0.0" +tailwindcss@4.1.12, tailwindcss@^4.1.12: + version "4.1.12" + resolved "https://registry.yarnpkg.com/tailwindcss/-/tailwindcss-4.1.12.tgz#7baeed5b5ac77370571c2baa72ee06e0050fc0a8" + integrity sha512-DzFtxOi+7NsFf7DBtI3BJsynR+0Yp6etH+nRPTbpWnS2pZBaSksv/JGctNwSWzbFjp0vxSqknaUylseZqMDGrA== + +tapable@^2.2.0: + version "2.2.3" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.3.tgz#4b67b635b2d97578a06a2713d2f04800c237e99b" + integrity sha512-ZL6DDuAlRlLGghwcfmSn9sK3Hr6ArtyudlSAiCqQ6IfE+b+HHbydbYDIG15IfS5do+7XQQBdBiubF/cV2dnDzg== + +tar@^7.4.3: + version "7.4.3" + resolved "https://registry.yarnpkg.com/tar/-/tar-7.4.3.tgz#88bbe9286a3fcd900e94592cda7a22b192e80571" + integrity sha512-5S7Va8hKfV7W5U6g3aYxXmlPoZVAwUMy9AOKyF2fVuZa2UD3qZjg578OrLRt8PcNN1PleVaL/5/yYATNL0ICUw== + dependencies: + "@isaacs/fs-minipass" "^4.0.0" + chownr "^3.0.0" + minipass "^7.1.2" + minizlib "^3.0.1" + mkdirp "^3.0.1" + yallist "^5.0.0" + test-exclude@^6.0.0: version "6.0.0" resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" @@ -2071,6 +4181,19 @@ test-exclude@^6.0.0: glob "^7.1.4" minimatch "^3.0.4" +tinyexec@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/tinyexec/-/tinyexec-1.0.1.tgz#70c31ab7abbb4aea0a24f55d120e5990bfa1e0b1" + integrity sha512-5uC6DDlmeqiOwCPmK9jMSdOuZTh8bU39Ys6yidB+UTt5hfZUPGAypSgFRiEp+jbi9qH40BLDvy85jIU88wKSqw== + +tinyglobby@^0.2.10, tinyglobby@^0.2.12: + version "0.2.14" + resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.14.tgz#5280b0cf3f972b050e74ae88406c0a6a58f4079d" + integrity sha512-tX5e7OM1HnYr2+a2C/4V0htOcSQcoSTH9KgJnVvNm5zm/cyEWKJ7j7YutsH9CxMdtOkkLFy2AHrMci9IM8IPZQ== + dependencies: + fdir "^6.4.4" + picomatch "^4.0.2" + tinyglobby@^0.2.9: version "0.2.10" resolved "https://registry.yarnpkg.com/tinyglobby/-/tinyglobby-0.2.10.tgz#e712cf2dc9b95a1f5c5bbd159720e15833977a0f" @@ -2093,6 +4216,11 @@ to-regex-range@^5.0.1: dependencies: is-number "^7.0.0" +totalist@^3.0.0: + version "3.0.1" + resolved "https://registry.yarnpkg.com/totalist/-/totalist-3.0.1.tgz#ba3a3d600c915b1a97872348f79c127475f6acf8" + integrity sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ== + ts-mocha@10.0.0: version "10.0.0" resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-10.0.0.tgz#41a8d099ac90dbbc64b06976c5025ffaebc53cb9" @@ -2102,6 +4230,11 @@ ts-mocha@10.0.0: optionalDependencies: tsconfig-paths "^3.5.0" +ts-mocha@11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/ts-mocha/-/ts-mocha-11.1.0.tgz#d8336ec0146bd6f36cca2555f4cfc7df85bd1586" + integrity sha512-yT7FfzNRCu8ZKkYvAOiH01xNma/vLq6Vit7yINKYFNVP8e5UyrYXSOMIipERTpzVKJQ4Qcos5bQo1tNERNZevQ== + ts-morph@24.0.0: version "24.0.0" resolved "https://registry.yarnpkg.com/ts-morph/-/ts-morph-24.0.0.tgz#6249b526ade40cf99c8803e7abdae6c65882e58e" @@ -2110,6 +4243,14 @@ ts-morph@24.0.0: "@ts-morph/common" "~0.25.0" code-block-writer "^13.0.3" +ts-morph@25.0.1: + version "25.0.1" + resolved "https://registry.yarnpkg.com/ts-morph/-/ts-morph-25.0.1.tgz#7de0b60fcc6e86955c8766831bcd2c5d87ffbd4f" + integrity sha512-QJEiTdnz1YjrB3JFhd626gX4rKHDLSjSVMvGGG4v7ONc3RBwa0Eei98G9AT9uNFDMtV54JyuXsFeC+OH0n6bXQ== + dependencies: + "@ts-morph/common" "~0.26.0" + code-block-writer "^13.0.3" + ts-node@10.9.2: version "10.9.2" resolved "https://registry.yarnpkg.com/ts-node/-/ts-node-10.9.2.tgz#70f021c9e185bccdca820e26dc413805c101c71f" @@ -2153,6 +4294,11 @@ tsconfig-paths@^3.5.0: minimist "^1.2.6" strip-bom "^3.0.0" +tslib@^2.0.0, tslib@^2.3.1, tslib@^2.4.0, tslib@^2.6.2, tslib@^2.7.0, tslib@^2.8.0, tslib@^2.8.1: + version "2.8.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.8.1.tgz#612efe4ed235d567e8aba5f2a5fab70280ade83f" + integrity sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w== + tsx@4.19.3: version "4.19.3" resolved "https://registry.yarnpkg.com/tsx/-/tsx-4.19.3.tgz#2bdbcb87089374d933596f8645615142ed727666" @@ -2190,11 +4336,74 @@ typescript@5.7.2: resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.7.2.tgz#3169cf8c4c8a828cde53ba9ecb3d2b1d5dd67be6" integrity sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg== +typescript@5.8.3: + version "5.8.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.8.3.tgz#92f8a3e5e3cf497356f4178c34cd65a7f5e8440e" + integrity sha512-p1diW6TqL9L07nNxvRMM7hMMw4c5XOo/1ibL4aAIGmSAt9slTE1Xgw5KWuof2uTOvCg9BY7ZRi+GaF+7sfgPeQ== + +ufo@^1.5.4, ufo@^1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.6.1.tgz#ac2db1d54614d1b22c1d603e3aef44a85d8f146b" + integrity sha512-9a4/uxlTWJ4+a5i0ooc1rU7C7YOw3wT+UGqdeNNHWnOF9qcMBgLRS+4IYUqbczewFx4mLEig6gawh7X6mFlEkA== + +unconfig@~7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/unconfig/-/unconfig-7.0.0.tgz#0c917fbbeb9ac49341b4bc56b155351646dd6ff2" + integrity sha512-G5CJSoG6ZTxgzCJblEfgpdRK2tos9+UdD2WtecDUVfImzQ0hFjwpH5RVvGMhP4pRpC9ML7NrC4qBsBl0Ttj35A== + dependencies: + "@antfu/utils" "^8.1.0" + defu "^6.1.4" + jiti "^2.4.2" + undici-types@~6.19.8: version "6.19.8" resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.19.8.tgz#35111c9d1437ab83a7cdc0abae2f26d88eda0a02" integrity sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw== +undici-types@~6.21.0: + version "6.21.0" + resolved "https://registry.yarnpkg.com/undici-types/-/undici-types-6.21.0.tgz#691d00af3909be93a7faa13be61b3a5b50ef12cb" + integrity sha512-iwDZqg0QAGrg9Rav5H4n0M64c3mkR59cJ6wQp+7C4nI0gsmExaedaYLNO44eT4AtBBwjbTiGPMlt2Md0T9H9JQ== + +universal-cookie@8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/universal-cookie/-/universal-cookie-8.0.1.tgz#19263fcda6889978a081c610a90fc395eeaeec64" + integrity sha512-B6ks9FLLnP1UbPPcveOidfvB9pHjP+wekP2uRYB9YDfKVpvcjKgy1W5Zj+cEXJ9KTPnqOKGfVDQBmn8/YCQfRg== + dependencies: + cookie "^1.0.2" + +unocss@66.0.0: + version "66.0.0" + resolved "https://registry.yarnpkg.com/unocss/-/unocss-66.0.0.tgz#4f6842b54fc1a1a1c7d86d925b972ba035e03c4f" + integrity sha512-SHstiv1s7zGPSjzOsADzlwRhQM+6817+OqQE3Fv+N/nn2QLNx1bi3WXybFfz5tWkzBtyTZlwdPmeecsIs1yOCA== + dependencies: + "@unocss/astro" "66.0.0" + "@unocss/cli" "66.0.0" + "@unocss/core" "66.0.0" + "@unocss/postcss" "66.0.0" + "@unocss/preset-attributify" "66.0.0" + "@unocss/preset-icons" "66.0.0" + "@unocss/preset-mini" "66.0.0" + "@unocss/preset-tagify" "66.0.0" + "@unocss/preset-typography" "66.0.0" + "@unocss/preset-uno" "66.0.0" + "@unocss/preset-web-fonts" "66.0.0" + "@unocss/preset-wind" "66.0.0" + "@unocss/preset-wind3" "66.0.0" + "@unocss/transformer-attributify-jsx" "66.0.0" + "@unocss/transformer-compile-class" "66.0.0" + "@unocss/transformer-directives" "66.0.0" + "@unocss/transformer-variant-group" "66.0.0" + "@unocss/vite" "66.0.0" + +unplugin-utils@^0.2.4: + version "0.2.5" + resolved "https://registry.yarnpkg.com/unplugin-utils/-/unplugin-utils-0.2.5.tgz#d2fe44566ffffd7f216579bbb01184f6702e379b" + integrity sha512-gwXJnPRewT4rT7sBi/IvxKTjsms7jX7QIDLOClApuZwR49SXbrB1z2NLUZ+vDHyqCj/n58OzRRqaW+B8OZi8vg== + dependencies: + pathe "^2.0.3" + picomatch "^4.0.3" + update-browserslist-db@^1.1.1: version "1.1.2" resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.2.tgz#97e9c96ab0ae7bcac08e9ae5151d26e6bc6b5580" @@ -2203,6 +4412,11 @@ update-browserslist-db@^1.1.1: escalade "^3.2.0" picocolors "^1.1.1" +urlpattern-polyfill@^8.0.0: + version "8.0.2" + resolved "https://registry.yarnpkg.com/urlpattern-polyfill/-/urlpattern-polyfill-8.0.2.tgz#99f096e35eff8bf4b5a2aa7d58a1523d6ebc7ce5" + integrity sha512-Qp95D4TPJl1kC9SKigDcqgyM2VDVO4RiJc2d4qe5GrYm+zbIQCWWKAFaJNQ4BhdFeDGwBmAxqJBwWSJDb9T3BQ== + uuid@^8.3.2: version "8.3.2" resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" @@ -2213,6 +4427,51 @@ v8-compile-cache-lib@^3.0.1: resolved "https://registry.yarnpkg.com/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz#6336e8d71965cb3d35a1bbb7868445a7c05264bf" integrity sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg== +vanta-react@^0.4.3: + version "0.4.3" + resolved "https://registry.yarnpkg.com/vanta-react/-/vanta-react-0.4.3.tgz#f43610997847b6184117d55fc000aaa24a8178b4" + integrity sha512-X49ntvepgReasWH26AxkBETY1DLaHJ/0rS2CaumiDcn7dkxb7Mx8oD3UIKwd4vSOMK2b7KAZFjhR6X5VvVlWiw== + +vite@6.3.2: + version "6.3.2" + resolved "https://registry.yarnpkg.com/vite/-/vite-6.3.2.tgz#4c1bb01b1cea853686a191657bbc14272a038f0a" + integrity sha512-ZSvGOXKGceizRQIZSz7TGJ0pS3QLlVY/9hwxVh17W3re67je1RKYzFHivZ/t0tubU78Vkyb9WnHPENSBCzbckg== + dependencies: + esbuild "^0.25.0" + fdir "^6.4.3" + picomatch "^4.0.2" + postcss "^8.5.3" + rollup "^4.34.9" + tinyglobby "^0.2.12" + optionalDependencies: + fsevents "~2.3.3" + +vue-flow-layout@^0.1.1: + version "0.1.1" + resolved "https://registry.yarnpkg.com/vue-flow-layout/-/vue-flow-layout-0.1.1.tgz#4095d9e79b80e845f110d4d015de6faf2c71f735" + integrity sha512-JdgRRUVrN0Y2GosA0M68DEbKlXMqJ7FQgsK8CjQD2vxvNSqAU6PZEpi4cfcTVtfM2GVOMjHo7GKKLbXxOBqDqA== + +w3c-keyname@^2.2.4: + version "2.2.8" + resolved "https://registry.yarnpkg.com/w3c-keyname/-/w3c-keyname-2.2.8.tgz#7b17c8c6883d4e8b86ac8aba79d39e880f8869c5" + integrity sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ== + +web-streams-polyfill@^3.2.1: + version "3.3.3" + resolved "https://registry.yarnpkg.com/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz#2073b91a2fdb1fbfbd401e7de0ac9f8214cecb4b" + integrity sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw== + +webcrypto-core@^1.8.0: + version "1.8.1" + resolved "https://registry.yarnpkg.com/webcrypto-core/-/webcrypto-core-1.8.1.tgz#09d5bd8a9c48e9fbcaf412e06b1ff1a57514ce86" + integrity sha512-P+x1MvlNCXlKbLSOY4cYrdreqPG5hbzkmawbcXLKN/mf6DZW0SdNNkZ+sjwsqVkI4A4Ko2sPZmkZtCKY58w83A== + dependencies: + "@peculiar/asn1-schema" "^2.3.13" + "@peculiar/json-schema" "^1.1.12" + asn1js "^3.0.5" + pvtsutils "^1.3.5" + tslib "^2.7.0" + which-module@^2.0.0: version "2.0.1" resolved "https://registry.yarnpkg.com/which-module/-/which-module-2.0.1.tgz#776b1fe35d90aebe99e8ac15eb24093389a4a409" @@ -2230,6 +4489,15 @@ workerpool@^6.5.1: resolved "https://registry.yarnpkg.com/workerpool/-/workerpool-6.5.1.tgz#060f73b39d0caf97c6db64da004cd01b4c099544" integrity sha512-Fs4dNYcsdpYSAfVxhnl1L5zTksjvOJxtC5hzMNl+1t9B8hTJTdKDyZ5ju7ztgPy+ft9tBFXoOlDNiOT9WUXZlA== +"wrap-ansi-cjs@npm:wrap-ansi@^7.0.0": + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + wrap-ansi@^6.2.0: version "6.2.0" resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-6.2.0.tgz#e9393ba07102e6c91a3b221478f0257cd2856e53" @@ -2248,6 +4516,15 @@ wrap-ansi@^7.0.0: string-width "^4.1.0" strip-ansi "^6.0.0" +wrap-ansi@^8.1.0: + version "8.1.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-8.1.0.tgz#56dc22368ee570face1b49819975d9b9a5ead214" + integrity sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ== + dependencies: + ansi-styles "^6.1.0" + string-width "^5.0.1" + strip-ansi "^7.0.1" + wrappy@1: version "1.0.2" resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" @@ -2263,6 +4540,11 @@ write-file-atomic@^3.0.0: signal-exit "^3.0.2" typedarray-to-buffer "^3.1.5" +xtend@^4.0.0: + version "4.0.2" + resolved "https://registry.yarnpkg.com/xtend/-/xtend-4.0.2.tgz#bb72779f5fa465186b1f438f674fa347fdb5db54" + integrity sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ== + y18n@^4.0.0: version "4.0.3" resolved "https://registry.yarnpkg.com/y18n/-/y18n-4.0.3.tgz#b5f259c82cd6e336921efd7bfd8bf560de9eeedf" @@ -2278,6 +4560,11 @@ yallist@^3.0.2: resolved "https://registry.yarnpkg.com/yallist/-/yallist-3.1.1.tgz#dbb7daf9bfd8bac9ab45ebf602b8cbad0d5d08fd" integrity sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g== +yallist@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-5.0.0.tgz#00e2de443639ed0d78fd87de0d27469fbcffb533" + integrity sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw== + yargs-parser@^18.1.2: version "18.1.3" resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-18.1.3.tgz#be68c4975c6b2abf469236b0c870362fab09a7b0" @@ -2291,6 +4578,11 @@ yargs-parser@^20.2.2, yargs-parser@^20.2.9: resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-20.2.9.tgz#2eb7dc3b0289718fc295f362753845c41a0c94ee" integrity sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w== +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + yargs-unparser@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/yargs-unparser/-/yargs-unparser-2.0.0.tgz#f131f9226911ae5d9ad38c432fe809366c2325eb" @@ -2331,6 +4623,19 @@ yargs@^16.2.0: y18n "^5.0.5" yargs-parser "^20.2.2" +yargs@^17.7.2: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + yn@3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/yn/-/yn-3.1.1.tgz#1e87401a09d767c1d5eab26a6e4c185182d2eb50"