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,62 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Emits messages.ts and regex.ts as plain TypeScript with zero framework imports.
|
|
6
|
+
* Shared by React Native, React (web), and Angular generators — Flutter emits
|
|
7
|
+
* Dart instead (see generate-flutter.js), since these files contain no JS runtime.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const path = require('path');
|
|
12
|
+
|
|
13
|
+
// ── messages.ts ────────────────────────────────────────────────────────────────
|
|
14
|
+
|
|
15
|
+
function genMessages(messages, outDir, fileName = 'messages.ts') {
|
|
16
|
+
const content = [
|
|
17
|
+
`// Auto-generated by validation-engine-builder skill. DO NOT EDIT MANUALLY.`,
|
|
18
|
+
`// Edit templates/messages.json and re-run apply-to-project.js`,
|
|
19
|
+
``,
|
|
20
|
+
`export const VALIDATION_MESSAGES = ${JSON.stringify(messages, null, 2)} as const;`,
|
|
21
|
+
``,
|
|
22
|
+
`export type MessageKey = keyof typeof VALIDATION_MESSAGES;`,
|
|
23
|
+
``,
|
|
24
|
+
`/** Interpolation helpers - insert runtime values into messages */`,
|
|
25
|
+
`export const msg = {`,
|
|
26
|
+
` required: (field: string) => VALIDATION_MESSAGES.required.replace('{{field}}', field),`,
|
|
27
|
+
` minLength: (min: number) => VALIDATION_MESSAGES.minLength.replace('{{min}}', String(min)),`,
|
|
28
|
+
` maxLength: (max: number) => VALIDATION_MESSAGES.maxLength.replace('{{max}}', String(max)),`,
|
|
29
|
+
` minNumber: (min: number) => VALIDATION_MESSAGES.minNumber.replace('{{min}}', String(min)),`,
|
|
30
|
+
` maxNumber: (max: number) => VALIDATION_MESSAGES.maxNumber.replace('{{max}}', String(max)),`,
|
|
31
|
+
` minAge: (min: number) => VALIDATION_MESSAGES.minAge.replace('{{min}}', String(min)),`,
|
|
32
|
+
` fileSize: (max: number) => VALIDATION_MESSAGES.fileSize.replace('{{max}}', String(max)),`,
|
|
33
|
+
`};`,
|
|
34
|
+
].join('\n');
|
|
35
|
+
|
|
36
|
+
fs.writeFileSync(path.join(outDir, fileName), content);
|
|
37
|
+
console.log(` ✅ ${fileName}`);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ── regex.ts ───────────────────────────────────────────────────────────────────
|
|
41
|
+
|
|
42
|
+
function genRegex(regexMap, outDir, fileName = 'regex.ts') {
|
|
43
|
+
const entries = Object.entries(regexMap)
|
|
44
|
+
.map(([key, pattern]) => ` ${key}: new RegExp(${JSON.stringify(pattern)}),`)
|
|
45
|
+
.join('\n');
|
|
46
|
+
|
|
47
|
+
const content = [
|
|
48
|
+
`// Auto-generated by validation-engine-builder skill. DO NOT EDIT MANUALLY.`,
|
|
49
|
+
`// Edit templates/regex.json and re-run apply-to-project.js`,
|
|
50
|
+
``,
|
|
51
|
+
`export const VALIDATION_REGEX = {`,
|
|
52
|
+
entries,
|
|
53
|
+
`} as const;`,
|
|
54
|
+
``,
|
|
55
|
+
`export type RegexKey = keyof typeof VALIDATION_REGEX;`,
|
|
56
|
+
].join('\n');
|
|
57
|
+
|
|
58
|
+
fs.writeFileSync(path.join(outDir, fileName), content);
|
|
59
|
+
console.log(` ✅ ${fileName}`);
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
module.exports = { genMessages, genRegex };
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
const fs = require('fs');
|
|
5
|
+
const path = require('path');
|
|
6
|
+
|
|
7
|
+
const TEMPLATES_DIR = path.join(__dirname, '..', '..', 'templates');
|
|
8
|
+
|
|
9
|
+
function readTemplate(name) {
|
|
10
|
+
return JSON.parse(fs.readFileSync(path.join(TEMPLATES_DIR, name), 'utf-8'));
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
function ensureDir(dir) {
|
|
14
|
+
if (!fs.existsSync(dir)) fs.mkdirSync(dir, { recursive: true });
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
/**
|
|
18
|
+
* Computes a JS/TS-style relative import path from `fromDir` to `toDir`,
|
|
19
|
+
* always forward-slashed and always prefixed with './' or '../' (required
|
|
20
|
+
* for a relative module specifier — without it, bundlers treat the string
|
|
21
|
+
* as a package name instead of a relative path).
|
|
22
|
+
*
|
|
23
|
+
* Uses path.relative() rather than counting path segments in the caller's
|
|
24
|
+
* input string — segment-counting breaks as soon as the screen/page file
|
|
25
|
+
* lives in its own subfolder (one extra level) or the validation output
|
|
26
|
+
* directory isn't exactly one level under the project root.
|
|
27
|
+
*/
|
|
28
|
+
function relativeImportPath(fromDir, toDir) {
|
|
29
|
+
let rel = path.relative(fromDir, toDir).split(path.sep).join('/');
|
|
30
|
+
if (!rel.startsWith('.')) rel = './' + rel;
|
|
31
|
+
return rel;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Same idea for Dart: a relative import that stays in the same directory
|
|
36
|
+
* has no path-relative prefix requirement (Dart resolves a bare filename
|
|
37
|
+
* relative to the importing file), and Dart does not use a './' prefix for
|
|
38
|
+
* same-or-descendant paths the way JS/TS does — only './'-free segments.
|
|
39
|
+
*/
|
|
40
|
+
function relativeDartImportPath(fromDir, toDir) {
|
|
41
|
+
return path.relative(fromDir, toDir).split(path.sep).join('/');
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
module.exports = { readTemplate, ensureDir, relativeImportPath, relativeDartImportPath, TEMPLATES_DIR };
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
'use strict';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Emits schemas.ts as Yup object schemas. Yup is a plain JS validation library
|
|
6
|
+
* (no framework dependency of its own) but is only wired into this skill via
|
|
7
|
+
* react-hook-form's yupResolver — so this generator is shared by React Native
|
|
8
|
+
* and React (web) only. Angular uses its own framework-native Validators
|
|
9
|
+
* (see generate-angular.js) and Flutter uses plain Dart functions
|
|
10
|
+
* (see generate-flutter.js) — neither can run a JS library at all.
|
|
11
|
+
*/
|
|
12
|
+
|
|
13
|
+
const fs = require('fs');
|
|
14
|
+
const path = require('path');
|
|
15
|
+
|
|
16
|
+
function buildFieldChain(fieldName, rules) {
|
|
17
|
+
let chain = ` ${fieldName}: yup.${rules.type || 'string'}()`;
|
|
18
|
+
|
|
19
|
+
if (rules.required) {
|
|
20
|
+
const label = rules.label || fieldName;
|
|
21
|
+
chain += `\n .required(msg.required(${JSON.stringify(label)}))`;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
if (rules.min !== undefined) {
|
|
25
|
+
const fn = rules.type === 'number'
|
|
26
|
+
? `msg.minNumber(${rules.min})`
|
|
27
|
+
: `msg.minLength(${rules.min})`;
|
|
28
|
+
chain += `\n .min(${rules.min}, ${fn})`;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
if (rules.max !== undefined) {
|
|
32
|
+
const fn = rules.type === 'number'
|
|
33
|
+
? `msg.maxNumber(${rules.max})`
|
|
34
|
+
: `msg.maxLength(${rules.max})`;
|
|
35
|
+
chain += `\n .max(${rules.max}, ${fn})`;
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
if (rules.regex) {
|
|
39
|
+
const msgKey = rules.regexMessage || rules.regex;
|
|
40
|
+
chain += `\n .matches(VALIDATION_REGEX.${rules.regex}, VALIDATION_MESSAGES.${msgKey})`;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
if (rules.nullable) chain += `\n .nullable()`;
|
|
44
|
+
|
|
45
|
+
return chain + `,`;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
function genSchemas(schemasRaw, outDir) {
|
|
49
|
+
const schemaBlocks = Object.entries(schemasRaw).map(([schemaName, fields]) => {
|
|
50
|
+
const fieldLines = Object.entries(fields).map(([fieldName, rules]) =>
|
|
51
|
+
buildFieldChain(fieldName, rules)
|
|
52
|
+
);
|
|
53
|
+
return [
|
|
54
|
+
` ${schemaName}: yup.object({`,
|
|
55
|
+
...fieldLines,
|
|
56
|
+
` }),`,
|
|
57
|
+
].join('\n');
|
|
58
|
+
});
|
|
59
|
+
|
|
60
|
+
const content = [
|
|
61
|
+
`// Auto-generated by validation-engine-builder skill. DO NOT EDIT MANUALLY.`,
|
|
62
|
+
`// Edit templates/schemas.json and re-run apply-to-project.js`,
|
|
63
|
+
``,
|
|
64
|
+
`import * as yup from 'yup';`,
|
|
65
|
+
`import { VALIDATION_MESSAGES, msg } from './messages';`,
|
|
66
|
+
`import { VALIDATION_REGEX } from './regex';`,
|
|
67
|
+
``,
|
|
68
|
+
`export const schemas = {`,
|
|
69
|
+
...schemaBlocks,
|
|
70
|
+
`};`,
|
|
71
|
+
``,
|
|
72
|
+
`export type SchemaKey = keyof typeof schemas;`,
|
|
73
|
+
`export type FormData<T extends SchemaKey> = yup.InferType<typeof schemas[T]>;`,
|
|
74
|
+
].join('\n');
|
|
75
|
+
|
|
76
|
+
fs.writeFileSync(path.join(outDir, 'schemas.ts'), content);
|
|
77
|
+
console.log(' ✅ schemas.ts');
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
module.exports = { genSchemas, buildFieldChain };
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# Template Reference
|
|
2
|
+
|
|
3
|
+
This file documents the JSON template format used by the validation-engine-builder skill. The same three
|
|
4
|
+
JSON files are the single source of truth for **all 4 supported platforms** (React Native, React
|
|
5
|
+
web, Angular, Flutter) — only the generated output differs (a Yup schema, an Angular `Validators[]`
|
|
6
|
+
map, or a Dart validator class), never the source templates. Edit the templates in `templates/` —
|
|
7
|
+
never edit the generated output directly (`src/validation/` on RN/React, `src/app/validation/` on
|
|
8
|
+
Angular, `lib/core/validation/` on Flutter).
|
|
9
|
+
|
|
10
|
+
## templates/messages.json — flat key → message string
|
|
11
|
+
|
|
12
|
+
> **Excerpt only** — the actual `templates/messages.json` contains all 19 keys. Do not add keys shown here if they already exist in the file.
|
|
13
|
+
|
|
14
|
+
```json
|
|
15
|
+
{
|
|
16
|
+
"required": "{{field}} is required",
|
|
17
|
+
"email": "Please enter a valid email address",
|
|
18
|
+
"minLength": "Must be at least {{min}} characters",
|
|
19
|
+
"maxLength": "Cannot exceed {{max}} characters",
|
|
20
|
+
"passwordMatch": "Passwords do not match"
|
|
21
|
+
}
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Use `{{field}}`, `{{min}}`, `{{max}}` placeholders for runtime interpolation. The generator creates `msg.required(field)`, `msg.minLength(n)` helpers automatically.
|
|
25
|
+
|
|
26
|
+
## templates/regex.json — key → regex string (double-escaped for JSON)
|
|
27
|
+
|
|
28
|
+
> **Excerpt only** — the actual `templates/regex.json` contains all 14 keys. Do not add keys shown here if they already exist in the file.
|
|
29
|
+
|
|
30
|
+
```json
|
|
31
|
+
{
|
|
32
|
+
"email": "^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$",
|
|
33
|
+
"phone": "^[0-9]{10}$",
|
|
34
|
+
"otp": "^[0-9]{6}$"
|
|
35
|
+
}
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
Always double-escape backslashes in JSON (`\\d` for `\d`).
|
|
39
|
+
|
|
40
|
+
## templates/schemas.json — key → field definitions
|
|
41
|
+
|
|
42
|
+
```json
|
|
43
|
+
{
|
|
44
|
+
"login": {
|
|
45
|
+
"email": { "type": "string", "required": true, "regex": "email", "label": "Email" },
|
|
46
|
+
"password": { "type": "string", "required": true, "min": 8, "label": "Password" }
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
### Field definition properties
|
|
52
|
+
|
|
53
|
+
| Property | Type | Effect |
|
|
54
|
+
|---|---|---|
|
|
55
|
+
| `type` | `"string"` or `"number"` | Yup base type |
|
|
56
|
+
| `required` | `boolean` | `.required(msg.required("Field Label"))` |
|
|
57
|
+
| `min` | `number` | `.min(n, msg.minLength(n))` or `.min(n, msg.minNumber(n))` |
|
|
58
|
+
| `max` | `number` | `.max(n, msg.maxLength(n))` or `.max(n, msg.maxNumber(n))` |
|
|
59
|
+
| `regex` | `string` | Key from regex.json — `.matches(VALIDATION_REGEX.key, ...)` |
|
|
60
|
+
| `regexMessage` | `string` | Key from messages.json for the regex error |
|
|
61
|
+
| `nullable` | `boolean` | `.nullable()` for optional fields |
|
|
62
|
+
| `label` | `string` | Human-readable field name / placeholder (also used in required message) |
|
|
63
|
+
|
|
64
|
+
## Regenerate after any template edit
|
|
65
|
+
|
|
66
|
+
```powershell
|
|
67
|
+
node .github/skills/validation-engine-builder/scripts/apply-to-project.js --projectPath <path>
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
The platform is auto-detected (`pubspec.yaml` → Flutter, `angular.json` → Angular, a
|
|
71
|
+
`react-native`/`react` dependency in `package.json` → React Native/React). Pass
|
|
72
|
+
`--platform <react-native|react|angular|flutter>` explicitly if the repo contains more than one
|
|
73
|
+
platform, or if detection is ambiguous.
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"required": "{{field}} is required",
|
|
3
|
+
"email": "Please enter a valid email address",
|
|
4
|
+
"phone": "Please enter a valid 10-digit phone number",
|
|
5
|
+
"minLength": "Must be at least {{min}} characters",
|
|
6
|
+
"maxLength": "Cannot exceed {{max}} characters",
|
|
7
|
+
"minNumber": "Must be at least {{min}}",
|
|
8
|
+
"maxNumber": "Cannot exceed {{max}}",
|
|
9
|
+
"passwordMatch": "Passwords do not match",
|
|
10
|
+
"passwordStrength": "Password must contain uppercase, lowercase, number and special character",
|
|
11
|
+
"url": "Please enter a valid URL starting with https://",
|
|
12
|
+
"otp": "Please enter a valid 6-digit OTP",
|
|
13
|
+
"name": "Please enter a valid name (letters and spaces only)",
|
|
14
|
+
"postalCode": "Please enter a valid 6-digit postal code",
|
|
15
|
+
"alphanumeric": "Only letters and numbers are allowed",
|
|
16
|
+
"numericOnly": "Only numbers are allowed",
|
|
17
|
+
"date": "Please enter a valid date",
|
|
18
|
+
"minAge": "You must be at least {{min}} years old",
|
|
19
|
+
"fileSize": "File size must not exceed {{max}} MB",
|
|
20
|
+
"invalidFormat": "Invalid format",
|
|
21
|
+
"panCard": "Please enter a valid PAN number (e.g. ABCDE1234F)"
|
|
22
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
{
|
|
2
|
+
"email": "^[^\\s@]+@[^\\s@]+\\.[^\\s@]+$",
|
|
3
|
+
"phone": "^[0-9]{10}$",
|
|
4
|
+
"otp": "^[0-9]{6}$",
|
|
5
|
+
"name": "^[a-zA-Z ]+$",
|
|
6
|
+
"postalCode": "^[0-9]{6}$",
|
|
7
|
+
"password": "^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d)(?=.*[@$!%*?&])[A-Za-z\\d@$!%*?&]{8,}$",
|
|
8
|
+
"url": "^https://([\\w-]+\\.)+[\\w-]+(/[\\w-./?%&=]*)?$",
|
|
9
|
+
"alphanumeric": "^[a-zA-Z0-9]+$",
|
|
10
|
+
"numericOnly": "^[0-9]+$",
|
|
11
|
+
"date": "^\\d{2}/\\d{2}/\\d{4}$",
|
|
12
|
+
"panCard": "^[A-Z]{5}[0-9]{4}[A-Z]{1}$",
|
|
13
|
+
"aadhaar": "^[2-9]{1}[0-9]{11}$",
|
|
14
|
+
"ifsc": "^[A-Z]{4}0[A-Z0-9]{6}$",
|
|
15
|
+
"pincode": "^[1-9][0-9]{5}$"
|
|
16
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
{
|
|
2
|
+
"login": {
|
|
3
|
+
"email": { "type": "string", "required": true, "regex": "email", "label": "Email" },
|
|
4
|
+
"password": { "type": "string", "required": true, "min": 8, "label": "Password" }
|
|
5
|
+
},
|
|
6
|
+
"signup": {
|
|
7
|
+
"name": { "type": "string", "required": true, "regex": "name", "min": 2, "label": "Full Name" },
|
|
8
|
+
"email": { "type": "string", "required": true, "regex": "email", "label": "Email" },
|
|
9
|
+
"phone": { "type": "string", "required": true, "regex": "phone", "label": "Phone Number" },
|
|
10
|
+
"password": { "type": "string", "required": true, "min": 8, "regex": "password", "regexMessage": "passwordStrength", "label": "Password" }
|
|
11
|
+
},
|
|
12
|
+
"forgotPassword": {
|
|
13
|
+
"email": { "type": "string", "required": true, "regex": "email", "label": "Email" }
|
|
14
|
+
},
|
|
15
|
+
"resetPassword": {
|
|
16
|
+
"password": { "type": "string", "required": true, "min": 8, "regex": "password", "regexMessage": "passwordStrength", "label": "New Password" },
|
|
17
|
+
"confirmPassword": { "type": "string", "required": true, "min": 8, "label": "Confirm Password" }
|
|
18
|
+
},
|
|
19
|
+
"otp": {
|
|
20
|
+
"otp": { "type": "string", "required": true, "regex": "otp", "label": "OTP" }
|
|
21
|
+
},
|
|
22
|
+
"profileUpdate": {
|
|
23
|
+
"name": { "type": "string", "required": true, "regex": "name", "min": 2, "label": "Full Name" },
|
|
24
|
+
"phone": { "type": "string", "required": true, "regex": "phone", "label": "Phone Number" },
|
|
25
|
+
"email": { "type": "string", "required": true, "regex": "email", "label": "Email" }
|
|
26
|
+
},
|
|
27
|
+
"mobileLogin": {
|
|
28
|
+
"phoneNumber": { "type": "string", "required": true, "regex": "phone", "label": "Phone Number" }
|
|
29
|
+
},
|
|
30
|
+
"address": {
|
|
31
|
+
"addressLine1": { "type": "string", "required": true, "min": 5, "label": "Address Line 1" },
|
|
32
|
+
"city": { "type": "string", "required": true, "regex": "name", "label": "City" },
|
|
33
|
+
"postalCode": { "type": "string", "required": true, "regex": "postalCode", "label": "Postal Code" },
|
|
34
|
+
"state": { "type": "string", "required": true, "label": "State" }
|
|
35
|
+
},
|
|
36
|
+
"enterPanForm": {
|
|
37
|
+
"pan": { "type": "string", "required": true, "min": 10, "max": 10, "regex": "panCard", "regexMessage": "panCard", "label": "PAN" }
|
|
38
|
+
},
|
|
39
|
+
"addNomineeForm": {
|
|
40
|
+
"firstName": { "type": "string", "required": true, "min": 2, "regex": "name", "label": "First Name" },
|
|
41
|
+
"middleName": { "type": "string", "required": true, "min": 2, "regex": "name", "label": "Middle Name" },
|
|
42
|
+
"lastName": { "type": "string", "required": true, "min": 2, "regex": "name", "label": "Last Name" },
|
|
43
|
+
"dob": { "type": "string", "required": true, "regex": "date", "regexMessage": "date", "label": "Date of Birth" }
|
|
44
|
+
},
|
|
45
|
+
"addBankDetailsForm": {
|
|
46
|
+
"accountNumber": { "type": "string", "required": true, "min": 9, "max": 18, "regex": "numericOnly", "regexMessage": "numericOnly", "label": "Account Number" }
|
|
47
|
+
}
|
|
48
|
+
}
|
package/bin/index.js
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
console.log("NEW CLI VERSION RUNNING");
|
|
4
|
+
|
|
5
|
+
const fs = require('fs-extra');
|
|
6
|
+
const path = require('path');
|
|
7
|
+
const os = require('os');
|
|
8
|
+
const simpleGit = require('simple-git');
|
|
9
|
+
|
|
10
|
+
const git = simpleGit();
|
|
11
|
+
|
|
12
|
+
const command = process.argv[2];
|
|
13
|
+
const repoUrl = process.argv[3];
|
|
14
|
+
|
|
15
|
+
const skillIndex = process.argv.indexOf('--skill');
|
|
16
|
+
|
|
17
|
+
if (skillIndex === -1 || !process.argv[skillIndex + 1]) {
|
|
18
|
+
|
|
19
|
+
console.log('Please provide --skill');
|
|
20
|
+
|
|
21
|
+
process.exit(1);
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const skillArgument = process.argv[skillIndex + 1];
|
|
25
|
+
|
|
26
|
+
console.log("Command:", command);
|
|
27
|
+
console.log("Repo URL:", repoUrl);
|
|
28
|
+
console.log("Skill Argument:", skillArgument);
|
|
29
|
+
|
|
30
|
+
async function installSkill() {
|
|
31
|
+
|
|
32
|
+
const tempDir = path.join(
|
|
33
|
+
os.tmpdir(),
|
|
34
|
+
'skill-package-temp'
|
|
35
|
+
);
|
|
36
|
+
|
|
37
|
+
// Remove old temp directory
|
|
38
|
+
|
|
39
|
+
if (fs.existsSync(tempDir)) {
|
|
40
|
+
fs.removeSync(tempDir);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
console.log('Cloning repository...');
|
|
44
|
+
|
|
45
|
+
await git.clone(repoUrl, tempDir);
|
|
46
|
+
|
|
47
|
+
console.log('Repository cloned');
|
|
48
|
+
|
|
49
|
+
// Root skills folder in cloned repo
|
|
50
|
+
|
|
51
|
+
const repoSkillsFolder = path.join(
|
|
52
|
+
tempDir,
|
|
53
|
+
'.github',
|
|
54
|
+
'skills'
|
|
55
|
+
);
|
|
56
|
+
|
|
57
|
+
if (!fs.existsSync(repoSkillsFolder)) {
|
|
58
|
+
|
|
59
|
+
console.log('.github/skills folder not found in repository');
|
|
60
|
+
|
|
61
|
+
return;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
// Project destination folders
|
|
65
|
+
|
|
66
|
+
const projectRoot = path.resolve('.');
|
|
67
|
+
|
|
68
|
+
const githubFolder = path.join(
|
|
69
|
+
projectRoot,
|
|
70
|
+
'.github'
|
|
71
|
+
);
|
|
72
|
+
|
|
73
|
+
const skillsFolder = path.join(
|
|
74
|
+
githubFolder,
|
|
75
|
+
'skills'
|
|
76
|
+
);
|
|
77
|
+
|
|
78
|
+
fs.ensureDirSync(githubFolder);
|
|
79
|
+
fs.ensureDirSync(skillsFolder);
|
|
80
|
+
|
|
81
|
+
console.log('Destination Skills Folder:', skillsFolder);
|
|
82
|
+
|
|
83
|
+
let skillNames = [];
|
|
84
|
+
|
|
85
|
+
// =========================================
|
|
86
|
+
// CASE 1 -> ALL SKILLS
|
|
87
|
+
// =========================================
|
|
88
|
+
|
|
89
|
+
if (skillArgument.toLowerCase() === 'all') {
|
|
90
|
+
|
|
91
|
+
console.log('Installing all skills...');
|
|
92
|
+
|
|
93
|
+
skillNames = fs.readdirSync(repoSkillsFolder);
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
// =========================================
|
|
97
|
+
// CASE 2 -> SINGLE OR MULTIPLE SKILLS
|
|
98
|
+
// =========================================
|
|
99
|
+
|
|
100
|
+
else {
|
|
101
|
+
|
|
102
|
+
skillNames = skillArgument
|
|
103
|
+
.split(',')
|
|
104
|
+
.map(skill => skill.trim())
|
|
105
|
+
.filter(skill => skill.length > 0);
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
console.log('Skills To Install:', skillNames);
|
|
109
|
+
|
|
110
|
+
// =========================================
|
|
111
|
+
// INSTALL EACH SKILL
|
|
112
|
+
// =========================================
|
|
113
|
+
|
|
114
|
+
for (const skillName of skillNames) {
|
|
115
|
+
|
|
116
|
+
console.log(`Installing Skill: ${skillName}`);
|
|
117
|
+
|
|
118
|
+
const source = path.join(
|
|
119
|
+
repoSkillsFolder,
|
|
120
|
+
skillName
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
console.log('Source Path:', source);
|
|
124
|
+
|
|
125
|
+
if (!fs.existsSync(source)) {
|
|
126
|
+
|
|
127
|
+
console.log(`Skill not found: ${skillName}`);
|
|
128
|
+
|
|
129
|
+
continue;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const destination = path.join(
|
|
133
|
+
skillsFolder,
|
|
134
|
+
skillName
|
|
135
|
+
);
|
|
136
|
+
|
|
137
|
+
fs.copySync(source, destination);
|
|
138
|
+
|
|
139
|
+
console.log(`${skillName} installed successfully!`);
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
console.log('All requested skills processed successfully!');
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
installSkill();
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "devendra-skill-package",
|
|
3
|
+
"version": "1.0.2",
|
|
4
|
+
"description": "CLI for installing GitHub Copilot skills",
|
|
5
|
+
"main": "bin/index.js",
|
|
6
|
+
"bin": {
|
|
7
|
+
"devendra-skill-package": "bin/index.js"
|
|
8
|
+
},
|
|
9
|
+
"dependencies": {
|
|
10
|
+
"commander": "^12.0.0",
|
|
11
|
+
"fs-extra": "^11.3.5",
|
|
12
|
+
"simple-git": "^3.36.0"
|
|
13
|
+
},
|
|
14
|
+
"devDependencies": {},
|
|
15
|
+
"scripts": {
|
|
16
|
+
"test": "echo \"Error: no test specified\" && exit 1"
|
|
17
|
+
},
|
|
18
|
+
"keywords": [],
|
|
19
|
+
"author": "",
|
|
20
|
+
"license": "ISC",
|
|
21
|
+
"type": "commonjs"
|
|
22
|
+
}
|
package/readme.md
ADDED
|
File without changes
|