@stacksjs/defaults 0.70.207 → 0.70.208
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/TODO.md +21 -0
- package/ai/AGENTS.md +79 -0
- package/ai/README.md +45 -0
- package/ai/claude/launch.json +12 -0
- package/ai/skills/stacks-actions/SKILL.md +128 -0
- package/ai/skills/stacks-ai/SKILL.md +276 -0
- package/ai/skills/stacks-alias/SKILL.md +94 -0
- package/ai/skills/stacks-analytics/SKILL.md +91 -0
- package/ai/skills/stacks-api/SKILL.md +738 -0
- package/ai/skills/stacks-arrays/SKILL.md +277 -0
- package/ai/skills/stacks-auth/SKILL.md +422 -0
- package/ai/skills/stacks-auto-imports/SKILL.md +138 -0
- package/ai/skills/stacks-brandkit/SKILL.md +811 -0
- package/ai/skills/stacks-browse/SKILL.md +127 -0
- package/ai/skills/stacks-browse/scripts/browse.ts +492 -0
- package/ai/skills/stacks-browser/SKILL.md +145 -0
- package/ai/skills/stacks-buddy/SKILL.md +676 -0
- package/ai/skills/stacks-build/SKILL.md +163 -0
- package/ai/skills/stacks-cache/SKILL.md +125 -0
- package/ai/skills/stacks-calendar/SKILL.md +113 -0
- package/ai/skills/stacks-chat/SKILL.md +371 -0
- package/ai/skills/stacks-cli/SKILL.md +112 -0
- package/ai/skills/stacks-cloud/SKILL.md +192 -0
- package/ai/skills/stacks-cms/SKILL.md +217 -0
- package/ai/skills/stacks-collections/SKILL.md +82 -0
- package/ai/skills/stacks-commerce/SKILL.md +114 -0
- package/ai/skills/stacks-composables/SKILL.md +161 -0
- package/ai/skills/stacks-config/SKILL.md +144 -0
- package/ai/skills/stacks-configuration/SKILL.md +154 -0
- package/ai/skills/stacks-cron/SKILL.md +123 -0
- package/ai/skills/stacks-crosswind/SKILL.md +190 -0
- package/ai/skills/stacks-dashboard/SKILL.md +173 -0
- package/ai/skills/stacks-database/SKILL.md +286 -0
- package/ai/skills/stacks-datetime/SKILL.md +269 -0
- package/ai/skills/stacks-dependencies/SKILL.md +111 -0
- package/ai/skills/stacks-deploy/SKILL.md +102 -0
- package/ai/skills/stacks-design-brutalist/SKILL.md +110 -0
- package/ai/skills/stacks-design-minimalist/SKILL.md +115 -0
- package/ai/skills/stacks-design-output/SKILL.md +55 -0
- package/ai/skills/stacks-design-soft/SKILL.md +156 -0
- package/ai/skills/stacks-design-taste/SKILL.md +1012 -0
- package/ai/skills/stacks-design-taste-codex/SKILL.md +294 -0
- package/ai/skills/stacks-desktop/SKILL.md +78 -0
- package/ai/skills/stacks-development/SKILL.md +298 -0
- package/ai/skills/stacks-dns/SKILL.md +149 -0
- package/ai/skills/stacks-docs/SKILL.md +109 -0
- package/ai/skills/stacks-email/SKILL.md +236 -0
- package/ai/skills/stacks-enums/SKILL.md +100 -0
- package/ai/skills/stacks-env/SKILL.md +181 -0
- package/ai/skills/stacks-error-handling/SKILL.md +137 -0
- package/ai/skills/stacks-events/SKILL.md +228 -0
- package/ai/skills/stacks-faker/SKILL.md +158 -0
- package/ai/skills/stacks-git/SKILL.md +158 -0
- package/ai/skills/stacks-guard/SKILL.md +98 -0
- package/ai/skills/stacks-health/SKILL.md +75 -0
- package/ai/skills/stacks-http/SKILL.md +316 -0
- package/ai/skills/stacks-i18n/SKILL.md +198 -0
- package/ai/skills/stacks-image-to-code/SKILL.md +629 -0
- package/ai/skills/stacks-imagegen-mobile/SKILL.md +1474 -0
- package/ai/skills/stacks-imagegen-web/SKILL.md +998 -0
- package/ai/skills/stacks-investigate/SKILL.md +119 -0
- package/ai/skills/stacks-jobs/SKILL.md +136 -0
- package/ai/skills/stacks-lint/SKILL.md +184 -0
- package/ai/skills/stacks-listeners/SKILL.md +99 -0
- package/ai/skills/stacks-logging/SKILL.md +78 -0
- package/ai/skills/stacks-mail/SKILL.md +120 -0
- package/ai/skills/stacks-middleware/SKILL.md +249 -0
- package/ai/skills/stacks-migrations/SKILL.md +105 -0
- package/ai/skills/stacks-models/SKILL.md +267 -0
- package/ai/skills/stacks-new-feature/SKILL.md +206 -0
- package/ai/skills/stacks-notifications/SKILL.md +210 -0
- package/ai/skills/stacks-objects/SKILL.md +205 -0
- package/ai/skills/stacks-office-hours/SKILL.md +134 -0
- package/ai/skills/stacks-orm/SKILL.md +342 -0
- package/ai/skills/stacks-path/SKILL.md +118 -0
- package/ai/skills/stacks-payments/SKILL.md +373 -0
- package/ai/skills/stacks-plan-review/SKILL.md +152 -0
- package/ai/skills/stacks-plugins/SKILL.md +149 -0
- package/ai/skills/stacks-push/SKILL.md +376 -0
- package/ai/skills/stacks-query-builder/SKILL.md +128 -0
- package/ai/skills/stacks-queue/SKILL.md +559 -0
- package/ai/skills/stacks-realtime/SKILL.md +442 -0
- package/ai/skills/stacks-redesign/SKILL.md +182 -0
- package/ai/skills/stacks-registry/SKILL.md +58 -0
- package/ai/skills/stacks-repl/SKILL.md +80 -0
- package/ai/skills/stacks-retro/SKILL.md +122 -0
- package/ai/skills/stacks-review/SKILL.md +135 -0
- package/ai/skills/stacks-router/SKILL.md +231 -0
- package/ai/skills/stacks-routes/SKILL.md +105 -0
- package/ai/skills/stacks-scaffolding/SKILL.md +162 -0
- package/ai/skills/stacks-scheduler/SKILL.md +363 -0
- package/ai/skills/stacks-search-engine/SKILL.md +112 -0
- package/ai/skills/stacks-security/SKILL.md +129 -0
- package/ai/skills/stacks-security-audit/SKILL.md +128 -0
- package/ai/skills/stacks-server/SKILL.md +458 -0
- package/ai/skills/stacks-shell/SKILL.md +62 -0
- package/ai/skills/stacks-slug/SKILL.md +87 -0
- package/ai/skills/stacks-sms/SKILL.md +385 -0
- package/ai/skills/stacks-socials/SKILL.md +303 -0
- package/ai/skills/stacks-storage/SKILL.md +576 -0
- package/ai/skills/stacks-strings/SKILL.md +416 -0
- package/ai/skills/stacks-stx/SKILL.md +176 -0
- package/ai/skills/stacks-technical-diagrams/LICENSE +22 -0
- package/ai/skills/stacks-technical-diagrams/SKILL.md +290 -0
- package/ai/skills/stacks-technical-diagrams/agents/openai.yaml +4 -0
- package/ai/skills/stacks-technical-diagrams/assets/template.html +1252 -0
- package/ai/skills/stacks-technical-diagrams/bin/technical-diagrams.mjs +289 -0
- package/ai/skills/stacks-technical-diagrams/bunfig.toml +1 -0
- package/ai/skills/stacks-technical-diagrams/examples/agent-run.lifecycle.json +64 -0
- package/ai/skills/stacks-technical-diagrams/examples/agent-tool-call.workflow.json +88 -0
- package/ai/skills/stacks-technical-diagrams/examples/cache-miss-request.sequence.json +75 -0
- package/ai/skills/stacks-technical-diagrams/examples/product-analytics.dataflow.json +70 -0
- package/ai/skills/stacks-technical-diagrams/examples/web-app.architecture.json +41 -0
- package/ai/skills/stacks-technical-diagrams/renderers/architecture/grid.mjs +62 -0
- package/ai/skills/stacks-technical-diagrams/renderers/architecture/render-architecture.mjs +371 -0
- package/ai/skills/stacks-technical-diagrams/renderers/dataflow/README.md +82 -0
- package/ai/skills/stacks-technical-diagrams/renderers/dataflow/render-dataflow.mjs +295 -0
- package/ai/skills/stacks-technical-diagrams/renderers/lifecycle/README.md +91 -0
- package/ai/skills/stacks-technical-diagrams/renderers/lifecycle/render-lifecycle.mjs +384 -0
- package/ai/skills/stacks-technical-diagrams/renderers/sequence/README.md +84 -0
- package/ai/skills/stacks-technical-diagrams/renderers/sequence/render-sequence.mjs +257 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/cli.mjs +42 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/generated-validators.mjs +13 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/geometry.mjs +230 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/layout-report.mjs +40 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/utils.mjs +88 -0
- package/ai/skills/stacks-technical-diagrams/renderers/shared/validator.mjs +40 -0
- package/ai/skills/stacks-technical-diagrams/renderers/workflow/README.md +103 -0
- package/ai/skills/stacks-technical-diagrams/renderers/workflow/render-workflow.mjs +481 -0
- package/ai/skills/stacks-technical-diagrams/schemas/README.md +68 -0
- package/ai/skills/stacks-technical-diagrams/schemas/architecture.schema.json +121 -0
- package/ai/skills/stacks-technical-diagrams/schemas/common.schema.json +43 -0
- package/ai/skills/stacks-technical-diagrams/schemas/dataflow.schema.json +221 -0
- package/ai/skills/stacks-technical-diagrams/schemas/lifecycle.schema.json +241 -0
- package/ai/skills/stacks-technical-diagrams/schemas/sequence.schema.json +186 -0
- package/ai/skills/stacks-technical-diagrams/schemas/workflow.schema.json +332 -0
- package/ai/skills/stacks-technical-diagrams/scripts/check-render-output.mjs +297 -0
- package/ai/skills/stacks-technical-diagrams/scripts/render-examples.mjs +28 -0
- package/ai/skills/stacks-testing/SKILL.md +129 -0
- package/ai/skills/stacks-tunnel/SKILL.md +125 -0
- package/ai/skills/stacks-types/SKILL.md +178 -0
- package/ai/skills/stacks-ui/SKILL.md +246 -0
- package/ai/skills/stacks-utils/SKILL.md +444 -0
- package/ai/skills/stacks-validation/SKILL.md +371 -0
- package/ai/skills/stacks-whois/SKILL.md +315 -0
- package/assets/world-map-data.ts +121 -0
- package/bootstrap.ts +114 -0
- package/docs/api-examples.md +46 -0
- package/docs/index.md +24 -0
- package/docs/markdown-examples.md +87 -0
- package/functions/analytics.ts +97 -0
- package/functions/api.ts +143 -0
- package/functions/auth.ts +208 -0
- package/functions/billing/payments.ts +149 -0
- package/functions/blog.ts +120 -0
- package/functions/cms/categorizables.ts +107 -0
- package/functions/cms/pages.ts +108 -0
- package/functions/cms/posts.ts +100 -0
- package/functions/cms/taggables.ts +102 -0
- package/functions/commerce/coupons.ts +128 -0
- package/functions/commerce/customers.ts +128 -0
- package/functions/commerce/gift-cards.ts +119 -0
- package/functions/commerce/orders.ts +112 -0
- package/functions/commerce/payments.ts +119 -0
- package/functions/commerce/products/categories.ts +123 -0
- package/functions/commerce/products/manufacturers.ts +123 -0
- package/functions/commerce/products/products.ts +123 -0
- package/functions/commerce/products/reviews.ts +123 -0
- package/functions/commerce/products/units.ts +123 -0
- package/functions/commerce/products/variants.ts +123 -0
- package/functions/commerce/shippings/delivery-routes.ts +123 -0
- package/functions/commerce/shippings/digital-deliveries.ts +119 -0
- package/functions/commerce/shippings/drivers.ts +123 -0
- package/functions/commerce/shippings/license-keys.ts +123 -0
- package/functions/commerce/shippings/shipping-methods.ts +123 -0
- package/functions/commerce/shippings/shipping-rates.ts +119 -0
- package/functions/commerce/shippings/shipping-zones.ts +119 -0
- package/functions/commerce/taxes.ts +119 -0
- package/functions/commerce/waitlist/products.ts +123 -0
- package/functions/commerce/waitlist/restaurants.ts +123 -0
- package/functions/craft.ts +107 -0
- package/functions/dashboard.ts +153 -0
- package/functions/inbox.ts +95 -0
- package/functions/jobs.ts +86 -0
- package/functions/monitoring/errors.ts +295 -0
- package/functions/queue.ts +111 -0
- package/functions/realtime/websockets.ts +96 -0
- package/functions/realtime.ts +52 -0
- package/functions/releases.ts +49 -0
- package/functions/search.ts +126 -0
- package/functions/toasts.ts +95 -0
- package/functions/uploads.ts +216 -0
- package/ide/.gitignore +4 -0
- package/ide/cursor/rules/auto-imports.mdc +574 -0
- package/ide/cursor/rules/code-style.mdc +12 -0
- package/ide/cursor/rules/documentation.mdc +9 -0
- package/ide/cursor/rules/error-handling-validation.mdc +11 -0
- package/ide/cursor/rules/key-conventions.mdc +11 -0
- package/ide/cursor/rules/project-structure.mdc +169 -0
- package/ide/cursor/rules/readme.mdc +318 -0
- package/ide/cursor/rules/syntax-formatting.mdc +9 -0
- package/ide/cursor/rules/testing.mdc +10 -0
- package/ide/cursor/rules/typescript.mdc +9 -0
- package/ide/cursor/rules/ui-styling.mdc +0 -0
- package/ide/dictionary.txt +397 -0
- package/ide/jetbrains/.fleet/settings.json +4 -0
- package/ide/jetbrains/.idea/.gitignore +5 -0
- package/ide/jetbrains/.idea/.name +1 -0
- package/ide/jetbrains/.idea/inspectionProfiles/Project_Default.xml +6 -0
- package/ide/jetbrains/.idea/jsLinters/eslint.xml +7 -0
- package/ide/jetbrains/.idea/modules.xml +8 -0
- package/ide/jetbrains/.idea/stacks.iml +22 -0
- package/ide/jetbrains/.idea/vcs.xml +6 -0
- package/ide/jetbrains/.idea/webResources.xml +14 -0
- package/ide/jetbrains/IntelliJ IDEA Global Settings +0 -0
- package/ide/jetbrains/installed.txt +4 -0
- package/ide/jetbrains/options/github-copilot.xml +5 -0
- package/ide/jetbrains/options/nodejs.xml +7 -0
- package/ide/jetbrains/options/templates.xml +124 -0
- package/ide/jetbrains/templates/JavaScript.xml +6 -0
- package/ide/jetbrains/templates/Stacks.xml +8 -0
- package/ide/vscode/.vscode/README.md +23 -0
- package/ide/vscode/.vscode/extensions.json +5 -0
- package/ide/vscode/.vscode/settings.json +176 -0
- package/ide/vscode/.vscode/stacks.code-snippets +181 -0
- package/ide/vscode/LICENSE.md +21 -0
- package/ide/vscode/README.md +36 -0
- package/ide/vscode/logo.png +0 -0
- package/ide/vscode/package.json +79 -0
- package/ide/zed/.zed/settings.json +139 -0
- package/lang/README.md +28 -0
- package/lang/de.yml +14 -0
- package/lang/en.yml +15 -0
- package/package.json +19 -3
- package/project/bootstrap +161 -0
- package/project/buddy +175 -0
- package/project/storage/framework/tsconfig.app.json +50 -0
- package/project/storage/framework/tsconfig.base.json +58 -0
- package/routes/core.ts +78 -0
- package/routes/dashboard-api.ts +233 -0
- package/routes/dashboard.ts +739 -0
- package/routes/email.ts +129 -0
- package/stores/[name].stx +16 -0
- package/stores/git.ts +71 -0
- package/stores/payment.ts +474 -0
- package/stores/queue.ts +43 -0
- package/stores/user.ts +29 -0
- package/stx-components-plugin.ts +25 -0
- package/styles/design-tokens.css +597 -0
- package/types/dashboard.ts +70 -0
- package/types/defaults.ts +438 -0
- package/vcs/github/CODE_OF_CONDUCT.md +83 -0
- package/vcs/github/CONTRIBUTING.md +187 -0
- package/vcs/github/EXPLANATIONS.md +41 -0
- package/vcs/github/FUNDING.yml +1 -0
- package/vcs/github/ISSUE_TEMPLATE/bug_report.yml +49 -0
- package/vcs/github/ISSUE_TEMPLATE/config.yml +10 -0
- package/vcs/github/ISSUE_TEMPLATE/feature_request.yml +44 -0
- package/vcs/github/SECURITY.md +70 -0
- package/vcs/github/renovate.json +5 -0
- package/vcs/github/stale.yml +14 -0
- package/vcs/github/workflows/README.md +16 -0
- package/vcs/github/workflows/ci.yml +114 -0
- package/vcs/github/workflows/export-size.yml +25 -0
- package/vcs/github/workflows/labeler.yml +13 -0
- package/vcs/github/workflows/release.yml +219 -0
- package/views/[...all].stx +8 -0
- package/views/about.md +3 -0
- package/views/auth/login.stx +1 -0
- package/views/auth/signup.stx +85 -0
- package/views/dashboard/.discovered-models.json +542 -0
- package/views/dashboard/AUDIT.md +904 -0
- package/views/dashboard/[...all].stx +89 -0
- package/views/dashboard/access-tokens/index.stx +177 -0
- package/views/dashboard/actions/index.stx +129 -0
- package/views/dashboard/analytics/blog/index.stx +356 -0
- package/views/dashboard/analytics/browsers/index.stx +263 -0
- package/views/dashboard/analytics/commerce/sales/index.stx +329 -0
- package/views/dashboard/analytics/commerce/web/index.stx +379 -0
- package/views/dashboard/analytics/countries/index.stx +289 -0
- package/views/dashboard/analytics/devices/index.stx +305 -0
- package/views/dashboard/analytics/events/index.stx +536 -0
- package/views/dashboard/analytics/index.stx +88 -0
- package/views/dashboard/analytics/marketing/index.stx +315 -0
- package/views/dashboard/analytics/pages/index.stx +271 -0
- package/views/dashboard/analytics/referrers/index.stx +319 -0
- package/views/dashboard/analytics/web/index.stx +356 -0
- package/views/dashboard/buddy/index.stx +198 -0
- package/views/dashboard/ci/index.stx +462 -0
- package/views/dashboard/cloud/index.stx +452 -0
- package/views/dashboard/commands/index.stx +295 -0
- package/views/dashboard/commerce/categories/index.stx +406 -0
- package/views/dashboard/commerce/coupons/index.stx +485 -0
- package/views/dashboard/commerce/customers/index.stx +410 -0
- package/views/dashboard/commerce/dashboard/index.stx +287 -0
- package/views/dashboard/commerce/delivery/delivery-routes.stx +305 -0
- package/views/dashboard/commerce/delivery/digital-delivery.stx +332 -0
- package/views/dashboard/commerce/delivery/drivers.stx +397 -0
- package/views/dashboard/commerce/delivery/index.stx +18 -0
- package/views/dashboard/commerce/delivery/license-keys.stx +380 -0
- package/views/dashboard/commerce/delivery/shipping-methods.stx +346 -0
- package/views/dashboard/commerce/delivery/shipping-rates.stx +338 -0
- package/views/dashboard/commerce/delivery/shipping-zones.stx +302 -0
- package/views/dashboard/commerce/delivery/tabs.ts +25 -0
- package/views/dashboard/commerce/gift-cards/index.stx +561 -0
- package/views/dashboard/commerce/manufacturers/index.stx +308 -0
- package/views/dashboard/commerce/orders/index.stx +247 -0
- package/views/dashboard/commerce/payments/index.stx +535 -0
- package/views/dashboard/commerce/pos/index.stx +653 -0
- package/views/dashboard/commerce/printers/devices/index.stx +273 -0
- package/views/dashboard/commerce/printers/receipts/index.stx +308 -0
- package/views/dashboard/commerce/products/detail.stx +563 -0
- package/views/dashboard/commerce/products/index.stx +370 -0
- package/views/dashboard/commerce/reviews/index.stx +656 -0
- package/views/dashboard/commerce/reviews/index.ts +0 -0
- package/views/dashboard/commerce/taxes/index.stx +377 -0
- package/views/dashboard/commerce/units/index.stx +317 -0
- package/views/dashboard/commerce/variants/index.stx +319 -0
- package/views/dashboard/commerce/waitlist/products.stx +942 -0
- package/views/dashboard/commerce/waitlist/restaurant.stx +1024 -0
- package/views/dashboard/components/index.stx +330 -0
- package/views/dashboard/composables/index.ts +19 -0
- package/views/dashboard/composables/useChart.ts +77 -0
- package/views/dashboard/composables/useNavigation.ts +99 -0
- package/views/dashboard/composables/useRole.ts +58 -0
- package/views/dashboard/composables/useTheme.ts +74 -0
- package/views/dashboard/content/authors/index.stx +171 -0
- package/views/dashboard/content/blog/index.stx +493 -0
- package/views/dashboard/content/categories/index.stx +169 -0
- package/views/dashboard/content/comments/index.stx +189 -0
- package/views/dashboard/content/dashboard.stx +383 -0
- package/views/dashboard/content/files/index.stx +706 -0
- package/views/dashboard/content/pages/index.stx +174 -0
- package/views/dashboard/content/posts/index.stx +269 -0
- package/views/dashboard/content/seo/index.stx +240 -0
- package/views/dashboard/content/tags/index.stx +167 -0
- package/views/dashboard/data/activity/index.stx +261 -0
- package/views/dashboard/data/dashboard/index.stx +116 -0
- package/views/dashboard/data/subscribers.stx +270 -0
- package/views/dashboard/data/teams.stx +275 -0
- package/views/dashboard/data/users.stx +279 -0
- package/views/dashboard/dependencies/index.stx +178 -0
- package/views/dashboard/deployments/[id].stx +234 -0
- package/views/dashboard/deployments/index.stx +9 -0
- package/views/dashboard/dns/index.stx +163 -0
- package/views/dashboard/environment/index.stx +283 -0
- package/views/dashboard/errors/index.stx +274 -0
- package/views/dashboard/forgot-password.stx +57 -0
- package/views/dashboard/functions/index.stx +159 -0
- package/views/dashboard/health/index.stx +248 -0
- package/views/dashboard/inbox/activity.stx +350 -0
- package/views/dashboard/inbox/index.stx +452 -0
- package/views/dashboard/inbox/settings.stx +290 -0
- package/views/dashboard/index.stx +252 -0
- package/views/dashboard/insights/index.stx +529 -0
- package/views/dashboard/jobs/[id].stx +430 -0
- package/views/dashboard/jobs/history.stx +222 -0
- package/views/dashboard/jobs/index.stx +214 -0
- package/views/dashboard/kanban/[id].stx +899 -0
- package/views/dashboard/kanban/index.stx +260 -0
- package/views/dashboard/layouts/default.stx +565 -0
- package/views/dashboard/layouts/guest.stx +10 -0
- package/views/dashboard/login.stx +48 -0
- package/views/dashboard/logs/index.stx +540 -0
- package/views/dashboard/mailboxes/index.stx +149 -0
- package/views/dashboard/management/permissions/index.stx +490 -0
- package/views/dashboard/marketing/campaigns/index.stx +604 -0
- package/views/dashboard/marketing/lists/index.stx +514 -0
- package/views/dashboard/marketing/reviews/index.stx +475 -0
- package/views/dashboard/marketing/social-posts/index.stx +560 -0
- package/views/dashboard/models/[model].stx +195 -0
- package/views/dashboard/models/index.stx +159 -0
- package/views/dashboard/monitoring/errors/index.stx +415 -0
- package/views/dashboard/notifications/dashboard.stx +383 -0
- package/views/dashboard/notifications/email.stx +336 -0
- package/views/dashboard/notifications/history.stx +373 -0
- package/views/dashboard/notifications/sms.stx +332 -0
- package/views/dashboard/packages/index.stx +195 -0
- package/views/dashboard/queries/[id].stx +381 -0
- package/views/dashboard/queries/history.stx +227 -0
- package/views/dashboard/queries/index.stx +335 -0
- package/views/dashboard/queries/slow.stx +318 -0
- package/views/dashboard/queue/index.stx +427 -0
- package/views/dashboard/realtime/index.stx +429 -0
- package/views/dashboard/register.stx +46 -0
- package/views/dashboard/releases/index.stx +389 -0
- package/views/dashboard/requests/index.stx +462 -0
- package/views/dashboard/serverless/index.stx +475 -0
- package/views/dashboard/servers/[id].stx +299 -0
- package/views/dashboard/servers/index.stx +483 -0
- package/views/dashboard/settings/billing.stx +50 -0
- package/views/dashboard/settings/index.stx +256 -0
- package/views/dashboard/settings/mail.stx +252 -0
- package/views/dashboard/stores/auth.ts +123 -0
- package/views/dashboard/stores/ci.ts +342 -0
- package/views/dashboard/stores/index.ts +129 -0
- package/views/dashboard/stores/kanban.ts +723 -0
- package/views/dashboard/stores/rbac.ts +350 -0
- package/views/dashboard/stx.config.ts +34 -0
- package/views/dashboard/teams/[id].stx +170 -0
- package/views/forum/category.stx +92 -0
- package/views/forum/index.stx +209 -0
- package/views/forum/new-topic.stx +113 -0
- package/views/forum/profile.stx +1 -0
- package/views/forum/topic.stx +143 -0
- package/views/hello-world/[name].stx +47 -0
- package/views/index.stx +21 -0
- package/views/system-tray/index.stx +147 -0
|
@@ -0,0 +1,371 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: stacks-validation
|
|
3
|
+
description: Use when implementing validation in Stacks — type guards (isString, isNumber, isBoolean, isObject, isArray, isFunction, etc.), numeric checks (isPositive, isEven, isInteger), the schema builder for model attribute validation, or request validation. Covers @stacksjs/validation.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Bun >= 1.3.0, TypeScript
|
|
6
|
+
allowed-tools: Read Edit Write Bash Grep Glob
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Stacks Validation
|
|
10
|
+
|
|
11
|
+
## Key Paths
|
|
12
|
+
- Core package: `storage/framework/core/validation/src/`
|
|
13
|
+
- Package: `@stacksjs/validation`
|
|
14
|
+
|
|
15
|
+
## Architecture
|
|
16
|
+
|
|
17
|
+
The `index.ts` re-exports from multiple sources:
|
|
18
|
+
```typescript
|
|
19
|
+
// Re-export everything from the validation library
|
|
20
|
+
export * from '@stacksjs/ts-validation'
|
|
21
|
+
|
|
22
|
+
// Local modules
|
|
23
|
+
export * from './reporter' // error reporting
|
|
24
|
+
export * from './validator' // model/custom validation
|
|
25
|
+
export { schema } from './schema' // schema builder instance
|
|
26
|
+
|
|
27
|
+
// Type guard functions defined directly in index.ts
|
|
28
|
+
export function isString(value: unknown): value is string
|
|
29
|
+
export function isNumber(value: unknown): value is number
|
|
30
|
+
export function isBoolean(value: unknown): value is boolean
|
|
31
|
+
export function isObject(value: unknown): value is Record<string, unknown>
|
|
32
|
+
export function isArray(value: unknown): value is unknown[]
|
|
33
|
+
export function isFunction(value: unknown): value is Function
|
|
34
|
+
export function isUndefined(value: unknown): value is undefined
|
|
35
|
+
export function isNull(value: unknown): value is null
|
|
36
|
+
export function isNullOrUndefined(value: unknown): value is null | undefined
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
Additional type guards are in `is.ts` (but not directly imported by index.ts -- available via separate import).
|
|
40
|
+
|
|
41
|
+
## Type Guards (`index.ts`)
|
|
42
|
+
|
|
43
|
+
Basic type guards with TypeScript type narrowing:
|
|
44
|
+
|
|
45
|
+
```typescript
|
|
46
|
+
import { isString, isNumber, isBoolean, isObject, isArray, isFunction } from '@stacksjs/validation'
|
|
47
|
+
|
|
48
|
+
isString('hello') // true -- typeof value === 'string'
|
|
49
|
+
isNumber(42) // true -- typeof value === 'number' && !Number.isNaN(value)
|
|
50
|
+
isNumber(NaN) // FALSE -- NaN is explicitly excluded
|
|
51
|
+
isBoolean(true) // true -- typeof value === 'boolean'
|
|
52
|
+
isObject({}) // true -- typeof === 'object' && !== null && !Array.isArray
|
|
53
|
+
isObject([]) // FALSE -- arrays are excluded
|
|
54
|
+
isObject(null) // FALSE -- null is excluded
|
|
55
|
+
isArray([]) // true -- Array.isArray()
|
|
56
|
+
isFunction(() => {}) // true -- typeof value === 'function'
|
|
57
|
+
isUndefined(undefined) // true
|
|
58
|
+
isNull(null) // true
|
|
59
|
+
isNullOrUndefined(null) // true
|
|
60
|
+
isNullOrUndefined(undefined) // true
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Extended Type Guards (`is.ts`)
|
|
64
|
+
|
|
65
|
+
Additional guards using `getTypeName()` from `@stacksjs/types` and `toString()` from `@stacksjs/strings`:
|
|
66
|
+
|
|
67
|
+
```typescript
|
|
68
|
+
isDef(value) // true if typeof value !== 'undefined'
|
|
69
|
+
isMap(new Map()) // true -- toString check '[object Map]'
|
|
70
|
+
isSet(new Set()) // true -- toString check '[object Set]'
|
|
71
|
+
isPromise(Promise.resolve()) // true -- toString check '[object Promise]'
|
|
72
|
+
isSymbol(Symbol()) // true
|
|
73
|
+
isDate(new Date()) // true
|
|
74
|
+
isRegExp(/test/) // true
|
|
75
|
+
isWindow(globalThis) // true in browser -- toString check '[object Window]'
|
|
76
|
+
isPrimitive(42) // true (string, number, boolean, null, undefined, symbol)
|
|
77
|
+
isPrimitive({}) // false
|
|
78
|
+
|
|
79
|
+
// Environment detection
|
|
80
|
+
isBrowser: boolean // typeof window !== 'undefined'
|
|
81
|
+
isServer: boolean // typeof document === 'undefined'
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
## Numeric Checks (`is.ts`)
|
|
85
|
+
|
|
86
|
+
```typescript
|
|
87
|
+
isInteger(42) // true -- Number.isInteger()
|
|
88
|
+
isInteger(42.0) // true -- 42.0 is an integer in JS
|
|
89
|
+
isFloat(3.14) // true -- isNumber && !Number.isInteger
|
|
90
|
+
isFloat(42) // false
|
|
91
|
+
|
|
92
|
+
isPositive(5) // true -- > 0
|
|
93
|
+
isNegative(-5) // true -- < 0
|
|
94
|
+
isEven(4) // true -- % 2 === 0
|
|
95
|
+
isOdd(3) // true -- % 2 !== 0
|
|
96
|
+
|
|
97
|
+
// Classification functions (return string, not boolean)
|
|
98
|
+
isEvenOrOdd(4) // 'even'
|
|
99
|
+
isEvenOrOdd(3) // 'odd'
|
|
100
|
+
isEvenOrOdd('not a number') // 'odd' -- non-numbers default to 'odd'
|
|
101
|
+
|
|
102
|
+
isPositiveOrNegative(5) // 'positive'
|
|
103
|
+
isPositiveOrNegative(-5) // 'negative'
|
|
104
|
+
isPositiveOrNegative('x') // 'negative' -- non-numbers default to 'negative'
|
|
105
|
+
|
|
106
|
+
isIntegerOrFloat(42) // 'integer'
|
|
107
|
+
isIntegerOrFloat(3.14) // 'float'
|
|
108
|
+
isIntegerOrFloat('x') // 'float' -- non-numbers default to 'float'
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
## Schema Builder (`schema.ts`)
|
|
112
|
+
|
|
113
|
+
The `schema` object is an instance of `ValidationInstance` from `@stacksjs/ts-validation`. It provides fluent validators for model attribute definitions.
|
|
114
|
+
|
|
115
|
+
```typescript
|
|
116
|
+
import { schema } from '@stacksjs/validation'
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
### Available Schema Types
|
|
120
|
+
|
|
121
|
+
```typescript
|
|
122
|
+
// String types
|
|
123
|
+
schema.string() // StringValidatorType
|
|
124
|
+
schema.string().minLength(2) // chain: min length
|
|
125
|
+
schema.string().maxLength(100) // chain: max length
|
|
126
|
+
schema.string().email() // chain: must be email
|
|
127
|
+
schema.string().url() // chain: must be URL
|
|
128
|
+
schema.string().matches(/pattern/) // chain: regex match
|
|
129
|
+
schema.string().equals('exact') // chain: exact match
|
|
130
|
+
schema.string().alphanumeric() // chain: alphanumeric only
|
|
131
|
+
schema.string().alpha() // chain: letters only
|
|
132
|
+
schema.string().numeric() // chain: numeric string
|
|
133
|
+
schema.string().custom(fn, msg) // chain: custom validator
|
|
134
|
+
schema.text() // TextValidatorType (extends StringValidatorType)
|
|
135
|
+
|
|
136
|
+
// Number types
|
|
137
|
+
schema.number() // NumberValidatorType
|
|
138
|
+
schema.number().min(0).max(100) // chain: min/max
|
|
139
|
+
schema.bigint() // BigintValidatorType
|
|
140
|
+
schema.integer() // IntegerValidatorType
|
|
141
|
+
schema.smallint() // SmallintValidatorType
|
|
142
|
+
schema.float() // FloatValidatorType
|
|
143
|
+
schema.double() // DoubleValidatorType
|
|
144
|
+
schema.decimal() // DecimalValidatorType
|
|
145
|
+
|
|
146
|
+
// Boolean
|
|
147
|
+
schema.boolean() // BooleanValidatorType
|
|
148
|
+
|
|
149
|
+
// Enum
|
|
150
|
+
schema.enum(['draft', 'published', 'archived']) // EnumValidatorType
|
|
151
|
+
|
|
152
|
+
// Date/time types
|
|
153
|
+
schema.date() // DateValidatorType
|
|
154
|
+
schema.datetime() // DatetimeValidatorType
|
|
155
|
+
schema.timestamp() // TimestampValidatorType
|
|
156
|
+
schema.timestampTz() // TimestampTzValidatorType (with timezone)
|
|
157
|
+
schema.unix() // UnixValidatorType
|
|
158
|
+
schema.time() // TimeValidatorType
|
|
159
|
+
|
|
160
|
+
// Binary/blob
|
|
161
|
+
schema.binary() // BinaryValidatorType
|
|
162
|
+
schema.blob() // BlobValidatorType
|
|
163
|
+
|
|
164
|
+
// JSON
|
|
165
|
+
schema.json() // JsonValidatorType
|
|
166
|
+
|
|
167
|
+
// Password
|
|
168
|
+
schema.password() // PasswordValidatorType
|
|
169
|
+
|
|
170
|
+
// Array
|
|
171
|
+
schema.array<T>() // ArrayValidatorType<T>
|
|
172
|
+
|
|
173
|
+
// Object
|
|
174
|
+
schema.object<T>(shapeSchema?) // ObjectValidatorType<T>
|
|
175
|
+
|
|
176
|
+
// Custom
|
|
177
|
+
schema.custom<T>(validationFn, message) // CustomValidatorType<T>
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
### Model Attribute Usage
|
|
181
|
+
|
|
182
|
+
Schema validators are used in `defineModel()` attribute validation:
|
|
183
|
+
|
|
184
|
+
```typescript
|
|
185
|
+
import { defineModel } from '@stacksjs/config'
|
|
186
|
+
import { schema } from '@stacksjs/validation'
|
|
187
|
+
|
|
188
|
+
export default defineModel({
|
|
189
|
+
attributes: {
|
|
190
|
+
name: {
|
|
191
|
+
validation: {
|
|
192
|
+
rule: schema.string().minLength(2).maxLength(100),
|
|
193
|
+
message: {
|
|
194
|
+
minLength: 'Name must be at least 2 characters',
|
|
195
|
+
maxLength: 'Name cannot exceed 100 characters',
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
},
|
|
199
|
+
|
|
200
|
+
email: {
|
|
201
|
+
validation: {
|
|
202
|
+
rule: schema.string().email(),
|
|
203
|
+
message: {
|
|
204
|
+
email: 'Please provide a valid email address',
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
},
|
|
208
|
+
|
|
209
|
+
price: {
|
|
210
|
+
validation: {
|
|
211
|
+
rule: schema.number().min(1),
|
|
212
|
+
message: {
|
|
213
|
+
min: 'Price must be at least 1',
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
},
|
|
217
|
+
|
|
218
|
+
status: {
|
|
219
|
+
validation: {
|
|
220
|
+
rule: schema.enum(['active', 'inactive', 'archived']),
|
|
221
|
+
message: {
|
|
222
|
+
enum: 'Invalid status value',
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
},
|
|
226
|
+
|
|
227
|
+
bio: {
|
|
228
|
+
validation: {
|
|
229
|
+
rule: schema.string().maxLength(500),
|
|
230
|
+
message: {
|
|
231
|
+
maxLength: 'Bio cannot exceed 500 characters',
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
},
|
|
235
|
+
}
|
|
236
|
+
})
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
## Model Validation (`validator.ts`)
|
|
240
|
+
|
|
241
|
+
### `validateField(modelFile, params)`
|
|
242
|
+
|
|
243
|
+
Validates request data against a model's attribute rules. Used internally by the framework for API request validation.
|
|
244
|
+
|
|
245
|
+
```typescript
|
|
246
|
+
import { validateField } from '@stacksjs/validation'
|
|
247
|
+
|
|
248
|
+
// Loads model file, extracts validation rules, validates params
|
|
249
|
+
const result = await validateField('User', { name: 'John', email: 'john@example.com' })
|
|
250
|
+
```
|
|
251
|
+
|
|
252
|
+
Behavior:
|
|
253
|
+
1. Finds the model file by name in user models or framework defaults
|
|
254
|
+
2. Extracts validation rules from model attributes
|
|
255
|
+
3. Converts attribute names to snake_case for validation
|
|
256
|
+
4. Sets custom error messages via `MessageProvider`
|
|
257
|
+
5. Validates using `schema.object(ruleObject).validate(params)`
|
|
258
|
+
6. Throws `HttpError(422)` with error JSON on validation failure
|
|
259
|
+
7. Throws `HttpError(404)` if model not found
|
|
260
|
+
8. Skips validation for attributes with default values unless `isRequired` is true
|
|
261
|
+
|
|
262
|
+
### `customValidate(attributes, params)`
|
|
263
|
+
|
|
264
|
+
Validates request data against custom attribute rules (not tied to a model):
|
|
265
|
+
|
|
266
|
+
```typescript
|
|
267
|
+
import { customValidate } from '@stacksjs/validation'
|
|
268
|
+
|
|
269
|
+
const result = await customValidate({
|
|
270
|
+
email: {
|
|
271
|
+
rule: schema.string().email(),
|
|
272
|
+
message: { email: 'Invalid email' }
|
|
273
|
+
},
|
|
274
|
+
age: {
|
|
275
|
+
rule: schema.number().min(18),
|
|
276
|
+
message: { min: 'Must be at least 18' }
|
|
277
|
+
}
|
|
278
|
+
}, requestData)
|
|
279
|
+
```
|
|
280
|
+
|
|
281
|
+
Uses `schema.object().shape(ruleObject)` for validation.
|
|
282
|
+
|
|
283
|
+
### `isObjectNotEmpty(obj)`
|
|
284
|
+
|
|
285
|
+
```typescript
|
|
286
|
+
isObjectNotEmpty({}) // false
|
|
287
|
+
isObjectNotEmpty({ a: 1 }) // true
|
|
288
|
+
isObjectNotEmpty(undefined) // false
|
|
289
|
+
```
|
|
290
|
+
|
|
291
|
+
## Error Reporter (`reporter.ts`)
|
|
292
|
+
|
|
293
|
+
Simple error accumulator for validation:
|
|
294
|
+
|
|
295
|
+
```typescript
|
|
296
|
+
import { reportError, getErrors } from '@stacksjs/validation'
|
|
297
|
+
|
|
298
|
+
reportError([{ message: 'Invalid', value: '', field: 'email' }])
|
|
299
|
+
const errors = getErrors() // returns accumulated MessageObject[]
|
|
300
|
+
```
|
|
301
|
+
|
|
302
|
+
Interface: `{ message: string, value: string, field: string }`
|
|
303
|
+
|
|
304
|
+
## Error Reporter Contract (from `rules.ts`)
|
|
305
|
+
|
|
306
|
+
VineJS-inspired types for the validation pipeline:
|
|
307
|
+
|
|
308
|
+
```typescript
|
|
309
|
+
interface FieldContext {
|
|
310
|
+
value: unknown
|
|
311
|
+
data: any // top-level object under validation
|
|
312
|
+
meta: Record<string, any>
|
|
313
|
+
mutate: (newValue: any, field: FieldContext) => void
|
|
314
|
+
report: ErrorReporterContract['report']
|
|
315
|
+
isValid: boolean
|
|
316
|
+
isDefined: boolean
|
|
317
|
+
wildCardPath: string // nested pointer, '*' for array members
|
|
318
|
+
parent: any
|
|
319
|
+
name: string | number
|
|
320
|
+
isArrayMember: boolean
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
interface ErrorReporterContract {
|
|
324
|
+
hasErrors: boolean
|
|
325
|
+
createError: () => Error
|
|
326
|
+
report: (message: string, rule: string, field: FieldContext, args?: Record<string, any>) => any
|
|
327
|
+
}
|
|
328
|
+
```
|
|
329
|
+
|
|
330
|
+
## Re-exports from @stacksjs/ts-validation
|
|
331
|
+
|
|
332
|
+
The package re-exports everything from `@stacksjs/ts-validation`, which includes:
|
|
333
|
+
|
|
334
|
+
- `v` and `schema` -- the validation instance
|
|
335
|
+
- `validator` -- the validator library (default export from lib)
|
|
336
|
+
- `MessageProvider`, `setCustomMessages` -- custom message handling
|
|
337
|
+
- All type definitions (ValidatorType, StringValidatorType, NumberValidatorType, etc.)
|
|
338
|
+
- Configuration utilities
|
|
339
|
+
|
|
340
|
+
## Validation Types (`types/index.ts`)
|
|
341
|
+
|
|
342
|
+
Local type definitions:
|
|
343
|
+
```typescript
|
|
344
|
+
interface ValidationResult {
|
|
345
|
+
valid: boolean
|
|
346
|
+
errors?: Array<{ message: string }>
|
|
347
|
+
}
|
|
348
|
+
|
|
349
|
+
interface ValidationRule {
|
|
350
|
+
validate: (value: unknown) => ValidationResult
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
type ValidationBoolean = ValidationRule
|
|
354
|
+
type ValidationEnum = ValidationRule
|
|
355
|
+
type ValidationNumber = ValidationRule
|
|
356
|
+
type ValidationString = ValidationRule
|
|
357
|
+
```
|
|
358
|
+
|
|
359
|
+
## Gotchas
|
|
360
|
+
- `isNumber()` in `index.ts` returns FALSE for `NaN` -- this differs from `typeof NaN === 'number'`
|
|
361
|
+
- `isObject()` in `index.ts` excludes arrays and null -- `isObject([])` is false
|
|
362
|
+
- `isObject()` in `is.ts` uses `toString()` check (`[object Object]`) which also excludes arrays/null but through a different mechanism
|
|
363
|
+
- `isPrimitive()` includes null and undefined (6 primitive types: string, number, boolean, null, undefined, symbol)
|
|
364
|
+
- Numeric classification functions (`isEvenOrOdd`, etc.) return string defaults for non-numbers rather than throwing
|
|
365
|
+
- Schema validators map to database column types -- `schema.integer()` creates an integer column, `schema.string()` creates a varchar, etc.
|
|
366
|
+
- `validateField` converts attribute names to snake_case using `snakeCase()` from `@stacksjs/strings`
|
|
367
|
+
- `validateField` skips attributes with default values unless `isRequired` is explicitly set
|
|
368
|
+
- Validation error messages are customizable per-rule in model definitions via the `message` object
|
|
369
|
+
- The `schema` export is the `v` instance from `@stacksjs/ts-validation` -- they are the same object
|
|
370
|
+
- Custom validators can be added with `schema.custom<T>(fn, message)` for types not covered by built-in validators
|
|
371
|
+
- `customValidate` uses `schema.object().shape()` while `validateField` uses `schema.object(ruleObject)` -- slightly different API
|
|
@@ -0,0 +1,315 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: stacks-whois
|
|
3
|
+
description: Use when performing WHOIS lookups in Stacks — domain queries, batch lookups, SOCKS proxy support, TLD server discovery, response parsing, the WhoIsParser class, or the built-in SocksClient. Covers @stacksjs/whois.
|
|
4
|
+
license: MIT
|
|
5
|
+
compatibility: Bun >= 1.3.0, TypeScript
|
|
6
|
+
allowed-tools: Read Edit Write Bash Grep Glob
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Stacks WHOIS
|
|
10
|
+
|
|
11
|
+
Domain WHOIS lookup with SOCKS proxy support, batch processing, TLD server discovery, and response parsing. Includes a native SOCKS4/SOCKS5 client implementation.
|
|
12
|
+
|
|
13
|
+
## Key Paths
|
|
14
|
+
- Core package: `storage/framework/core/whois/src/`
|
|
15
|
+
|
|
16
|
+
## Source Files
|
|
17
|
+
```
|
|
18
|
+
whois/src/
|
|
19
|
+
├── index.ts # whois(), lookup(), batchWhois(), tcpWhois(), WhoIsParser, exports
|
|
20
|
+
├── types.ts # WhoIsResponse, WhoIsOptions, ProxyData, ProxyType
|
|
21
|
+
├── constants.ts # IANA_CHK_URL, PARAMETERS, SERVERS
|
|
22
|
+
├── utils.ts # shallowCopy helper
|
|
23
|
+
└── socks.ts # Native SocksClient implementation (SOCKS4/SOCKS5)
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Main Functions
|
|
27
|
+
|
|
28
|
+
### whois() -- Primary Lookup
|
|
29
|
+
```typescript
|
|
30
|
+
async function whois(
|
|
31
|
+
domain: string,
|
|
32
|
+
parse?: boolean, // default: false (but still parses with default fields)
|
|
33
|
+
options?: WhoIsOptions | null,
|
|
34
|
+
): Promise<WhoIsResponse>
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
When `parse` is `false` (default), it still calls `WhoIsParser.parseData(rawData, null)` which parses with the default field set. When `parse` is `true` and `options.parseData` is provided, it uses a shallow copy of that object as the parse template.
|
|
38
|
+
|
|
39
|
+
Flow:
|
|
40
|
+
1. Determine TLD from domain (or use `options.tld`)
|
|
41
|
+
2. Find WHOIS server: check `SERVERS` map first, then query IANA via `findWhoIsServer()`
|
|
42
|
+
3. Get query parameters via `getParameters()` for the server
|
|
43
|
+
4. Execute TCP query via `tcpWhois()`
|
|
44
|
+
5. Parse response via `WhoIsParser.parseData()`
|
|
45
|
+
6. Returns `{ _raw: string, parsedData: any | null }`
|
|
46
|
+
|
|
47
|
+
### lookup() -- Parsed Lookup Shortcut
|
|
48
|
+
```typescript
|
|
49
|
+
function lookup(domain: string, options?: WhoIsOptions | null): Promise<WhoIsResponse>
|
|
50
|
+
```
|
|
51
|
+
Calls `whois(domain, true, options)` -- always parses the response.
|
|
52
|
+
|
|
53
|
+
### batchWhois() -- Batch Lookups
|
|
54
|
+
```typescript
|
|
55
|
+
async function batchWhois(
|
|
56
|
+
domains: string[],
|
|
57
|
+
parallel?: boolean, // default: false
|
|
58
|
+
threads?: number, // default: 1 (batch size for parallel mode)
|
|
59
|
+
parse?: boolean, // default: false
|
|
60
|
+
options?: WhoIsOptions | null,
|
|
61
|
+
): Promise<WhoIsResponse[]>
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
- Sequential mode (`parallel=false`): processes domains one at a time
|
|
65
|
+
- Parallel mode (`parallel=true`): processes in batches of `threads` size using `Promise.all`
|
|
66
|
+
- If `threads > domains.length`, clamps to `domains.length`
|
|
67
|
+
- Note: In parallel mode, only the last batch's results are returned (`response` is reassigned, not concatenated)
|
|
68
|
+
|
|
69
|
+
### tcpWhois() -- Raw TCP Query
|
|
70
|
+
```typescript
|
|
71
|
+
async function tcpWhois(
|
|
72
|
+
domain: string,
|
|
73
|
+
queryOptions: string, // server-specific prefix (e.g., '-T dn,ace')
|
|
74
|
+
server: string,
|
|
75
|
+
port: number, // default 43
|
|
76
|
+
encoding: string, // default 'utf-8'
|
|
77
|
+
proxy: ProxyData | null,
|
|
78
|
+
): Promise<string>
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
- Without proxy: creates `Net.Socket`, connects directly to WHOIS server on specified port
|
|
82
|
+
- With proxy: uses `SocksClient.createConnection()` to tunnel through SOCKS proxy
|
|
83
|
+
- Sends query as `"<queryOptions> <domain>\r\n"` or `"<domain>\r\n"` if no queryOptions
|
|
84
|
+
- Uses `TextDecoder` with specified encoding for response
|
|
85
|
+
|
|
86
|
+
## Server Discovery
|
|
87
|
+
|
|
88
|
+
### findWhoIsServer() -- Remote IANA Lookup
|
|
89
|
+
```typescript
|
|
90
|
+
async function findWhoIsServer(tld: string): Promise<string>
|
|
91
|
+
```
|
|
92
|
+
Fetches `https://www.iana.org/whois?q=<tld>` and extracts server from `whois:\s+(\S+)` regex match. Returns empty string on failure.
|
|
93
|
+
|
|
94
|
+
### getWhoIsServer() -- Local Lookup
|
|
95
|
+
```typescript
|
|
96
|
+
function getWhoIsServer(tld: keyof typeof SERVERS): string | undefined
|
|
97
|
+
```
|
|
98
|
+
Looks up TLD in the built-in `SERVERS` map. Special case: `'com'` always returns `'whois.verisign-grs.com'`.
|
|
99
|
+
|
|
100
|
+
### getTLD() -- Extract TLD
|
|
101
|
+
```typescript
|
|
102
|
+
function getTLD(domain: string): keyof typeof SERVERS
|
|
103
|
+
```
|
|
104
|
+
Splits domain by `.` and checks from longest suffix first against the `SERVERS` map. For example, `sub.example.co.uk` checks `co.uk` first (which exists in SERVERS), not just `uk`. Falls back to the last part if no match found.
|
|
105
|
+
|
|
106
|
+
### getParameters() -- Server Query Parameters
|
|
107
|
+
```typescript
|
|
108
|
+
function getParameters(server: string): string | undefined
|
|
109
|
+
```
|
|
110
|
+
Returns server-specific query format from the `PARAMETERS` map.
|
|
111
|
+
|
|
112
|
+
## WhoIsParser
|
|
113
|
+
|
|
114
|
+
```typescript
|
|
115
|
+
class WhoIsParser {
|
|
116
|
+
// Parse raw WHOIS text with custom or default field template
|
|
117
|
+
static parseData(rawData: string, outputData: any | null): any
|
|
118
|
+
|
|
119
|
+
// Internal iterative parser (private)
|
|
120
|
+
private static iterParse(rawData: string, outputData: any): any
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
When `outputData` is `null`, `parseData()` uses this default template:
|
|
125
|
+
```typescript
|
|
126
|
+
{
|
|
127
|
+
'Domain Name': '',
|
|
128
|
+
'Creation Date': '',
|
|
129
|
+
'Updated Date': '',
|
|
130
|
+
'Registry Expiry Date': '',
|
|
131
|
+
'Domain Status': [], // array collects multiple values
|
|
132
|
+
'Registrar': '',
|
|
133
|
+
}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
The parser iterates character by character through raw WHOIS text:
|
|
137
|
+
- Keys are identified when a line matches a key in `outputData`
|
|
138
|
+
- Values follow after `": "` separator
|
|
139
|
+
- Array-typed fields (like `Domain Status`) accumulate multiple values
|
|
140
|
+
- Parsing stops at `"Record maintained by"` or `">>>"` markers
|
|
141
|
+
|
|
142
|
+
Custom parse templates: pass an object with the field names you want extracted. Use empty string `''` for single values, use `[]` for fields with multiple values.
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
const result = await whois('example.com', true, {
|
|
146
|
+
parseData: {
|
|
147
|
+
'Domain Name': '',
|
|
148
|
+
'Domain Status': [], // collects ALL status values
|
|
149
|
+
'Registrar': '',
|
|
150
|
+
'Name Server': [], // collects ALL name servers
|
|
151
|
+
}
|
|
152
|
+
})
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
## Types
|
|
156
|
+
|
|
157
|
+
### WhoIsResponse
|
|
158
|
+
```typescript
|
|
159
|
+
interface WhoIsResponse {
|
|
160
|
+
_raw: string // raw text from WHOIS server
|
|
161
|
+
parsedData: any | null // parsed key-value pairs (null on error)
|
|
162
|
+
}
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### WhoIsOptions
|
|
166
|
+
```typescript
|
|
167
|
+
interface WhoIsOptions {
|
|
168
|
+
tld?: string | null // override TLD detection
|
|
169
|
+
encoding?: string | null // character encoding (default: 'utf-8')
|
|
170
|
+
proxy?: ProxyData | null // SOCKS proxy configuration
|
|
171
|
+
server?: string | null // override WHOIS server
|
|
172
|
+
serverPort?: number | null // override port (default: 43)
|
|
173
|
+
parseData?: object | null // custom parse template (keys to extract)
|
|
174
|
+
}
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### ProxyData
|
|
178
|
+
```typescript
|
|
179
|
+
interface ProxyData {
|
|
180
|
+
ip: string
|
|
181
|
+
port: number
|
|
182
|
+
username?: string | null
|
|
183
|
+
password?: string | null
|
|
184
|
+
type: ProxyType
|
|
185
|
+
}
|
|
186
|
+
```
|
|
187
|
+
|
|
188
|
+
### ProxyType
|
|
189
|
+
```typescript
|
|
190
|
+
enum ProxyType {
|
|
191
|
+
SOCKS4 = 0,
|
|
192
|
+
SOCKS5 = 1,
|
|
193
|
+
}
|
|
194
|
+
```
|
|
195
|
+
|
|
196
|
+
Note: `ProxyType.SOCKS4 = 0` and `ProxyType.SOCKS5 = 1` -- these are mapped to SOCKS versions `4` and `5` internally when creating SocksClient options.
|
|
197
|
+
|
|
198
|
+
## SOCKS Proxy Support
|
|
199
|
+
|
|
200
|
+
```typescript
|
|
201
|
+
const result = await whois('example.com', false, {
|
|
202
|
+
proxy: {
|
|
203
|
+
ip: '127.0.0.1',
|
|
204
|
+
port: 1080,
|
|
205
|
+
type: ProxyType.SOCKS5,
|
|
206
|
+
username: 'user', // optional
|
|
207
|
+
password: 'pass', // optional
|
|
208
|
+
}
|
|
209
|
+
})
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Built-in SocksClient (socks.ts)
|
|
213
|
+
|
|
214
|
+
Native SOCKS client implementation using `node:net`. Replaces the `socks` npm package.
|
|
215
|
+
|
|
216
|
+
```typescript
|
|
217
|
+
class SocksClient {
|
|
218
|
+
static createConnection(
|
|
219
|
+
options: SocksClientOptions,
|
|
220
|
+
callback: (err: Error | null, info?: SocksClientEstablishedEvent) => void,
|
|
221
|
+
): void
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
interface SocksClientOptions {
|
|
225
|
+
proxy: SocksProxy
|
|
226
|
+
command: 'connect' | 'bind' | 'associate'
|
|
227
|
+
destination: SocksDestination
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
interface SocksProxy {
|
|
231
|
+
host: string
|
|
232
|
+
port: number
|
|
233
|
+
type: 4 | 5 // SOCKS version
|
|
234
|
+
userId?: string
|
|
235
|
+
password?: string
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
interface SocksDestination {
|
|
239
|
+
host: string
|
|
240
|
+
port: number
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
interface SocksClientEstablishedEvent {
|
|
244
|
+
socket: Net.Socket
|
|
245
|
+
remoteHost?: string
|
|
246
|
+
remotePort?: number
|
|
247
|
+
}
|
|
248
|
+
```
|
|
249
|
+
|
|
250
|
+
### SOCKS4 Implementation
|
|
251
|
+
- Supports SOCKS4 and SOCKS4a (domain name support via special IP marker `0.0.0.1`)
|
|
252
|
+
- Request format: VN(1) + CD(1) + DSTPORT(2) + DSTIP(4) + USERID(var) + NULL(1)
|
|
253
|
+
- Success response: status byte `0x5A` (90)
|
|
254
|
+
|
|
255
|
+
### SOCKS5 Implementation
|
|
256
|
+
- Three-step handshake: greeting -> authentication (optional) -> connect request
|
|
257
|
+
- Supports no-auth (`0x00`) and username/password auth (`0x02`)
|
|
258
|
+
- Supports IPv4 (`0x01`), IPv6 (`0x04`), and domain name (`0x03`) address types
|
|
259
|
+
- Detailed error messages for all SOCKS5 status codes (general failure, not allowed, network unreachable, host unreachable, connection refused, TTL expired, command not supported, address type not supported)
|
|
260
|
+
|
|
261
|
+
## Constants
|
|
262
|
+
|
|
263
|
+
### IANA_CHK_URL
|
|
264
|
+
```typescript
|
|
265
|
+
const IANA_CHK_URL = 'https://www.iana.org/whois?q='
|
|
266
|
+
```
|
|
267
|
+
|
|
268
|
+
### PARAMETERS -- Server-Specific Query Formats
|
|
269
|
+
```typescript
|
|
270
|
+
const PARAMETERS: Record<string, string> = {
|
|
271
|
+
'whois.denic.de': '-T dn,ace',
|
|
272
|
+
'whois.nic.fr': '-V Md5.2',
|
|
273
|
+
}
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
### SERVERS -- TLD to WHOIS Server Mapping
|
|
277
|
+
Comprehensive mapping of hundreds of TLDs to their WHOIS servers. Examples:
|
|
278
|
+
- `'com'` -> `'whois.verisign-grs.com'`
|
|
279
|
+
- `'net'` -> `'whois.verisign-grs.com'`
|
|
280
|
+
- `'org'` -> `'whois.pir.org'`
|
|
281
|
+
- `'io'` -> `'whois.nic.io'`
|
|
282
|
+
- `'co.uk'` -> compound TLD support via `getTLD()` longest-match logic
|
|
283
|
+
- Country code TLDs, new gTLDs, compound TLDs (e.g., `br.com`, `co.ca`)
|
|
284
|
+
|
|
285
|
+
## Utility: shallowCopy (utils.ts)
|
|
286
|
+
|
|
287
|
+
```typescript
|
|
288
|
+
function shallowCopy<T>(obj: T): T
|
|
289
|
+
```
|
|
290
|
+
Recursively copies objects and arrays. Used to clone `parseData` templates before filling them with parsed values, so the original template is not mutated.
|
|
291
|
+
|
|
292
|
+
## Exports from index.ts
|
|
293
|
+
|
|
294
|
+
Functions: `whois`, `lookup`, `batchWhois`, `tcpWhois`, `findWhoIsServer`, `getWhoIsServer`, `getTLD`, `getParameters`
|
|
295
|
+
Classes: `WhoIsParser`, `SocksClient`
|
|
296
|
+
Constants: `IANA_CHK_URL`, `PARAMETERS`, `SERVERS`
|
|
297
|
+
Types: `WhoIsResponse`, `WhoIsOptions`, `ProxyData`, `ProxyType`, `SocksClientOptions`
|
|
298
|
+
|
|
299
|
+
## Dependencies
|
|
300
|
+
- `node:net` -- TCP socket connections (direct WHOIS queries and SOCKS client)
|
|
301
|
+
- `@stacksjs/logging` -- `log` for debug logging during lookups
|
|
302
|
+
|
|
303
|
+
## Gotchas
|
|
304
|
+
- `whois()` with `parse=false` still parses with default fields -- the `parse` flag controls whether custom `parseData` is used
|
|
305
|
+
- `batchWhois()` in parallel mode has a bug: it reassigns `response` each batch instead of concatenating, so only the last batch's results are returned
|
|
306
|
+
- `ProxyType` enum values are `0` and `1`, not `4` and `5` -- they are mapped to SOCKS versions internally
|
|
307
|
+
- `getWhoIsServer()` returns `undefined` for unknown TLDs, not an empty string
|
|
308
|
+
- `findWhoIsServer()` returns empty string `''` on failure (not `undefined`)
|
|
309
|
+
- `getTLD()` checks compound TLDs (like `co.uk`) before simple ones via longest-suffix matching
|
|
310
|
+
- The parser stops at `"Record maintained by"` or `">>>"` markers in the raw response
|
|
311
|
+
- WHOIS servers are rate-limited -- batch queries should use small thread counts
|
|
312
|
+
- `shallowCopy()` is a recursive deep copy despite its name -- it clones nested objects and arrays
|
|
313
|
+
- TCP connections use `node:net` Socket, not `fetch` -- WHOIS is a raw TCP protocol on port 43
|
|
314
|
+
- The SOCKS client uses callback-style API, not promises
|
|
315
|
+
- Query options are prepended to the domain in the TCP query (e.g., `"-T dn,ace example.de\r\n"`)
|