@thanhvn14/csvibe 0.1.4 → 0.1.5
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/agents/schemas/base-output.schema.json +88 -0
- package/.github/agents/schemas/brainstorm-output.schema.json +88 -0
- package/.github/agents/schemas/scout-output.schema.json +60 -0
- package/.github/agents/scripts/fetch-copilot-tools.js +245 -0
- package/.github/agents/scripts/lib/parse-agent-file.js +275 -0
- package/.github/agents/scripts/package-lock.json +78 -0
- package/.github/agents/scripts/package.json +22 -0
- package/.github/agents/scripts/schemas/agent-frontmatter.schema.json +83 -0
- package/.github/agents/scripts/validate-agent-all.js +157 -0
- package/.github/agents/scripts/validate-agent-frontmatter.js +96 -0
- package/.github/agents/scripts/validate-agent-handoffs.js +169 -0
- package/.github/agents/scripts/validate-agent-output.js +157 -0
- package/.github/agents/scripts/validate-agent-tools.js +278 -0
- package/.github/skills/.env.example +100 -0
- package/.github/skills/.install-state.json +23 -0
- package/.github/skills/README.md +149 -0
- package/.github/skills/ai-multimodal/.env.example +204 -0
- package/.github/skills/ai-multimodal/scripts/.coverage +0 -0
- package/.github/skills/ai-multimodal/scripts/check_setup.py +305 -0
- package/.github/skills/ai-multimodal/scripts/document_converter.py +395 -0
- package/.github/skills/ai-multimodal/scripts/gemini_batch_process.py +1184 -0
- package/.github/skills/ai-multimodal/scripts/media_optimizer.py +506 -0
- package/.github/skills/ai-multimodal/scripts/requirements.txt +26 -0
- package/.github/skills/better-auth/scripts/.coverage +0 -0
- package/.github/skills/better-auth/scripts/better_auth_init.py +521 -0
- package/.github/skills/better-auth/scripts/requirements.txt +15 -0
- package/.github/skills/chrome-devtools/scripts/README.md +272 -0
- package/.github/skills/chrome-devtools/scripts/__tests__/selector.test.js +210 -0
- package/.github/skills/chrome-devtools/scripts/aria-snapshot.js +362 -0
- package/.github/skills/chrome-devtools/scripts/click.js +83 -0
- package/.github/skills/chrome-devtools/scripts/console.js +79 -0
- package/.github/skills/chrome-devtools/scripts/evaluate.js +53 -0
- package/.github/skills/chrome-devtools/scripts/fill.js +76 -0
- package/.github/skills/chrome-devtools/scripts/inject-auth.js +229 -0
- package/.github/skills/chrome-devtools/scripts/install-deps.sh +181 -0
- package/.github/skills/chrome-devtools/scripts/install.sh +83 -0
- package/.github/skills/chrome-devtools/scripts/lib/browser.js +318 -0
- package/.github/skills/chrome-devtools/scripts/lib/selector.js +178 -0
- package/.github/skills/chrome-devtools/scripts/navigate.js +54 -0
- package/.github/skills/chrome-devtools/scripts/network.js +106 -0
- package/.github/skills/chrome-devtools/scripts/package-lock.json +1589 -0
- package/.github/skills/chrome-devtools/scripts/package.json +16 -0
- package/.github/skills/chrome-devtools/scripts/performance.js +149 -0
- package/.github/skills/chrome-devtools/scripts/screenshot.js +198 -0
- package/.github/skills/chrome-devtools/scripts/select-ref.js +131 -0
- package/.github/skills/chrome-devtools/scripts/snapshot.js +135 -0
- package/.github/skills/common/README.md +120 -0
- package/.github/skills/common/api_key_helper.py +411 -0
- package/.github/skills/common/api_key_rotator.py +248 -0
- package/.github/skills/databases/scripts/.coverage +0 -0
- package/.github/skills/databases/scripts/db_backup.py +502 -0
- package/.github/skills/databases/scripts/db_migrate.py +425 -0
- package/.github/skills/databases/scripts/db_performance_check.py +456 -0
- package/.github/skills/databases/scripts/requirements.txt +20 -0
- package/.github/skills/debugging/scripts/find-polluter.sh +63 -0
- package/.github/skills/devops/.env.example +76 -0
- package/.github/skills/devops/scripts/cloudflare_deploy.py +269 -0
- package/.github/skills/devops/scripts/docker_optimize.py +331 -0
- package/.github/skills/devops/scripts/requirements.txt +20 -0
- package/.github/skills/docs-seeker/.env.example +15 -0
- package/.github/skills/docs-seeker/package.json +25 -0
- package/.github/skills/docs-seeker/scripts/analyze-llms-txt.js +211 -0
- package/.github/skills/docs-seeker/scripts/detect-topic.js +172 -0
- package/.github/skills/docs-seeker/scripts/fetch-docs.js +213 -0
- package/.github/skills/docs-seeker/scripts/utils/env-loader.js +94 -0
- package/.github/skills/document-skills/docx/LICENSE.txt +30 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/mce/mc.xsd +75 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/.github/skills/document-skills/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/pack.py +159 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/unpack.py +29 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/validate.py +69 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/validation/__init__.py +15 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/validation/base.py +951 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/validation/docx.py +274 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/validation/pptx.py +315 -0
- package/.github/skills/document-skills/docx/ooxml/scripts/validation/redlining.py +279 -0
- package/.github/skills/document-skills/docx/scripts/__init__.py +1 -0
- package/.github/skills/document-skills/docx/scripts/document.py +1276 -0
- package/.github/skills/document-skills/docx/scripts/templates/comments.xml +3 -0
- package/.github/skills/document-skills/docx/scripts/templates/commentsExtended.xml +3 -0
- package/.github/skills/document-skills/docx/scripts/templates/commentsExtensible.xml +3 -0
- package/.github/skills/document-skills/docx/scripts/templates/commentsIds.xml +3 -0
- package/.github/skills/document-skills/docx/scripts/templates/people.xml +3 -0
- package/.github/skills/document-skills/docx/scripts/utilities.py +374 -0
- package/.github/skills/document-skills/pdf/LICENSE.txt +30 -0
- package/.github/skills/document-skills/pdf/scripts/check_bounding_boxes.py +70 -0
- package/.github/skills/document-skills/pdf/scripts/check_bounding_boxes_test.py +226 -0
- package/.github/skills/document-skills/pdf/scripts/check_fillable_fields.py +12 -0
- package/.github/skills/document-skills/pdf/scripts/convert_pdf_to_images.py +35 -0
- package/.github/skills/document-skills/pdf/scripts/create_validation_image.py +41 -0
- package/.github/skills/document-skills/pdf/scripts/extract_form_field_info.py +152 -0
- package/.github/skills/document-skills/pdf/scripts/fill_fillable_fields.py +114 -0
- package/.github/skills/document-skills/pdf/scripts/fill_pdf_form_with_annotations.py +108 -0
- package/.github/skills/document-skills/pptx/LICENSE.txt +30 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/mce/mc.xsd +75 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2010.xsd +560 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2012.xsd +67 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-2018.xsd +14 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -0
- package/.github/skills/document-skills/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/pack.py +159 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/unpack.py +29 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/validate.py +69 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/validation/__init__.py +15 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/validation/base.py +951 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/validation/docx.py +274 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/validation/pptx.py +315 -0
- package/.github/skills/document-skills/pptx/ooxml/scripts/validation/redlining.py +279 -0
- package/.github/skills/document-skills/pptx/scripts/html2pptx.js +979 -0
- package/.github/skills/document-skills/pptx/scripts/inventory.py +1020 -0
- package/.github/skills/document-skills/pptx/scripts/rearrange.py +231 -0
- package/.github/skills/document-skills/pptx/scripts/replace.py +385 -0
- package/.github/skills/document-skills/pptx/scripts/thumbnail.py +450 -0
- package/.github/skills/document-skills/xlsx/LICENSE.txt +30 -0
- package/.github/skills/document-skills/xlsx/recalc.py +190 -0
- package/.github/skills/install.ps1 +1220 -0
- package/.github/skills/install.sh +1032 -0
- package/.github/skills/markdown-novel-viewer/assets/directory-browser.css +215 -0
- package/.github/skills/markdown-novel-viewer/assets/favicon.png +0 -0
- package/.github/skills/markdown-novel-viewer/assets/novel-theme.css +818 -0
- package/.github/skills/markdown-novel-viewer/assets/reader.js +262 -0
- package/.github/skills/markdown-novel-viewer/assets/template.html +80 -0
- package/.github/skills/markdown-novel-viewer/package-lock.json +146 -0
- package/.github/skills/markdown-novel-viewer/package.json +15 -0
- package/.github/skills/markdown-novel-viewer/scripts/lib/http-server.cjs +434 -0
- package/.github/skills/markdown-novel-viewer/scripts/lib/markdown-renderer.cjs +272 -0
- package/.github/skills/markdown-novel-viewer/scripts/lib/plan-navigator.cjs +509 -0
- package/.github/skills/markdown-novel-viewer/scripts/lib/port-finder.cjs +48 -0
- package/.github/skills/markdown-novel-viewer/scripts/lib/process-mgr.cjs +150 -0
- package/.github/skills/markdown-novel-viewer/scripts/server.cjs +411 -0
- package/.github/skills/mcp-builder/LICENSE.txt +202 -0
- package/.github/skills/mcp-builder/scripts/connections.py +151 -0
- package/.github/skills/mcp-builder/scripts/evaluation.py +373 -0
- package/.github/skills/mcp-builder/scripts/example_evaluation.xml +22 -0
- package/.github/skills/mcp-builder/scripts/requirements.txt +2 -0
- package/.github/skills/mcp-management/README.md +219 -0
- package/.github/skills/mcp-management/assets/tools.json +3146 -0
- package/.github/skills/mcp-management/package-lock.json +6 -0
- package/.github/skills/mcp-management/scripts/.env.example +10 -0
- package/.github/skills/mcp-management/scripts/cli.ts +195 -0
- package/.github/skills/mcp-management/scripts/dist/analyze-tools.js +70 -0
- package/.github/skills/mcp-management/scripts/dist/cli.js +160 -0
- package/.github/skills/mcp-management/scripts/dist/mcp-client.js +183 -0
- package/.github/skills/mcp-management/scripts/mcp-client.ts +230 -0
- package/.github/skills/mcp-management/scripts/package.json +20 -0
- package/.github/skills/media-processing/scripts/README.md +111 -0
- package/.github/skills/media-processing/scripts/batch-remove-background.sh +124 -0
- package/.github/skills/media-processing/scripts/batch_resize.py +342 -0
- package/.github/skills/media-processing/scripts/media_convert.py +311 -0
- package/.github/skills/media-processing/scripts/remove-background.sh +96 -0
- package/.github/skills/media-processing/scripts/remove-bg-node.js +158 -0
- package/.github/skills/media-processing/scripts/requirements.txt +24 -0
- package/.github/skills/media-processing/scripts/video_optimize.py +414 -0
- package/.github/skills/payment-integration/README.md +185 -0
- package/.github/skills/payment-integration/scripts/.env.example +20 -0
- package/.github/skills/payment-integration/scripts/checkout-helper.js +244 -0
- package/.github/skills/payment-integration/scripts/package.json +17 -0
- package/.github/skills/payment-integration/scripts/polar-webhook-verify.js +202 -0
- package/.github/skills/payment-integration/scripts/sepay-webhook-verify.js +193 -0
- package/.github/skills/payment-integration/scripts/test-scripts.js +237 -0
- package/.github/skills/plans-kanban/assets/dashboard-template.html +119 -0
- package/.github/skills/plans-kanban/assets/dashboard.css +1594 -0
- package/.github/skills/plans-kanban/assets/dashboard.js +596 -0
- package/.github/skills/plans-kanban/assets/favicon.png +0 -0
- package/.github/skills/plans-kanban/package-lock.json +123 -0
- package/.github/skills/plans-kanban/package.json +13 -0
- package/.github/skills/plans-kanban/scripts/lib/dashboard-renderer.cjs +884 -0
- package/.github/skills/plans-kanban/scripts/lib/http-server.cjs +310 -0
- package/.github/skills/plans-kanban/scripts/lib/plan-metadata-extractor.cjs +489 -0
- package/.github/skills/plans-kanban/scripts/lib/plan-parser.cjs +175 -0
- package/.github/skills/plans-kanban/scripts/lib/plan-scanner.cjs +272 -0
- package/.github/skills/plans-kanban/scripts/lib/port-finder.cjs +48 -0
- package/.github/skills/plans-kanban/scripts/lib/process-mgr.cjs +128 -0
- package/.github/skills/plans-kanban/scripts/server.cjs +260 -0
- package/.github/skills/repomix/scripts/.coverage +0 -0
- package/.github/skills/repomix/scripts/README.md +179 -0
- package/.github/skills/repomix/scripts/repomix_batch.py +455 -0
- package/.github/skills/repomix/scripts/repos.example.json +15 -0
- package/.github/skills/repomix/scripts/requirements.txt +15 -0
- package/.github/skills/scout-validation/scripts/lib/broad-pattern-detector.cjs +124 -0
- package/.github/skills/scout-validation/scripts/lib/path-checker.cjs +66 -0
- package/.github/skills/scout-validation/scripts/lib/schema-validator.cjs +45 -0
- package/.github/skills/scout-validation/scripts/package.json +11 -0
- package/.github/skills/scout-validation/scripts/validate-scout-output.cjs +219 -0
- package/.github/skills/scout-validation/test/broad-pattern-output.json +18 -0
- package/.github/skills/scout-validation/test/invalid-path-output.json +18 -0
- package/.github/skills/scout-validation/test/valid-scout-output.json +26 -0
- package/.github/skills/sequential-thinking/.env.example +8 -0
- package/.github/skills/sequential-thinking/README.md +183 -0
- package/.github/skills/sequential-thinking/package.json +31 -0
- package/.github/skills/sequential-thinking/scripts/format-thought.js +159 -0
- package/.github/skills/sequential-thinking/scripts/process-thought.js +236 -0
- package/.github/skills/shopify/README.md +66 -0
- package/.github/skills/shopify/scripts/.coverage +0 -0
- package/.github/skills/shopify/scripts/requirements.txt +19 -0
- package/.github/skills/shopify/scripts/shopify_init.py +423 -0
- package/.github/skills/skill-creator/LICENSE.txt +202 -0
- package/.github/skills/skill-creator/scripts/init_skill.py +303 -0
- package/.github/skills/skill-creator/scripts/package_skill.py +110 -0
- package/.github/skills/skill-creator/scripts/quick_validate.py +65 -0
- package/.github/skills/ui-styling/LICENSE.txt +202 -0
- package/.github/skills/ui-styling/canvas-fonts/ArsenalSC-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/ArsenalSC-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/BigShoulders-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/BigShoulders-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/BigShoulders-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Boldonse-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Boldonse-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/BricolageGrotesque-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/BricolageGrotesque-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/BricolageGrotesque-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/CrimsonPro-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/CrimsonPro-Italic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/CrimsonPro-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/CrimsonPro-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/DMMono-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/DMMono-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/EricaOne-OFL.txt +94 -0
- package/.github/skills/ui-styling/canvas-fonts/EricaOne-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/GeistMono-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/GeistMono-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/GeistMono-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Gloock-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Gloock-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexMono-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexMono-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexMono-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexSerif-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexSerif-BoldItalic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexSerif-Italic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/IBMPlexSerif-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-BoldItalic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-Italic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSans-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSerif-Italic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/InstrumentSerif-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Italiana-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Italiana-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/JetBrainsMono-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/JetBrainsMono-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/JetBrainsMono-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Jura-Light.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Jura-Medium.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Jura-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/LibreBaskerville-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/LibreBaskerville-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Lora-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Lora-BoldItalic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Lora-Italic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Lora-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Lora-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/NationalPark-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/NationalPark-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/NationalPark-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/NothingYouCouldDo-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Outfit-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Outfit-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Outfit-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/PixelifySans-Medium.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/PixelifySans-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/PoiretOne-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/PoiretOne-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/RedHatMono-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/RedHatMono-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/RedHatMono-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Silkscreen-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Silkscreen-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/SmoochSans-Medium.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/SmoochSans-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Tektur-Medium.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/Tektur-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/Tektur-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/WorkSans-Bold.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/WorkSans-BoldItalic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/WorkSans-Italic.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/WorkSans-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/WorkSans-Regular.ttf +0 -0
- package/.github/skills/ui-styling/canvas-fonts/YoungSerif-OFL.txt +93 -0
- package/.github/skills/ui-styling/canvas-fonts/YoungSerif-Regular.ttf +0 -0
- package/.github/skills/ui-styling/scripts/.coverage +0 -0
- package/.github/skills/ui-styling/scripts/requirements.txt +17 -0
- package/.github/skills/ui-styling/scripts/shadcn_add.py +292 -0
- package/.github/skills/ui-styling/scripts/tailwind_config_gen.py +456 -0
- package/.github/skills/ui-ux-pro-max/data/charts.csv +26 -0
- package/.github/skills/ui-ux-pro-max/data/colors.csv +97 -0
- package/.github/skills/ui-ux-pro-max/data/landing.csv +31 -0
- package/.github/skills/ui-ux-pro-max/data/products.csv +97 -0
- package/.github/skills/ui-ux-pro-max/data/prompts.csv +24 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/flutter.csv +53 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/html-tailwind.csv +51 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/nextjs.csv +53 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/react-native.csv +52 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/react.csv +54 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/svelte.csv +54 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/swiftui.csv +51 -0
- package/.github/skills/ui-ux-pro-max/data/stacks/vue.csv +50 -0
- package/.github/skills/ui-ux-pro-max/data/styles.csv +59 -0
- package/.github/skills/ui-ux-pro-max/data/typography.csv +58 -0
- package/.github/skills/ui-ux-pro-max/data/ux-guidelines.csv +100 -0
- package/.github/skills/ui-ux-pro-max/scripts/core.py +236 -0
- package/.github/skills/ui-ux-pro-max/scripts/search.py +76 -0
- package/.github/skills/web-frameworks/scripts/.coverage +0 -0
- package/.github/skills/web-frameworks/scripts/__init__.py +0 -0
- package/.github/skills/web-frameworks/scripts/nextjs_init.py +547 -0
- package/.github/skills/web-frameworks/scripts/requirements.txt +16 -0
- package/.github/skills/web-frameworks/scripts/turborepo_migrate.py +394 -0
- package/dist/config/constants.d.ts +2 -0
- package/dist/config/constants.d.ts.map +1 -1
- package/dist/config/constants.js +4 -1
- package/dist/config/constants.js.map +1 -1
- package/dist/domains/github/github-client.d.ts +5 -0
- package/dist/domains/github/github-client.d.ts.map +1 -1
- package/dist/domains/github/github-client.js +44 -0
- package/dist/domains/github/github-client.js.map +1 -1
- package/dist/utils/downloader.d.ts +3 -1
- package/dist/utils/downloader.d.ts.map +1 -1
- package/dist/utils/downloader.js +48 -11
- package/dist/utils/downloader.js.map +1 -1
- package/package.json +3 -1
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
# Payment Integration Skill
|
|
2
|
+
|
|
3
|
+
Comprehensive payment integration skill for SePay (Vietnamese payment gateway) and Polar (global SaaS monetization platform).
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
### SePay Integration
|
|
8
|
+
- Vietnamese payment gateway with VietQR, NAPAS, bank transfers, and cards
|
|
9
|
+
- 44+ supported banks
|
|
10
|
+
- Webhook verification with API Key/OAuth2 authentication
|
|
11
|
+
- QR code generation API
|
|
12
|
+
- Order-based virtual accounts
|
|
13
|
+
- SDK support for Node.js, PHP, and Laravel
|
|
14
|
+
|
|
15
|
+
### Polar Integration
|
|
16
|
+
- Global SaaS monetization platform
|
|
17
|
+
- Merchant of Record (handles global tax compliance)
|
|
18
|
+
- Subscription management with trials, upgrades, downgrades
|
|
19
|
+
- Usage-based billing with events and meters
|
|
20
|
+
- Automated benefit delivery (GitHub repos, Discord roles, license keys, files)
|
|
21
|
+
- Customer self-service portal
|
|
22
|
+
- Multi-language SDKs (TypeScript, Python, PHP, Go)
|
|
23
|
+
- Framework adapters (Next.js, Laravel, Remix, etc.)
|
|
24
|
+
|
|
25
|
+
## Structure
|
|
26
|
+
|
|
27
|
+
```
|
|
28
|
+
payment-integration/
|
|
29
|
+
├── SKILL.md # Main skill definition
|
|
30
|
+
├── README.md # This file
|
|
31
|
+
├── references/ # Progressive disclosure documentation
|
|
32
|
+
│ ├── sepay/ # SePay integration guides
|
|
33
|
+
│ │ ├── overview.md # Auth, capabilities, environments
|
|
34
|
+
│ │ ├── api.md # API endpoints and operations
|
|
35
|
+
│ │ ├── webhooks.md # Webhook setup and handling
|
|
36
|
+
│ │ ├── sdk.md # SDK usage (Node.js, PHP, Laravel)
|
|
37
|
+
│ │ ├── qr-codes.md # VietQR generation
|
|
38
|
+
│ │ └── best-practices.md # Security, patterns, monitoring
|
|
39
|
+
│ └── polar/ # Polar integration guides
|
|
40
|
+
│ ├── overview.md # Auth, MoR concept, environments
|
|
41
|
+
│ ├── products.md # Products, pricing, usage-based billing
|
|
42
|
+
│ ├── checkouts.md # Checkout flows and embedded checkout
|
|
43
|
+
│ ├── subscriptions.md # Lifecycle, upgrades, trials
|
|
44
|
+
│ ├── webhooks.md # Event handling and verification
|
|
45
|
+
│ ├── benefits.md # Automated benefit delivery
|
|
46
|
+
│ ├── sdk.md # Multi-language SDK usage
|
|
47
|
+
│ └── best-practices.md # Security, patterns, monitoring
|
|
48
|
+
└── scripts/ # Integration helper scripts
|
|
49
|
+
├── sepay-webhook-verify.js # SePay webhook verification
|
|
50
|
+
├── polar-webhook-verify.js # Polar webhook verification
|
|
51
|
+
├── checkout-helper.js # Checkout session generation
|
|
52
|
+
├── test-scripts.js # Test suite for all scripts
|
|
53
|
+
├── package.json # Node.js package configuration
|
|
54
|
+
└── .env.example # Environment variable template
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
## Usage
|
|
58
|
+
|
|
59
|
+
### Activate the Skill
|
|
60
|
+
|
|
61
|
+
Claude Code will automatically activate this skill when you mention payment integration, subscriptions, webhooks, or platform-specific terms (SePay, Polar).
|
|
62
|
+
|
|
63
|
+
### Manual Activation
|
|
64
|
+
|
|
65
|
+
In conversations, simply reference the platforms:
|
|
66
|
+
- "Implement SePay payment integration"
|
|
67
|
+
- "Set up Polar subscriptions with usage-based billing"
|
|
68
|
+
- "Create webhook handler for payment notifications"
|
|
69
|
+
|
|
70
|
+
### Using Scripts
|
|
71
|
+
|
|
72
|
+
**SePay Webhook Verification:**
|
|
73
|
+
```bash
|
|
74
|
+
cd %USERPROFILE%/.claude/skills/payment-integration/scripts
|
|
75
|
+
node sepay-webhook-verify.js '{"id":12345,"gateway":"Vietcombank",...}'
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
**Polar Webhook Verification:**
|
|
79
|
+
```bash
|
|
80
|
+
node polar-webhook-verify.js '{"type":"order.paid","data":{...}}' base64secret
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
**Checkout Helper:**
|
|
84
|
+
```bash
|
|
85
|
+
# SePay
|
|
86
|
+
node checkout-helper.js sepay '{"orderInvoiceNumber":"ORD001","orderAmount":100000,...}'
|
|
87
|
+
|
|
88
|
+
# Polar
|
|
89
|
+
node checkout-helper.js polar '{"productPriceId":"price_xxx","successUrl":"https://..."}'
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
**Run Tests:**
|
|
93
|
+
```bash
|
|
94
|
+
npm test
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
## Environment Variables
|
|
98
|
+
|
|
99
|
+
Copy `.env.example` to `.env` and configure:
|
|
100
|
+
|
|
101
|
+
```env
|
|
102
|
+
# SePay
|
|
103
|
+
SEPAY_MERCHANT_ID=SP-TEST-XXXXXXX
|
|
104
|
+
SEPAY_SECRET_KEY=spsk_test_xxxxxxxxxxxxx
|
|
105
|
+
SEPAY_ENV=sandbox
|
|
106
|
+
SEPAY_WEBHOOK_API_KEY=your_key
|
|
107
|
+
|
|
108
|
+
# Polar
|
|
109
|
+
POLAR_ACCESS_TOKEN=polar_xxxxxxxxxxxxxxxx
|
|
110
|
+
POLAR_SERVER=sandbox
|
|
111
|
+
POLAR_WEBHOOK_SECRET=base64_secret
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
## Progressive Disclosure
|
|
115
|
+
|
|
116
|
+
The skill uses progressive disclosure to minimize context usage:
|
|
117
|
+
1. **SKILL.md** - Overview and quick reference (~99 lines)
|
|
118
|
+
2. **references/** - Detailed guides loaded as needed (<100 lines each)
|
|
119
|
+
3. **scripts/** - Executable helpers with embedded examples
|
|
120
|
+
|
|
121
|
+
Load only the references you need for your current task.
|
|
122
|
+
|
|
123
|
+
## Platform Selection Guide
|
|
124
|
+
|
|
125
|
+
**Choose SePay for:**
|
|
126
|
+
- Vietnamese market targeting
|
|
127
|
+
- Bank transfer automation
|
|
128
|
+
- Local payment methods
|
|
129
|
+
- QR code payments (VietQR/NAPAS)
|
|
130
|
+
- Direct bank monitoring
|
|
131
|
+
|
|
132
|
+
**Choose Polar for:**
|
|
133
|
+
- Global market
|
|
134
|
+
- SaaS/subscription business
|
|
135
|
+
- Usage-based billing
|
|
136
|
+
- Automated benefit delivery
|
|
137
|
+
- Tax compliance (Merchant of Record)
|
|
138
|
+
- Customer self-service
|
|
139
|
+
|
|
140
|
+
## Examples
|
|
141
|
+
|
|
142
|
+
### SePay Payment Flow
|
|
143
|
+
1. Load `references/sepay/overview.md` for authentication
|
|
144
|
+
2. Load `references/sepay/sdk.md` for integration
|
|
145
|
+
3. Use `checkout-helper.js` to generate payment form
|
|
146
|
+
4. Load `references/sepay/webhooks.md` for notifications
|
|
147
|
+
5. Use `sepay-webhook-verify.js` to verify authenticity
|
|
148
|
+
|
|
149
|
+
### Polar Subscription Flow
|
|
150
|
+
1. Load `references/polar/overview.md` for setup
|
|
151
|
+
2. Load `references/polar/products.md` for pricing
|
|
152
|
+
3. Load `references/polar/checkouts.md` for payment
|
|
153
|
+
4. Load `references/polar/subscriptions.md` for lifecycle
|
|
154
|
+
5. Load `references/polar/webhooks.md` for events
|
|
155
|
+
6. Load `references/polar/benefits.md` for automation
|
|
156
|
+
|
|
157
|
+
## Testing
|
|
158
|
+
|
|
159
|
+
All scripts include comprehensive test coverage:
|
|
160
|
+
- SePay webhook verification (with/without authentication)
|
|
161
|
+
- Polar webhook signature validation
|
|
162
|
+
- Checkout configuration generation
|
|
163
|
+
- Error handling and edge cases
|
|
164
|
+
|
|
165
|
+
Run `npm test` in the scripts directory to verify functionality.
|
|
166
|
+
|
|
167
|
+
## Support
|
|
168
|
+
|
|
169
|
+
### SePay
|
|
170
|
+
- Docs: https://developer.sepay.vn/en
|
|
171
|
+
- Email: info@sepay.vn
|
|
172
|
+
- Hotline: 02873059589
|
|
173
|
+
|
|
174
|
+
### Polar
|
|
175
|
+
- Docs: https://polar.sh/docs
|
|
176
|
+
- API Reference: https://polar.sh/docs/api-reference
|
|
177
|
+
- GitHub: https://github.com/polarsource/polar
|
|
178
|
+
|
|
179
|
+
## License
|
|
180
|
+
|
|
181
|
+
MIT
|
|
182
|
+
|
|
183
|
+
## Version
|
|
184
|
+
|
|
185
|
+
1.0.0
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# SePay Configuration
|
|
2
|
+
SEPAY_MERCHANT_ID=SP-TEST-XXXXXXX
|
|
3
|
+
SEPAY_SECRET_KEY=spsk_test_xxxxxxxxxxxxx
|
|
4
|
+
SEPAY_ENV=sandbox # or 'production'
|
|
5
|
+
|
|
6
|
+
# SePay Webhook Configuration
|
|
7
|
+
SEPAY_WEBHOOK_AUTH_TYPE=api_key # or 'oauth2' or 'none'
|
|
8
|
+
SEPAY_WEBHOOK_API_KEY=your_webhook_api_key
|
|
9
|
+
|
|
10
|
+
# Polar Configuration
|
|
11
|
+
POLAR_ACCESS_TOKEN=polar_xxxxxxxxxxxxxxxx
|
|
12
|
+
POLAR_SERVER=sandbox # or 'production'
|
|
13
|
+
POLAR_ORG_ID=org_xxxxxxxxxxxxx
|
|
14
|
+
|
|
15
|
+
# Polar Webhook Configuration
|
|
16
|
+
POLAR_WEBHOOK_SECRET=base64_encoded_secret
|
|
17
|
+
|
|
18
|
+
# Optional: Database or other configuration
|
|
19
|
+
# DATABASE_URL=postgresql://user:password@localhost:5432/dbname
|
|
20
|
+
# REDIS_URL=redis://localhost:6379
|
|
@@ -0,0 +1,244 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Checkout Helper Script
|
|
5
|
+
*
|
|
6
|
+
* Generate checkout sessions for both SePay and Polar platforms.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* node checkout-helper.js <platform> <config-json>
|
|
10
|
+
*
|
|
11
|
+
* Platforms: sepay, polar
|
|
12
|
+
*
|
|
13
|
+
* Environment Variables:
|
|
14
|
+
* SEPAY_MERCHANT_ID, SEPAY_SECRET_KEY, SEPAY_ENV
|
|
15
|
+
* POLAR_ACCESS_TOKEN, POLAR_SERVER
|
|
16
|
+
*/
|
|
17
|
+
|
|
18
|
+
const crypto = require('crypto');
|
|
19
|
+
|
|
20
|
+
class CheckoutHelper {
|
|
21
|
+
/**
|
|
22
|
+
* Generate SePay checkout form fields
|
|
23
|
+
*/
|
|
24
|
+
static generateSePayCheckout(config) {
|
|
25
|
+
const {
|
|
26
|
+
merchantId,
|
|
27
|
+
secretKey,
|
|
28
|
+
orderInvoiceNumber,
|
|
29
|
+
orderAmount,
|
|
30
|
+
currency = 'VND',
|
|
31
|
+
successUrl,
|
|
32
|
+
errorUrl,
|
|
33
|
+
cancelUrl,
|
|
34
|
+
orderDescription,
|
|
35
|
+
operation = 'PURCHASE'
|
|
36
|
+
} = config;
|
|
37
|
+
|
|
38
|
+
// Validate required fields
|
|
39
|
+
const required = ['merchantId', 'secretKey', 'orderInvoiceNumber', 'orderAmount', 'successUrl', 'errorUrl', 'cancelUrl'];
|
|
40
|
+
for (const field of required) {
|
|
41
|
+
if (!config[field]) {
|
|
42
|
+
throw new Error(`Missing required field: ${field}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Build fields
|
|
47
|
+
const fields = {
|
|
48
|
+
merchant_id: merchantId,
|
|
49
|
+
operation: operation,
|
|
50
|
+
order_invoice_number: orderInvoiceNumber,
|
|
51
|
+
order_amount: orderAmount,
|
|
52
|
+
currency: currency,
|
|
53
|
+
success_url: successUrl,
|
|
54
|
+
error_url: errorUrl,
|
|
55
|
+
cancel_url: cancelUrl,
|
|
56
|
+
order_description: orderDescription || `Order ${orderInvoiceNumber}`,
|
|
57
|
+
timestamp: new Date().toISOString()
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
// Generate HMAC SHA256 signature
|
|
61
|
+
const signatureData = Object.keys(fields)
|
|
62
|
+
.sort()
|
|
63
|
+
.map(key => `${key}=${fields[key]}`)
|
|
64
|
+
.join('&');
|
|
65
|
+
|
|
66
|
+
const signature = crypto
|
|
67
|
+
.createHmac('sha256', secretKey)
|
|
68
|
+
.update(signatureData)
|
|
69
|
+
.digest('hex');
|
|
70
|
+
|
|
71
|
+
fields.signature = signature;
|
|
72
|
+
|
|
73
|
+
return {
|
|
74
|
+
fields,
|
|
75
|
+
formUrl: config.env === 'production'
|
|
76
|
+
? 'https://pay.sepay.vn/v1/init'
|
|
77
|
+
: 'https://sandbox.pay.sepay.vn/v1/init',
|
|
78
|
+
htmlForm: this.generateHTMLForm(fields, config.env === 'production'
|
|
79
|
+
? 'https://pay.sepay.vn/v1/init'
|
|
80
|
+
: 'https://sandbox.pay.sepay.vn/v1/init')
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Generate Polar checkout configuration
|
|
86
|
+
*/
|
|
87
|
+
static generatePolarCheckout(config) {
|
|
88
|
+
const {
|
|
89
|
+
productPriceId,
|
|
90
|
+
successUrl,
|
|
91
|
+
externalCustomerId,
|
|
92
|
+
customerEmail,
|
|
93
|
+
customerName,
|
|
94
|
+
discountId,
|
|
95
|
+
metadata,
|
|
96
|
+
embedOrigin
|
|
97
|
+
} = config;
|
|
98
|
+
|
|
99
|
+
// Validate required fields
|
|
100
|
+
if (!productPriceId) {
|
|
101
|
+
throw new Error('Missing required field: productPriceId');
|
|
102
|
+
}
|
|
103
|
+
if (!successUrl) {
|
|
104
|
+
throw new Error('Missing required field: successUrl');
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// Must be absolute URL
|
|
108
|
+
if (!successUrl.startsWith('http://') && !successUrl.startsWith('https://')) {
|
|
109
|
+
throw new Error('successUrl must be an absolute URL');
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
const checkoutConfig = {
|
|
113
|
+
product_price_id: productPriceId,
|
|
114
|
+
success_url: successUrl
|
|
115
|
+
};
|
|
116
|
+
|
|
117
|
+
// Add optional fields
|
|
118
|
+
if (externalCustomerId) checkoutConfig.external_customer_id = externalCustomerId;
|
|
119
|
+
if (customerEmail) checkoutConfig.customer_email = customerEmail;
|
|
120
|
+
if (customerName) checkoutConfig.customer_name = customerName;
|
|
121
|
+
if (discountId) checkoutConfig.discount_id = discountId;
|
|
122
|
+
if (metadata) checkoutConfig.metadata = metadata;
|
|
123
|
+
if (embedOrigin) checkoutConfig.embed_origin = embedOrigin;
|
|
124
|
+
|
|
125
|
+
return {
|
|
126
|
+
config: checkoutConfig,
|
|
127
|
+
apiEndpoint: config.server === 'sandbox'
|
|
128
|
+
? 'https://sandbox-api.polar.sh/v1/checkouts'
|
|
129
|
+
: 'https://api.polar.sh/v1/checkouts',
|
|
130
|
+
curlCommand: this.generatePolarCurl(checkoutConfig, config.accessToken, config.server)
|
|
131
|
+
};
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
/**
|
|
135
|
+
* Generate HTML form for SePay
|
|
136
|
+
*/
|
|
137
|
+
static generateHTMLForm(fields, actionUrl) {
|
|
138
|
+
const inputs = Object.keys(fields)
|
|
139
|
+
.map(key => ` <input type="hidden" name="${key}" value="${fields[key]}" />`)
|
|
140
|
+
.join('\n');
|
|
141
|
+
|
|
142
|
+
return `
|
|
143
|
+
<!DOCTYPE html>
|
|
144
|
+
<html>
|
|
145
|
+
<head>
|
|
146
|
+
<meta charset="UTF-8">
|
|
147
|
+
<title>SePay Payment</title>
|
|
148
|
+
</head>
|
|
149
|
+
<body>
|
|
150
|
+
<form id="payment-form" action="${actionUrl}" method="POST">
|
|
151
|
+
${inputs}
|
|
152
|
+
<button type="submit">Pay Now</button>
|
|
153
|
+
</form>
|
|
154
|
+
|
|
155
|
+
<script>
|
|
156
|
+
// Auto-submit form
|
|
157
|
+
// document.getElementById('payment-form').submit();
|
|
158
|
+
</script>
|
|
159
|
+
</body>
|
|
160
|
+
</html>
|
|
161
|
+
`.trim();
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/**
|
|
165
|
+
* Generate cURL command for Polar
|
|
166
|
+
*/
|
|
167
|
+
static generatePolarCurl(config, accessToken, server = 'production') {
|
|
168
|
+
const endpoint = server === 'sandbox'
|
|
169
|
+
? 'https://sandbox-api.polar.sh/v1/checkouts'
|
|
170
|
+
: 'https://api.polar.sh/v1/checkouts';
|
|
171
|
+
|
|
172
|
+
return `curl -X POST ${endpoint} \\
|
|
173
|
+
-H "Authorization: Bearer ${accessToken}" \\
|
|
174
|
+
-H "Content-Type: application/json" \\
|
|
175
|
+
-d '${JSON.stringify(config, null, 2)}'`;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
|
|
179
|
+
// CLI Usage
|
|
180
|
+
if (require.main === module) {
|
|
181
|
+
const args = process.argv.slice(2);
|
|
182
|
+
|
|
183
|
+
if (args.length < 2) {
|
|
184
|
+
console.log('Usage: node checkout-helper.js <platform> <config-json>');
|
|
185
|
+
console.log('\nPlatforms:');
|
|
186
|
+
console.log(' sepay - SePay checkout form generation');
|
|
187
|
+
console.log(' polar - Polar checkout session configuration');
|
|
188
|
+
console.log('\nExamples:');
|
|
189
|
+
console.log('\nSePay:');
|
|
190
|
+
console.log(' node checkout-helper.js sepay \'{"orderInvoiceNumber":"ORD001","orderAmount":100000,"successUrl":"https://example.com/success","errorUrl":"https://example.com/error","cancelUrl":"https://example.com/cancel"}\'');
|
|
191
|
+
console.log('\nPolar:');
|
|
192
|
+
console.log(' node checkout-helper.js polar \'{"productPriceId":"price_xxx","successUrl":"https://example.com/success","externalCustomerId":"user_123"}\'');
|
|
193
|
+
process.exit(1);
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
try {
|
|
197
|
+
const platform = args[0].toLowerCase();
|
|
198
|
+
const config = JSON.parse(args[1]);
|
|
199
|
+
|
|
200
|
+
if (platform === 'sepay') {
|
|
201
|
+
// Get from environment or config
|
|
202
|
+
config.merchantId = config.merchantId || process.env.SEPAY_MERCHANT_ID;
|
|
203
|
+
config.secretKey = config.secretKey || process.env.SEPAY_SECRET_KEY;
|
|
204
|
+
config.env = config.env || process.env.SEPAY_ENV || 'sandbox';
|
|
205
|
+
|
|
206
|
+
const result = CheckoutHelper.generateSePayCheckout(config);
|
|
207
|
+
|
|
208
|
+
console.log('✓ SePay Checkout Generated\n');
|
|
209
|
+
console.log('Form URL:', result.formUrl);
|
|
210
|
+
console.log('\nForm Fields:');
|
|
211
|
+
console.log(JSON.stringify(result.fields, null, 2));
|
|
212
|
+
console.log('\nHTML Form:');
|
|
213
|
+
console.log(result.htmlForm);
|
|
214
|
+
} else if (platform === 'polar') {
|
|
215
|
+
// Get from environment or config
|
|
216
|
+
config.accessToken = config.accessToken || process.env.POLAR_ACCESS_TOKEN;
|
|
217
|
+
config.server = config.server || process.env.POLAR_SERVER || 'production';
|
|
218
|
+
|
|
219
|
+
if (!config.accessToken) {
|
|
220
|
+
console.error('✗ Error: POLAR_ACCESS_TOKEN is required');
|
|
221
|
+
console.error('Set it via environment variable or in config JSON');
|
|
222
|
+
process.exit(1);
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
const result = CheckoutHelper.generatePolarCheckout(config);
|
|
226
|
+
|
|
227
|
+
console.log('✓ Polar Checkout Configuration Generated\n');
|
|
228
|
+
console.log('API Endpoint:', result.apiEndpoint);
|
|
229
|
+
console.log('\nCheckout Configuration:');
|
|
230
|
+
console.log(JSON.stringify(result.config, null, 2));
|
|
231
|
+
console.log('\ncURL Command:');
|
|
232
|
+
console.log(result.curlCommand);
|
|
233
|
+
} else {
|
|
234
|
+
console.error(`✗ Error: Unknown platform '${platform}'`);
|
|
235
|
+
console.error('Supported platforms: sepay, polar');
|
|
236
|
+
process.exit(1);
|
|
237
|
+
}
|
|
238
|
+
} catch (error) {
|
|
239
|
+
console.error('✗ Error:', error.message);
|
|
240
|
+
process.exit(1);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
module.exports = CheckoutHelper;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "payment-integration-scripts",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "Helper scripts for SePay and Polar payment integration",
|
|
5
|
+
"scripts": {
|
|
6
|
+
"test": "node test-scripts.js"
|
|
7
|
+
},
|
|
8
|
+
"keywords": [
|
|
9
|
+
"payment",
|
|
10
|
+
"sepay",
|
|
11
|
+
"polar",
|
|
12
|
+
"webhook",
|
|
13
|
+
"checkout"
|
|
14
|
+
],
|
|
15
|
+
"author": "",
|
|
16
|
+
"license": "MIT"
|
|
17
|
+
}
|
|
@@ -0,0 +1,202 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Polar Webhook Verification Script
|
|
5
|
+
*
|
|
6
|
+
* Verifies Polar webhook signatures following Standard Webhooks specification.
|
|
7
|
+
*
|
|
8
|
+
* Usage:
|
|
9
|
+
* node polar-webhook-verify.js <webhook-payload-json> <webhook-secret>
|
|
10
|
+
*
|
|
11
|
+
* Environment Variables:
|
|
12
|
+
* POLAR_WEBHOOK_SECRET - Webhook secret (base64 encoded)
|
|
13
|
+
*/
|
|
14
|
+
|
|
15
|
+
const crypto = require('crypto');
|
|
16
|
+
|
|
17
|
+
class PolarWebhookVerifier {
|
|
18
|
+
constructor(secret) {
|
|
19
|
+
if (!secret) {
|
|
20
|
+
throw new Error('Webhook secret is required');
|
|
21
|
+
}
|
|
22
|
+
// Decode base64 secret
|
|
23
|
+
this.secret = Buffer.from(secret, 'base64');
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Verify webhook signature
|
|
28
|
+
*/
|
|
29
|
+
verifySignature(payload, headers) {
|
|
30
|
+
const webhookId = headers['webhook-id'];
|
|
31
|
+
const webhookTimestamp = headers['webhook-timestamp'];
|
|
32
|
+
const webhookSignature = headers['webhook-signature'];
|
|
33
|
+
|
|
34
|
+
if (!webhookId || !webhookTimestamp || !webhookSignature) {
|
|
35
|
+
throw new Error('Missing required webhook headers');
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
// Check timestamp (reject if > 5 minutes old)
|
|
39
|
+
const timestamp = parseInt(webhookTimestamp);
|
|
40
|
+
const now = Math.floor(Date.now() / 1000);
|
|
41
|
+
|
|
42
|
+
if (Math.abs(now - timestamp) > 300) {
|
|
43
|
+
throw new Error('Webhook timestamp too old or in future');
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
// Parse signatures
|
|
47
|
+
const signatures = webhookSignature.split(',').map(sig => {
|
|
48
|
+
const parts = sig.split('=');
|
|
49
|
+
const version = parts[0];
|
|
50
|
+
const signature = parts.slice(1).join('='); // Rejoin in case signature contains '='
|
|
51
|
+
return { version, signature };
|
|
52
|
+
});
|
|
53
|
+
|
|
54
|
+
// Create signed payload
|
|
55
|
+
const signedPayload = `${webhookTimestamp}.${payload}`;
|
|
56
|
+
|
|
57
|
+
// Compute expected signature
|
|
58
|
+
const expectedSignature = crypto
|
|
59
|
+
.createHmac('sha256', this.secret)
|
|
60
|
+
.update(signedPayload)
|
|
61
|
+
.digest('base64');
|
|
62
|
+
|
|
63
|
+
// Check if any signature matches
|
|
64
|
+
const isValid = signatures.some(sig => {
|
|
65
|
+
return sig.version === 'v1' && sig.signature === expectedSignature;
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
if (!isValid) {
|
|
69
|
+
throw new Error('Invalid webhook signature');
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
return true;
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/**
|
|
76
|
+
* Process webhook event
|
|
77
|
+
*/
|
|
78
|
+
process(payload, headers) {
|
|
79
|
+
try {
|
|
80
|
+
// Verify signature
|
|
81
|
+
this.verifySignature(payload, headers);
|
|
82
|
+
|
|
83
|
+
// Parse payload
|
|
84
|
+
const event = typeof payload === 'string' ? JSON.parse(payload) : payload;
|
|
85
|
+
|
|
86
|
+
// Validate event structure
|
|
87
|
+
if (!event.type || !event.data) {
|
|
88
|
+
throw new Error('Invalid event structure');
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
return {
|
|
92
|
+
success: true,
|
|
93
|
+
event: {
|
|
94
|
+
type: event.type,
|
|
95
|
+
data: event.data
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
} catch (error) {
|
|
99
|
+
return {
|
|
100
|
+
success: false,
|
|
101
|
+
error: error.message
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
/**
|
|
107
|
+
* Get event category
|
|
108
|
+
*/
|
|
109
|
+
static getEventCategory(eventType) {
|
|
110
|
+
const categories = {
|
|
111
|
+
'checkout.': 'checkout',
|
|
112
|
+
'order.': 'order',
|
|
113
|
+
'subscription.': 'subscription',
|
|
114
|
+
'customer.': 'customer',
|
|
115
|
+
'benefit_grant.': 'benefit',
|
|
116
|
+
'refund.': 'refund',
|
|
117
|
+
'product.': 'product'
|
|
118
|
+
};
|
|
119
|
+
|
|
120
|
+
for (const [prefix, category] of Object.entries(categories)) {
|
|
121
|
+
if (eventType.startsWith(prefix)) {
|
|
122
|
+
return category;
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
return 'unknown';
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
/**
|
|
130
|
+
* Check if event is a payment
|
|
131
|
+
*/
|
|
132
|
+
static isPaymentEvent(eventType) {
|
|
133
|
+
return ['order.paid', 'order.created'].includes(eventType);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
/**
|
|
137
|
+
* Check if event is a subscription change
|
|
138
|
+
*/
|
|
139
|
+
static isSubscriptionEvent(eventType) {
|
|
140
|
+
return eventType.startsWith('subscription.');
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
// CLI Usage
|
|
145
|
+
if (require.main === module) {
|
|
146
|
+
const args = process.argv.slice(2);
|
|
147
|
+
|
|
148
|
+
if (args.length < 1) {
|
|
149
|
+
console.log('Usage: node polar-webhook-verify.js <webhook-payload-json> [webhook-secret]');
|
|
150
|
+
console.log('\nWebhook secret can also be provided via POLAR_WEBHOOK_SECRET environment variable');
|
|
151
|
+
console.log('\nExample:');
|
|
152
|
+
console.log(' node polar-webhook-verify.js \'{"type":"order.paid","data":{...}}\' base64secret');
|
|
153
|
+
process.exit(1);
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
try {
|
|
157
|
+
const payload = args[0];
|
|
158
|
+
const secret = args[1] || process.env.POLAR_WEBHOOK_SECRET;
|
|
159
|
+
|
|
160
|
+
if (!secret) {
|
|
161
|
+
console.error('✗ Error: Webhook secret is required');
|
|
162
|
+
console.error('Provide it as second argument or set POLAR_WEBHOOK_SECRET environment variable');
|
|
163
|
+
process.exit(1);
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// Mock headers for CLI testing
|
|
167
|
+
const timestamp = Math.floor(Date.now() / 1000);
|
|
168
|
+
const signedPayload = `${timestamp}.${payload}`;
|
|
169
|
+
const signature = crypto
|
|
170
|
+
.createHmac('sha256', Buffer.from(secret, 'base64'))
|
|
171
|
+
.update(signedPayload)
|
|
172
|
+
.digest('base64');
|
|
173
|
+
|
|
174
|
+
const headers = {
|
|
175
|
+
'webhook-id': 'msg_test_' + Date.now(),
|
|
176
|
+
'webhook-timestamp': timestamp.toString(),
|
|
177
|
+
'webhook-signature': `v1=${signature}`
|
|
178
|
+
};
|
|
179
|
+
|
|
180
|
+
const verifier = new PolarWebhookVerifier(secret);
|
|
181
|
+
const result = verifier.process(payload, headers);
|
|
182
|
+
|
|
183
|
+
if (result.success) {
|
|
184
|
+
console.log('✓ Webhook verified successfully\n');
|
|
185
|
+
console.log('Event Details:');
|
|
186
|
+
console.log(` Type: ${result.event.type}`);
|
|
187
|
+
console.log(` Category: ${PolarWebhookVerifier.getEventCategory(result.event.type)}`);
|
|
188
|
+
console.log(` Is Payment: ${PolarWebhookVerifier.isPaymentEvent(result.event.type) ? 'Yes' : 'No'}`);
|
|
189
|
+
console.log(` Is Subscription: ${PolarWebhookVerifier.isSubscriptionEvent(result.event.type) ? 'Yes' : 'No'}`);
|
|
190
|
+
console.log('\nEvent Data:');
|
|
191
|
+
console.log(JSON.stringify(result.event.data, null, 2));
|
|
192
|
+
} else {
|
|
193
|
+
console.error('✗ Verification failed:', result.error);
|
|
194
|
+
process.exit(1);
|
|
195
|
+
}
|
|
196
|
+
} catch (error) {
|
|
197
|
+
console.error('✗ Error:', error.message);
|
|
198
|
+
process.exit(1);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
module.exports = PolarWebhookVerifier;
|