@mytechtoday/augment-extensions 0.1.2 → 0.4.0
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/README.md +614 -39
- package/augment-extensions/coding-standards/bash/README.md +196 -0
- package/augment-extensions/coding-standards/bash/module.json +163 -0
- package/augment-extensions/coding-standards/bash/rules/naming-conventions.md +336 -0
- package/augment-extensions/coding-standards/bash/rules/universal-standards.md +289 -0
- package/augment-extensions/coding-standards/css/README.md +40 -0
- package/augment-extensions/coding-standards/css/examples/css-examples.css +550 -0
- package/augment-extensions/coding-standards/css/module.json +44 -0
- package/augment-extensions/coding-standards/css/rules/css-modern-features.md +448 -0
- package/augment-extensions/coding-standards/css/rules/css-standards.md +492 -0
- package/augment-extensions/coding-standards/html/README.md +40 -0
- package/augment-extensions/coding-standards/html/examples/html-examples.html +267 -0
- package/augment-extensions/coding-standards/html/examples/responsive-layout.html +505 -0
- package/augment-extensions/coding-standards/html/module.json +44 -0
- package/augment-extensions/coding-standards/html/rules/html-standards.md +349 -0
- package/augment-extensions/coding-standards/html-css-js/README.md +194 -0
- package/augment-extensions/coding-standards/html-css-js/examples/async-examples.js +487 -0
- package/augment-extensions/coding-standards/html-css-js/examples/css-examples.css +550 -0
- package/augment-extensions/coding-standards/html-css-js/examples/dom-examples.js +667 -0
- package/augment-extensions/coding-standards/html-css-js/examples/html-examples.html +267 -0
- package/augment-extensions/coding-standards/html-css-js/examples/javascript-examples.js +612 -0
- package/augment-extensions/coding-standards/html-css-js/examples/responsive-layout.html +505 -0
- package/augment-extensions/coding-standards/html-css-js/module.json +48 -0
- package/augment-extensions/coding-standards/html-css-js/rules/async-patterns.md +515 -0
- package/augment-extensions/coding-standards/html-css-js/rules/css-modern-features.md +448 -0
- package/augment-extensions/coding-standards/html-css-js/rules/css-standards.md +492 -0
- package/augment-extensions/coding-standards/html-css-js/rules/dom-manipulation.md +439 -0
- package/augment-extensions/coding-standards/html-css-js/rules/html-standards.md +349 -0
- package/augment-extensions/coding-standards/html-css-js/rules/javascript-standards.md +486 -0
- package/augment-extensions/coding-standards/html-css-js/rules/performance.md +463 -0
- package/augment-extensions/coding-standards/html-css-js/rules/tooling.md +543 -0
- package/augment-extensions/coding-standards/js/README.md +46 -0
- package/augment-extensions/coding-standards/js/examples/async-examples.js +487 -0
- package/augment-extensions/coding-standards/js/examples/dom-examples.js +667 -0
- package/augment-extensions/coding-standards/js/examples/javascript-examples.js +612 -0
- package/augment-extensions/coding-standards/js/module.json +49 -0
- package/augment-extensions/coding-standards/js/rules/async-patterns.md +515 -0
- package/augment-extensions/coding-standards/js/rules/dom-manipulation.md +439 -0
- package/augment-extensions/coding-standards/js/rules/javascript-standards.md +486 -0
- package/augment-extensions/coding-standards/js/rules/performance.md +463 -0
- package/augment-extensions/coding-standards/js/rules/tooling.md +543 -0
- package/augment-extensions/coding-standards/php/README.md +248 -0
- package/augment-extensions/coding-standards/php/examples/api-endpoint-example.php +204 -0
- package/augment-extensions/coding-standards/php/examples/cli-command-example.php +206 -0
- package/augment-extensions/coding-standards/php/examples/legacy-refactoring-example.php +234 -0
- package/augment-extensions/coding-standards/php/examples/web-application-example.php +211 -0
- package/augment-extensions/coding-standards/php/examples/woocommerce-extension-example.php +215 -0
- package/augment-extensions/coding-standards/php/examples/wordpress-plugin-example.php +189 -0
- package/augment-extensions/coding-standards/php/module.json +166 -0
- package/augment-extensions/coding-standards/php/rules/api-development.md +480 -0
- package/augment-extensions/coding-standards/php/rules/category-configuration.md +332 -0
- package/augment-extensions/coding-standards/php/rules/cli-tools.md +472 -0
- package/augment-extensions/coding-standards/php/rules/cms-integration.md +561 -0
- package/augment-extensions/coding-standards/php/rules/code-quality.md +402 -0
- package/augment-extensions/coding-standards/php/rules/documentation.md +425 -0
- package/augment-extensions/coding-standards/php/rules/ecommerce.md +627 -0
- package/augment-extensions/coding-standards/php/rules/error-handling.md +336 -0
- package/augment-extensions/coding-standards/php/rules/legacy-migration.md +677 -0
- package/augment-extensions/coding-standards/php/rules/naming-conventions.md +279 -0
- package/augment-extensions/coding-standards/php/rules/performance.md +392 -0
- package/augment-extensions/coding-standards/php/rules/psr-standards.md +186 -0
- package/augment-extensions/coding-standards/php/rules/security.md +358 -0
- package/augment-extensions/coding-standards/php/rules/testing.md +403 -0
- package/augment-extensions/coding-standards/php/rules/type-declarations.md +331 -0
- package/augment-extensions/coding-standards/php/rules/web-applications.md +426 -0
- package/augment-extensions/coding-standards/powershell/README.md +154 -0
- package/augment-extensions/coding-standards/powershell/examples/admin-example.ps1 +272 -0
- package/augment-extensions/coding-standards/powershell/examples/automation-example.ps1 +173 -0
- package/augment-extensions/coding-standards/powershell/examples/cloud-example.ps1 +243 -0
- package/augment-extensions/coding-standards/powershell/examples/cross-platform-example.ps1 +297 -0
- package/augment-extensions/coding-standards/powershell/examples/dsc-example.ps1 +224 -0
- package/augment-extensions/coding-standards/powershell/examples/legacy-migration-example.ps1 +340 -0
- package/augment-extensions/coding-standards/powershell/examples/module-example.psm1 +255 -0
- package/augment-extensions/coding-standards/powershell/module.json +165 -0
- package/augment-extensions/coding-standards/powershell/rules/administrative-tools.md +439 -0
- package/augment-extensions/coding-standards/powershell/rules/automation-scripts.md +240 -0
- package/augment-extensions/coding-standards/powershell/rules/cloud-orchestration.md +384 -0
- package/augment-extensions/coding-standards/powershell/rules/configuration-schema.md +383 -0
- package/augment-extensions/coding-standards/powershell/rules/cross-platform-scripts.md +482 -0
- package/augment-extensions/coding-standards/powershell/rules/dsc-configurations.md +296 -0
- package/augment-extensions/coding-standards/powershell/rules/error-handling.md +314 -0
- package/augment-extensions/coding-standards/powershell/rules/legacy-migrations.md +466 -0
- package/augment-extensions/coding-standards/powershell/rules/modules-functions.md +244 -0
- package/augment-extensions/coding-standards/powershell/rules/naming-conventions.md +266 -0
- package/augment-extensions/coding-standards/powershell/rules/performance-optimization.md +209 -0
- package/augment-extensions/coding-standards/powershell/rules/security-practices.md +314 -0
- package/augment-extensions/coding-standards/powershell/rules/testing-guidelines.md +268 -0
- package/augment-extensions/coding-standards/powershell/rules/universal-standards.md +197 -0
- package/augment-extensions/coding-standards/python/README.md +12 -8
- package/augment-extensions/coding-standards/python/examples/best-practices.py +373 -0
- package/augment-extensions/coding-standards/python/module.json +8 -4
- package/augment-extensions/coding-standards/python/rules/async-patterns.md +884 -0
- package/augment-extensions/coding-standards/python/rules/documentation.md +831 -0
- package/augment-extensions/coding-standards/python/rules/error-handling.md +855 -68
- package/augment-extensions/coding-standards/python/rules/testing.md +409 -0
- package/augment-extensions/coding-standards/python/rules/tooling.md +446 -0
- package/augment-extensions/coding-standards/python/rules/type-hints.md +115 -50
- package/augment-extensions/collections/html-css-js/README.md +82 -0
- package/augment-extensions/collections/html-css-js/collection.json +41 -0
- package/augment-extensions/domain-rules/database/README.md +161 -0
- package/augment-extensions/domain-rules/database/examples/flat-database-example.md +793 -0
- package/augment-extensions/domain-rules/database/examples/hybrid-database-example.md +1132 -0
- package/augment-extensions/domain-rules/database/examples/nosql-document-example.md +868 -0
- package/augment-extensions/domain-rules/database/examples/nosql-graph-example.md +805 -0
- package/augment-extensions/domain-rules/database/examples/relational-schema-example.md +621 -0
- package/augment-extensions/domain-rules/database/examples/vector-database-example.md +965 -0
- package/augment-extensions/domain-rules/database/module.json +28 -0
- package/augment-extensions/domain-rules/database/rules/flat-databases.md +624 -0
- package/augment-extensions/domain-rules/database/rules/nosql-databases.md +588 -0
- package/augment-extensions/domain-rules/database/rules/nosql-document-stores.md +856 -0
- package/augment-extensions/domain-rules/database/rules/nosql-graph-databases.md +778 -0
- package/augment-extensions/domain-rules/database/rules/nosql-key-value-stores.md +963 -0
- package/augment-extensions/domain-rules/database/rules/performance-optimization.md +1076 -0
- package/augment-extensions/domain-rules/database/rules/relational-databases.md +697 -0
- package/augment-extensions/domain-rules/database/rules/relational-indexing.md +671 -0
- package/augment-extensions/domain-rules/database/rules/relational-query-optimization.md +607 -0
- package/augment-extensions/domain-rules/database/rules/relational-schema-design.md +907 -0
- package/augment-extensions/domain-rules/database/rules/relational-transactions.md +783 -0
- package/augment-extensions/domain-rules/database/rules/security-standards.md +980 -0
- package/augment-extensions/domain-rules/database/rules/universal-best-practices.md +485 -0
- package/augment-extensions/domain-rules/database/rules/vector-databases.md +521 -0
- package/augment-extensions/domain-rules/database/rules/vector-embeddings.md +858 -0
- package/augment-extensions/domain-rules/database/rules/vector-indexing.md +934 -0
- package/augment-extensions/domain-rules/mcp/README.md +150 -0
- package/augment-extensions/domain-rules/mcp/examples/compressed-example.md +522 -0
- package/augment-extensions/domain-rules/mcp/examples/graph-augmented-example.md +520 -0
- package/augment-extensions/domain-rules/mcp/examples/hybrid-example.md +570 -0
- package/augment-extensions/domain-rules/mcp/examples/state-based-example.md +427 -0
- package/augment-extensions/domain-rules/mcp/examples/token-based-example.md +435 -0
- package/augment-extensions/domain-rules/mcp/examples/vector-based-example.md +502 -0
- package/augment-extensions/domain-rules/mcp/module.json +49 -0
- package/augment-extensions/domain-rules/mcp/rules/compressed-mcp.md +595 -0
- package/augment-extensions/domain-rules/mcp/rules/configuration.md +345 -0
- package/augment-extensions/domain-rules/mcp/rules/graph-augmented-mcp.md +687 -0
- package/augment-extensions/domain-rules/mcp/rules/hybrid-mcp.md +636 -0
- package/augment-extensions/domain-rules/mcp/rules/state-based-mcp.md +484 -0
- package/augment-extensions/domain-rules/mcp/rules/testing-validation.md +360 -0
- package/augment-extensions/domain-rules/mcp/rules/token-based-mcp.md +393 -0
- package/augment-extensions/domain-rules/mcp/rules/universal-rules.md +194 -0
- package/augment-extensions/domain-rules/mcp/rules/vector-based-mcp.md +625 -0
- package/augment-extensions/domain-rules/wordpress/README.md +163 -0
- package/augment-extensions/domain-rules/wordpress/module.json +32 -0
- package/augment-extensions/domain-rules/wordpress/rules/coding-standards.md +617 -0
- package/augment-extensions/domain-rules/wordpress/rules/directory-structure.md +270 -0
- package/augment-extensions/domain-rules/wordpress/rules/file-patterns.md +423 -0
- package/augment-extensions/domain-rules/wordpress/rules/gutenberg-blocks.md +493 -0
- package/augment-extensions/domain-rules/wordpress/rules/performance.md +568 -0
- package/augment-extensions/domain-rules/wordpress/rules/plugin-development.md +510 -0
- package/augment-extensions/domain-rules/wordpress/rules/project-detection.md +251 -0
- package/augment-extensions/domain-rules/wordpress/rules/rest-api.md +501 -0
- package/augment-extensions/domain-rules/wordpress/rules/security.md +564 -0
- package/augment-extensions/domain-rules/wordpress/rules/theme-development.md +388 -0
- package/augment-extensions/domain-rules/wordpress/rules/woocommerce.md +441 -0
- package/augment-extensions/domain-rules/wordpress-plugin/README.md +139 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/ajax-plugin.md +1599 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/custom-post-type-plugin.md +1727 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/gutenberg-block-plugin.md +428 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/gutenberg-block.md +422 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/mvc-plugin.md +1623 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/object-oriented-plugin.md +1343 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/rest-endpoint.md +734 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/settings-page-plugin.md +1350 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/simple-procedural-plugin.md +503 -0
- package/augment-extensions/domain-rules/wordpress-plugin/examples/singleton-plugin.md +971 -0
- package/augment-extensions/domain-rules/wordpress-plugin/module.json +53 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/activation-hooks.md +770 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/admin-interface.md +874 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/ajax-handlers.md +629 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/asset-management.md +559 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/context-providers.md +709 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/cron-jobs.md +736 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/database-management.md +1057 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/documentation-standards.md +463 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/frontend-functionality.md +478 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/gutenberg-blocks.md +818 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/internationalization.md +416 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/migration.md +667 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/performance-optimization.md +878 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/plugin-architecture.md +693 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/plugin-structure.md +352 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/rest-api.md +818 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/scaffolding-workflow.md +624 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/security-best-practices.md +866 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/testing-patterns.md +1165 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/testing.md +414 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/vscode-integration.md +751 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/woocommerce-integration.md +949 -0
- package/augment-extensions/domain-rules/wordpress-plugin/rules/wordpress-org-submission.md +458 -0
- package/augment-extensions/examples/gutenberg-block-plugin/README.md +101 -0
- package/augment-extensions/examples/gutenberg-block-plugin/examples/testimonial-block.md +428 -0
- package/augment-extensions/examples/gutenberg-block-plugin/module.json +40 -0
- package/augment-extensions/examples/rest-api-plugin/README.md +98 -0
- package/augment-extensions/examples/rest-api-plugin/examples/task-manager-api.md +1299 -0
- package/augment-extensions/examples/rest-api-plugin/module.json +40 -0
- package/augment-extensions/examples/woocommerce-extension/README.md +98 -0
- package/augment-extensions/examples/woocommerce-extension/examples/product-customizer.md +763 -0
- package/augment-extensions/examples/woocommerce-extension/module.json +40 -0
- package/augment-extensions/workflows/beads/module.json +4 -3
- package/augment-extensions/workflows/database/README.md +195 -0
- package/augment-extensions/workflows/database/ai-prompt-testing.md +295 -0
- package/augment-extensions/workflows/database/examples/migration-example.md +498 -0
- package/augment-extensions/workflows/database/examples/optimization-example.md +496 -0
- package/augment-extensions/workflows/database/examples/schema-design-example.md +444 -0
- package/augment-extensions/workflows/database/module.json +42 -0
- package/augment-extensions/workflows/database/rules/data-migration.md +249 -0
- package/augment-extensions/workflows/database/rules/documentation-standards.md +339 -0
- package/augment-extensions/workflows/database/rules/migration-workflow.md +352 -0
- package/augment-extensions/workflows/database/rules/optimization-workflow.md +435 -0
- package/augment-extensions/workflows/database/rules/schema-design-workflow.md +535 -0
- package/augment-extensions/workflows/database/rules/testing-patterns.md +305 -0
- package/augment-extensions/workflows/database/rules/workflow.md +458 -0
- package/augment-extensions/workflows/openspec/module.json +4 -3
- package/augment-extensions/workflows/wordpress-plugin/README.md +232 -0
- package/augment-extensions/workflows/wordpress-plugin/ai-prompts.md +839 -0
- package/augment-extensions/workflows/wordpress-plugin/bead-decomposition-patterns.md +854 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/complete-plugin-example.md +540 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/custom-post-type-example.md +1083 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/feature-addition-workflow.md +669 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/plugin-creation-workflow.md +597 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/secure-form-handler-example.md +925 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/security-audit-workflow.md +752 -0
- package/augment-extensions/workflows/wordpress-plugin/examples/wordpress-org-submission-workflow.md +773 -0
- package/augment-extensions/workflows/wordpress-plugin/module.json +49 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/best-practices.md +942 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/development-workflow.md +702 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/submission-workflow.md +728 -0
- package/augment-extensions/workflows/wordpress-plugin/rules/testing-workflow.md +775 -0
- package/augment-extensions/writing-standards/screenplay/README.md +171 -0
- package/augment-extensions/writing-standards/screenplay/examples/aaa-hollywood-scene.fountain +164 -0
- package/augment-extensions/writing-standards/screenplay/module.json +124 -0
- package/augment-extensions/writing-standards/screenplay/rules/universal-formatting.md +339 -0
- package/cli/MODULES.md +302 -0
- package/cli/dist/cli.js +142 -9
- package/cli/dist/cli.js.map +1 -1
- package/cli/dist/commands/catalog.d.ts +13 -0
- package/cli/dist/commands/catalog.d.ts.map +1 -0
- package/cli/dist/commands/catalog.js +104 -0
- package/cli/dist/commands/catalog.js.map +1 -0
- package/cli/dist/commands/gui.d.ts +6 -0
- package/cli/dist/commands/gui.d.ts.map +1 -0
- package/cli/dist/commands/gui.js +211 -0
- package/cli/dist/commands/gui.js.map +1 -0
- package/cli/dist/commands/init.d.ts.map +1 -1
- package/cli/dist/commands/init.js +12 -0
- package/cli/dist/commands/init.js.map +1 -1
- package/cli/dist/commands/install-rules.d.ts +14 -0
- package/cli/dist/commands/install-rules.d.ts.map +1 -0
- package/cli/dist/commands/install-rules.js +127 -0
- package/cli/dist/commands/install-rules.js.map +1 -0
- package/cli/dist/commands/link.d.ts.map +1 -1
- package/cli/dist/commands/link.js +9 -11
- package/cli/dist/commands/link.js.map +1 -1
- package/cli/dist/commands/list.d.ts.map +1 -1
- package/cli/dist/commands/list.js +11 -28
- package/cli/dist/commands/list.js.map +1 -1
- package/cli/dist/commands/mcp.d.ts +48 -0
- package/cli/dist/commands/mcp.d.ts.map +1 -0
- package/cli/dist/commands/mcp.js +229 -0
- package/cli/dist/commands/mcp.js.map +1 -0
- package/cli/dist/commands/self-remove.d.ts +7 -0
- package/cli/dist/commands/self-remove.d.ts.map +1 -0
- package/cli/dist/commands/self-remove.js +179 -0
- package/cli/dist/commands/self-remove.js.map +1 -0
- package/cli/dist/commands/show.d.ts.map +1 -1
- package/cli/dist/commands/show.js +42 -71
- package/cli/dist/commands/show.js.map +1 -1
- package/cli/dist/commands/skill.d.ts +67 -0
- package/cli/dist/commands/skill.d.ts.map +1 -0
- package/cli/dist/commands/skill.js +513 -0
- package/cli/dist/commands/skill.js.map +1 -0
- package/cli/dist/commands/unlink.d.ts +6 -0
- package/cli/dist/commands/unlink.d.ts.map +1 -0
- package/cli/dist/commands/unlink.js +115 -0
- package/cli/dist/commands/unlink.js.map +1 -0
- package/cli/dist/commands/validate.d.ts +6 -0
- package/cli/dist/commands/validate.d.ts.map +1 -0
- package/cli/dist/commands/validate.js +159 -0
- package/cli/dist/commands/validate.js.map +1 -0
- package/cli/dist/utils/catalog-sync.d.ts +22 -0
- package/cli/dist/utils/catalog-sync.d.ts.map +1 -0
- package/cli/dist/utils/catalog-sync.js +157 -0
- package/cli/dist/utils/catalog-sync.js.map +1 -0
- package/cli/dist/utils/character-count.d.ts +56 -0
- package/cli/dist/utils/character-count.d.ts.map +1 -0
- package/cli/dist/utils/character-count.js +190 -0
- package/cli/dist/utils/character-count.js.map +1 -0
- package/cli/dist/utils/documentation-validator.d.ts +18 -0
- package/cli/dist/utils/documentation-validator.d.ts.map +1 -0
- package/cli/dist/utils/documentation-validator.js +233 -0
- package/cli/dist/utils/documentation-validator.js.map +1 -0
- package/cli/dist/utils/install-rules.d.ts +32 -0
- package/cli/dist/utils/install-rules.d.ts.map +1 -0
- package/cli/dist/utils/install-rules.js +375 -0
- package/cli/dist/utils/install-rules.js.map +1 -0
- package/cli/dist/utils/mcp-integration.d.ts +70 -0
- package/cli/dist/utils/mcp-integration.d.ts.map +1 -0
- package/cli/dist/utils/mcp-integration.js +292 -0
- package/cli/dist/utils/mcp-integration.js.map +1 -0
- package/cli/dist/utils/module-system.d.ts +153 -0
- package/cli/dist/utils/module-system.d.ts.map +1 -0
- package/cli/dist/utils/module-system.js +528 -0
- package/cli/dist/utils/module-system.js.map +1 -0
- package/cli/dist/utils/modules-catalog.d.ts +33 -0
- package/cli/dist/utils/modules-catalog.d.ts.map +1 -0
- package/cli/dist/utils/modules-catalog.js +163 -0
- package/cli/dist/utils/modules-catalog.js.map +1 -0
- package/cli/dist/utils/rule-install-hooks.d.ts +19 -0
- package/cli/dist/utils/rule-install-hooks.d.ts.map +1 -0
- package/cli/dist/utils/rule-install-hooks.js +224 -0
- package/cli/dist/utils/rule-install-hooks.js.map +1 -0
- package/cli/dist/utils/skill-system.d.ts +95 -0
- package/cli/dist/utils/skill-system.d.ts.map +1 -0
- package/cli/dist/utils/skill-system.js +313 -0
- package/cli/dist/utils/skill-system.js.map +1 -0
- package/modules.md +534 -70
- package/package.json +12 -3
|
@@ -0,0 +1,963 @@
|
|
|
1
|
+
# NoSQL Key-Value Stores
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This document covers key-value store databases (Redis, DynamoDB, Memcached), including data modeling patterns, caching strategies, TTL management, atomic operations, pub/sub patterns, data structures, and persistence options.
|
|
6
|
+
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Key-Value Store Fundamentals
|
|
10
|
+
|
|
11
|
+
### What is a Key-Value Store?
|
|
12
|
+
|
|
13
|
+
**Definition**: Database that stores data as simple key-value pairs
|
|
14
|
+
|
|
15
|
+
**Characteristics:**
|
|
16
|
+
- Simplest NoSQL database model
|
|
17
|
+
- Fast lookups by key (O(1) complexity)
|
|
18
|
+
- Limited query capabilities (no complex queries)
|
|
19
|
+
- High performance and scalability
|
|
20
|
+
- In-memory or persistent storage
|
|
21
|
+
|
|
22
|
+
**Basic Operations:**
|
|
23
|
+
- `GET key` - Retrieve value by key
|
|
24
|
+
- `SET key value` - Store value with key
|
|
25
|
+
- `DELETE key` - Remove key-value pair
|
|
26
|
+
- `EXISTS key` - Check if key exists
|
|
27
|
+
|
|
28
|
+
**Example:**
|
|
29
|
+
```
|
|
30
|
+
Key: "user:123:name"
|
|
31
|
+
Value: "John Doe"
|
|
32
|
+
|
|
33
|
+
Key: "session:abc123"
|
|
34
|
+
Value: '{"user_id": 123, "expires_at": "2024-01-15T12:00:00Z"}'
|
|
35
|
+
|
|
36
|
+
Key: "cache:product:456"
|
|
37
|
+
Value: '{"id": 456, "name": "Widget", "price": 19.99}'
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
### Popular Key-Value Databases
|
|
41
|
+
|
|
42
|
+
**Redis:**
|
|
43
|
+
- In-memory data store
|
|
44
|
+
- Rich data structures (strings, lists, sets, hashes, sorted sets)
|
|
45
|
+
- Pub/sub messaging
|
|
46
|
+
- Persistence options (RDB, AOF)
|
|
47
|
+
- Replication and clustering
|
|
48
|
+
- Lua scripting
|
|
49
|
+
|
|
50
|
+
**DynamoDB (AWS):**
|
|
51
|
+
- Fully managed NoSQL database
|
|
52
|
+
- Key-value and document store
|
|
53
|
+
- Automatic scaling
|
|
54
|
+
- Single-digit millisecond latency
|
|
55
|
+
- ACID transactions
|
|
56
|
+
- Global tables (multi-region)
|
|
57
|
+
|
|
58
|
+
**Memcached:**
|
|
59
|
+
- In-memory caching system
|
|
60
|
+
- Simple key-value storage
|
|
61
|
+
- No persistence
|
|
62
|
+
- Multi-threaded
|
|
63
|
+
- LRU eviction
|
|
64
|
+
|
|
65
|
+
**Riak:**
|
|
66
|
+
- Distributed key-value store
|
|
67
|
+
- High availability (AP in CAP)
|
|
68
|
+
- Eventual consistency
|
|
69
|
+
- Multi-datacenter replication
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Data Modeling
|
|
74
|
+
|
|
75
|
+
### Key Design Patterns
|
|
76
|
+
|
|
77
|
+
**Pattern 1: Namespace with colons**
|
|
78
|
+
```
|
|
79
|
+
user:123:profile
|
|
80
|
+
user:123:settings
|
|
81
|
+
user:123:sessions
|
|
82
|
+
product:456:details
|
|
83
|
+
product:456:inventory
|
|
84
|
+
cache:homepage:en
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Pattern 2: Hierarchical keys**
|
|
88
|
+
```
|
|
89
|
+
app:production:user:123:name
|
|
90
|
+
app:production:user:123:email
|
|
91
|
+
app:staging:user:123:name
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
**Pattern 3: Composite keys**
|
|
95
|
+
```
|
|
96
|
+
user_session:123:abc123
|
|
97
|
+
order_item:456:789
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Key Naming Conventions
|
|
101
|
+
|
|
102
|
+
**Best practices:**
|
|
103
|
+
- ✅ Use descriptive names
|
|
104
|
+
- ✅ Use consistent separators (`:` or `_`)
|
|
105
|
+
- ✅ Include entity type in key
|
|
106
|
+
- ✅ Keep keys short but readable
|
|
107
|
+
- ✅ Use namespaces to avoid collisions
|
|
108
|
+
|
|
109
|
+
**Examples:**
|
|
110
|
+
```
|
|
111
|
+
✅ GOOD:
|
|
112
|
+
user:123:profile
|
|
113
|
+
session:abc123
|
|
114
|
+
cache:product:456
|
|
115
|
+
|
|
116
|
+
❌ BAD:
|
|
117
|
+
u123p (too cryptic)
|
|
118
|
+
user_profile_for_user_id_123 (too long)
|
|
119
|
+
123 (no context)
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Value Serialization
|
|
123
|
+
|
|
124
|
+
**Store complex data as JSON:**
|
|
125
|
+
|
|
126
|
+
```javascript
|
|
127
|
+
// Node.js with Redis
|
|
128
|
+
const user = {
|
|
129
|
+
id: 123,
|
|
130
|
+
name: "John Doe",
|
|
131
|
+
email: "john@example.com",
|
|
132
|
+
created_at: "2024-01-15T10:00:00Z"
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
// Store as JSON string
|
|
136
|
+
await redis.set(`user:${user.id}`, JSON.stringify(user));
|
|
137
|
+
|
|
138
|
+
// Retrieve and parse
|
|
139
|
+
const data = await redis.get(`user:${user.id}`);
|
|
140
|
+
const user = JSON.parse(data);
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
**Store binary data:**
|
|
144
|
+
```javascript
|
|
145
|
+
// Store image as binary
|
|
146
|
+
const imageBuffer = fs.readFileSync('avatar.jpg');
|
|
147
|
+
await redis.set(`avatar:${userId}`, imageBuffer);
|
|
148
|
+
|
|
149
|
+
// Retrieve binary data
|
|
150
|
+
const avatar = await redis.get(`avatar:${userId}`);
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Caching Strategies
|
|
156
|
+
|
|
157
|
+
### Cache-Aside (Lazy Loading)
|
|
158
|
+
|
|
159
|
+
**Pattern**: Application checks cache first, then database
|
|
160
|
+
|
|
161
|
+
```javascript
|
|
162
|
+
async function getUser(userId) {
|
|
163
|
+
const cacheKey = `user:${userId}`;
|
|
164
|
+
|
|
165
|
+
// Try cache first
|
|
166
|
+
let user = await redis.get(cacheKey);
|
|
167
|
+
if (user) {
|
|
168
|
+
return JSON.parse(user);
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Cache miss - query database
|
|
172
|
+
user = await db.query('SELECT * FROM users WHERE id = $1', [userId]);
|
|
173
|
+
|
|
174
|
+
// Store in cache with TTL
|
|
175
|
+
await redis.setex(cacheKey, 3600, JSON.stringify(user));
|
|
176
|
+
|
|
177
|
+
return user;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
async function updateUser(userId, data) {
|
|
181
|
+
// Update database
|
|
182
|
+
await db.query('UPDATE users SET ... WHERE id = $1', [userId]);
|
|
183
|
+
|
|
184
|
+
// Invalidate cache
|
|
185
|
+
await redis.del(`user:${userId}`);
|
|
186
|
+
}
|
|
187
|
+
```
|
|
188
|
+
|
|
189
|
+
**Advantages:**
|
|
190
|
+
- ✅ Only requested data is cached
|
|
191
|
+
- ✅ Cache failures don't break application
|
|
192
|
+
|
|
193
|
+
**Disadvantages:**
|
|
194
|
+
- ❌ Cache miss penalty (extra latency)
|
|
195
|
+
- ❌ Stale data possible
|
|
196
|
+
|
|
197
|
+
### Write-Through Cache
|
|
198
|
+
|
|
199
|
+
**Pattern**: Write to cache and database simultaneously
|
|
200
|
+
|
|
201
|
+
```javascript
|
|
202
|
+
async function updateUser(userId, data) {
|
|
203
|
+
const cacheKey = `user:${userId}`;
|
|
204
|
+
|
|
205
|
+
// Update database
|
|
206
|
+
const user = await db.query('UPDATE users SET ... WHERE id = $1 RETURNING *', [userId]);
|
|
207
|
+
|
|
208
|
+
// Update cache
|
|
209
|
+
await redis.setex(cacheKey, 3600, JSON.stringify(user));
|
|
210
|
+
|
|
211
|
+
return user;
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
**Advantages:**
|
|
216
|
+
- ✅ Cache always up-to-date
|
|
217
|
+
- ✅ No stale data
|
|
218
|
+
|
|
219
|
+
**Disadvantages:**
|
|
220
|
+
- ❌ Write latency (two operations)
|
|
221
|
+
- ❌ Unused data may be cached
|
|
222
|
+
|
|
223
|
+
### Write-Behind Cache (Write-Back)
|
|
224
|
+
|
|
225
|
+
**Pattern**: Write to cache immediately, write to database asynchronously
|
|
226
|
+
|
|
227
|
+
```javascript
|
|
228
|
+
async function updateUser(userId, data) {
|
|
229
|
+
const cacheKey = `user:${userId}`;
|
|
230
|
+
|
|
231
|
+
// Update cache immediately
|
|
232
|
+
await redis.setex(cacheKey, 3600, JSON.stringify(data));
|
|
233
|
+
|
|
234
|
+
// Queue database write (async)
|
|
235
|
+
await queue.add('update-user', { userId, data });
|
|
236
|
+
|
|
237
|
+
return data;
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
// Background worker processes queue
|
|
241
|
+
async function processUpdateQueue(job) {
|
|
242
|
+
const { userId, data } = job.data;
|
|
243
|
+
await db.query('UPDATE users SET ... WHERE id = $1', [userId]);
|
|
244
|
+
}
|
|
245
|
+
```
|
|
246
|
+
|
|
247
|
+
**Advantages:**
|
|
248
|
+
- ✅ Fast writes
|
|
249
|
+
- ✅ Reduced database load
|
|
250
|
+
|
|
251
|
+
**Disadvantages:**
|
|
252
|
+
- ❌ Data loss risk if cache fails
|
|
253
|
+
- ❌ Complex implementation
|
|
254
|
+
|
|
255
|
+
### Cache Invalidation Strategies
|
|
256
|
+
|
|
257
|
+
**Strategy 1: TTL (Time-To-Live)**
|
|
258
|
+
```javascript
|
|
259
|
+
// Set expiration time
|
|
260
|
+
await redis.setex('user:123', 3600, JSON.stringify(user)); // Expires in 1 hour
|
|
261
|
+
|
|
262
|
+
// Check TTL
|
|
263
|
+
const ttl = await redis.ttl('user:123'); // Returns seconds remaining
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
**Strategy 2: Explicit invalidation**
|
|
267
|
+
```javascript
|
|
268
|
+
// Delete on update
|
|
269
|
+
async function updateUser(userId, data) {
|
|
270
|
+
await db.query('UPDATE users SET ... WHERE id = $1', [userId]);
|
|
271
|
+
await redis.del(`user:${userId}`);
|
|
272
|
+
}
|
|
273
|
+
```
|
|
274
|
+
|
|
275
|
+
**Strategy 3: Tag-based invalidation**
|
|
276
|
+
```javascript
|
|
277
|
+
// Store tags for related keys
|
|
278
|
+
await redis.sadd('tag:user:123', 'user:123:profile', 'user:123:settings');
|
|
279
|
+
|
|
280
|
+
// Invalidate all keys with tag
|
|
281
|
+
async function invalidateUserCache(userId) {
|
|
282
|
+
const keys = await redis.smembers(`tag:user:${userId}`);
|
|
283
|
+
if (keys.length > 0) {
|
|
284
|
+
await redis.del(...keys);
|
|
285
|
+
await redis.del(`tag:user:${userId}`);
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
**Strategy 4: Version-based invalidation**
|
|
291
|
+
```javascript
|
|
292
|
+
// Include version in key
|
|
293
|
+
const version = await redis.incr('user:123:version');
|
|
294
|
+
const cacheKey = `user:123:v${version}`;
|
|
295
|
+
await redis.setex(cacheKey, 3600, JSON.stringify(user));
|
|
296
|
+
|
|
297
|
+
// Increment version to invalidate
|
|
298
|
+
await redis.incr('user:123:version'); // Old cache keys become stale
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## TTL Management
|
|
304
|
+
|
|
305
|
+
### Setting TTL
|
|
306
|
+
|
|
307
|
+
**Set TTL on creation:**
|
|
308
|
+
```javascript
|
|
309
|
+
// Redis: SETEX (set with expiration)
|
|
310
|
+
await redis.setex('session:abc123', 1800, JSON.stringify(session)); // 30 minutes
|
|
311
|
+
|
|
312
|
+
// Redis: SET with EX option
|
|
313
|
+
await redis.set('session:abc123', JSON.stringify(session), 'EX', 1800);
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
**Set TTL on existing key:**
|
|
317
|
+
```javascript
|
|
318
|
+
// Redis: EXPIRE
|
|
319
|
+
await redis.expire('session:abc123', 1800);
|
|
320
|
+
|
|
321
|
+
// Redis: EXPIREAT (expire at timestamp)
|
|
322
|
+
const expiresAt = Math.floor(Date.now() / 1000) + 1800;
|
|
323
|
+
await redis.expireat('session:abc123', expiresAt);
|
|
324
|
+
```
|
|
325
|
+
|
|
326
|
+
**Remove TTL:**
|
|
327
|
+
```javascript
|
|
328
|
+
// Redis: PERSIST (remove expiration)
|
|
329
|
+
await redis.persist('session:abc123');
|
|
330
|
+
```
|
|
331
|
+
|
|
332
|
+
### TTL Patterns
|
|
333
|
+
|
|
334
|
+
**Pattern 1: Sliding expiration (extend on access)**
|
|
335
|
+
```javascript
|
|
336
|
+
async function getSession(sessionId) {
|
|
337
|
+
const session = await redis.get(`session:${sessionId}`);
|
|
338
|
+
if (session) {
|
|
339
|
+
// Extend TTL on access
|
|
340
|
+
await redis.expire(`session:${sessionId}`, 1800);
|
|
341
|
+
return JSON.parse(session);
|
|
342
|
+
}
|
|
343
|
+
return null;
|
|
344
|
+
}
|
|
345
|
+
```
|
|
346
|
+
|
|
347
|
+
**Pattern 2: Absolute expiration**
|
|
348
|
+
```javascript
|
|
349
|
+
// Session expires at specific time
|
|
350
|
+
const expiresAt = new Date('2024-01-15T23:59:59Z');
|
|
351
|
+
const ttl = Math.floor((expiresAt - Date.now()) / 1000);
|
|
352
|
+
await redis.setex(`session:${sessionId}`, ttl, JSON.stringify(session));
|
|
353
|
+
```
|
|
354
|
+
|
|
355
|
+
**Pattern 3: Tiered TTL**
|
|
356
|
+
```javascript
|
|
357
|
+
// Different TTL for different data types
|
|
358
|
+
await redis.setex('cache:hot:product:123', 300, data); // 5 minutes
|
|
359
|
+
await redis.setex('cache:warm:product:123', 3600, data); // 1 hour
|
|
360
|
+
await redis.setex('cache:cold:product:123', 86400, data); // 24 hours
|
|
361
|
+
```
|
|
362
|
+
|
|
363
|
+
---
|
|
364
|
+
|
|
365
|
+
## Atomic Operations
|
|
366
|
+
|
|
367
|
+
### Increment/Decrement
|
|
368
|
+
|
|
369
|
+
**Counters:**
|
|
370
|
+
```javascript
|
|
371
|
+
// Increment counter
|
|
372
|
+
await redis.incr('page:views:123');
|
|
373
|
+
|
|
374
|
+
// Increment by amount
|
|
375
|
+
await redis.incrby('user:points:123', 10);
|
|
376
|
+
|
|
377
|
+
// Decrement
|
|
378
|
+
await redis.decr('inventory:product:456');
|
|
379
|
+
|
|
380
|
+
// Decrement by amount
|
|
381
|
+
await redis.decrby('inventory:product:456', 5);
|
|
382
|
+
```
|
|
383
|
+
|
|
384
|
+
**Rate limiting:**
|
|
385
|
+
```javascript
|
|
386
|
+
async function checkRateLimit(userId) {
|
|
387
|
+
const key = `ratelimit:${userId}:${Math.floor(Date.now() / 60000)}`; // Per minute
|
|
388
|
+
const count = await redis.incr(key);
|
|
389
|
+
await redis.expire(key, 60); // Expire after 1 minute
|
|
390
|
+
|
|
391
|
+
if (count > 100) {
|
|
392
|
+
throw new Error('Rate limit exceeded');
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
```
|
|
396
|
+
|
|
397
|
+
### Compare-and-Set (CAS)
|
|
398
|
+
|
|
399
|
+
**Optimistic locking with WATCH:**
|
|
400
|
+
```javascript
|
|
401
|
+
// Redis: WATCH for optimistic locking
|
|
402
|
+
async function transferPoints(fromUser, toUser, points) {
|
|
403
|
+
const fromKey = `user:points:${fromUser}`;
|
|
404
|
+
const toKey = `user:points:${toUser}`;
|
|
405
|
+
|
|
406
|
+
await redis.watch(fromKey);
|
|
407
|
+
|
|
408
|
+
const balance = parseInt(await redis.get(fromKey));
|
|
409
|
+
if (balance < points) {
|
|
410
|
+
await redis.unwatch();
|
|
411
|
+
throw new Error('Insufficient points');
|
|
412
|
+
}
|
|
413
|
+
|
|
414
|
+
// Execute transaction
|
|
415
|
+
const result = await redis.multi()
|
|
416
|
+
.decrby(fromKey, points)
|
|
417
|
+
.incrby(toKey, points)
|
|
418
|
+
.exec();
|
|
419
|
+
|
|
420
|
+
if (!result) {
|
|
421
|
+
throw new Error('Transaction failed - retry');
|
|
422
|
+
}
|
|
423
|
+
}
|
|
424
|
+
```
|
|
425
|
+
|
|
426
|
+
### Transactions (MULTI/EXEC)
|
|
427
|
+
|
|
428
|
+
**Atomic batch operations:**
|
|
429
|
+
```javascript
|
|
430
|
+
// Redis: MULTI/EXEC transaction
|
|
431
|
+
await redis.multi()
|
|
432
|
+
.set('user:123:name', 'John Doe')
|
|
433
|
+
.set('user:123:email', 'john@example.com')
|
|
434
|
+
.sadd('users:active', '123')
|
|
435
|
+
.incr('stats:total_users')
|
|
436
|
+
.exec();
|
|
437
|
+
|
|
438
|
+
// All commands execute atomically
|
|
439
|
+
```
|
|
440
|
+
|
|
441
|
+
---
|
|
442
|
+
|
|
443
|
+
## Redis Data Structures
|
|
444
|
+
|
|
445
|
+
### Strings
|
|
446
|
+
|
|
447
|
+
**Simple key-value:**
|
|
448
|
+
```javascript
|
|
449
|
+
await redis.set('user:123:name', 'John Doe');
|
|
450
|
+
const name = await redis.get('user:123:name');
|
|
451
|
+
|
|
452
|
+
// Append
|
|
453
|
+
await redis.append('log:123', 'New log entry\n');
|
|
454
|
+
|
|
455
|
+
// Get substring
|
|
456
|
+
const substr = await redis.getrange('log:123', 0, 10);
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
### Lists
|
|
460
|
+
|
|
461
|
+
**Ordered collection:**
|
|
462
|
+
```javascript
|
|
463
|
+
// Push to list
|
|
464
|
+
await redis.lpush('queue:tasks', 'task1', 'task2', 'task3'); // Left push
|
|
465
|
+
await redis.rpush('queue:tasks', 'task4'); // Right push
|
|
466
|
+
|
|
467
|
+
// Pop from list
|
|
468
|
+
const task = await redis.lpop('queue:tasks'); // Left pop
|
|
469
|
+
const task = await redis.rpop('queue:tasks'); // Right pop
|
|
470
|
+
|
|
471
|
+
// Blocking pop (wait for item)
|
|
472
|
+
const task = await redis.blpop('queue:tasks', 5); // Wait 5 seconds
|
|
473
|
+
|
|
474
|
+
// Get range
|
|
475
|
+
const tasks = await redis.lrange('queue:tasks', 0, 9); // First 10 items
|
|
476
|
+
|
|
477
|
+
// List length
|
|
478
|
+
const length = await redis.llen('queue:tasks');
|
|
479
|
+
```
|
|
480
|
+
|
|
481
|
+
**Use cases:**
|
|
482
|
+
- Task queues
|
|
483
|
+
- Activity feeds
|
|
484
|
+
- Recent items
|
|
485
|
+
|
|
486
|
+
### Sets
|
|
487
|
+
|
|
488
|
+
**Unordered unique collection:**
|
|
489
|
+
```javascript
|
|
490
|
+
// Add to set
|
|
491
|
+
await redis.sadd('user:123:tags', 'developer', 'nodejs', 'react');
|
|
492
|
+
|
|
493
|
+
// Check membership
|
|
494
|
+
const isMember = await redis.sismember('user:123:tags', 'nodejs');
|
|
495
|
+
|
|
496
|
+
// Get all members
|
|
497
|
+
const tags = await redis.smembers('user:123:tags');
|
|
498
|
+
|
|
499
|
+
// Remove from set
|
|
500
|
+
await redis.srem('user:123:tags', 'react');
|
|
501
|
+
|
|
502
|
+
// Set operations
|
|
503
|
+
await redis.sinter('user:123:tags', 'user:456:tags'); // Intersection
|
|
504
|
+
await redis.sunion('user:123:tags', 'user:456:tags'); // Union
|
|
505
|
+
await redis.sdiff('user:123:tags', 'user:456:tags'); // Difference
|
|
506
|
+
|
|
507
|
+
// Random member
|
|
508
|
+
const randomTag = await redis.srandmember('user:123:tags');
|
|
509
|
+
|
|
510
|
+
// Set size
|
|
511
|
+
const size = await redis.scard('user:123:tags');
|
|
512
|
+
```
|
|
513
|
+
|
|
514
|
+
**Use cases:**
|
|
515
|
+
- Tags
|
|
516
|
+
- Unique visitors
|
|
517
|
+
- Relationships
|
|
518
|
+
|
|
519
|
+
### Hashes
|
|
520
|
+
|
|
521
|
+
**Field-value pairs within a key:**
|
|
522
|
+
```javascript
|
|
523
|
+
// Set hash fields
|
|
524
|
+
await redis.hset('user:123', 'name', 'John Doe');
|
|
525
|
+
await redis.hset('user:123', 'email', 'john@example.com');
|
|
526
|
+
|
|
527
|
+
// Set multiple fields
|
|
528
|
+
await redis.hmset('user:123', {
|
|
529
|
+
name: 'John Doe',
|
|
530
|
+
email: 'john@example.com',
|
|
531
|
+
age: '30'
|
|
532
|
+
});
|
|
533
|
+
|
|
534
|
+
// Get field
|
|
535
|
+
const name = await redis.hget('user:123', 'name');
|
|
536
|
+
|
|
537
|
+
// Get all fields
|
|
538
|
+
const user = await redis.hgetall('user:123');
|
|
539
|
+
|
|
540
|
+
// Increment field
|
|
541
|
+
await redis.hincrby('user:123', 'login_count', 1);
|
|
542
|
+
|
|
543
|
+
// Check field exists
|
|
544
|
+
const exists = await redis.hexists('user:123', 'name');
|
|
545
|
+
|
|
546
|
+
// Delete field
|
|
547
|
+
await redis.hdel('user:123', 'age');
|
|
548
|
+
|
|
549
|
+
// Get all keys
|
|
550
|
+
const keys = await redis.hkeys('user:123');
|
|
551
|
+
|
|
552
|
+
// Get all values
|
|
553
|
+
const values = await redis.hvals('user:123');
|
|
554
|
+
```
|
|
555
|
+
|
|
556
|
+
**Use cases:**
|
|
557
|
+
- User profiles
|
|
558
|
+
- Object storage
|
|
559
|
+
- Counters per entity
|
|
560
|
+
|
|
561
|
+
### Sorted Sets
|
|
562
|
+
|
|
563
|
+
**Ordered collection with scores:**
|
|
564
|
+
```javascript
|
|
565
|
+
// Add to sorted set
|
|
566
|
+
await redis.zadd('leaderboard', 100, 'user:123');
|
|
567
|
+
await redis.zadd('leaderboard', 200, 'user:456');
|
|
568
|
+
await redis.zadd('leaderboard', 150, 'user:789');
|
|
569
|
+
|
|
570
|
+
// Get rank (0-based)
|
|
571
|
+
const rank = await redis.zrank('leaderboard', 'user:123');
|
|
572
|
+
|
|
573
|
+
// Get score
|
|
574
|
+
const score = await redis.zscore('leaderboard', 'user:123');
|
|
575
|
+
|
|
576
|
+
// Increment score
|
|
577
|
+
await redis.zincrby('leaderboard', 10, 'user:123');
|
|
578
|
+
|
|
579
|
+
// Get range by rank
|
|
580
|
+
const top10 = await redis.zrange('leaderboard', 0, 9, 'WITHSCORES');
|
|
581
|
+
|
|
582
|
+
// Get range by score
|
|
583
|
+
const highScorers = await redis.zrangebyscore('leaderboard', 150, 200);
|
|
584
|
+
|
|
585
|
+
// Reverse range (highest first)
|
|
586
|
+
const top10Desc = await redis.zrevrange('leaderboard', 0, 9, 'WITHSCORES');
|
|
587
|
+
|
|
588
|
+
// Remove by rank
|
|
589
|
+
await redis.zremrangebyrank('leaderboard', 0, 0); // Remove lowest
|
|
590
|
+
|
|
591
|
+
// Remove by score
|
|
592
|
+
await redis.zremrangebyscore('leaderboard', 0, 50); // Remove scores 0-50
|
|
593
|
+
|
|
594
|
+
// Count in range
|
|
595
|
+
const count = await redis.zcount('leaderboard', 100, 200);
|
|
596
|
+
|
|
597
|
+
// Sorted set size
|
|
598
|
+
const size = await redis.zcard('leaderboard');
|
|
599
|
+
```
|
|
600
|
+
|
|
601
|
+
**Use cases:**
|
|
602
|
+
- Leaderboards
|
|
603
|
+
- Priority queues
|
|
604
|
+
- Time-series data (score = timestamp)
|
|
605
|
+
|
|
606
|
+
---
|
|
607
|
+
|
|
608
|
+
## Pub/Sub Patterns
|
|
609
|
+
|
|
610
|
+
### Publish/Subscribe
|
|
611
|
+
|
|
612
|
+
**Pattern**: Broadcast messages to multiple subscribers
|
|
613
|
+
|
|
614
|
+
```javascript
|
|
615
|
+
// Subscriber 1
|
|
616
|
+
const subscriber1 = redis.duplicate();
|
|
617
|
+
await subscriber1.subscribe('notifications');
|
|
618
|
+
subscriber1.on('message', (channel, message) => {
|
|
619
|
+
console.log(`Subscriber 1 received: ${message}`);
|
|
620
|
+
});
|
|
621
|
+
|
|
622
|
+
// Subscriber 2
|
|
623
|
+
const subscriber2 = redis.duplicate();
|
|
624
|
+
await subscriber2.subscribe('notifications');
|
|
625
|
+
subscriber2.on('message', (channel, message) => {
|
|
626
|
+
console.log(`Subscriber 2 received: ${message}`);
|
|
627
|
+
});
|
|
628
|
+
|
|
629
|
+
// Publisher
|
|
630
|
+
await redis.publish('notifications', 'New message!');
|
|
631
|
+
// Both subscribers receive the message
|
|
632
|
+
```
|
|
633
|
+
|
|
634
|
+
**Pattern matching:**
|
|
635
|
+
```javascript
|
|
636
|
+
// Subscribe to pattern
|
|
637
|
+
await subscriber.psubscribe('user:*:notifications');
|
|
638
|
+
|
|
639
|
+
// Publish to specific channels
|
|
640
|
+
await redis.publish('user:123:notifications', 'Message for user 123');
|
|
641
|
+
await redis.publish('user:456:notifications', 'Message for user 456');
|
|
642
|
+
// Subscriber receives both
|
|
643
|
+
```
|
|
644
|
+
|
|
645
|
+
### Use Cases
|
|
646
|
+
|
|
647
|
+
**Real-time notifications:**
|
|
648
|
+
```javascript
|
|
649
|
+
// Publish notification
|
|
650
|
+
await redis.publish('user:123:notifications', JSON.stringify({
|
|
651
|
+
type: 'new_message',
|
|
652
|
+
from: 'user:456',
|
|
653
|
+
message: 'Hello!'
|
|
654
|
+
}));
|
|
655
|
+
|
|
656
|
+
// Subscribe to notifications
|
|
657
|
+
await subscriber.subscribe('user:123:notifications');
|
|
658
|
+
subscriber.on('message', (channel, message) => {
|
|
659
|
+
const notification = JSON.parse(message);
|
|
660
|
+
// Display notification to user
|
|
661
|
+
});
|
|
662
|
+
```
|
|
663
|
+
|
|
664
|
+
**Cache invalidation:**
|
|
665
|
+
```javascript
|
|
666
|
+
// Publish cache invalidation event
|
|
667
|
+
await redis.publish('cache:invalidate', JSON.stringify({
|
|
668
|
+
keys: ['user:123', 'user:456']
|
|
669
|
+
}));
|
|
670
|
+
|
|
671
|
+
// All application servers subscribe and invalidate local cache
|
|
672
|
+
await subscriber.subscribe('cache:invalidate');
|
|
673
|
+
subscriber.on('message', (channel, message) => {
|
|
674
|
+
const { keys } = JSON.parse(message);
|
|
675
|
+
keys.forEach(key => localCache.delete(key));
|
|
676
|
+
});
|
|
677
|
+
```
|
|
678
|
+
|
|
679
|
+
**Event broadcasting:**
|
|
680
|
+
```javascript
|
|
681
|
+
// Publish event
|
|
682
|
+
await redis.publish('events:order', JSON.stringify({
|
|
683
|
+
type: 'order_created',
|
|
684
|
+
order_id: 'order123',
|
|
685
|
+
user_id: 'user456'
|
|
686
|
+
}));
|
|
687
|
+
|
|
688
|
+
// Multiple services subscribe
|
|
689
|
+
// Service 1: Send email
|
|
690
|
+
// Service 2: Update inventory
|
|
691
|
+
// Service 3: Log analytics
|
|
692
|
+
```
|
|
693
|
+
|
|
694
|
+
---
|
|
695
|
+
|
|
696
|
+
## Persistence Options
|
|
697
|
+
|
|
698
|
+
### Redis Persistence
|
|
699
|
+
|
|
700
|
+
**RDB (Redis Database Backup):**
|
|
701
|
+
- Point-in-time snapshots
|
|
702
|
+
- Compact binary format
|
|
703
|
+
- Fast restarts
|
|
704
|
+
- Data loss possible (between snapshots)
|
|
705
|
+
|
|
706
|
+
```conf
|
|
707
|
+
# redis.conf
|
|
708
|
+
save 900 1 # Save after 900 seconds if 1 key changed
|
|
709
|
+
save 300 10 # Save after 300 seconds if 10 keys changed
|
|
710
|
+
save 60 10000 # Save after 60 seconds if 10000 keys changed
|
|
711
|
+
```
|
|
712
|
+
|
|
713
|
+
**AOF (Append-Only File):**
|
|
714
|
+
- Log every write operation
|
|
715
|
+
- Better durability
|
|
716
|
+
- Larger file size
|
|
717
|
+
- Slower restarts
|
|
718
|
+
|
|
719
|
+
```conf
|
|
720
|
+
# redis.conf
|
|
721
|
+
appendonly yes
|
|
722
|
+
appendfsync everysec # Sync every second (default)
|
|
723
|
+
# appendfsync always # Sync every write (slowest, most durable)
|
|
724
|
+
# appendfsync no # Let OS decide (fastest, least durable)
|
|
725
|
+
```
|
|
726
|
+
|
|
727
|
+
**Hybrid (RDB + AOF):**
|
|
728
|
+
```conf
|
|
729
|
+
# Use both for best durability and performance
|
|
730
|
+
save 900 1
|
|
731
|
+
appendonly yes
|
|
732
|
+
appendfsync everysec
|
|
733
|
+
```
|
|
734
|
+
|
|
735
|
+
### DynamoDB Persistence
|
|
736
|
+
|
|
737
|
+
**Automatic persistence:**
|
|
738
|
+
- All data automatically persisted
|
|
739
|
+
- Point-in-time recovery (PITR)
|
|
740
|
+
- On-demand backups
|
|
741
|
+
- Continuous backups (35 days)
|
|
742
|
+
|
|
743
|
+
---
|
|
744
|
+
|
|
745
|
+
## DynamoDB Patterns
|
|
746
|
+
|
|
747
|
+
### Primary Key Design
|
|
748
|
+
|
|
749
|
+
**Simple primary key (partition key only):**
|
|
750
|
+
```javascript
|
|
751
|
+
// Table: Users
|
|
752
|
+
// Partition key: user_id
|
|
753
|
+
|
|
754
|
+
await dynamodb.putItem({
|
|
755
|
+
TableName: 'Users',
|
|
756
|
+
Item: {
|
|
757
|
+
user_id: { S: 'user123' },
|
|
758
|
+
name: { S: 'John Doe' },
|
|
759
|
+
email: { S: 'john@example.com' }
|
|
760
|
+
}
|
|
761
|
+
});
|
|
762
|
+
|
|
763
|
+
// Query by partition key
|
|
764
|
+
await dynamodb.getItem({
|
|
765
|
+
TableName: 'Users',
|
|
766
|
+
Key: { user_id: { S: 'user123' } }
|
|
767
|
+
});
|
|
768
|
+
```
|
|
769
|
+
|
|
770
|
+
**Composite primary key (partition key + sort key):**
|
|
771
|
+
```javascript
|
|
772
|
+
// Table: Orders
|
|
773
|
+
// Partition key: user_id
|
|
774
|
+
// Sort key: order_date
|
|
775
|
+
|
|
776
|
+
await dynamodb.putItem({
|
|
777
|
+
TableName: 'Orders',
|
|
778
|
+
Item: {
|
|
779
|
+
user_id: { S: 'user123' },
|
|
780
|
+
order_date: { S: '2024-01-15' },
|
|
781
|
+
order_id: { S: 'order456' },
|
|
782
|
+
total: { N: '99.99' }
|
|
783
|
+
}
|
|
784
|
+
});
|
|
785
|
+
|
|
786
|
+
// Query all orders for user
|
|
787
|
+
await dynamodb.query({
|
|
788
|
+
TableName: 'Orders',
|
|
789
|
+
KeyConditionExpression: 'user_id = :userId',
|
|
790
|
+
ExpressionAttributeValues: {
|
|
791
|
+
':userId': { S: 'user123' }
|
|
792
|
+
}
|
|
793
|
+
});
|
|
794
|
+
|
|
795
|
+
// Query orders in date range
|
|
796
|
+
await dynamodb.query({
|
|
797
|
+
TableName: 'Orders',
|
|
798
|
+
KeyConditionExpression: 'user_id = :userId AND order_date BETWEEN :start AND :end',
|
|
799
|
+
ExpressionAttributeValues: {
|
|
800
|
+
':userId': { S: 'user123' },
|
|
801
|
+
':start': { S: '2024-01-01' },
|
|
802
|
+
':end': { S: '2024-01-31' }
|
|
803
|
+
}
|
|
804
|
+
});
|
|
805
|
+
```
|
|
806
|
+
|
|
807
|
+
### Secondary Indexes
|
|
808
|
+
|
|
809
|
+
**Global Secondary Index (GSI):**
|
|
810
|
+
```javascript
|
|
811
|
+
// Create GSI on email
|
|
812
|
+
await dynamodb.createTable({
|
|
813
|
+
TableName: 'Users',
|
|
814
|
+
KeySchema: [
|
|
815
|
+
{ AttributeName: 'user_id', KeyType: 'HASH' }
|
|
816
|
+
],
|
|
817
|
+
GlobalSecondaryIndexes: [
|
|
818
|
+
{
|
|
819
|
+
IndexName: 'EmailIndex',
|
|
820
|
+
KeySchema: [
|
|
821
|
+
{ AttributeName: 'email', KeyType: 'HASH' }
|
|
822
|
+
],
|
|
823
|
+
Projection: { ProjectionType: 'ALL' }
|
|
824
|
+
}
|
|
825
|
+
]
|
|
826
|
+
});
|
|
827
|
+
|
|
828
|
+
// Query by email
|
|
829
|
+
await dynamodb.query({
|
|
830
|
+
TableName: 'Users',
|
|
831
|
+
IndexName: 'EmailIndex',
|
|
832
|
+
KeyConditionExpression: 'email = :email',
|
|
833
|
+
ExpressionAttributeValues: {
|
|
834
|
+
':email': { S: 'john@example.com' }
|
|
835
|
+
}
|
|
836
|
+
});
|
|
837
|
+
```
|
|
838
|
+
|
|
839
|
+
**Local Secondary Index (LSI):**
|
|
840
|
+
```javascript
|
|
841
|
+
// Create LSI on status (same partition key as table)
|
|
842
|
+
await dynamodb.createTable({
|
|
843
|
+
TableName: 'Orders',
|
|
844
|
+
KeySchema: [
|
|
845
|
+
{ AttributeName: 'user_id', KeyType: 'HASH' },
|
|
846
|
+
{ AttributeName: 'order_date', KeyType: 'RANGE' }
|
|
847
|
+
],
|
|
848
|
+
LocalSecondaryIndexes: [
|
|
849
|
+
{
|
|
850
|
+
IndexName: 'StatusIndex',
|
|
851
|
+
KeySchema: [
|
|
852
|
+
{ AttributeName: 'user_id', KeyType: 'HASH' },
|
|
853
|
+
{ AttributeName: 'status', KeyType: 'RANGE' }
|
|
854
|
+
],
|
|
855
|
+
Projection: { ProjectionType: 'ALL' }
|
|
856
|
+
}
|
|
857
|
+
]
|
|
858
|
+
});
|
|
859
|
+
|
|
860
|
+
// Query orders by status
|
|
861
|
+
await dynamodb.query({
|
|
862
|
+
TableName: 'Orders',
|
|
863
|
+
IndexName: 'StatusIndex',
|
|
864
|
+
KeyConditionExpression: 'user_id = :userId AND status = :status',
|
|
865
|
+
ExpressionAttributeValues: {
|
|
866
|
+
':userId': { S: 'user123' },
|
|
867
|
+
':status': { S: 'shipped' }
|
|
868
|
+
}
|
|
869
|
+
});
|
|
870
|
+
```
|
|
871
|
+
|
|
872
|
+
### Conditional Writes
|
|
873
|
+
|
|
874
|
+
**Optimistic locking:**
|
|
875
|
+
```javascript
|
|
876
|
+
// Update only if version matches
|
|
877
|
+
await dynamodb.updateItem({
|
|
878
|
+
TableName: 'Users',
|
|
879
|
+
Key: { user_id: { S: 'user123' } },
|
|
880
|
+
UpdateExpression: 'SET #name = :name, #version = :newVersion',
|
|
881
|
+
ConditionExpression: '#version = :currentVersion',
|
|
882
|
+
ExpressionAttributeNames: {
|
|
883
|
+
'#name': 'name',
|
|
884
|
+
'#version': 'version'
|
|
885
|
+
},
|
|
886
|
+
ExpressionAttributeValues: {
|
|
887
|
+
':name': { S: 'John Doe' },
|
|
888
|
+
':currentVersion': { N: '5' },
|
|
889
|
+
':newVersion': { N: '6' }
|
|
890
|
+
}
|
|
891
|
+
});
|
|
892
|
+
```
|
|
893
|
+
|
|
894
|
+
**Prevent overwrites:**
|
|
895
|
+
```javascript
|
|
896
|
+
// Create only if doesn't exist
|
|
897
|
+
await dynamodb.putItem({
|
|
898
|
+
TableName: 'Users',
|
|
899
|
+
Item: { user_id: { S: 'user123' }, name: { S: 'John Doe' } },
|
|
900
|
+
ConditionExpression: 'attribute_not_exists(user_id)'
|
|
901
|
+
});
|
|
902
|
+
```
|
|
903
|
+
|
|
904
|
+
---
|
|
905
|
+
|
|
906
|
+
## Best Practices
|
|
907
|
+
|
|
908
|
+
### DO
|
|
909
|
+
|
|
910
|
+
✅ **Use descriptive key names** with namespaces
|
|
911
|
+
✅ **Set appropriate TTLs** for cached data
|
|
912
|
+
✅ **Use atomic operations** for counters and flags
|
|
913
|
+
✅ **Implement connection pooling** for better performance
|
|
914
|
+
✅ **Monitor memory usage** (Redis is in-memory)
|
|
915
|
+
✅ **Use appropriate data structures** (lists, sets, hashes, sorted sets)
|
|
916
|
+
✅ **Enable persistence** for critical data (Redis RDB/AOF)
|
|
917
|
+
✅ **Use pub/sub** for real-time messaging
|
|
918
|
+
✅ **Implement retry logic** for transient failures
|
|
919
|
+
✅ **Use pipelining** for batch operations
|
|
920
|
+
|
|
921
|
+
### DON'T
|
|
922
|
+
|
|
923
|
+
❌ **Don't store large values** (> 1MB) - use object storage instead
|
|
924
|
+
❌ **Don't use key-value stores for complex queries** - use document/relational DB
|
|
925
|
+
❌ **Don't skip TTL** - memory will fill up
|
|
926
|
+
❌ **Don't use blocking operations** in production (BLPOP with long timeout)
|
|
927
|
+
❌ **Don't ignore eviction policies** - configure LRU/LFU appropriately
|
|
928
|
+
❌ **Don't use KEYS command** in production - use SCAN instead
|
|
929
|
+
❌ **Don't forget to handle cache misses** gracefully
|
|
930
|
+
❌ **Don't store sensitive data unencrypted**
|
|
931
|
+
❌ **Don't skip monitoring** - track hit rates, memory, latency
|
|
932
|
+
❌ **Don't use Redis as primary database** without persistence
|
|
933
|
+
|
|
934
|
+
---
|
|
935
|
+
|
|
936
|
+
## Summary
|
|
937
|
+
|
|
938
|
+
**Key-value stores are ideal for:**
|
|
939
|
+
- Simple lookups by key
|
|
940
|
+
- Caching frequently accessed data
|
|
941
|
+
- Session storage
|
|
942
|
+
- Real-time counters and metrics
|
|
943
|
+
- Message queues and pub/sub
|
|
944
|
+
|
|
945
|
+
**Redis data structures:**
|
|
946
|
+
- **Strings**: Simple key-value
|
|
947
|
+
- **Lists**: Ordered collections, queues
|
|
948
|
+
- **Sets**: Unique collections, tags
|
|
949
|
+
- **Hashes**: Object storage
|
|
950
|
+
- **Sorted Sets**: Leaderboards, priority queues
|
|
951
|
+
|
|
952
|
+
**Caching strategies:**
|
|
953
|
+
- **Cache-aside**: Lazy loading
|
|
954
|
+
- **Write-through**: Always up-to-date
|
|
955
|
+
- **Write-behind**: Fast writes, async persistence
|
|
956
|
+
|
|
957
|
+
**Performance tips:**
|
|
958
|
+
- Use appropriate data structures
|
|
959
|
+
- Set TTLs to prevent memory bloat
|
|
960
|
+
- Use pipelining for batch operations
|
|
961
|
+
- Monitor hit rates and memory usage
|
|
962
|
+
- Enable persistence for critical data
|
|
963
|
+
|