@mytechtoday/augment-extensions 0.2.0 → 0.5.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/design/color/themes/catppuccin-latte/README.md +23 -0
- package/augment-extensions/domain-rules/design/color/themes/catppuccin-latte/module.json +26 -0
- package/augment-extensions/domain-rules/design/color/themes/catppuccin-mocha/README.md +23 -0
- package/augment-extensions/domain-rules/design/color/themes/catppuccin-mocha/module.json +26 -0
- package/augment-extensions/domain-rules/design/color/themes/dracula/README.md +23 -0
- package/augment-extensions/domain-rules/design/color/themes/dracula/module.json +26 -0
- package/augment-extensions/domain-rules/design/color/themes/gruvbox-dark/README.md +23 -0
- package/augment-extensions/domain-rules/design/color/themes/gruvbox-dark/module.json +26 -0
- package/augment-extensions/domain-rules/design/color/themes/gruvbox-light/README.md +23 -0
- package/augment-extensions/domain-rules/design/color/themes/gruvbox-light/module.json +26 -0
- package/augment-extensions/domain-rules/design/color/themes/high-contrast/README.md +27 -0
- package/augment-extensions/domain-rules/design/color/themes/high-contrast/module.json +26 -0
- package/augment-extensions/domain-rules/design/color/themes/monokai/README.md +23 -0
- package/augment-extensions/domain-rules/design/color/themes/monokai/module.json +26 -0
- package/augment-extensions/domain-rules/design/color/themes/nord/README.md +23 -0
- package/augment-extensions/domain-rules/design/color/themes/nord/module.json +26 -0
- package/augment-extensions/domain-rules/design/color/themes/one-dark/README.md +23 -0
- package/augment-extensions/domain-rules/design/color/themes/one-dark/module.json +26 -0
- package/augment-extensions/domain-rules/design/color/themes/one-light/README.md +23 -0
- package/augment-extensions/domain-rules/design/color/themes/one-light/module.json +26 -0
- package/augment-extensions/domain-rules/design/color/themes/solarized-dark/README.md +23 -0
- package/augment-extensions/domain-rules/design/color/themes/solarized-dark/module.json +26 -0
- package/augment-extensions/domain-rules/design/color/themes/solarized-light/README.md +23 -0
- package/augment-extensions/domain-rules/design/color/themes/solarized-light/module.json +26 -0
- package/augment-extensions/domain-rules/design/color/themes/tokyo-night/README.md +23 -0
- package/augment-extensions/domain-rules/design/color/themes/tokyo-night/module.json +26 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/README.md +136 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/SCHEMA-VALIDATION-REPORT.md +216 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/examples/brand-kit-example.yaml +292 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/examples/campaign-brief-example.yaml +389 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/examples/content-calendar-example.yaml +643 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/examples/email-newsletter-example.md +376 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/examples/landing-page-example.md +934 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/examples/ppc-ad-copy-example.md +301 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/examples/seo-blog-post-example.md +347 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/examples/social-media-campaign-example.md +606 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/module.json +50 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/rules/affiliate-influencer-marketing.md +593 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/rules/asset-management.md +418 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/rules/brand-consistency.md +210 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/rules/content-marketing.md +337 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/rules/conversion-optimization.md +455 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/rules/direct-sales.md +499 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/rules/email-marketing.md +439 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/rules/legal-compliance.md +227 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/rules/ppc-advertising.md +569 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/rules/seo-optimization.md +470 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/rules/social-media-marketing.md +414 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/rules/universal-marketing.md +177 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/schemas/asset-inventory.schema.json +247 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/schemas/brand-kit.schema.json +326 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/schemas/campaign-brief.schema.json +342 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/schemas/color-palette.schema.json +223 -0
- package/augment-extensions/domain-rules/marketing-standards/seo-sales-marketing/schemas/content-template.schema.json +383 -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/workflows/beads/module.json +4 -3
- package/augment-extensions/workflows/beads-integration/IMPLEMENTATION-STATUS.md +145 -0
- package/augment-extensions/workflows/beads-integration/README.md +143 -0
- package/augment-extensions/workflows/beads-integration/config/defaults.json +32 -0
- package/augment-extensions/workflows/beads-integration/config/schema.json +140 -0
- package/augment-extensions/workflows/beads-integration/examples/basic-task-generation.md +293 -0
- package/augment-extensions/workflows/beads-integration/module.json +75 -0
- package/augment-extensions/workflows/beads-integration/rules/core-rules.md +219 -0
- package/augment-extensions/workflows/beads-integration/rules/effectiveness-standards.md +256 -0
- package/augment-extensions/workflows/beads-integration/rules/task-generation.md +607 -0
- 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/writing-standards/screenplay/README.md +300 -0
- package/augment-extensions/writing-standards/screenplay/_templates/README.md +121 -0
- package/augment-extensions/writing-standards/screenplay/_templates/genre-template.md +153 -0
- package/augment-extensions/writing-standards/screenplay/_templates/style-template.md +243 -0
- package/augment-extensions/writing-standards/screenplay/_templates/theme-template.md +213 -0
- package/augment-extensions/writing-standards/screenplay/examples/aaa-hollywood-scene.fountain +164 -0
- package/augment-extensions/writing-standards/screenplay/examples/beat-sheet-example.yaml +95 -0
- package/augment-extensions/writing-standards/screenplay/examples/character-profile-example.yaml +116 -0
- package/augment-extensions/writing-standards/screenplay/examples/commercial-30sec.fountain +151 -0
- package/augment-extensions/writing-standards/screenplay/examples/independent-monologue.fountain +67 -0
- package/augment-extensions/writing-standards/screenplay/examples/news-segment.fountain +142 -0
- package/augment-extensions/writing-standards/screenplay/examples/plot-outline-example.yaml +184 -0
- package/augment-extensions/writing-standards/screenplay/examples/tv-episode-teaser.fountain +204 -0
- package/augment-extensions/writing-standards/screenplay/genres/README.md +181 -0
- package/augment-extensions/writing-standards/screenplay/genres/examples/.gitkeep +2 -0
- package/augment-extensions/writing-standards/screenplay/genres/module.json +70 -0
- package/augment-extensions/writing-standards/screenplay/genres/rules/.gitkeep +2 -0
- package/augment-extensions/writing-standards/screenplay/genres/rules/action.md +399 -0
- package/augment-extensions/writing-standards/screenplay/genres/rules/adventure.md +407 -0
- package/augment-extensions/writing-standards/screenplay/genres/rules/animation.md +293 -0
- package/augment-extensions/writing-standards/screenplay/genres/rules/biographical.md +293 -0
- package/augment-extensions/writing-standards/screenplay/genres/rules/comedy.md +401 -0
- package/augment-extensions/writing-standards/screenplay/genres/rules/documentary.md +293 -0
- package/augment-extensions/writing-standards/screenplay/genres/rules/drama.md +409 -0
- package/augment-extensions/writing-standards/screenplay/genres/rules/fantasy.md +293 -0
- package/augment-extensions/writing-standards/screenplay/genres/rules/historical.md +293 -0
- package/augment-extensions/writing-standards/screenplay/genres/rules/horror.md +268 -0
- package/augment-extensions/writing-standards/screenplay/genres/rules/musical.md +294 -0
- package/augment-extensions/writing-standards/screenplay/genres/rules/mystery.md +293 -0
- package/augment-extensions/writing-standards/screenplay/genres/rules/noir.md +294 -0
- package/augment-extensions/writing-standards/screenplay/genres/rules/romance.md +293 -0
- package/augment-extensions/writing-standards/screenplay/genres/rules/sci-fi.md +289 -0
- package/augment-extensions/writing-standards/screenplay/genres/rules/superhero.md +293 -0
- package/augment-extensions/writing-standards/screenplay/genres/rules/thriller.md +294 -0
- package/augment-extensions/writing-standards/screenplay/genres/rules/western.md +293 -0
- package/augment-extensions/writing-standards/screenplay/module.json +124 -0
- package/augment-extensions/writing-standards/screenplay/rules/aaa-hollywood-films.md +339 -0
- package/augment-extensions/writing-standards/screenplay/rules/ai-integration-testing.md +329 -0
- package/augment-extensions/writing-standards/screenplay/rules/character-development.md +169 -0
- package/augment-extensions/writing-standards/screenplay/rules/commercials.md +437 -0
- package/augment-extensions/writing-standards/screenplay/rules/dialogue-writing.md +263 -0
- package/augment-extensions/writing-standards/screenplay/rules/diversity-inclusion.md +261 -0
- package/augment-extensions/writing-standards/screenplay/rules/examples-guide.md +315 -0
- package/augment-extensions/writing-standards/screenplay/rules/formatting-validation.md +413 -0
- package/augment-extensions/writing-standards/screenplay/rules/fountain-format.md +372 -0
- package/augment-extensions/writing-standards/screenplay/rules/independent-films.md +374 -0
- package/augment-extensions/writing-standards/screenplay/rules/live-tv-productions.md +443 -0
- package/augment-extensions/writing-standards/screenplay/rules/narrative-structures.md +207 -0
- package/augment-extensions/writing-standards/screenplay/rules/news-broadcasts.md +444 -0
- package/augment-extensions/writing-standards/screenplay/rules/pacing-timing.md +331 -0
- package/augment-extensions/writing-standards/screenplay/rules/quality-review-checklist.md +334 -0
- package/augment-extensions/writing-standards/screenplay/rules/quick-reference.md +299 -0
- package/augment-extensions/writing-standards/screenplay/rules/screen-continuity.md +263 -0
- package/augment-extensions/writing-standards/screenplay/rules/streaming-content.md +412 -0
- package/augment-extensions/writing-standards/screenplay/rules/trope-management.md +370 -0
- package/augment-extensions/writing-standards/screenplay/rules/tv-series.md +374 -0
- package/augment-extensions/writing-standards/screenplay/rules/universal-formatting.md +339 -0
- package/augment-extensions/writing-standards/screenplay/rules/vscode-integration.md +277 -0
- package/augment-extensions/writing-standards/screenplay/rules/web-content.md +393 -0
- package/augment-extensions/writing-standards/screenplay/schemas/beat-sheet.json +332 -0
- package/augment-extensions/writing-standards/screenplay/schemas/character-profile.json +247 -0
- package/augment-extensions/writing-standards/screenplay/schemas/feature-selection.json +200 -0
- package/augment-extensions/writing-standards/screenplay/schemas/plot-outline.json +233 -0
- package/augment-extensions/writing-standards/screenplay/schemas/screenplay-config.json +245 -0
- package/augment-extensions/writing-standards/screenplay/schemas/trope-inventory.json +221 -0
- package/augment-extensions/writing-standards/screenplay/styles/README.md +159 -0
- package/augment-extensions/writing-standards/screenplay/styles/examples/.gitkeep +2 -0
- package/augment-extensions/writing-standards/screenplay/styles/examples/style-applications.md +1449 -0
- package/augment-extensions/writing-standards/screenplay/styles/module.json +64 -0
- package/augment-extensions/writing-standards/screenplay/styles/rules/.gitkeep +2 -0
- package/augment-extensions/writing-standards/screenplay/styles/rules/dialogue-centric.md +520 -0
- package/augment-extensions/writing-standards/screenplay/styles/rules/ensemble.md +499 -0
- package/augment-extensions/writing-standards/screenplay/styles/rules/epic.md +497 -0
- package/augment-extensions/writing-standards/screenplay/styles/rules/experimental.md +492 -0
- package/augment-extensions/writing-standards/screenplay/styles/rules/flashback.md +509 -0
- package/augment-extensions/writing-standards/screenplay/styles/rules/linear.md +490 -0
- package/augment-extensions/writing-standards/screenplay/styles/rules/minimalist.md +499 -0
- package/augment-extensions/writing-standards/screenplay/styles/rules/non-linear.md +501 -0
- package/augment-extensions/writing-standards/screenplay/styles/rules/poetic.md +499 -0
- package/augment-extensions/writing-standards/screenplay/styles/rules/realistic.md +498 -0
- package/augment-extensions/writing-standards/screenplay/styles/rules/satirical.md +499 -0
- package/augment-extensions/writing-standards/screenplay/styles/rules/surreal.md +508 -0
- package/augment-extensions/writing-standards/screenplay/styles/rules/voice-over.md +500 -0
- package/augment-extensions/writing-standards/screenplay/themes/README.md +158 -0
- package/augment-extensions/writing-standards/screenplay/themes/examples/.gitkeep +2 -0
- package/augment-extensions/writing-standards/screenplay/themes/examples/common-mistakes-and-fixes.md +643 -0
- package/augment-extensions/writing-standards/screenplay/themes/examples/complete-scene-example.md +311 -0
- package/augment-extensions/writing-standards/screenplay/themes/examples/individual-theme-examples.md +562 -0
- package/augment-extensions/writing-standards/screenplay/themes/examples/multi-theme-weaving.md +538 -0
- package/augment-extensions/writing-standards/screenplay/themes/examples/theme-application-guide.md +432 -0
- package/augment-extensions/writing-standards/screenplay/themes/examples/theme-integration-across-acts.md +637 -0
- package/augment-extensions/writing-standards/screenplay/themes/module.json +66 -0
- package/augment-extensions/writing-standards/screenplay/themes/rules/.gitkeep +2 -0
- package/augment-extensions/writing-standards/screenplay/themes/rules/ambition.md +458 -0
- package/augment-extensions/writing-standards/screenplay/themes/rules/betrayal.md +490 -0
- package/augment-extensions/writing-standards/screenplay/themes/rules/environment.md +458 -0
- package/augment-extensions/writing-standards/screenplay/themes/rules/fate.md +459 -0
- package/augment-extensions/writing-standards/screenplay/themes/rules/friendship.md +491 -0
- package/augment-extensions/writing-standards/screenplay/themes/rules/growth.md +491 -0
- package/augment-extensions/writing-standards/screenplay/themes/rules/identity.md +490 -0
- package/augment-extensions/writing-standards/screenplay/themes/rules/isolation.md +464 -0
- package/augment-extensions/writing-standards/screenplay/themes/rules/justice.md +461 -0
- package/augment-extensions/writing-standards/screenplay/themes/rules/love.md +489 -0
- package/augment-extensions/writing-standards/screenplay/themes/rules/power.md +494 -0
- package/augment-extensions/writing-standards/screenplay/themes/rules/redemption.md +483 -0
- package/augment-extensions/writing-standards/screenplay/themes/rules/revenge.md +489 -0
- package/augment-extensions/writing-standards/screenplay/themes/rules/survival.md +496 -0
- package/augment-extensions/writing-standards/screenplay/themes/rules/technology.md +463 -0
- package/cli/MODULES.md +302 -0
- package/cli/dist/cli.js +168 -10
- 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 +19 -0
- package/cli/dist/commands/show.d.ts.map +1 -1
- package/cli/dist/commands/show.js +478 -63
- 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/types/gui.d.ts +62 -0
- package/cli/dist/types/gui.d.ts.map +1 -0
- package/cli/dist/types/gui.js +30 -0
- package/cli/dist/types/gui.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/gui-helpers.d.ts +23 -0
- package/cli/dist/utils/gui-helpers.d.ts.map +1 -0
- package/cli/dist/utils/gui-helpers.js +159 -0
- package/cli/dist/utils/gui-helpers.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 +232 -0
- package/cli/dist/utils/module-system.d.ts.map +1 -0
- package/cli/dist/utils/module-system.js +900 -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 +559 -105
- package/package.json +17 -6
|
@@ -0,0 +1,793 @@
|
|
|
1
|
+
# Flat Database Example: Configuration Management System
|
|
2
|
+
|
|
3
|
+
## Overview
|
|
4
|
+
|
|
5
|
+
This example demonstrates a complete configuration management system using JSON files with:
|
|
6
|
+
- **Schema validation** with JSON Schema
|
|
7
|
+
- **Atomic writes** to prevent corruption
|
|
8
|
+
- **File locking** for concurrent access
|
|
9
|
+
- **Backup/restore** functionality
|
|
10
|
+
- **Migration to SQLite** when needed
|
|
11
|
+
- **Sample code** in both Python and JavaScript
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Use Case
|
|
16
|
+
|
|
17
|
+
**Application Configuration Manager:**
|
|
18
|
+
- Store application settings in JSON files
|
|
19
|
+
- Support multiple environments (dev, staging, production)
|
|
20
|
+
- Validate configuration against schema
|
|
21
|
+
- Provide safe concurrent access
|
|
22
|
+
- Backup before changes
|
|
23
|
+
- Migrate to SQLite when configuration grows
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Directory Structure
|
|
28
|
+
|
|
29
|
+
```
|
|
30
|
+
config-manager/
|
|
31
|
+
├── config/
|
|
32
|
+
│ ├── dev.json # Development config
|
|
33
|
+
│ ├── staging.json # Staging config
|
|
34
|
+
│ ├── production.json # Production config
|
|
35
|
+
│ └── schema.json # JSON Schema
|
|
36
|
+
├── backups/ # Configuration backups
|
|
37
|
+
├── config_manager.py # Python implementation
|
|
38
|
+
├── config_manager.js # JavaScript implementation
|
|
39
|
+
└── migrate_to_sqlite.py # Migration script
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## JSON Schema Definition
|
|
45
|
+
|
|
46
|
+
**File: `config/schema.json`**
|
|
47
|
+
|
|
48
|
+
```json
|
|
49
|
+
{
|
|
50
|
+
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
51
|
+
"title": "Application Configuration",
|
|
52
|
+
"type": "object",
|
|
53
|
+
"properties": {
|
|
54
|
+
"environment": {
|
|
55
|
+
"type": "string",
|
|
56
|
+
"enum": ["development", "staging", "production"]
|
|
57
|
+
},
|
|
58
|
+
"database": {
|
|
59
|
+
"type": "object",
|
|
60
|
+
"properties": {
|
|
61
|
+
"host": { "type": "string" },
|
|
62
|
+
"port": { "type": "integer", "minimum": 1, "maximum": 65535 },
|
|
63
|
+
"name": { "type": "string" },
|
|
64
|
+
"username": { "type": "string" },
|
|
65
|
+
"password": { "type": "string" },
|
|
66
|
+
"pool_size": { "type": "integer", "minimum": 1, "default": 10 }
|
|
67
|
+
},
|
|
68
|
+
"required": ["host", "port", "name", "username", "password"]
|
|
69
|
+
},
|
|
70
|
+
"cache": {
|
|
71
|
+
"type": "object",
|
|
72
|
+
"properties": {
|
|
73
|
+
"enabled": { "type": "boolean", "default": true },
|
|
74
|
+
"ttl": { "type": "integer", "minimum": 0, "default": 3600 },
|
|
75
|
+
"max_size": { "type": "integer", "minimum": 0, "default": 1000 }
|
|
76
|
+
}
|
|
77
|
+
},
|
|
78
|
+
"features": {
|
|
79
|
+
"type": "object",
|
|
80
|
+
"additionalProperties": { "type": "boolean" }
|
|
81
|
+
},
|
|
82
|
+
"logging": {
|
|
83
|
+
"type": "object",
|
|
84
|
+
"properties": {
|
|
85
|
+
"level": {
|
|
86
|
+
"type": "string",
|
|
87
|
+
"enum": ["DEBUG", "INFO", "WARNING", "ERROR", "CRITICAL"]
|
|
88
|
+
},
|
|
89
|
+
"format": { "type": "string" },
|
|
90
|
+
"output": {
|
|
91
|
+
"type": "string",
|
|
92
|
+
"enum": ["console", "file", "both"]
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
"required": ["level"]
|
|
96
|
+
}
|
|
97
|
+
},
|
|
98
|
+
"required": ["environment", "database", "logging"]
|
|
99
|
+
}
|
|
100
|
+
```
|
|
101
|
+
|
|
102
|
+
---
|
|
103
|
+
|
|
104
|
+
## Sample Configuration
|
|
105
|
+
|
|
106
|
+
**File: `config/dev.json`**
|
|
107
|
+
|
|
108
|
+
```json
|
|
109
|
+
{
|
|
110
|
+
"environment": "development",
|
|
111
|
+
"database": {
|
|
112
|
+
"host": "localhost",
|
|
113
|
+
"port": 5432,
|
|
114
|
+
"name": "myapp_dev",
|
|
115
|
+
"username": "dev_user",
|
|
116
|
+
"password": "dev_password",
|
|
117
|
+
"pool_size": 5
|
|
118
|
+
},
|
|
119
|
+
"cache": {
|
|
120
|
+
"enabled": true,
|
|
121
|
+
"ttl": 300,
|
|
122
|
+
"max_size": 100
|
|
123
|
+
},
|
|
124
|
+
"features": {
|
|
125
|
+
"new_ui": true,
|
|
126
|
+
"beta_features": true,
|
|
127
|
+
"analytics": false
|
|
128
|
+
},
|
|
129
|
+
"logging": {
|
|
130
|
+
"level": "DEBUG",
|
|
131
|
+
"format": "%(asctime)s - %(name)s - %(levelname)s - %(message)s",
|
|
132
|
+
"output": "console"
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## Python Implementation
|
|
140
|
+
|
|
141
|
+
**File: `config_manager.py`**
|
|
142
|
+
|
|
143
|
+
```python
|
|
144
|
+
import json
|
|
145
|
+
import os
|
|
146
|
+
import fcntl
|
|
147
|
+
import tempfile
|
|
148
|
+
import shutil
|
|
149
|
+
from datetime import datetime
|
|
150
|
+
from pathlib import Path
|
|
151
|
+
import jsonschema
|
|
152
|
+
|
|
153
|
+
class ConfigManager:
|
|
154
|
+
"""Configuration manager with validation, locking, and backups."""
|
|
155
|
+
|
|
156
|
+
def __init__(self, config_dir='config', backup_dir='backups'):
|
|
157
|
+
self.config_dir = Path(config_dir)
|
|
158
|
+
self.backup_dir = Path(backup_dir)
|
|
159
|
+
self.backup_dir.mkdir(exist_ok=True)
|
|
160
|
+
|
|
161
|
+
# Load schema
|
|
162
|
+
schema_path = self.config_dir / 'schema.json'
|
|
163
|
+
with open(schema_path) as f:
|
|
164
|
+
self.schema = json.load(f)
|
|
165
|
+
|
|
166
|
+
def _validate(self, config):
|
|
167
|
+
"""Validate configuration against schema."""
|
|
168
|
+
jsonschema.validate(instance=config, schema=self.schema)
|
|
169
|
+
|
|
170
|
+
def _backup(self, filepath):
|
|
171
|
+
"""Create timestamped backup of configuration file."""
|
|
172
|
+
if not filepath.exists():
|
|
173
|
+
return None
|
|
174
|
+
|
|
175
|
+
timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
|
|
176
|
+
filename = filepath.name
|
|
177
|
+
backup_path = self.backup_dir / f"{filename}.backup_{timestamp}"
|
|
178
|
+
shutil.copy2(filepath, backup_path)
|
|
179
|
+
return backup_path
|
|
180
|
+
|
|
181
|
+
def _rotate_backups(self, filename, keep=5):
|
|
182
|
+
"""Keep only N most recent backups."""
|
|
183
|
+
pattern = f"{filename}.backup_*"
|
|
184
|
+
backups = sorted(self.backup_dir.glob(pattern), reverse=True)
|
|
185
|
+
|
|
186
|
+
# Delete old backups
|
|
187
|
+
for old_backup in backups[keep:]:
|
|
188
|
+
old_backup.unlink()
|
|
189
|
+
|
|
190
|
+
def read(self, environment):
|
|
191
|
+
"""Read configuration with shared lock."""
|
|
192
|
+
filepath = self.config_dir / f"{environment}.json"
|
|
193
|
+
|
|
194
|
+
with open(filepath, 'r') as f:
|
|
195
|
+
fcntl.flock(f.fileno(), fcntl.LOCK_SH) # Shared lock
|
|
196
|
+
try:
|
|
197
|
+
config = json.load(f)
|
|
198
|
+
self._validate(config)
|
|
199
|
+
return config
|
|
200
|
+
finally:
|
|
201
|
+
fcntl.flock(f.fileno(), fcntl.LOCK_UN) # Unlock
|
|
202
|
+
|
|
203
|
+
def write(self, environment, config):
|
|
204
|
+
"""Write configuration with validation, backup, and atomic write."""
|
|
205
|
+
filepath = self.config_dir / f"{environment}.json"
|
|
206
|
+
|
|
207
|
+
# Validate first
|
|
208
|
+
self._validate(config)
|
|
209
|
+
|
|
210
|
+
# Create backup
|
|
211
|
+
if filepath.exists():
|
|
212
|
+
backup_path = self._backup(filepath)
|
|
213
|
+
print(f"Created backup: {backup_path}")
|
|
214
|
+
self._rotate_backups(filepath.name)
|
|
215
|
+
|
|
216
|
+
# Atomic write with exclusive lock
|
|
217
|
+
with tempfile.NamedTemporaryFile(
|
|
218
|
+
mode='w',
|
|
219
|
+
dir=self.config_dir,
|
|
220
|
+
delete=False
|
|
221
|
+
) as tmp:
|
|
222
|
+
json.dump(config, tmp, indent=2)
|
|
223
|
+
tmp_path = tmp.name
|
|
224
|
+
|
|
225
|
+
# Atomic rename
|
|
226
|
+
os.replace(tmp_path, filepath)
|
|
227
|
+
print(f"Configuration written: {filepath}")
|
|
228
|
+
|
|
229
|
+
def update(self, environment, updates):
|
|
230
|
+
"""Update specific configuration values."""
|
|
231
|
+
config = self.read(environment)
|
|
232
|
+
|
|
233
|
+
# Deep merge updates
|
|
234
|
+
def deep_merge(base, updates):
|
|
235
|
+
for key, value in updates.items():
|
|
236
|
+
if isinstance(value, dict) and key in base:
|
|
237
|
+
deep_merge(base[key], value)
|
|
238
|
+
else:
|
|
239
|
+
base[key] = value
|
|
240
|
+
|
|
241
|
+
deep_merge(config, updates)
|
|
242
|
+
self.write(environment, config)
|
|
243
|
+
|
|
244
|
+
def restore(self, environment, backup_timestamp):
|
|
245
|
+
"""Restore configuration from backup."""
|
|
246
|
+
filename = f"{environment}.json"
|
|
247
|
+
backup_path = self.backup_dir / f"{filename}.backup_{backup_timestamp}"
|
|
248
|
+
|
|
249
|
+
if not backup_path.exists():
|
|
250
|
+
raise FileNotFoundError(f"Backup not found: {backup_path}")
|
|
251
|
+
|
|
252
|
+
# Read backup
|
|
253
|
+
with open(backup_path) as f:
|
|
254
|
+
config = json.load(f)
|
|
255
|
+
|
|
256
|
+
# Write as current config
|
|
257
|
+
self.write(environment, config)
|
|
258
|
+
print(f"Restored from backup: {backup_path}")
|
|
259
|
+
|
|
260
|
+
# Usage Example
|
|
261
|
+
if __name__ == '__main__':
|
|
262
|
+
manager = ConfigManager()
|
|
263
|
+
|
|
264
|
+
# Read configuration
|
|
265
|
+
config = manager.read('dev')
|
|
266
|
+
print(f"Database host: {config['database']['host']}")
|
|
267
|
+
|
|
268
|
+
# Update configuration
|
|
269
|
+
manager.update('dev', {
|
|
270
|
+
'cache': {'ttl': 600},
|
|
271
|
+
'features': {'new_feature': True}
|
|
272
|
+
})
|
|
273
|
+
|
|
274
|
+
# Restore from backup
|
|
275
|
+
# manager.restore('dev', '20240120_100000')
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
---
|
|
279
|
+
|
|
280
|
+
## JavaScript Implementation
|
|
281
|
+
|
|
282
|
+
**File: `config_manager.js`**
|
|
283
|
+
|
|
284
|
+
```javascript
|
|
285
|
+
const fs = require('fs').promises;
|
|
286
|
+
const fsSync = require('fs');
|
|
287
|
+
const path = require('path');
|
|
288
|
+
const Ajv = require('ajv');
|
|
289
|
+
const lockfile = require('proper-lockfile');
|
|
290
|
+
|
|
291
|
+
class ConfigManager {
|
|
292
|
+
constructor(configDir = 'config', backupDir = 'backups') {
|
|
293
|
+
this.configDir = configDir;
|
|
294
|
+
this.backupDir = backupDir;
|
|
295
|
+
this.ajv = new Ajv();
|
|
296
|
+
|
|
297
|
+
// Ensure backup directory exists
|
|
298
|
+
if (!fsSync.existsSync(backupDir)) {
|
|
299
|
+
fsSync.mkdirSync(backupDir, { recursive: true });
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
async init() {
|
|
304
|
+
// Load schema
|
|
305
|
+
const schemaPath = path.join(this.configDir, 'schema.json');
|
|
306
|
+
const schemaData = await fs.readFile(schemaPath, 'utf8');
|
|
307
|
+
this.schema = JSON.parse(schemaData);
|
|
308
|
+
this.validate = this.ajv.compile(this.schema);
|
|
309
|
+
}
|
|
310
|
+
|
|
311
|
+
_validateConfig(config) {
|
|
312
|
+
const valid = this.validate(config);
|
|
313
|
+
if (!valid) {
|
|
314
|
+
throw new Error(`Validation failed: ${JSON.stringify(this.validate.errors)}`);
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
async _backup(filepath) {
|
|
319
|
+
try {
|
|
320
|
+
await fs.access(filepath);
|
|
321
|
+
} catch {
|
|
322
|
+
return null; // File doesn't exist
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
const timestamp = new Date().toISOString().replace(/[:.]/g, '-').slice(0, -5);
|
|
326
|
+
const filename = path.basename(filepath);
|
|
327
|
+
const backupPath = path.join(this.backupDir, `${filename}.backup_${timestamp}`);
|
|
328
|
+
|
|
329
|
+
await fs.copyFile(filepath, backupPath);
|
|
330
|
+
return backupPath;
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
async _rotateBackups(filename, keep = 5) {
|
|
334
|
+
const files = await fs.readdir(this.backupDir);
|
|
335
|
+
const backups = files
|
|
336
|
+
.filter(f => f.startsWith(`${filename}.backup_`))
|
|
337
|
+
.sort()
|
|
338
|
+
.reverse();
|
|
339
|
+
|
|
340
|
+
// Delete old backups
|
|
341
|
+
for (const backup of backups.slice(keep)) {
|
|
342
|
+
await fs.unlink(path.join(this.backupDir, backup));
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
async read(environment) {
|
|
347
|
+
const filepath = path.join(this.configDir, `${environment}.json`);
|
|
348
|
+
|
|
349
|
+
// Acquire shared lock
|
|
350
|
+
const release = await lockfile.lock(filepath, { retries: 5 });
|
|
351
|
+
|
|
352
|
+
try {
|
|
353
|
+
const data = await fs.readFile(filepath, 'utf8');
|
|
354
|
+
const config = JSON.parse(data);
|
|
355
|
+
this._validateConfig(config);
|
|
356
|
+
return config;
|
|
357
|
+
} finally {
|
|
358
|
+
await release();
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
async write(environment, config) {
|
|
363
|
+
const filepath = path.join(this.configDir, `${environment}.json`);
|
|
364
|
+
|
|
365
|
+
// Validate first
|
|
366
|
+
this._validateConfig(config);
|
|
367
|
+
|
|
368
|
+
// Create backup
|
|
369
|
+
try {
|
|
370
|
+
const backupPath = await this._backup(filepath);
|
|
371
|
+
if (backupPath) {
|
|
372
|
+
console.log(`Created backup: ${backupPath}`);
|
|
373
|
+
await this._rotateBackups(path.basename(filepath));
|
|
374
|
+
}
|
|
375
|
+
} catch (err) {
|
|
376
|
+
console.error(`Backup failed: ${err.message}`);
|
|
377
|
+
}
|
|
378
|
+
|
|
379
|
+
// Atomic write
|
|
380
|
+
const tmpPath = `${filepath}.tmp`;
|
|
381
|
+
await fs.writeFile(tmpPath, JSON.stringify(config, null, 2));
|
|
382
|
+
await fs.rename(tmpPath, filepath);
|
|
383
|
+
|
|
384
|
+
console.log(`Configuration written: ${filepath}`);
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
async update(environment, updates) {
|
|
388
|
+
const config = await this.read(environment);
|
|
389
|
+
|
|
390
|
+
// Deep merge
|
|
391
|
+
function deepMerge(base, updates) {
|
|
392
|
+
for (const [key, value] of Object.entries(updates)) {
|
|
393
|
+
if (typeof value === 'object' && !Array.isArray(value) && key in base) {
|
|
394
|
+
deepMerge(base[key], value);
|
|
395
|
+
} else {
|
|
396
|
+
base[key] = value;
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
deepMerge(config, updates);
|
|
402
|
+
await this.write(environment, config);
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
async restore(environment, backupTimestamp) {
|
|
406
|
+
const filename = `${environment}.json`;
|
|
407
|
+
const backupPath = path.join(this.backupDir, `${filename}.backup_${backupTimestamp}`);
|
|
408
|
+
|
|
409
|
+
const data = await fs.readFile(backupPath, 'utf8');
|
|
410
|
+
const config = JSON.parse(data);
|
|
411
|
+
|
|
412
|
+
await this.write(environment, config);
|
|
413
|
+
console.log(`Restored from backup: ${backupPath}`);
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
// Usage Example
|
|
418
|
+
(async () => {
|
|
419
|
+
const manager = new ConfigManager();
|
|
420
|
+
await manager.init();
|
|
421
|
+
|
|
422
|
+
// Read configuration
|
|
423
|
+
const config = await manager.read('dev');
|
|
424
|
+
console.log(`Database host: ${config.database.host}`);
|
|
425
|
+
|
|
426
|
+
// Update configuration
|
|
427
|
+
await manager.update('dev', {
|
|
428
|
+
cache: { ttl: 600 },
|
|
429
|
+
features: { new_feature: true }
|
|
430
|
+
});
|
|
431
|
+
|
|
432
|
+
// Restore from backup
|
|
433
|
+
// await manager.restore('dev', '2024-01-20T10-00-00');
|
|
434
|
+
})();
|
|
435
|
+
```
|
|
436
|
+
|
|
437
|
+
---
|
|
438
|
+
|
|
439
|
+
## Migration to SQLite
|
|
440
|
+
|
|
441
|
+
**File: `migrate_to_sqlite.py`**
|
|
442
|
+
|
|
443
|
+
When configuration grows beyond simple key-value pairs or you need query capabilities, migrate to SQLite.
|
|
444
|
+
|
|
445
|
+
```python
|
|
446
|
+
import json
|
|
447
|
+
import sqlite3
|
|
448
|
+
from pathlib import Path
|
|
449
|
+
|
|
450
|
+
class ConfigMigrator:
|
|
451
|
+
"""Migrate JSON configuration to SQLite database."""
|
|
452
|
+
|
|
453
|
+
def __init__(self, db_path='config.db'):
|
|
454
|
+
self.db_path = db_path
|
|
455
|
+
self.conn = None
|
|
456
|
+
|
|
457
|
+
def connect(self):
|
|
458
|
+
"""Connect to SQLite database."""
|
|
459
|
+
self.conn = sqlite3.connect(self.db_path)
|
|
460
|
+
self.conn.row_factory = sqlite3.Row
|
|
461
|
+
|
|
462
|
+
def create_schema(self):
|
|
463
|
+
"""Create database schema."""
|
|
464
|
+
cursor = self.conn.cursor()
|
|
465
|
+
|
|
466
|
+
# Environments table
|
|
467
|
+
cursor.execute('''
|
|
468
|
+
CREATE TABLE IF NOT EXISTS environments (
|
|
469
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
470
|
+
name TEXT UNIQUE NOT NULL,
|
|
471
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
|
|
472
|
+
)
|
|
473
|
+
''')
|
|
474
|
+
|
|
475
|
+
# Configuration table (key-value pairs)
|
|
476
|
+
cursor.execute('''
|
|
477
|
+
CREATE TABLE IF NOT EXISTS config_values (
|
|
478
|
+
id INTEGER PRIMARY KEY AUTOINCREMENT,
|
|
479
|
+
environment_id INTEGER NOT NULL,
|
|
480
|
+
section TEXT NOT NULL,
|
|
481
|
+
key TEXT NOT NULL,
|
|
482
|
+
value TEXT NOT NULL,
|
|
483
|
+
value_type TEXT NOT NULL,
|
|
484
|
+
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
485
|
+
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
|
|
486
|
+
FOREIGN KEY (environment_id) REFERENCES environments(id),
|
|
487
|
+
UNIQUE(environment_id, section, key)
|
|
488
|
+
)
|
|
489
|
+
''')
|
|
490
|
+
|
|
491
|
+
# Indexes
|
|
492
|
+
cursor.execute('''
|
|
493
|
+
CREATE INDEX IF NOT EXISTS idx_config_env_section
|
|
494
|
+
ON config_values(environment_id, section)
|
|
495
|
+
''')
|
|
496
|
+
|
|
497
|
+
self.conn.commit()
|
|
498
|
+
|
|
499
|
+
def migrate_json_file(self, json_path, environment):
|
|
500
|
+
"""Migrate JSON configuration file to SQLite."""
|
|
501
|
+
# Read JSON file
|
|
502
|
+
with open(json_path) as f:
|
|
503
|
+
config = json.load(f)
|
|
504
|
+
|
|
505
|
+
cursor = self.conn.cursor()
|
|
506
|
+
|
|
507
|
+
# Insert environment
|
|
508
|
+
cursor.execute(
|
|
509
|
+
'INSERT OR IGNORE INTO environments (name) VALUES (?)',
|
|
510
|
+
(environment,)
|
|
511
|
+
)
|
|
512
|
+
env_id = cursor.execute(
|
|
513
|
+
'SELECT id FROM environments WHERE name = ?',
|
|
514
|
+
(environment,)
|
|
515
|
+
).fetchone()[0]
|
|
516
|
+
|
|
517
|
+
# Flatten and insert configuration
|
|
518
|
+
def flatten_config(obj, section=''):
|
|
519
|
+
"""Recursively flatten nested configuration."""
|
|
520
|
+
for key, value in obj.items():
|
|
521
|
+
full_key = f"{section}.{key}" if section else key
|
|
522
|
+
|
|
523
|
+
if isinstance(value, dict):
|
|
524
|
+
flatten_config(value, full_key)
|
|
525
|
+
else:
|
|
526
|
+
value_type = type(value).__name__
|
|
527
|
+
value_str = json.dumps(value) if isinstance(value, (list, dict)) else str(value)
|
|
528
|
+
|
|
529
|
+
cursor.execute('''
|
|
530
|
+
INSERT OR REPLACE INTO config_values
|
|
531
|
+
(environment_id, section, key, value, value_type)
|
|
532
|
+
VALUES (?, ?, ?, ?, ?)
|
|
533
|
+
''', (env_id, section or 'root', key, value_str, value_type))
|
|
534
|
+
|
|
535
|
+
flatten_config(config)
|
|
536
|
+
self.conn.commit()
|
|
537
|
+
print(f"Migrated {json_path} to SQLite as '{environment}'")
|
|
538
|
+
|
|
539
|
+
def get_config(self, environment, section=None):
|
|
540
|
+
"""Retrieve configuration from SQLite."""
|
|
541
|
+
cursor = self.conn.cursor()
|
|
542
|
+
|
|
543
|
+
# Get environment ID
|
|
544
|
+
env_row = cursor.execute(
|
|
545
|
+
'SELECT id FROM environments WHERE name = ?',
|
|
546
|
+
(environment,)
|
|
547
|
+
).fetchone()
|
|
548
|
+
|
|
549
|
+
if not env_row:
|
|
550
|
+
raise ValueError(f"Environment not found: {environment}")
|
|
551
|
+
|
|
552
|
+
env_id = env_row[0]
|
|
553
|
+
|
|
554
|
+
# Query configuration
|
|
555
|
+
if section:
|
|
556
|
+
rows = cursor.execute('''
|
|
557
|
+
SELECT section, key, value, value_type
|
|
558
|
+
FROM config_values
|
|
559
|
+
WHERE environment_id = ? AND section = ?
|
|
560
|
+
''', (env_id, section)).fetchall()
|
|
561
|
+
else:
|
|
562
|
+
rows = cursor.execute('''
|
|
563
|
+
SELECT section, key, value, value_type
|
|
564
|
+
FROM config_values
|
|
565
|
+
WHERE environment_id = ?
|
|
566
|
+
''', (env_id,)).fetchall()
|
|
567
|
+
|
|
568
|
+
# Reconstruct configuration
|
|
569
|
+
config = {}
|
|
570
|
+
for row in rows:
|
|
571
|
+
section_name = row['section']
|
|
572
|
+
key = row['key']
|
|
573
|
+
value = row['value']
|
|
574
|
+
value_type = row['value_type']
|
|
575
|
+
|
|
576
|
+
# Parse value based on type
|
|
577
|
+
if value_type == 'bool':
|
|
578
|
+
value = value.lower() == 'true'
|
|
579
|
+
elif value_type == 'int':
|
|
580
|
+
value = int(value)
|
|
581
|
+
elif value_type == 'float':
|
|
582
|
+
value = float(value)
|
|
583
|
+
elif value_type in ('list', 'dict'):
|
|
584
|
+
value = json.loads(value)
|
|
585
|
+
|
|
586
|
+
# Build nested structure
|
|
587
|
+
if section_name not in config:
|
|
588
|
+
config[section_name] = {}
|
|
589
|
+
config[section_name][key] = value
|
|
590
|
+
|
|
591
|
+
return config
|
|
592
|
+
|
|
593
|
+
def update_value(self, environment, section, key, value):
|
|
594
|
+
"""Update a single configuration value."""
|
|
595
|
+
cursor = self.conn.cursor()
|
|
596
|
+
|
|
597
|
+
# Get environment ID
|
|
598
|
+
env_row = cursor.execute(
|
|
599
|
+
'SELECT id FROM environments WHERE name = ?',
|
|
600
|
+
(environment,)
|
|
601
|
+
).fetchone()
|
|
602
|
+
|
|
603
|
+
if not env_row:
|
|
604
|
+
raise ValueError(f"Environment not found: {environment}")
|
|
605
|
+
|
|
606
|
+
env_id = env_row[0]
|
|
607
|
+
value_type = type(value).__name__
|
|
608
|
+
value_str = json.dumps(value) if isinstance(value, (list, dict)) else str(value)
|
|
609
|
+
|
|
610
|
+
cursor.execute('''
|
|
611
|
+
INSERT OR REPLACE INTO config_values
|
|
612
|
+
(environment_id, section, key, value, value_type, updated_at)
|
|
613
|
+
VALUES (?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
|
|
614
|
+
''', (env_id, section, key, value_str, value_type))
|
|
615
|
+
|
|
616
|
+
self.conn.commit()
|
|
617
|
+
|
|
618
|
+
def close(self):
|
|
619
|
+
"""Close database connection."""
|
|
620
|
+
if self.conn:
|
|
621
|
+
self.conn.close()
|
|
622
|
+
|
|
623
|
+
# Migration Example
|
|
624
|
+
if __name__ == '__main__':
|
|
625
|
+
migrator = ConfigMigrator()
|
|
626
|
+
migrator.connect()
|
|
627
|
+
migrator.create_schema()
|
|
628
|
+
|
|
629
|
+
# Migrate JSON files
|
|
630
|
+
migrator.migrate_json_file('config/dev.json', 'development')
|
|
631
|
+
migrator.migrate_json_file('config/staging.json', 'staging')
|
|
632
|
+
migrator.migrate_json_file('config/production.json', 'production')
|
|
633
|
+
|
|
634
|
+
# Query configuration
|
|
635
|
+
dev_config = migrator.get_config('development')
|
|
636
|
+
print(f"Dev database config: {dev_config.get('database', {})}")
|
|
637
|
+
|
|
638
|
+
# Update value
|
|
639
|
+
migrator.update_value('development', 'cache', 'ttl', 1200)
|
|
640
|
+
|
|
641
|
+
migrator.close()
|
|
642
|
+
```
|
|
643
|
+
|
|
644
|
+
---
|
|
645
|
+
|
|
646
|
+
## Testing
|
|
647
|
+
|
|
648
|
+
**File: `test_config_manager.py`**
|
|
649
|
+
|
|
650
|
+
```python
|
|
651
|
+
import unittest
|
|
652
|
+
import tempfile
|
|
653
|
+
import shutil
|
|
654
|
+
from pathlib import Path
|
|
655
|
+
from config_manager import ConfigManager
|
|
656
|
+
|
|
657
|
+
class TestConfigManager(unittest.TestCase):
|
|
658
|
+
def setUp(self):
|
|
659
|
+
"""Create temporary directories for testing."""
|
|
660
|
+
self.test_dir = tempfile.mkdtemp()
|
|
661
|
+
self.config_dir = Path(self.test_dir) / 'config'
|
|
662
|
+
self.backup_dir = Path(self.test_dir) / 'backups'
|
|
663
|
+
self.config_dir.mkdir()
|
|
664
|
+
|
|
665
|
+
# Copy schema
|
|
666
|
+
shutil.copy('config/schema.json', self.config_dir / 'schema.json')
|
|
667
|
+
|
|
668
|
+
self.manager = ConfigManager(
|
|
669
|
+
config_dir=str(self.config_dir),
|
|
670
|
+
backup_dir=str(self.backup_dir)
|
|
671
|
+
)
|
|
672
|
+
|
|
673
|
+
def tearDown(self):
|
|
674
|
+
"""Clean up temporary directories."""
|
|
675
|
+
shutil.rmtree(self.test_dir)
|
|
676
|
+
|
|
677
|
+
def test_write_and_read(self):
|
|
678
|
+
"""Test writing and reading configuration."""
|
|
679
|
+
config = {
|
|
680
|
+
"environment": "development",
|
|
681
|
+
"database": {
|
|
682
|
+
"host": "localhost",
|
|
683
|
+
"port": 5432,
|
|
684
|
+
"name": "test_db",
|
|
685
|
+
"username": "test_user",
|
|
686
|
+
"password": "test_pass"
|
|
687
|
+
},
|
|
688
|
+
"logging": {
|
|
689
|
+
"level": "DEBUG"
|
|
690
|
+
}
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
self.manager.write('test', config)
|
|
694
|
+
read_config = self.manager.read('test')
|
|
695
|
+
|
|
696
|
+
self.assertEqual(config, read_config)
|
|
697
|
+
|
|
698
|
+
def test_validation(self):
|
|
699
|
+
"""Test schema validation."""
|
|
700
|
+
invalid_config = {
|
|
701
|
+
"environment": "invalid_env", # Not in enum
|
|
702
|
+
"database": {
|
|
703
|
+
"host": "localhost"
|
|
704
|
+
# Missing required fields
|
|
705
|
+
}
|
|
706
|
+
}
|
|
707
|
+
|
|
708
|
+
with self.assertRaises(Exception):
|
|
709
|
+
self.manager.write('test', invalid_config)
|
|
710
|
+
|
|
711
|
+
def test_backup_creation(self):
|
|
712
|
+
"""Test backup creation."""
|
|
713
|
+
config = {
|
|
714
|
+
"environment": "development",
|
|
715
|
+
"database": {
|
|
716
|
+
"host": "localhost",
|
|
717
|
+
"port": 5432,
|
|
718
|
+
"name": "test_db",
|
|
719
|
+
"username": "test_user",
|
|
720
|
+
"password": "test_pass"
|
|
721
|
+
},
|
|
722
|
+
"logging": {"level": "DEBUG"}
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
# Write initial config
|
|
726
|
+
self.manager.write('test', config)
|
|
727
|
+
|
|
728
|
+
# Update config (should create backup)
|
|
729
|
+
config['database']['port'] = 5433
|
|
730
|
+
self.manager.write('test', config)
|
|
731
|
+
|
|
732
|
+
# Check backup exists
|
|
733
|
+
backups = list(self.backup_dir.glob('test.json.backup_*'))
|
|
734
|
+
self.assertEqual(len(backups), 1)
|
|
735
|
+
|
|
736
|
+
def test_update(self):
|
|
737
|
+
"""Test configuration update."""
|
|
738
|
+
config = {
|
|
739
|
+
"environment": "development",
|
|
740
|
+
"database": {
|
|
741
|
+
"host": "localhost",
|
|
742
|
+
"port": 5432,
|
|
743
|
+
"name": "test_db",
|
|
744
|
+
"username": "test_user",
|
|
745
|
+
"password": "test_pass"
|
|
746
|
+
},
|
|
747
|
+
"logging": {"level": "DEBUG"}
|
|
748
|
+
}
|
|
749
|
+
|
|
750
|
+
self.manager.write('test', config)
|
|
751
|
+
|
|
752
|
+
# Update
|
|
753
|
+
self.manager.update('test', {
|
|
754
|
+
'database': {'port': 5433}
|
|
755
|
+
})
|
|
756
|
+
|
|
757
|
+
# Verify
|
|
758
|
+
updated = self.manager.read('test')
|
|
759
|
+
self.assertEqual(updated['database']['port'], 5433)
|
|
760
|
+
self.assertEqual(updated['database']['host'], 'localhost') # Unchanged
|
|
761
|
+
|
|
762
|
+
if __name__ == '__main__':
|
|
763
|
+
unittest.main()
|
|
764
|
+
```
|
|
765
|
+
|
|
766
|
+
---
|
|
767
|
+
|
|
768
|
+
## Summary
|
|
769
|
+
|
|
770
|
+
This example demonstrates:
|
|
771
|
+
|
|
772
|
+
✅ **Schema Validation**: JSON Schema ensures configuration correctness
|
|
773
|
+
✅ **Atomic Writes**: Temp file + rename prevents corruption
|
|
774
|
+
✅ **File Locking**: Prevents concurrent write conflicts
|
|
775
|
+
✅ **Backup/Restore**: Automatic backups with rotation
|
|
776
|
+
✅ **Migration Path**: Clear path to SQLite when needed
|
|
777
|
+
✅ **Multi-Language**: Both Python and JavaScript implementations
|
|
778
|
+
✅ **Testing**: Comprehensive unit tests
|
|
779
|
+
|
|
780
|
+
**When to Use This Pattern:**
|
|
781
|
+
- Application configuration management
|
|
782
|
+
- Feature flags
|
|
783
|
+
- Environment-specific settings
|
|
784
|
+
- Small datasets (< 1000 records)
|
|
785
|
+
- Git-backed configuration
|
|
786
|
+
|
|
787
|
+
**When to Migrate:**
|
|
788
|
+
- Configuration grows > 1 MB
|
|
789
|
+
- Need complex queries
|
|
790
|
+
- Multiple applications sharing config
|
|
791
|
+
- Audit trail requirements
|
|
792
|
+
- Fine-grained access control needed
|
|
793
|
+
|