devendra-skill-package 1.0.2
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/.github/skills/boiler-project-generator/SKILL.md +103 -0
- package/.github/skills/boiler-project-generator/assets/templates/android/README.md +3 -0
- package/.github/skills/boiler-project-generator/assets/templates/angular/README.md +3 -0
- package/.github/skills/boiler-project-generator/assets/templates/flutter/README.md +3 -0
- package/.github/skills/boiler-project-generator/assets/templates/ios/README.md +3 -0
- package/.github/skills/boiler-project-generator/assets/templates/react/README.md +3 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/README.md +3 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/api-setup.ts +76 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/component-primary-button.tsx +29 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/env-config.env +4 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/feature-auth-screen.tsx +45 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/feature-dashboard-screen.tsx +45 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/feature-profile-screen.tsx +45 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/hook-use-app-boot.ts +11 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/navigation-setup.tsx +25 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/project-structure.md +24 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/redux-hooks.ts +5 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/redux-session-slice.ts +29 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/redux-store.ts +15 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/theme-index.ts +23 -0
- package/.github/skills/boiler-project-generator/assets/templates/react-native/utils-helpers.ts +7 -0
- package/.github/skills/boiler-project-generator/metadata.yaml +29 -0
- package/.github/skills/boiler-project-generator/references/android.md +19 -0
- package/.github/skills/boiler-project-generator/references/angular.md +14 -0
- package/.github/skills/boiler-project-generator/references/flutter.md +17 -0
- package/.github/skills/boiler-project-generator/references/ios.md +17 -0
- package/.github/skills/boiler-project-generator/references/react-native.md +103 -0
- package/.github/skills/boiler-project-generator/references/react.md +17 -0
- package/.github/skills/boiler-project-generator/scripts/angular.js +43 -0
- package/.github/skills/boiler-project-generator/scripts/generate-project.mjs +107 -0
- package/.github/skills/boiler-project-generator/scripts/init.js +105 -0
- package/.github/skills/boiler-project-generator/scripts/react-native.js +1041 -0
- package/.github/skills/boiler-project-generator/scripts/react.js +32 -0
- package/.github/skills/clean-architecture-generator/SKILL.md +235 -0
- package/.github/skills/clean-architecture-generator/references/architecture-core.md +126 -0
- package/.github/skills/clean-architecture-generator/references/platform-angular.md +374 -0
- package/.github/skills/clean-architecture-generator/references/platform-flutter.md +366 -0
- package/.github/skills/clean-architecture-generator/references/platform-react-native.md +590 -0
- package/.github/skills/clean-architecture-generator/references/platform-react.md +261 -0
- package/.github/skills/code-test-coverage-analyzer/SKILL.md +1358 -0
- package/.github/skills/code-test-coverage-analyzer/assets/config-questionnaire.md +118 -0
- package/.github/skills/code-test-coverage-analyzer/assets/conflict-resolution-protocol.md +99 -0
- package/.github/skills/code-test-coverage-analyzer/assets/coverage-calculation-rules.md +294 -0
- package/.github/skills/code-test-coverage-analyzer/assets/multi-strategy-search.md +145 -0
- package/.github/skills/code-test-coverage-analyzer/assets/output-file-contracts.md +651 -0
- package/.github/skills/code-test-coverage-analyzer/assets/status-definitions.md +273 -0
- package/.github/skills/code-test-coverage-analyzer/examples/example-invocation.md +208 -0
- package/.github/skills/code-test-coverage-analyzer/references/android-patterns.md +229 -0
- package/.github/skills/code-test-coverage-analyzer/references/angular-patterns.md +177 -0
- package/.github/skills/code-test-coverage-analyzer/references/backend-patterns.md +383 -0
- package/.github/skills/code-test-coverage-analyzer/references/flutter-patterns.md +254 -0
- package/.github/skills/code-test-coverage-analyzer/references/ios-patterns.md +228 -0
- package/.github/skills/code-test-coverage-analyzer/references/react-native-patterns.md +431 -0
- package/.github/skills/code-test-coverage-analyzer/references/react-patterns.md +206 -0
- package/.github/skills/code-test-coverage-analyzer/scripts/detect-platform.ps1 +261 -0
- package/.github/skills/code-test-coverage-analyzer/scripts/scan-repository.ps1 +242 -0
- package/.github/skills/code-test-coverage-analyzer/templates/brd-compliance-row.md +107 -0
- package/.github/skills/code-test-coverage-analyzer/templates/test-case-row.md +130 -0
- package/.github/skills/code-test-coverage-analyzer/templates/user-story-compliance-row.md +170 -0
- package/.github/skills/custom-font-integrator/SKILL.md +373 -0
- package/.github/skills/custom-font-integrator/assets/FontTestScreen.js +150 -0
- package/.github/skills/custom-font-integrator/references/example-info-plist.xml +21 -0
- package/.github/skills/custom-font-integrator/scripts/setup-fonts.sh +99 -0
- package/.github/skills/encryption-decryption-utility/Instructions.md +282 -0
- package/.github/skills/encryption-decryption-utility/README.md +222 -0
- package/.github/skills/encryption-decryption-utility/SKILL.md +645 -0
- package/.github/skills/encryption-decryption-utility/assets/encryption-config-template.json +13 -0
- package/.github/skills/encryption-decryption-utility/assets/platform-matrix.json +180 -0
- package/.github/skills/encryption-decryption-utility/metadata.yaml +51 -0
- package/.github/skills/encryption-decryption-utility/references/android-crypto.md +157 -0
- package/.github/skills/encryption-decryption-utility/references/angular-crypto.md +130 -0
- package/.github/skills/encryption-decryption-utility/references/approach-1-webcrypto.md +95 -0
- package/.github/skills/encryption-decryption-utility/references/approach-2-rsa-aes-cbc.md +111 -0
- package/.github/skills/encryption-decryption-utility/references/approach-3-aes-sharedkey.md +114 -0
- package/.github/skills/encryption-decryption-utility/references/architecture.md +233 -0
- package/.github/skills/encryption-decryption-utility/references/backend-alignment.md +506 -0
- package/.github/skills/encryption-decryption-utility/references/dependency-guidance.md +234 -0
- package/.github/skills/encryption-decryption-utility/references/ec-implementation.md +832 -0
- package/.github/skills/encryption-decryption-utility/references/error-handling-playbook.md +234 -0
- package/.github/skills/encryption-decryption-utility/references/flutter-crypto.md +105 -0
- package/.github/skills/encryption-decryption-utility/references/ios-crypto.md +338 -0
- package/.github/skills/encryption-decryption-utility/references/native-rsa-implementation.md +373 -0
- package/.github/skills/encryption-decryption-utility/references/node-crypto.md +86 -0
- package/.github/skills/encryption-decryption-utility/references/react-crypto.md +105 -0
- package/.github/skills/encryption-decryption-utility/references/react-native-crypto.md +1001 -0
- package/.github/skills/encryption-decryption-utility/references/react-web-crypto.md +668 -0
- package/.github/skills/encryption-decryption-utility/references/security-checklist.md +176 -0
- package/.github/skills/encryption-decryption-utility/references/web-crypto.md +74 -0
- package/.github/skills/encryption-decryption-utility/scripts/detect.js +128 -0
- package/.github/skills/encryption-decryption-utility/scripts/install.js +1713 -0
- package/.github/skills/encryption-decryption-utility/scripts/setup.js +800 -0
- package/.github/skills/encryption-decryption-utility/template.md +241 -0
- package/.github/skills/encryption-decryption-utility/templates/config-questionnaire.md +467 -0
- package/.github/skills/encryption-decryption-utility/templates/delivery-checklist.md +206 -0
- package/.github/skills/encryption-decryption-utility/templates/implementation-plan.md +304 -0
- package/.github/skills/feature-generator/SKILL.MD +2741 -0
- package/.github/skills/feature-generator/assets/fingerprint-schema.json +385 -0
- package/.github/skills/feature-generator/assets/spec-template.md +172 -0
- package/.github/skills/feature-generator/assets/transform-rules.json +82 -0
- package/.github/skills/feature-generator/references/api-envelope-patterns.md +327 -0
- package/.github/skills/feature-generator/references/screen-logic-patterns.md +399 -0
- package/.github/skills/feature-generator/references/state-library-patterns.md +464 -0
- package/.github/skills/figma-ui-mapper/README.md +34 -0
- package/.github/skills/figma-ui-mapper/SKILL.md +101 -0
- package/.github/skills/figma-ui-mapper/assets/templates/component-map-template.md +30 -0
- package/.github/skills/figma-ui-mapper/assets/templates/generation-report-template.md +49 -0
- package/.github/skills/figma-ui-mapper/metadata.yaml +22 -0
- package/.github/skills/figma-ui-mapper/references/android.md +11 -0
- package/.github/skills/figma-ui-mapper/references/angular.md +18 -0
- package/.github/skills/figma-ui-mapper/references/capacitor.md +18 -0
- package/.github/skills/figma-ui-mapper/references/common.md +23 -0
- package/.github/skills/figma-ui-mapper/references/expo.md +18 -0
- package/.github/skills/figma-ui-mapper/references/flutter.md +18 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/angular/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/capacitor/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/expo/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/flutter/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/ionic/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/kotlin-multiplatform/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/native-android/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/native-ios/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/next/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/nuxt/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/react/rules.md +19 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/react-native/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/svelte/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/frameworks/vue/rules.md +23 -0
- package/.github/skills/figma-ui-mapper/references/ionic.md +18 -0
- package/.github/skills/figma-ui-mapper/references/ios.md +11 -0
- package/.github/skills/figma-ui-mapper/references/kotlin-multiplatform.md +18 -0
- package/.github/skills/figma-ui-mapper/references/native-android.md +18 -0
- package/.github/skills/figma-ui-mapper/references/native-ios.md +18 -0
- package/.github/skills/figma-ui-mapper/references/next.md +18 -0
- package/.github/skills/figma-ui-mapper/references/nuxt.md +18 -0
- package/.github/skills/figma-ui-mapper/references/react-figma-guideline.md +21 -0
- package/.github/skills/figma-ui-mapper/references/react-native.md +18 -0
- package/.github/skills/figma-ui-mapper/references/react.md +18 -0
- package/.github/skills/figma-ui-mapper/references/script-usage.md +46 -0
- package/.github/skills/figma-ui-mapper/references/svelte.md +18 -0
- package/.github/skills/figma-ui-mapper/references/vue.md +18 -0
- package/.github/skills/figma-ui-mapper/references/workflow.md +74 -0
- package/.github/skills/figma-ui-mapper/scripts/generate-page-through-figma.js +635 -0
- package/.github/skills/figma-ui-mapper/scripts/generate-react-page-through-figma.js +4 -0
- package/.github/skills/frontend-task-breakdown/SKILL.md +734 -0
- package/.github/skills/md-file-converter/SKILL.md +291 -0
- package/.github/skills/md-file-converter/config/formats.json +114 -0
- package/.github/skills/md-file-converter/extractors/extract-docx.sh +120 -0
- package/.github/skills/md-file-converter/extractors/extract-eml.py +108 -0
- package/.github/skills/md-file-converter/extractors/extract-pdf.sh +97 -0
- package/.github/skills/md-file-converter/extractors/extract-pptx.py +143 -0
- package/.github/skills/md-file-converter/extractors/extract-xlsx.py +175 -0
- package/.github/skills/md-file-converter/scripts/check-tools.sh +47 -0
- package/.github/skills/md-file-converter/scripts/extract-archive.sh +83 -0
- package/.github/skills/md-file-converter/scripts/extract-ocr.sh +77 -0
- package/.github/skills/md-file-converter/scripts/get-metadata.sh +57 -0
- package/.github/skills/md-file-converter/templates/output.md +73 -0
- package/.github/skills/md-file-converter/templates/unsupported-object.md +6 -0
- package/.github/skills/mockAPI-contract-generator/SKILL.md +607 -0
- package/.github/skills/test-case-validator/CHANGELOG.md +155 -0
- package/.github/skills/test-case-validator/CONFIGURATION.md +130 -0
- package/.github/skills/test-case-validator/EXAMPLES.md +50 -0
- package/.github/skills/test-case-validator/QUALITY_SCORING.md +98 -0
- package/.github/skills/test-case-validator/README.md +111 -0
- package/.github/skills/test-case-validator/REPORT_TEMPLATE.md +116 -0
- package/.github/skills/test-case-validator/SKILL.md +209 -0
- package/.github/skills/test-case-validator/SYSTEM_PROMPT.md +127 -0
- package/.github/skills/test-case-validator/TRACEABILITY_ENGINE.md +152 -0
- package/.github/skills/test-case-validator/VALIDATION_RULES.md +411 -0
- package/.github/skills/test-case-validator/config/default.config.yaml +62 -0
- package/.github/skills/test-case-validator/docs/ARCHITECTURE.md +66 -0
- package/.github/skills/test-case-validator/docs/EXTENDING.md +85 -0
- package/.github/skills/test-case-validator/docs/FAQ.md +88 -0
- package/.github/skills/test-case-validator/docs/VERSIONING.md +55 -0
- package/.github/skills/test-case-validator/examples/example-1-manual-qa-ecommerce/input-brd.md +43 -0
- package/.github/skills/test-case-validator/examples/example-1-manual-qa-ecommerce/input-test-cases.csv +9 -0
- package/.github/skills/test-case-validator/examples/example-1-manual-qa-ecommerce/input-user-story.md +29 -0
- package/.github/skills/test-case-validator/examples/example-1-manual-qa-ecommerce/output-report.md +303 -0
- package/.github/skills/test-case-validator/examples/example-2-automated-frontend-suite/input-spec.md +43 -0
- package/.github/skills/test-case-validator/examples/example-2-automated-frontend-suite/input-test-files-index.md +56 -0
- package/.github/skills/test-case-validator/examples/example-2-automated-frontend-suite/output-report.md +274 -0
- package/.github/skills/test-case-validator/prompts/00-applicability-resolution.md +61 -0
- package/.github/skills/test-case-validator/prompts/01-extraction-user-story.md +58 -0
- package/.github/skills/test-case-validator/prompts/02-extraction-brd.md +64 -0
- package/.github/skills/test-case-validator/prompts/03-extraction-test-cases.md +92 -0
- package/.github/skills/test-case-validator/prompts/04-traceability-matrix.md +41 -0
- package/.github/skills/test-case-validator/prompts/05-coverage-analysis.md +46 -0
- package/.github/skills/test-case-validator/prompts/06-missing-scenario-detection.md +32 -0
- package/.github/skills/test-case-validator/prompts/07-duplicate-detection.md +36 -0
- package/.github/skills/test-case-validator/prompts/08-risk-analysis.md +39 -0
- package/.github/skills/test-case-validator/prompts/09-gated-wiring-validation.md +53 -0
- package/.github/skills/test-case-validator/prompts/10-observation-report.md +56 -0
- package/.github/skills/test-case-validator/prompts/11-final-report-assembly.md +57 -0
- package/.github/skills/test-case-validator/templates/coverage-table.md +25 -0
- package/.github/skills/test-case-validator/templates/executive-summary.md +38 -0
- package/.github/skills/test-case-validator/templates/final-summary-block.md +87 -0
- package/.github/skills/test-case-validator/templates/observation-entry.md +41 -0
- package/.github/skills/test-case-validator/templates/rtm-row.md +25 -0
- package/.github/skills/validation-engine-builder/README.md +50 -0
- package/.github/skills/validation-engine-builder/SKILL.md +241 -0
- package/.github/skills/validation-engine-builder/references/core.md +158 -0
- package/.github/skills/validation-engine-builder/references/platform-angular.md +166 -0
- package/.github/skills/validation-engine-builder/references/platform-flutter.md +118 -0
- package/.github/skills/validation-engine-builder/references/platform-react-native.md +170 -0
- package/.github/skills/validation-engine-builder/references/platform-react.md +94 -0
- package/.github/skills/validation-engine-builder/scripts/apply-to-project.js +80 -0
- package/.github/skills/validation-engine-builder/scripts/generate-angular.js +271 -0
- package/.github/skills/validation-engine-builder/scripts/generate-flutter.js +298 -0
- package/.github/skills/validation-engine-builder/scripts/generate-react-native.js +217 -0
- package/.github/skills/validation-engine-builder/scripts/generate-react.js +163 -0
- package/.github/skills/validation-engine-builder/scripts/install-deps.js +53 -0
- package/.github/skills/validation-engine-builder/scripts/shared/detect-platform.js +68 -0
- package/.github/skills/validation-engine-builder/scripts/shared/npm-deps.js +103 -0
- package/.github/skills/validation-engine-builder/scripts/shared/rhf-hook.js +43 -0
- package/.github/skills/validation-engine-builder/scripts/shared/ts-messages-regex.js +62 -0
- package/.github/skills/validation-engine-builder/scripts/shared/util.js +44 -0
- package/.github/skills/validation-engine-builder/scripts/shared/yup-schemas.js +80 -0
- package/.github/skills/validation-engine-builder/template.md +73 -0
- package/.github/skills/validation-engine-builder/templates/messages.json +22 -0
- package/.github/skills/validation-engine-builder/templates/regex.json +16 -0
- package/.github/skills/validation-engine-builder/templates/schemas.json +48 -0
- package/bin/index.js +145 -0
- package/package.json +22 -0
- package/readme.md +0 -0
|
@@ -0,0 +1,241 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: validation-engine-builder
|
|
3
|
+
description: Apply centralized form validation to any screen, page, component, or widget across React Native, React (web), Angular, or Flutter. AI detects the target platform, reads the file, identifies every input field, reasons about the correct validation rules for each field, updates the central messages/regex/schema templates, and rewires the file with that platform's native form-validation mechanism (react-hook-form+Yup for React Native/React, Angular Reactive Forms Validators for Angular, TextFormField.validator for Flutter). All error messages in one file, all regex in one file, one shared schema template drives every platform. Use this skill when the user wants to add validation to a screen, page, form, login, signup, OTP, profile, address, or any input-based UI on any of the 4 supported platforms.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Validation Engine — Multi-Platform (AI-Driven)
|
|
7
|
+
|
|
8
|
+
This skill is AI-driven. The agent detects the platform, reads the target file, reasons about each
|
|
9
|
+
field, and applies validation directly. Do NOT rely on a script to analyze or wire an existing
|
|
10
|
+
screen/page/component/widget — the AI does the field analysis and file integration.
|
|
11
|
+
|
|
12
|
+
The scripts in this skill are for:
|
|
13
|
+
1. Detecting which of the 4 supported platforms the target project is
|
|
14
|
+
2. Installing compatible dependencies (React Native / React only — Angular and Flutter need none)
|
|
15
|
+
3. Regenerating the platform's validation output files after templates are updated
|
|
16
|
+
|
|
17
|
+
---
|
|
18
|
+
|
|
19
|
+
## Supported platforms
|
|
20
|
+
|
|
21
|
+
| Platform | Detection signal | Reference file |
|
|
22
|
+
|---|---|---|
|
|
23
|
+
| React Native | `package.json` has a `react-native` dependency | `references/platform-react-native.md` |
|
|
24
|
+
| React (web) | `package.json` has `react` + `react-dom`, no `react-native` | `references/platform-react.md` |
|
|
25
|
+
| Angular | `angular.json` at the project root | `references/platform-angular.md` |
|
|
26
|
+
| Flutter | `pubspec.yaml` with a `flutter:` SDK entry | `references/platform-flutter.md` |
|
|
27
|
+
|
|
28
|
+
Do not generate for a platform outside this list — there is no reference file for it, and
|
|
29
|
+
generating from memory for an unsupported platform (Vue, native Android/iOS, a backend framework)
|
|
30
|
+
is exactly the kind of unverified assumption this skill exists to avoid. Say so explicitly instead.
|
|
31
|
+
|
|
32
|
+
## When this skill applies
|
|
33
|
+
|
|
34
|
+
- User asks to add validation to a screen, page, form, or component
|
|
35
|
+
- User provides a file path to a screen/page/component/widget, or has one open
|
|
36
|
+
- User mentions fields like email, password, phone, OTP, name, address, date
|
|
37
|
+
- User wants form error messages centralized so they can be changed in one place
|
|
38
|
+
|
|
39
|
+
---
|
|
40
|
+
|
|
41
|
+
## STOP — READ REFERENCE FILES BEFORE ANY CODE
|
|
42
|
+
|
|
43
|
+
Always read, in this order:
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
.github/skills/validation-engine-builder/references/core.md
|
|
47
|
+
.github/skills/validation-engine-builder/references/platform-[detected-platform].md
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
- `core.md` — platform-agnostic: field-type detection quick-reference, available regex/message/
|
|
51
|
+
schema keys, golden rules. Applies identically on every platform, always read first.
|
|
52
|
+
- Exactly **one** `platform-*.md` file — the concrete wiring pattern (Controller vs `register()`
|
|
53
|
+
vs `FormGroup` vs `TextFormField.validator`), dependency table, and per-field props for the
|
|
54
|
+
platform detected below.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Full AI workflow (follow every step in order)
|
|
59
|
+
|
|
60
|
+
### Step 1 — Detect the platform
|
|
61
|
+
|
|
62
|
+
Check, in this order, and stop at the first match:
|
|
63
|
+
|
|
64
|
+
1. `pubspec.yaml` at the project root with a `flutter:` entry under `dependencies` → **Flutter**
|
|
65
|
+
2. `angular.json` at the project root → **Angular**
|
|
66
|
+
3. `package.json`: `react-native` in `dependencies`/`devDependencies` → **React Native**
|
|
67
|
+
4. `package.json`: `react` + `react-dom` present, `react-native` absent → **React (web)**
|
|
68
|
+
|
|
69
|
+
If more than one signal matches (a monorepo containing more than one app) or none match, **ask the
|
|
70
|
+
user** which platform this request targets — never guess. State the detected (or confirmed)
|
|
71
|
+
platform before proceeding, and load exactly that one `platform-*.md` file for the rest of this
|
|
72
|
+
request.
|
|
73
|
+
|
|
74
|
+
### Step 2 — Read the target file
|
|
75
|
+
|
|
76
|
+
Read the screen/page/component/widget file the user provided or currently has open. Identify every
|
|
77
|
+
input field:
|
|
78
|
+
- React Native: `TextInput` components
|
|
79
|
+
- React (web): `<input>`/`<select>`/`<textarea>` elements
|
|
80
|
+
- Angular: template `<input>` elements bound via `formControlName`, or the component's
|
|
81
|
+
`FormGroup`/`FormControl` declarations
|
|
82
|
+
- Flutter: `TextFormField` widgets
|
|
83
|
+
|
|
84
|
+
For each, record the variable/control name, placeholder/label text, and surrounding context
|
|
85
|
+
(label, comment). Build a field list:
|
|
86
|
+
```
|
|
87
|
+
fieldName | placeholder/label | inferred type
|
|
88
|
+
email | "Email address" | email
|
|
89
|
+
password | "Password" | password
|
|
90
|
+
phone | "Mobile number" | phone
|
|
91
|
+
```
|
|
92
|
+
Use `core.md`'s field-type detection quick-reference table for the inference — it is identical on
|
|
93
|
+
every platform.
|
|
94
|
+
|
|
95
|
+
### Step 3 — Check / install dependencies (platform-conditional)
|
|
96
|
+
|
|
97
|
+
**React Native / React (web)**: read `package.json`. Check if `react-hook-form`,
|
|
98
|
+
`@hookform/resolvers`, `yup` are present. If any are missing, run:
|
|
99
|
+
```powershell
|
|
100
|
+
node .github/skills/validation-engine-builder/scripts/install-deps.js --projectPath <path> --platform <react-native|react>
|
|
101
|
+
```
|
|
102
|
+
The script installs version-compatible packages — see `platform-react-native.md`'s dependency
|
|
103
|
+
table (React web uses the same table with no RN-version gate).
|
|
104
|
+
|
|
105
|
+
**Angular / Flutter**: nothing to install. Angular's Reactive Forms ships with `@angular/forms`;
|
|
106
|
+
Flutter's `TextFormField.validator` needs no package. Confirm this and move on — do not run
|
|
107
|
+
`install-deps.js` for these two platforms (it will no-op with an explanatory message if run anyway).
|
|
108
|
+
|
|
109
|
+
### Step 4 — Determine validation rules for each field
|
|
110
|
+
|
|
111
|
+
For every field identified in Step 2, decide the rules using `core.md`'s field-type table:
|
|
112
|
+
|
|
113
|
+
| Field type | Rules to apply |
|
|
114
|
+
|---|---|
|
|
115
|
+
| `email` | required, regex: email |
|
|
116
|
+
| `password` | required, min: 8 — add `regex: password` + `regexMessage: passwordStrength` for signup/register screens; omit regex for login |
|
|
117
|
+
| `confirmPassword` | required, min: 8 — note: must match password (see the platform file's cross-field section — this is never expressible in `schemas.json`) |
|
|
118
|
+
| `phone` / `mobile` | required, regex: phone (10 digits) |
|
|
119
|
+
| `otp` | required, regex: otp (6 digits) |
|
|
120
|
+
| `name` / `fullName` / `firstName` / `lastName` | required, min: 2, regex: name |
|
|
121
|
+
| `postalCode` / `zipCode` | required, regex: postalCode (generic 6-digit, allows leading zero) |
|
|
122
|
+
| `pincode` (India) | required, regex: pincode (6-digit, non-zero start — use this instead of postalCode for Indian pincodes) |
|
|
123
|
+
| `url` / `website` | optional, regex: url |
|
|
124
|
+
| `alphanumeric` field | required, regex: alphanumeric |
|
|
125
|
+
| `date` / `dob` / `dateOfBirth` | required, regex: date |
|
|
126
|
+
| Generic required text | required, min: 2 |
|
|
127
|
+
| Generic optional text | nullable |
|
|
128
|
+
| Number input | type: number, required |
|
|
129
|
+
|
|
130
|
+
Cross-reference `templates/regex.json` — only reference regex keys that exist there.
|
|
131
|
+
Cross-reference `templates/messages.json` — only reference message keys that exist there.
|
|
132
|
+
If a new regex or message is needed, add it to the templates first (Step 5).
|
|
133
|
+
|
|
134
|
+
This step is identical across all 4 platforms — the field-rule shape (`type`/`required`/`min`/
|
|
135
|
+
`max`/`regex`/`regexMessage`/`nullable`/`label`) is the shared contract that every platform's
|
|
136
|
+
generator compiles from.
|
|
137
|
+
|
|
138
|
+
### Step 5 — Update templates if needed
|
|
139
|
+
|
|
140
|
+
**Only** update templates when a new validation type is needed that is not already covered by an
|
|
141
|
+
existing key — check `core.md`'s available-keys tables first.
|
|
142
|
+
|
|
143
|
+
#### 5a. Add missing message to `templates/messages.json`
|
|
144
|
+
Add the new message key with a clear string value. Never duplicate existing keys.
|
|
145
|
+
For required-field messages, use `{{field}}` placeholder, e.g. `"required": "{{field}} is required"`.
|
|
146
|
+
|
|
147
|
+
#### 5b. Add missing regex to `templates/regex.json`
|
|
148
|
+
Add the new regex key with a valid JSON-escaped regex string. Use double-escaped backslashes (`\\d`
|
|
149
|
+
for `\d`). Never duplicate existing keys. The same pattern string compiles into every platform's
|
|
150
|
+
target language (`RegExp` in TS, `RegExp` in Dart) — verify it doesn't rely on a JS-only regex
|
|
151
|
+
feature Dart's engine lacks if adding something unusual (lookahead/lookbehind are both fine; Dart
|
|
152
|
+
supports them).
|
|
153
|
+
|
|
154
|
+
#### 5c. Add or update schema in `templates/schemas.json`
|
|
155
|
+
|
|
156
|
+
Check if a schema already exists that matches the target fields — reuse the key if so. Field
|
|
157
|
+
definition format:
|
|
158
|
+
|
|
159
|
+
```json
|
|
160
|
+
"screenNameForm": {
|
|
161
|
+
"email": { "type": "string", "required": true, "regex": "email", "label": "Email" },
|
|
162
|
+
"password": { "type": "string", "required": true, "min": 8, "label": "Password" }
|
|
163
|
+
}
|
|
164
|
+
```
|
|
165
|
+
|
|
166
|
+
| Property | Type | Description |
|
|
167
|
+
|---|---|---|
|
|
168
|
+
| `type` | `"string"` or `"number"` | Base type |
|
|
169
|
+
| `required` | `boolean` | Field must have a value |
|
|
170
|
+
| `min` | `number` | Minimum length (string) or minimum value (number) |
|
|
171
|
+
| `max` | `number` | Maximum length (string) or maximum value (number) |
|
|
172
|
+
| `regex` | `string` | Key from `regex.json` |
|
|
173
|
+
| `regexMessage` | `string` | Key from `messages.json` for the regex error (defaults to the regex key name) |
|
|
174
|
+
| `nullable` | `boolean` | Field may be empty/absent |
|
|
175
|
+
| `label` | `string` | Human-readable field name (used in the required message) |
|
|
176
|
+
|
|
177
|
+
### Step 6 — Regenerate the validation output
|
|
178
|
+
|
|
179
|
+
```powershell
|
|
180
|
+
node .github/skills/validation-engine-builder/scripts/apply-to-project.js --projectPath <path> --platform <react-native|react|angular|flutter>
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
This regenerates the platform's validation output only (see the platform file for the exact output
|
|
184
|
+
location and file list) — it does not scaffold or rewrite the target screen/page/component itself.
|
|
185
|
+
|
|
186
|
+
### Step 7 — Rewire the target file with validation wired
|
|
187
|
+
|
|
188
|
+
Rewrite the file using the wiring pattern documented in the detected platform's reference file:
|
|
189
|
+
|
|
190
|
+
- **React Native**: `Controller` from `react-hook-form` + `useValidatedForm` + `ValidationError` — see `platform-react-native.md`
|
|
191
|
+
- **React (web)**: `register()` from `react-hook-form` (not `Controller` — native `<input>` doesn't need it) + `useValidatedForm` + `ValidationError` — see `platform-react.md`
|
|
192
|
+
- **Angular**: `FormBuilder`/`FormGroup` built in the constructor body (never a field initializer — see the ordering warning in `platform-angular.md`) + `Validators` + `<app-validation-error>` — see `platform-angular.md`
|
|
193
|
+
- **Flutter**: `TextFormField.validator` pointing at the matching static validator method, wrapped in a `Form` + `GlobalKey<FormState>` — see `platform-flutter.md`
|
|
194
|
+
|
|
195
|
+
Each platform file's "optional screen/page scaffold generator" section documents a `generateScreen()`
|
|
196
|
+
helper for brand-new files; for an existing file, wire it by hand following the same pattern instead
|
|
197
|
+
of overwriting it.
|
|
198
|
+
|
|
199
|
+
---
|
|
200
|
+
|
|
201
|
+
## Strict rules (MUST follow — every platform)
|
|
202
|
+
|
|
203
|
+
1. Never hardcode any error message string in a component — all strings from the generated
|
|
204
|
+
messages module (`VALIDATION_MESSAGES` in TS, `ValidationMessages` in Dart).
|
|
205
|
+
2. Never hardcode any regex in a component — all patterns from the generated regex module
|
|
206
|
+
(`VALIDATION_REGEX` in TS, `ValidationRegex` in Dart).
|
|
207
|
+
3. Reuse existing schemas — check `templates/schemas.json` before creating a new schema key.
|
|
208
|
+
4. Never edit the generated output files directly — edit `templates/*.json` and re-run
|
|
209
|
+
`apply-to-project.js`. The one documented exception is a cross-field validator (confirmPassword,
|
|
210
|
+
etc.) — see the platform file for where that goes; each platform has its own answer since none
|
|
211
|
+
of them can express cross-field rules in the shared JSON template.
|
|
212
|
+
5. Never duplicate a schema — if an existing schema key covers the fields, reuse it.
|
|
213
|
+
6. Adjust relative import paths based on the target file's actual location — compute this from the
|
|
214
|
+
real project structure (see the platform file's generator notes), never a fixed assumption.
|
|
215
|
+
7. See the loaded platform file for additional platform-specific strict rules (e.g. always use
|
|
216
|
+
`Controller` on React Native; never build a `FormGroup` in an Angular field initializer).
|
|
217
|
+
|
|
218
|
+
---
|
|
219
|
+
|
|
220
|
+
## Reusing validation across multiple screens/pages/components
|
|
221
|
+
|
|
222
|
+
If two files share the same fields (e.g. two login screens, an admin login and a user login), use
|
|
223
|
+
the same schema key for both — do not create a duplicate schema. The validation rules and messages
|
|
224
|
+
are identical and stay in sync automatically. See the platform file's "Reusing the same validation"
|
|
225
|
+
section for the exact syntax on that platform.
|
|
226
|
+
|
|
227
|
+
---
|
|
228
|
+
|
|
229
|
+
## After applying validation, verify
|
|
230
|
+
|
|
231
|
+
Universal (every platform):
|
|
232
|
+
1. No hardcoded error strings remain in the target file.
|
|
233
|
+
2. Every input field has validation wired and a corresponding error-message display (or, on
|
|
234
|
+
Flutter, relies on `TextFormField`'s own built-in error rendering — no separate widget needed).
|
|
235
|
+
3. The submit action is gated on the form's validity state.
|
|
236
|
+
|
|
237
|
+
Platform-specific — see the matching section in the platform file:
|
|
238
|
+
- **React Native**: every `TextInput` wrapped in `Controller`; submit calls `handleSubmit(onSubmit)`; `isValid` gates the submit button.
|
|
239
|
+
- **React (web)**: every `<input>` uses `register()`; submit calls `handleSubmit(onSubmit)`; `isValid` gates the submit button.
|
|
240
|
+
- **Angular**: `FormGroup` built in the constructor body (not a field initializer); submit checks `this.form.invalid` and calls `markAllAsTouched()` on failure.
|
|
241
|
+
- **Flutter**: every `TextEditingController` is disposed in `dispose()`; submit calls `_formKey.currentState!.validate()`.
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
# Validation Engine — Core Reference (all platforms)
|
|
2
|
+
|
|
3
|
+
This file is platform-agnostic — everything here applies identically whether the target project is
|
|
4
|
+
React Native, React (web), Angular, or Flutter. Read this first, then read exactly one
|
|
5
|
+
`platform-*.md` file for the platform-specific wiring syntax (Controller vs `register()` vs
|
|
6
|
+
`FormGroup` vs `TextFormField.validator`).
|
|
7
|
+
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
## Field type detection quick-reference
|
|
11
|
+
|
|
12
|
+
When reading a screen/page/component/widget file, infer the field type from variable names,
|
|
13
|
+
placeholder text, and surrounding context — this inference is identical on every platform:
|
|
14
|
+
|
|
15
|
+
| Clue in code | Inferred field type |
|
|
16
|
+
|---|---|
|
|
17
|
+
| `email`, `emailAddress`, `userEmail` | email |
|
|
18
|
+
| `password`, `pwd`, `pass` | password |
|
|
19
|
+
| `confirmPassword`, `repeatPassword`, `rePassword` | confirmPassword |
|
|
20
|
+
| `phone`, `mobile`, `phoneNumber`, `mobileNumber` | phone |
|
|
21
|
+
| `otp`, `verificationCode`, `pinCode` | otp |
|
|
22
|
+
| `name`, `fullName`, `firstName`, `lastName`, `displayName` | name |
|
|
23
|
+
| `postalCode`, `zipCode`, `zip` | postalCode |
|
|
24
|
+
| `pincode` (India) | pincode (use regex key `pincode`, not `postalCode` — non-zero start enforced) |
|
|
25
|
+
| `url`, `website`, `link`, `profileUrl` | url (optional) |
|
|
26
|
+
| `dob`, `dateOfBirth`, `birthDate` | date |
|
|
27
|
+
| `address`, `addressLine1`, `street` | generic required string, min: 5 |
|
|
28
|
+
| `city`, `state`, `country` | generic required string, min: 2, regex: name |
|
|
29
|
+
| `age` | number, min: 18 |
|
|
30
|
+
| `quantity`, `count`, `amount` | number, min: 0 |
|
|
31
|
+
| `message`, `bio`, `description`, `notes` | string, optional or required, min: 10 |
|
|
32
|
+
|
|
33
|
+
---
|
|
34
|
+
|
|
35
|
+
## Available regex keys (from templates/regex.json)
|
|
36
|
+
|
|
37
|
+
| Key | Pattern | Use for |
|
|
38
|
+
|---|---|---|
|
|
39
|
+
| `email` | `^[^\s@]+@[^\s@]+\.[^\s@]+$` | email fields |
|
|
40
|
+
| `phone` | `^[0-9]{10}$` | 10-digit phone/mobile |
|
|
41
|
+
| `otp` | `^[0-9]{6}$` | 6-digit OTP |
|
|
42
|
+
| `name` | `^[a-zA-Z ]+$` | name fields (letters + spaces only) |
|
|
43
|
+
| `postalCode` | `^[0-9]{6}$` | 6-digit postal code |
|
|
44
|
+
| `password` | uppercase + lowercase + digit + special char, min 8 | strong password |
|
|
45
|
+
| `url` | `^https://...` | URL / website fields |
|
|
46
|
+
| `alphanumeric` | `^[a-zA-Z0-9]+$` | alphanumeric-only fields |
|
|
47
|
+
| `numericOnly` | `^[0-9]+$` | digits-only fields |
|
|
48
|
+
| `date` | `^\d{2}/\d{2}/\d{4}$` | date in DD/MM/YYYY |
|
|
49
|
+
| `panCard` | PAN card format | India PAN |
|
|
50
|
+
| `aadhaar` | 12-digit Aadhaar | India Aadhaar |
|
|
51
|
+
| `ifsc` | IFSC bank code | India IFSC |
|
|
52
|
+
| `pincode` | 6-digit, non-zero start | India pincode |
|
|
53
|
+
|
|
54
|
+
All 14 patterns are plain ECMAScript-compatible regex source strings, stored once in
|
|
55
|
+
`templates/regex.json` and compiled into whichever target language the platform needs
|
|
56
|
+
(`RegExp` in TS for React Native/React/Angular, `RegExp` in Dart for Flutter — Dart's regex engine
|
|
57
|
+
supports the same lookahead syntax used by the `password` pattern, so no pattern needed to change).
|
|
58
|
+
|
|
59
|
+
## Available message keys (from templates/messages.json)
|
|
60
|
+
|
|
61
|
+
| Key | Message |
|
|
62
|
+
|---|---|
|
|
63
|
+
| `required` | {{field}} is required |
|
|
64
|
+
| `email` | Please enter a valid email address |
|
|
65
|
+
| `phone` | Please enter a valid 10-digit phone number |
|
|
66
|
+
| `minLength` | Must be at least {{min}} characters |
|
|
67
|
+
| `maxLength` | Cannot exceed {{max}} characters |
|
|
68
|
+
| `minNumber` | Must be at least {{min}} |
|
|
69
|
+
| `maxNumber` | Cannot exceed {{max}} |
|
|
70
|
+
| `passwordMatch` | Passwords do not match |
|
|
71
|
+
| `passwordStrength` | Password must contain uppercase, lowercase, number and special character |
|
|
72
|
+
| `url` | Please enter a valid URL starting with https:// |
|
|
73
|
+
| `otp` | Please enter a valid 6-digit OTP |
|
|
74
|
+
| `name` | Please enter a valid name (letters and spaces only) |
|
|
75
|
+
| `postalCode` | Please enter a valid 6-digit postal code |
|
|
76
|
+
| `alphanumeric` | Only letters and numbers are allowed |
|
|
77
|
+
| `numericOnly` | Only numbers are allowed |
|
|
78
|
+
| `date` | Please enter a valid date |
|
|
79
|
+
| `minAge` | You must be at least {{min}} years old |
|
|
80
|
+
| `fileSize` | File size must not exceed {{max}} MB |
|
|
81
|
+
| `invalidFormat` | Invalid format |
|
|
82
|
+
| `panCard` | Please enter a valid PAN number (e.g. ABCDE1234F) |
|
|
83
|
+
|
|
84
|
+
## Available schemas (from templates/schemas.json)
|
|
85
|
+
|
|
86
|
+
Before creating a new schema, check if one of these already covers the screen/page/component's
|
|
87
|
+
fields — the same `templates/schemas.json` entry drives the generated output on every platform
|
|
88
|
+
(a Yup schema on React Native/React, an Angular `Validators[]` map, a Dart validator class):
|
|
89
|
+
|
|
90
|
+
| Schema key | Fields |
|
|
91
|
+
|---|---|
|
|
92
|
+
| `login` | email, password |
|
|
93
|
+
| `signup` | name, email, phone, password |
|
|
94
|
+
| `forgotPassword` | email |
|
|
95
|
+
| `resetPassword` | password, confirmPassword |
|
|
96
|
+
| `otp` | otp |
|
|
97
|
+
| `profileUpdate` | name, phone, email |
|
|
98
|
+
| `mobileLogin` | phoneNumber |
|
|
99
|
+
| `address` | addressLine1, city, postalCode, state |
|
|
100
|
+
| `enterPanForm` | pan |
|
|
101
|
+
| `addNomineeForm` | firstName, middleName, lastName, dob |
|
|
102
|
+
| `addBankDetailsForm` | accountNumber |
|
|
103
|
+
|
|
104
|
+
---
|
|
105
|
+
|
|
106
|
+
## Golden rules (every platform)
|
|
107
|
+
|
|
108
|
+
1. **Never edit generated files** — edit `templates/*.json` and re-run
|
|
109
|
+
`node .github/skills/validation-engine-builder/scripts/apply-to-project.js`.
|
|
110
|
+
2. **Never hardcode an error message string** in a component/page/widget — all strings must come
|
|
111
|
+
from the generated messages module (`VALIDATION_MESSAGES` in TS, `ValidationMessages` in Dart).
|
|
112
|
+
3. **Never hardcode a regex pattern** in a component/page/widget — all patterns must come from the
|
|
113
|
+
generated regex module (`VALIDATION_REGEX` in TS, `ValidationRegex` in Dart).
|
|
114
|
+
4. **Reuse schemas across screens/pages/components** — add the schema once to `schemas.json`, use
|
|
115
|
+
the same key everywhere. Two login-like screens with identical fields share one schema key.
|
|
116
|
+
5. **Cross-field validation (e.g. confirmPassword) is never expressible in `schemas.json`** — the
|
|
117
|
+
field-definition shape is per-field only. Each platform file documents the correct place to add
|
|
118
|
+
this by hand after generation (a Yup `.oneOf()`, an Angular `FormGroup`-level validator, a Dart
|
|
119
|
+
`TextEditingController` comparison) — see that platform's file.
|
|
120
|
+
|
|
121
|
+
## Adding a new validation rule
|
|
122
|
+
|
|
123
|
+
1. Add the error message to `templates/messages.json`.
|
|
124
|
+
2. Add the regex pattern to `templates/regex.json` (if needed).
|
|
125
|
+
3. Add or update the schema in `templates/schemas.json` using the new message/regex key.
|
|
126
|
+
4. Re-run:
|
|
127
|
+
```powershell
|
|
128
|
+
node .github/skills/validation-engine-builder/scripts/apply-to-project.js --projectPath <path>
|
|
129
|
+
```
|
|
130
|
+
The script detects the platform automatically (or pass `--platform <react-native|react|angular|flutter>`
|
|
131
|
+
explicitly if the target has more than one platform in the same repo).
|
|
132
|
+
5. The generated validation files are updated automatically. Existing screens/pages/components
|
|
133
|
+
still need AI wiring (or manual integration) if they don't already use the shared validation
|
|
134
|
+
layer.
|
|
135
|
+
|
|
136
|
+
## Import path calculation
|
|
137
|
+
|
|
138
|
+
The generated validation module always lives at a fixed location per platform (see the platform
|
|
139
|
+
file for the exact path). Never hand-count directory levels for the relative import — the
|
|
140
|
+
generator computes the correct relative path from the actual screen/page file location to the
|
|
141
|
+
actual validation output directory using the real filesystem structure, not a naming assumption.
|
|
142
|
+
If wiring a screen manually without running the generator's scaffold, use the same approach: count
|
|
143
|
+
from the file's own directory to the validation output directory using the project's real folder
|
|
144
|
+
structure.
|
|
145
|
+
|
|
146
|
+
## Adding a new screen/page/component with validation
|
|
147
|
+
|
|
148
|
+
Use the AI workflow in `SKILL.md` to detect the platform and wire the new screen/page/component.
|
|
149
|
+
The supported script command per platform is:
|
|
150
|
+
|
|
151
|
+
```powershell
|
|
152
|
+
node .github/skills/validation-engine-builder/scripts/apply-to-project.js --projectPath <path> --platform <platform>
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
That command regenerates the validation output only. It does not scaffold or rewrite an existing
|
|
156
|
+
screen — screen/page/component wiring is the AI's job (see SKILL.md Execution Steps), using the
|
|
157
|
+
`generateScreen()` export from the matching `generate-<platform>.js` module as an optional scaffold
|
|
158
|
+
helper for a brand-new file.
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Platform File — Angular
|
|
2
|
+
|
|
3
|
+
Read `core.md` first. Angular cannot use react-hook-form at all — it is a React library and has no
|
|
4
|
+
Angular equivalent. This platform targets Angular's own framework-native Reactive Forms
|
|
5
|
+
(`@angular/forms`: `FormBuilder`, `FormGroup`, `Validators`) instead of porting the Yup pattern.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Dependencies
|
|
10
|
+
|
|
11
|
+
None to install — Reactive Forms ships as part of `@angular/forms`, which every Angular project
|
|
12
|
+
already depends on. `scripts/shared/npm-deps.js` no-ops for this platform (prints an explanatory
|
|
13
|
+
message) rather than trying to install anything.
|
|
14
|
+
|
|
15
|
+
Confirm the target uses (or add) `provideHttpClient`/`ReactiveFormsModule` availability — for a
|
|
16
|
+
standalone component, `imports: [ReactiveFormsModule]` on the component itself is enough (see the
|
|
17
|
+
generated scaffold below); no root-level module registration is required.
|
|
18
|
+
|
|
19
|
+
## Generated files
|
|
20
|
+
|
|
21
|
+
`node scripts/apply-to-project.js --platform angular` writes to `src/app/validation/`:
|
|
22
|
+
|
|
23
|
+
| File | Role |
|
|
24
|
+
|---|---|
|
|
25
|
+
| `validation-messages.ts` | `VALIDATION_MESSAGES` const + `msg` interpolation helpers — identical shape to the RN/React `messages.ts`, zero Angular imports |
|
|
26
|
+
| `validation-regex.ts` | `VALIDATION_REGEX` const — identical shape to RN/React `regex.ts` |
|
|
27
|
+
| `pattern-with-message.validator.ts` | A `ValidatorFn` factory that reports a specific `VALIDATION_MESSAGES` key on failure (Angular's built-in `Validators.pattern` only reports a generic `pattern` error key, which can't carry which message to show) |
|
|
28
|
+
| `validators.ts` | Per-schema `Validators[]` arrays — this replaces `schemas.ts`; there is no Yup schema on this platform |
|
|
29
|
+
| `validation-error.component.ts` | A standalone `<app-validation-error>` component that reads a control's `.errors` and looks up the matching message |
|
|
30
|
+
|
|
31
|
+
There is no generated "hook" file on this platform — Angular's own `FormBuilder` (injected via
|
|
32
|
+
constructor) already serves that role; see the scaffold pattern below.
|
|
33
|
+
|
|
34
|
+
## Why Angular needs its own DI-aware approach
|
|
35
|
+
|
|
36
|
+
A TypeScript `interface` (or a `type`) has no runtime representation, so Angular's dependency
|
|
37
|
+
injector cannot use one as a lookup token. `patternWithMessage()` and `Validators.*` are plain
|
|
38
|
+
functions, not classes, so this doesn't come up for validators themselves — but if this project
|
|
39
|
+
also uses `clean-architecture-generator`'s Angular repository pattern (abstract-class-as-token),
|
|
40
|
+
the same principle applies there too; it's not specific to forms.
|
|
41
|
+
|
|
42
|
+
## `FormGroup` wiring per field type
|
|
43
|
+
|
|
44
|
+
```ts
|
|
45
|
+
import { Component } from '@angular/core';
|
|
46
|
+
import { FormBuilder, ReactiveFormsModule, type FormGroup } from '@angular/forms';
|
|
47
|
+
import { validators } from '../../validation/validators';
|
|
48
|
+
import { ValidationErrorComponent } from '../../validation/validation-error.component';
|
|
49
|
+
|
|
50
|
+
@Component({
|
|
51
|
+
selector: 'app-login-page',
|
|
52
|
+
standalone: true,
|
|
53
|
+
imports: [ReactiveFormsModule, ValidationErrorComponent],
|
|
54
|
+
templateUrl: './login-page.component.html',
|
|
55
|
+
styleUrl: './login-page.component.scss',
|
|
56
|
+
})
|
|
57
|
+
export class LoginPageComponent {
|
|
58
|
+
// Built in the constructor body, not as a field initializer — a field
|
|
59
|
+
// initializer runs before constructor parameter properties are assigned,
|
|
60
|
+
// so 'this.fb' would still be undefined if used at the field-declaration site.
|
|
61
|
+
readonly form: FormGroup;
|
|
62
|
+
|
|
63
|
+
constructor(private readonly fb: FormBuilder) {
|
|
64
|
+
this.form = this.fb.group({
|
|
65
|
+
email: ['', validators.login.email],
|
|
66
|
+
password: ['', validators.login.password],
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
onSubmit(): void {
|
|
71
|
+
if (this.form.invalid) {
|
|
72
|
+
this.form.markAllAsTouched();
|
|
73
|
+
return;
|
|
74
|
+
}
|
|
75
|
+
// TODO: submit logic
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
```
|
|
79
|
+
|
|
80
|
+
```html
|
|
81
|
+
<form [formGroup]="form" (ngSubmit)="onSubmit()">
|
|
82
|
+
<div class="field">
|
|
83
|
+
<label for="email">Email</label>
|
|
84
|
+
<input id="email" type="email" formControlName="email" />
|
|
85
|
+
<app-validation-error [control]="form.get('email')" label="Email"></app-validation-error>
|
|
86
|
+
</div>
|
|
87
|
+
<button type="submit">Submit</button>
|
|
88
|
+
</form>
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
**Never** put `this.fb.group(...)` in a field initializer (`readonly form = this.fb.group(...)`
|
|
92
|
+
directly on the class body) — constructor parameter properties (`private readonly fb: FormBuilder`)
|
|
93
|
+
are assigned inside the constructor body, and TypeScript emits class field initializers to run
|
|
94
|
+
*before* that assignment completes. Referencing `this.fb` from a field initializer reads it as
|
|
95
|
+
`undefined` and throws at runtime. Always build the `FormGroup` inside the constructor body.
|
|
96
|
+
|
|
97
|
+
### Per-field `type` attribute
|
|
98
|
+
|
|
99
|
+
| Field type | `type` attribute |
|
|
100
|
+
|---|---|
|
|
101
|
+
| password / confirmPassword | `password` |
|
|
102
|
+
| number fields | `number` |
|
|
103
|
+
| everything else | `text` |
|
|
104
|
+
|
|
105
|
+
## How `ValidationErrorComponent` maps errors to messages
|
|
106
|
+
|
|
107
|
+
Angular's built-in validators set well-known, lowercase error keys on `control.errors`:
|
|
108
|
+
`required`, `minlength` (with `{ requiredLength, actualLength }`), `maxlength`, `min`, `max`. The
|
|
109
|
+
generated `patternWithMessage()` validator instead sets `{ [yourMessageKey]: true }` directly, so
|
|
110
|
+
the component can look the key straight up in `VALIDATION_MESSAGES` without a translation table.
|
|
111
|
+
`ValidationErrorComponent` checks the built-in keys first, then falls back to any custom message
|
|
112
|
+
key it finds. Only show an error once the control is `dirty` or `touched`, matching react-hook-form's
|
|
113
|
+
`mode: 'onBlur'` behavior on the other platforms.
|
|
114
|
+
|
|
115
|
+
## confirmPassword / cross-field validation
|
|
116
|
+
|
|
117
|
+
Angular's per-field `Validators[]` array (same as `patternWithMessage`) cannot express "this field
|
|
118
|
+
must equal another field in the same group" — that requires a **`FormGroup`-level validator**
|
|
119
|
+
instead of a per-control one:
|
|
120
|
+
|
|
121
|
+
```ts
|
|
122
|
+
import type { ValidatorFn } from '@angular/forms';
|
|
123
|
+
|
|
124
|
+
export function passwordsMatch(): ValidatorFn {
|
|
125
|
+
return (group) => {
|
|
126
|
+
const password = group.get('password')?.value;
|
|
127
|
+
const confirmPassword = group.get('confirmPassword')?.value;
|
|
128
|
+
return password === confirmPassword ? null : { passwordMatch: true };
|
|
129
|
+
};
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
// wiring:
|
|
133
|
+
this.form = this.fb.group(
|
|
134
|
+
{ password: ['', validators.resetPassword.password], confirmPassword: ['', validators.resetPassword.confirmPassword] },
|
|
135
|
+
{ validators: [passwordsMatch()] },
|
|
136
|
+
);
|
|
137
|
+
```
|
|
138
|
+
|
|
139
|
+
Read the group-level error (`this.form.errors?.['passwordMatch']`) in the template, since a
|
|
140
|
+
group-level error doesn't attach to either individual control.
|
|
141
|
+
|
|
142
|
+
## Reusing the same validation on multiple pages
|
|
143
|
+
|
|
144
|
+
```ts
|
|
145
|
+
// login-page.component.ts
|
|
146
|
+
this.form = this.fb.group({ email: ['', validators.login.email], password: ['', validators.login.password] });
|
|
147
|
+
|
|
148
|
+
// admin-login-page.component.ts
|
|
149
|
+
this.form = this.fb.group({ email: ['', validators.login.email], password: ['', validators.login.password] }); // same validators, different page
|
|
150
|
+
```
|
|
151
|
+
|
|
152
|
+
## Page scaffold generator (optional)
|
|
153
|
+
|
|
154
|
+
`generate-angular.js` exports `generateScreen(projectRoot, pageName, schemaKey, pagePath, schemasRaw)`
|
|
155
|
+
— writes a starter `[pageName]/[pageName].component.ts` + `.html` + `.scss` wired with `FormBuilder`
|
|
156
|
+
and `<app-validation-error>` for every field in the given schema. `pageName` must be kebab-case, per
|
|
157
|
+
Angular's own naming convention (see `clean-architecture-generator`'s Angular platform file for the
|
|
158
|
+
same rule applied to other artifact types).
|
|
159
|
+
|
|
160
|
+
## Angular Material projects
|
|
161
|
+
|
|
162
|
+
If the target project uses Angular Material (`@angular/material` in `package.json`), prefer
|
|
163
|
+
`<mat-form-field>` + `<mat-error>` over the plain `<input>` + `<app-validation-error>` pair shown
|
|
164
|
+
above — `<mat-error>` already integrates with Material's own error-display timing. In that case,
|
|
165
|
+
still source the error text from `ValidationErrorComponent`'s `message` getter logic (or import
|
|
166
|
+
`VALIDATION_MESSAGES` directly) rather than hardcoding text inside `<mat-error>`.
|