@vodailoc/kilo-kit-mcp 1.1.0 → 1.1.1
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/.mcp/kilo-kit.codex-windows.toml +5 -0
- package/LICENSE +190 -190
- package/QUICKSTART.md +265 -255
- package/README.md +290 -266
- package/mcp/README.md +29 -5
- package/mcp/dist/server.js +1 -1
- package/mcp/package.json +1 -2
- package/package.json +3 -2
- package/skills/README.md +647 -647
- package/skills/SKILLS_INDEX.md +139 -139
- package/skills/ai-media/ai-multimodal/.env.example +97 -97
- package/skills/ai-media/ai-multimodal/SKILL.md +357 -357
- package/skills/ai-media/ai-multimodal/references/audio-processing.md +373 -373
- package/skills/ai-media/ai-multimodal/references/image-generation.md +558 -558
- package/skills/ai-media/ai-multimodal/references/video-analysis.md +502 -502
- package/skills/ai-media/ai-multimodal/references/vision-understanding.md +483 -483
- package/skills/ai-media/ai-multimodal/scripts/document_converter.py +395 -395
- package/skills/ai-media/ai-multimodal/scripts/gemini_batch_process.py +480 -480
- package/skills/ai-media/ai-multimodal/scripts/media_optimizer.py +506 -506
- package/skills/ai-media/ai-multimodal/scripts/requirements.txt +26 -26
- package/skills/ai-media/ai-multimodal/scripts/tests/requirements.txt +20 -20
- package/skills/ai-media/ai-multimodal/scripts/tests/test_document_converter.py +299 -299
- package/skills/ai-media/ai-multimodal/scripts/tests/test_gemini_batch_process.py +362 -362
- package/skills/ai-media/ai-multimodal/scripts/tests/test_media_optimizer.py +373 -373
- package/skills/ai-media/media-processing/SKILL.md +358 -358
- package/skills/ai-media/media-processing/references/ffmpeg-encoding.md +358 -358
- package/skills/ai-media/media-processing/references/ffmpeg-filters.md +503 -503
- package/skills/ai-media/media-processing/references/ffmpeg-streaming.md +403 -403
- package/skills/ai-media/media-processing/references/format-compatibility.md +375 -375
- package/skills/ai-media/media-processing/references/imagemagick-batch.md +612 -612
- package/skills/ai-media/media-processing/references/imagemagick-editing.md +623 -623
- package/skills/ai-media/media-processing/scripts/batch_resize.py +342 -342
- package/skills/ai-media/media-processing/scripts/media_convert.py +311 -311
- package/skills/ai-media/media-processing/scripts/requirements.txt +24 -24
- package/skills/ai-media/media-processing/scripts/tests/requirements.txt +2 -2
- package/skills/ai-media/media-processing/scripts/tests/test_batch_resize.py +372 -372
- package/skills/ai-media/media-processing/scripts/tests/test_media_convert.py +259 -259
- package/skills/ai-media/media-processing/scripts/tests/test_video_optimize.py +397 -397
- package/skills/ai-media/media-processing/scripts/video_optimize.py +414 -414
- package/skills/ai-media/screenshot/LICENSE.txt +201 -201
- package/skills/ai-media/screenshot/SKILL.md +267 -267
- package/skills/ai-media/screenshot/agents/openai.yaml +6 -6
- package/skills/ai-media/screenshot/assets/screenshot-small.svg +5 -5
- package/skills/ai-media/screenshot/scripts/ensure_macos_permissions.sh +54 -54
- package/skills/ai-media/screenshot/scripts/macos_display_info.swift +22 -22
- package/skills/ai-media/screenshot/scripts/macos_permissions.swift +40 -40
- package/skills/ai-media/screenshot/scripts/macos_window_info.swift +126 -126
- package/skills/ai-media/screenshot/scripts/take_screenshot.ps1 +163 -163
- package/skills/ai-media/screenshot/scripts/take_screenshot.py +585 -585
- package/skills/ai-media/sora/LICENSE.txt +201 -201
- package/skills/ai-media/sora/SKILL.md +153 -153
- package/skills/ai-media/sora/agents/openai.yaml +6 -6
- package/skills/ai-media/sora/assets/sora-small.svg +4 -4
- package/skills/ai-media/sora/references/cinematic-shots.md +53 -53
- package/skills/ai-media/sora/references/cli.md +248 -248
- package/skills/ai-media/sora/references/codex-network.md +28 -28
- package/skills/ai-media/sora/references/prompting.md +137 -137
- package/skills/ai-media/sora/references/sample-prompts.md +95 -95
- package/skills/ai-media/sora/references/social-ads.md +42 -42
- package/skills/ai-media/sora/references/troubleshooting.md +58 -58
- package/skills/ai-media/sora/references/video-api.md +45 -45
- package/skills/ai-media/sora/scripts/sora.py +970 -970
- package/skills/design/aesthetic/SKILL.md +121 -121
- package/skills/design/aesthetic/assets/design-guideline-template.md +163 -163
- package/skills/design/aesthetic/assets/design-story-template.md +135 -135
- package/skills/design/aesthetic/references/design-principles.md +62 -62
- package/skills/design/aesthetic/references/design-resources.md +75 -75
- package/skills/design/aesthetic/references/micro-interactions.md +53 -53
- package/skills/design/aesthetic/references/storytelling-design.md +50 -50
- package/skills/design/figma/LICENSE.txt +202 -202
- package/skills/design/figma/SKILL.md +42 -42
- package/skills/design/figma/agents/openai.yaml +14 -14
- package/skills/design/figma/assets/figma-small.svg +3 -3
- package/skills/design/figma/assets/icon.svg +28 -28
- package/skills/design/figma/references/figma-mcp-config.md +35 -35
- package/skills/design/figma/references/figma-tools-and-prompts.md +34 -34
- package/skills/design/figma-implement-design/LICENSE.txt +202 -202
- package/skills/design/figma-implement-design/SKILL.md +264 -264
- package/skills/design/figma-implement-design/agents/openai.yaml +14 -14
- package/skills/design/figma-implement-design/assets/figma-small.svg +3 -3
- package/skills/design/figma-implement-design/assets/icon.svg +28 -28
- package/skills/design/frontend-design/SKILL.md +41 -41
- package/skills/design/frontend-design/references/animejs.md +395 -395
- package/skills/design/ui-styling/LICENSE.txt +201 -201
- package/skills/design/ui-styling/SKILL.md +321 -321
- package/skills/design/ui-styling/canvas-fonts/ArsenalSC-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/BigShoulders-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/Boldonse-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/BricolageGrotesque-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/CrimsonPro-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/DMMono-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/EricaOne-OFL.txt +94 -94
- package/skills/design/ui-styling/canvas-fonts/GeistMono-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/Gloock-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/IBMPlexMono-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/InstrumentSans-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/Italiana-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/JetBrainsMono-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/Jura-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/LibreBaskerville-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/Lora-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/NationalPark-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/NothingYouCouldDo-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/Outfit-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/PixelifySans-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/PoiretOne-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/RedHatMono-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/Silkscreen-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/SmoochSans-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/Tektur-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/WorkSans-OFL.txt +93 -93
- package/skills/design/ui-styling/canvas-fonts/YoungSerif-OFL.txt +93 -93
- package/skills/design/ui-styling/references/canvas-design-system.md +320 -320
- package/skills/design/ui-styling/references/shadcn-accessibility.md +471 -471
- package/skills/design/ui-styling/references/shadcn-components.md +424 -424
- package/skills/design/ui-styling/references/shadcn-theming.md +373 -373
- package/skills/design/ui-styling/references/tailwind-customization.md +483 -483
- package/skills/design/ui-styling/references/tailwind-responsive.md +382 -382
- package/skills/design/ui-styling/references/tailwind-utilities.md +455 -455
- package/skills/design/ui-styling/scripts/requirements.txt +17 -17
- package/skills/design/ui-styling/scripts/shadcn_add.py +292 -292
- package/skills/design/ui-styling/scripts/tailwind_config_gen.py +456 -456
- package/skills/design/ui-styling/scripts/tests/requirements.txt +3 -3
- package/skills/design/ui-styling/scripts/tests/test_shadcn_add.py +266 -266
- package/skills/design/ui-styling/scripts/tests/test_tailwind_config_gen.py +336 -336
- package/skills/engineering/aspnet-core/LICENSE.txt +201 -201
- package/skills/engineering/aspnet-core/SKILL.md +61 -61
- package/skills/engineering/aspnet-core/agents/openai.yaml +5 -5
- package/skills/engineering/aspnet-core/references/_sections.md +40 -40
- package/skills/engineering/aspnet-core/references/apis-minimal-and-controllers.md +81 -81
- package/skills/engineering/aspnet-core/references/data-state-and-services.md +69 -69
- package/skills/engineering/aspnet-core/references/program-and-pipeline.md +103 -103
- package/skills/engineering/aspnet-core/references/realtime-grpc-and-background-work.md +58 -58
- package/skills/engineering/aspnet-core/references/security-and-identity.md +75 -75
- package/skills/engineering/aspnet-core/references/source-map.md +43 -43
- package/skills/engineering/aspnet-core/references/stack-selection.md +63 -63
- package/skills/engineering/aspnet-core/references/testing-performance-and-operations.md +92 -92
- package/skills/engineering/aspnet-core/references/ui-blazor.md +53 -53
- package/skills/engineering/aspnet-core/references/ui-mvc.md +56 -56
- package/skills/engineering/aspnet-core/references/ui-razor-pages.md +55 -55
- package/skills/engineering/aspnet-core/references/versioning-and-upgrades.md +51 -51
- package/skills/engineering/backend-development/SKILL.md +95 -95
- package/skills/engineering/backend-development/references/backend-api-design.md +495 -495
- package/skills/engineering/backend-development/references/backend-architecture.md +454 -454
- package/skills/engineering/backend-development/references/backend-authentication.md +338 -338
- package/skills/engineering/backend-development/references/backend-code-quality.md +659 -659
- package/skills/engineering/backend-development/references/backend-debugging.md +904 -904
- package/skills/engineering/backend-development/references/backend-devops.md +494 -494
- package/skills/engineering/backend-development/references/backend-mindset.md +387 -387
- package/skills/engineering/backend-development/references/backend-performance.md +397 -397
- package/skills/engineering/backend-development/references/backend-security.md +290 -290
- package/skills/engineering/backend-development/references/backend-technologies.md +256 -256
- package/skills/engineering/backend-development/references/backend-testing.md +429 -429
- package/skills/engineering/better-auth/SKILL.md +204 -204
- package/skills/engineering/better-auth/references/advanced-features.md +553 -553
- package/skills/engineering/better-auth/references/database-integration.md +577 -577
- package/skills/engineering/better-auth/references/email-password-auth.md +416 -416
- package/skills/engineering/better-auth/references/oauth-providers.md +430 -430
- package/skills/engineering/better-auth/scripts/better_auth_init.py +521 -521
- package/skills/engineering/better-auth/scripts/requirements.txt +15 -15
- package/skills/engineering/better-auth/scripts/tests/test_better_auth_init.py +421 -421
- package/skills/engineering/code-review/SKILL.md +140 -140
- package/skills/engineering/code-review/references/code-review-reception.md +208 -208
- package/skills/engineering/code-review/references/requesting-code-review.md +104 -104
- package/skills/engineering/code-review/references/verification-before-completion.md +138 -138
- package/skills/engineering/context-engineering/SKILL.md +86 -86
- package/skills/engineering/context-engineering/references/context-compression.md +84 -84
- package/skills/engineering/context-engineering/references/context-degradation.md +93 -93
- package/skills/engineering/context-engineering/references/context-fundamentals.md +75 -75
- package/skills/engineering/context-engineering/references/context-optimization.md +82 -82
- package/skills/engineering/context-engineering/references/evaluation.md +89 -89
- package/skills/engineering/context-engineering/references/memory-systems.md +88 -88
- package/skills/engineering/context-engineering/references/multi-agent-patterns.md +90 -90
- package/skills/engineering/context-engineering/references/project-development.md +97 -97
- package/skills/engineering/context-engineering/references/tool-design.md +86 -86
- package/skills/engineering/context-engineering/scripts/compression_evaluator.py +329 -329
- package/skills/engineering/context-engineering/scripts/context_analyzer.py +294 -294
- package/skills/engineering/databases/SKILL.md +232 -232
- package/skills/engineering/databases/references/mongodb-aggregation.md +447 -447
- package/skills/engineering/databases/references/mongodb-atlas.md +465 -465
- package/skills/engineering/databases/references/mongodb-crud.md +408 -408
- package/skills/engineering/databases/references/mongodb-indexing.md +442 -442
- package/skills/engineering/databases/references/postgresql-administration.md +594 -594
- package/skills/engineering/databases/references/postgresql-performance.md +527 -527
- package/skills/engineering/databases/references/postgresql-psql-cli.md +467 -467
- package/skills/engineering/databases/references/postgresql-queries.md +475 -475
- package/skills/engineering/databases/scripts/db_backup.py +502 -502
- package/skills/engineering/databases/scripts/db_migrate.py +414 -414
- package/skills/engineering/databases/scripts/db_performance_check.py +444 -444
- package/skills/engineering/databases/scripts/requirements.txt +20 -20
- package/skills/engineering/databases/scripts/tests/requirements.txt +4 -4
- package/skills/engineering/databases/scripts/tests/test_db_backup.py +340 -340
- package/skills/engineering/databases/scripts/tests/test_db_migrate.py +277 -277
- package/skills/engineering/databases/scripts/tests/test_db_performance_check.py +370 -370
- package/skills/engineering/diagnose/SKILL.md +117 -117
- package/skills/engineering/diagnose/scripts/hitl-loop.template.sh +41 -41
- package/skills/engineering/docs-seeker/SKILL.md +207 -207
- package/skills/engineering/docs-seeker/WORKFLOWS.md +505 -505
- package/skills/engineering/docs-seeker/references/best-practices.md +632 -632
- package/skills/engineering/docs-seeker/references/documentation-sources.md +461 -461
- package/skills/engineering/docs-seeker/references/error-handling.md +621 -621
- package/skills/engineering/docs-seeker/references/limitations.md +821 -821
- package/skills/engineering/docs-seeker/references/performance.md +574 -574
- package/skills/engineering/docs-seeker/references/tool-selection.md +262 -262
- package/skills/engineering/frontend-development/SKILL.md +398 -398
- package/skills/engineering/frontend-development/resources/common-patterns.md +330 -330
- package/skills/engineering/frontend-development/resources/complete-examples.md +871 -871
- package/skills/engineering/frontend-development/resources/component-patterns.md +501 -501
- package/skills/engineering/frontend-development/resources/data-fetching.md +766 -766
- package/skills/engineering/frontend-development/resources/file-organization.md +501 -501
- package/skills/engineering/frontend-development/resources/loading-and-error-states.md +500 -500
- package/skills/engineering/frontend-development/resources/performance.md +405 -405
- package/skills/engineering/frontend-development/resources/routing-guide.md +363 -363
- package/skills/engineering/frontend-development/resources/styling-guide.md +427 -427
- package/skills/engineering/frontend-development/resources/typescript-standards.md +417 -417
- package/skills/engineering/improve-codebase-architecture/DEEPENING.md +37 -37
- package/skills/engineering/improve-codebase-architecture/INTERFACE-DESIGN.md +44 -44
- package/skills/engineering/improve-codebase-architecture/LANGUAGE.md +53 -53
- package/skills/engineering/improve-codebase-architecture/SKILL.md +71 -71
- package/skills/engineering/openai-docs/LICENSE.txt +201 -201
- package/skills/engineering/openai-docs/SKILL.md +69 -69
- package/skills/engineering/openai-docs/agents/openai.yaml +14 -14
- package/skills/engineering/openai-docs/assets/openai-small.svg +3 -3
- package/skills/engineering/openai-docs/references/gpt-5p4-prompting-guide.md +433 -433
- package/skills/engineering/openai-docs/references/latest-model.md +35 -35
- package/skills/engineering/openai-docs/references/upgrading-to-gpt-5p4.md +164 -164
- package/skills/engineering/playwright/LICENSE.txt +201 -201
- package/skills/engineering/playwright/NOTICE.txt +14 -14
- package/skills/engineering/playwright/SKILL.md +147 -147
- package/skills/engineering/playwright/agents/openai.yaml +6 -6
- package/skills/engineering/playwright/assets/playwright-small.svg +3 -3
- package/skills/engineering/playwright/references/cli.md +116 -116
- package/skills/engineering/playwright/references/workflows.md +95 -95
- package/skills/engineering/playwright/scripts/playwright_cli.sh +25 -25
- package/skills/engineering/playwright-interactive/LICENSE.txt +201 -201
- package/skills/engineering/playwright-interactive/NOTICE.txt +13 -13
- package/skills/engineering/playwright-interactive/SKILL.md +689 -689
- package/skills/engineering/playwright-interactive/agents/openai.yaml +6 -6
- package/skills/engineering/playwright-interactive/assets/playwright-small.svg +3 -3
- package/skills/engineering/render-deploy/LICENSE.txt +201 -201
- package/skills/engineering/render-deploy/SKILL.md +479 -479
- package/skills/engineering/render-deploy/agents/openai.yaml +14 -14
- package/skills/engineering/render-deploy/assets/docker.yaml +62 -62
- package/skills/engineering/render-deploy/assets/go-api.yaml +35 -35
- package/skills/engineering/render-deploy/assets/nextjs-postgres.yaml +35 -35
- package/skills/engineering/render-deploy/assets/node-express.yaml +25 -25
- package/skills/engineering/render-deploy/assets/python-django.yaml +89 -89
- package/skills/engineering/render-deploy/assets/render-small.svg +3 -3
- package/skills/engineering/render-deploy/assets/static-site.yaml +54 -54
- package/skills/engineering/render-deploy/references/blueprint-spec.md +718 -718
- package/skills/engineering/render-deploy/references/codebase-analysis.md +49 -49
- package/skills/engineering/render-deploy/references/configuration-guide.md +603 -603
- package/skills/engineering/render-deploy/references/deployment-details.md +224 -224
- package/skills/engineering/render-deploy/references/direct-creation.md +113 -113
- package/skills/engineering/render-deploy/references/error-patterns.md +13 -13
- package/skills/engineering/render-deploy/references/post-deploy-checks.md +36 -36
- package/skills/engineering/render-deploy/references/runtimes.md +473 -473
- package/skills/engineering/render-deploy/references/service-types.md +450 -450
- package/skills/engineering/render-deploy/references/troubleshooting-basics.md +36 -36
- package/skills/engineering/repomix/SKILL.md +215 -215
- package/skills/engineering/repomix/references/configuration.md +211 -211
- package/skills/engineering/repomix/references/usage-patterns.md +232 -232
- package/skills/engineering/repomix/scripts/README.md +179 -179
- package/skills/engineering/repomix/scripts/repomix_batch.py +455 -455
- package/skills/engineering/repomix/scripts/repos.example.json +15 -15
- package/skills/engineering/repomix/scripts/requirements.txt +15 -15
- package/skills/engineering/repomix/scripts/tests/test_repomix_batch.py +531 -531
- package/skills/engineering/setup-matt-pocock-skills/SKILL.md +121 -121
- package/skills/engineering/setup-matt-pocock-skills/domain.md +51 -51
- package/skills/engineering/setup-matt-pocock-skills/issue-tracker-github.md +22 -22
- package/skills/engineering/setup-matt-pocock-skills/issue-tracker-gitlab.md +23 -23
- package/skills/engineering/setup-matt-pocock-skills/issue-tracker-local.md +19 -19
- package/skills/engineering/setup-matt-pocock-skills/triage-labels.md +15 -15
- package/skills/engineering/shopify/README.md +66 -66
- package/skills/engineering/shopify/SKILL.md +319 -319
- package/skills/engineering/shopify/references/app-development.md +470 -470
- package/skills/engineering/shopify/references/extensions.md +493 -493
- package/skills/engineering/shopify/references/themes.md +498 -498
- package/skills/engineering/shopify/scripts/requirements.txt +19 -19
- package/skills/engineering/shopify/scripts/shopify_init.py +423 -423
- package/skills/engineering/shopify/scripts/tests/test_shopify_init.py +385 -385
- package/skills/engineering/tdd/SKILL.md +109 -109
- package/skills/engineering/tdd/deep-modules.md +33 -33
- package/skills/engineering/tdd/interface-design.md +31 -31
- package/skills/engineering/tdd/mocking.md +59 -59
- package/skills/engineering/tdd/refactoring.md +10 -10
- package/skills/engineering/tdd/tests.md +61 -61
- package/skills/engineering/to-issues/SKILL.md +81 -81
- package/skills/engineering/to-prd/SKILL.md +74 -74
- package/skills/engineering/triage/AGENT-BRIEF.md +168 -168
- package/skills/engineering/triage/OUT-OF-SCOPE.md +101 -101
- package/skills/engineering/triage/SKILL.md +103 -103
- package/skills/engineering/web-frameworks/SKILL.md +324 -324
- package/skills/engineering/web-frameworks/references/nextjs-app-router.md +465 -465
- package/skills/engineering/web-frameworks/references/nextjs-data-fetching.md +459 -459
- package/skills/engineering/web-frameworks/references/nextjs-optimization.md +511 -511
- package/skills/engineering/web-frameworks/references/nextjs-server-components.md +495 -495
- package/skills/engineering/web-frameworks/references/remix-icon-integration.md +603 -603
- package/skills/engineering/web-frameworks/references/turborepo-caching.md +551 -551
- package/skills/engineering/web-frameworks/references/turborepo-pipelines.md +517 -517
- package/skills/engineering/web-frameworks/references/turborepo-setup.md +542 -542
- package/skills/engineering/web-frameworks/scripts/nextjs_init.py +547 -547
- package/skills/engineering/web-frameworks/scripts/requirements.txt +16 -16
- package/skills/engineering/web-frameworks/scripts/tests/requirements.txt +3 -3
- package/skills/engineering/web-frameworks/scripts/tests/test_nextjs_init.py +319 -319
- package/skills/engineering/web-frameworks/scripts/tests/test_turborepo_migrate.py +374 -374
- package/skills/engineering/web-frameworks/scripts/turborepo_migrate.py +394 -394
- package/skills/engineering/write-a-skill/SKILL.md +117 -117
- package/skills/kilo-kit/SKILL.md +346 -346
- package/skills/kilo-kit/_template/SKILL.md +185 -185
- package/skills/kilo-kit/debugging/root-cause/SKILL.md +360 -360
- package/skills/kilo-kit/debugging/systematic/SKILL.md +339 -339
- package/skills/kilo-kit/debugging/verification/SKILL.md +424 -424
- package/skills/kilo-kit/development/backend/SKILL.md +540 -540
- package/skills/kilo-kit/development/security/SKILL.md +529 -529
- package/skills/kilo-kit/quality/code-review/SKILL.md +297 -297
- package/skills/kilo-kit/quality/testing/SKILL.md +540 -540
- package/skills/kilo-kit/references/output-formats.md +204 -204
- package/skills/kilo-kit/references/patterns.md +156 -156
- package/skills/kilo-kit/references/performance-benchmarks.md +90 -90
- package/skills/operations/chrome-devtools/SKILL.md +392 -392
- package/skills/operations/chrome-devtools/references/cdp-domains.md +694 -694
- package/skills/operations/chrome-devtools/references/performance-guide.md +940 -940
- package/skills/operations/chrome-devtools/references/puppeteer-reference.md +953 -953
- package/skills/operations/chrome-devtools/scripts/PERSISTENT-BROWSER.md +107 -107
- package/skills/operations/chrome-devtools/scripts/README.md +213 -213
- package/skills/operations/chrome-devtools/scripts/__tests__/selector.test.js +210 -210
- package/skills/operations/chrome-devtools/scripts/click.js +79 -79
- package/skills/operations/chrome-devtools/scripts/close-persistent.js +36 -36
- package/skills/operations/chrome-devtools/scripts/console.js +75 -75
- package/skills/operations/chrome-devtools/scripts/evaluate.js +49 -49
- package/skills/operations/chrome-devtools/scripts/fill.js +72 -72
- package/skills/operations/chrome-devtools/scripts/install-deps.sh +181 -181
- package/skills/operations/chrome-devtools/scripts/install.sh +83 -83
- package/skills/operations/chrome-devtools/scripts/launch-persistent.js +71 -71
- package/skills/operations/chrome-devtools/scripts/lib/browser.js +144 -144
- package/skills/operations/chrome-devtools/scripts/lib/selector.js +178 -178
- package/skills/operations/chrome-devtools/scripts/navigate.js +46 -46
- package/skills/operations/chrome-devtools/scripts/network.js +102 -102
- package/skills/operations/chrome-devtools/scripts/package-lock.json +1206 -1206
- package/skills/operations/chrome-devtools/scripts/package.json +15 -15
- package/skills/operations/chrome-devtools/scripts/performance.js +145 -145
- package/skills/operations/chrome-devtools/scripts/screenshot.js +180 -180
- package/skills/operations/chrome-devtools/scripts/snapshot.js +131 -131
- package/skills/operations/devops/.env.example +76 -76
- package/skills/operations/devops/SKILL.md +285 -285
- package/skills/operations/devops/references/browser-rendering.md +305 -305
- package/skills/operations/devops/references/cloudflare-d1-kv.md +123 -123
- package/skills/operations/devops/references/cloudflare-platform.md +271 -271
- package/skills/operations/devops/references/cloudflare-r2-storage.md +280 -280
- package/skills/operations/devops/references/cloudflare-workers-advanced.md +312 -312
- package/skills/operations/devops/references/cloudflare-workers-apis.md +309 -309
- package/skills/operations/devops/references/cloudflare-workers-basics.md +418 -418
- package/skills/operations/devops/references/docker-basics.md +297 -297
- package/skills/operations/devops/references/docker-compose.md +292 -292
- package/skills/operations/devops/references/gcloud-platform.md +297 -297
- package/skills/operations/devops/references/gcloud-services.md +304 -304
- package/skills/operations/devops/scripts/cloudflare_deploy.py +269 -269
- package/skills/operations/devops/scripts/docker_optimize.py +320 -320
- package/skills/operations/devops/scripts/requirements.txt +20 -20
- package/skills/operations/devops/scripts/tests/requirements.txt +3 -3
- package/skills/operations/devops/scripts/tests/test_cloudflare_deploy.py +285 -285
- package/skills/operations/devops/scripts/tests/test_docker_optimize.py +436 -436
- package/skills/operations/mcp-builder/LICENSE.txt +201 -201
- package/skills/operations/mcp-builder/SKILL.md +328 -328
- package/skills/operations/mcp-builder/reference/evaluation.md +601 -601
- package/skills/operations/mcp-builder/reference/mcp_best_practices.md +915 -915
- package/skills/operations/mcp-builder/reference/node_mcp_server.md +915 -915
- package/skills/operations/mcp-builder/reference/python_mcp_server.md +751 -751
- package/skills/operations/mcp-builder/scripts/connections.py +151 -151
- package/skills/operations/mcp-builder/scripts/evaluation.py +373 -373
- package/skills/operations/mcp-builder/scripts/example_evaluation.xml +22 -22
- package/skills/operations/mcp-builder/scripts/requirements.txt +2 -2
- package/skills/operations/mcp-management/README.md +219 -219
- package/skills/operations/mcp-management/SKILL.md +175 -175
- package/skills/operations/mcp-management/assets/tools.json +3043 -3043
- package/skills/operations/mcp-management/references/configuration.md +114 -114
- package/skills/operations/mcp-management/references/gemini-cli-integration.md +201 -201
- package/skills/operations/mcp-management/references/mcp-protocol.md +116 -116
- package/skills/operations/mcp-management/scripts/.env.example +10 -10
- package/skills/operations/mcp-management/scripts/cli.ts +155 -155
- package/skills/operations/mcp-management/scripts/dist/analyze-tools.js +70 -70
- package/skills/operations/mcp-management/scripts/dist/cli.js +131 -131
- package/skills/operations/mcp-management/scripts/dist/mcp-client.js +115 -115
- package/skills/operations/mcp-management/scripts/mcp-client.ts +163 -163
- package/skills/operations/mcp-management/scripts/package.json +18 -18
- package/skills/operations/mcp-management/scripts/tsconfig.json +15 -15
- package/skills/problem-solving/collision-zone-thinking/SKILL.md +62 -62
- package/skills/problem-solving/defense-in-depth/SKILL.md +130 -130
- package/skills/problem-solving/inversion-exercise/SKILL.md +58 -58
- package/skills/problem-solving/meta-pattern-recognition/SKILL.md +54 -54
- package/skills/problem-solving/root-cause-tracing/SKILL.md +177 -177
- package/skills/problem-solving/root-cause-tracing/find-polluter.sh +63 -63
- package/skills/problem-solving/scale-game/SKILL.md +63 -63
- package/skills/problem-solving/sequential-thinking/README.md +118 -118
- package/skills/problem-solving/sequential-thinking/SKILL.md +93 -93
- package/skills/problem-solving/sequential-thinking/references/advanced.md +122 -122
- package/skills/problem-solving/sequential-thinking/references/examples.md +274 -274
- package/skills/problem-solving/simplification-cascades/SKILL.md +76 -76
- package/skills/problem-solving/when-stuck/SKILL.md +88 -88
- package/skills/productivity/caveman/SKILL.md +49 -49
- package/skills/productivity/grill-me/SKILL.md +10 -10
- package/skills/productivity/grill-with-docs/ADR-FORMAT.md +47 -47
- package/skills/productivity/grill-with-docs/CONTEXT-FORMAT.md +77 -77
- package/skills/productivity/grill-with-docs/SKILL.md +88 -88
- package/skills/productivity/writing-skills/graphviz-conventions.dot +171 -171
- package/skills/productivity/zoom-out/SKILL.md +7 -7
- package/skills/writing-docs/doc/LICENSE.txt +201 -201
- package/skills/writing-docs/doc/SKILL.md +80 -80
- package/skills/writing-docs/doc/agents/openai.yaml +6 -6
- package/skills/writing-docs/doc/assets/doc-small.svg +3 -3
- package/skills/writing-docs/doc/scripts/render_docx.py +296 -296
- package/skills/writing-docs/docx/LICENSE.txt +30 -30
- package/skills/writing-docs/docx/SKILL.md +196 -196
- package/skills/writing-docs/docx/docx-js.md +349 -349
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -1499
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -146
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -1085
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -11
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -3081
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -23
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -185
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -287
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -1676
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -28
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -144
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -174
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -25
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -18
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -59
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -56
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -195
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -582
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -25
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -4439
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -570
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -509
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -12
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -108
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -96
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -3646
- package/skills/writing-docs/docx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -116
- package/skills/writing-docs/docx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -42
- package/skills/writing-docs/docx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -50
- package/skills/writing-docs/docx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -49
- package/skills/writing-docs/docx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -33
- package/skills/writing-docs/docx/ooxml/schemas/mce/mc.xsd +75 -75
- package/skills/writing-docs/docx/ooxml/schemas/microsoft/wml-2010.xsd +560 -560
- package/skills/writing-docs/docx/ooxml/schemas/microsoft/wml-2012.xsd +67 -67
- package/skills/writing-docs/docx/ooxml/schemas/microsoft/wml-2018.xsd +14 -14
- package/skills/writing-docs/docx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -20
- package/skills/writing-docs/docx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -13
- package/skills/writing-docs/docx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -4
- package/skills/writing-docs/docx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -8
- package/skills/writing-docs/docx/ooxml/scripts/pack.py +159 -159
- package/skills/writing-docs/docx/ooxml/scripts/unpack.py +29 -29
- package/skills/writing-docs/docx/ooxml/scripts/validate.py +69 -69
- package/skills/writing-docs/docx/ooxml/scripts/validation/__init__.py +15 -15
- package/skills/writing-docs/docx/ooxml/scripts/validation/base.py +951 -951
- package/skills/writing-docs/docx/ooxml/scripts/validation/docx.py +274 -274
- package/skills/writing-docs/docx/ooxml/scripts/validation/pptx.py +315 -315
- package/skills/writing-docs/docx/ooxml/scripts/validation/redlining.py +279 -279
- package/skills/writing-docs/docx/ooxml.md +609 -609
- package/skills/writing-docs/docx/scripts/__init__.py +1 -1
- package/skills/writing-docs/docx/scripts/document.py +1276 -1276
- package/skills/writing-docs/docx/scripts/templates/comments.xml +2 -2
- package/skills/writing-docs/docx/scripts/templates/commentsExtended.xml +2 -2
- package/skills/writing-docs/docx/scripts/templates/commentsExtensible.xml +2 -2
- package/skills/writing-docs/docx/scripts/templates/commentsIds.xml +2 -2
- package/skills/writing-docs/docx/scripts/templates/people.xml +2 -2
- package/skills/writing-docs/docx/scripts/utilities.py +374 -374
- package/skills/writing-docs/mermaidjs-v11/SKILL.md +115 -115
- package/skills/writing-docs/mermaidjs-v11/references/cli-usage.md +228 -228
- package/skills/writing-docs/mermaidjs-v11/references/configuration.md +232 -232
- package/skills/writing-docs/mermaidjs-v11/references/diagram-types.md +315 -315
- package/skills/writing-docs/mermaidjs-v11/references/examples.md +344 -344
- package/skills/writing-docs/mermaidjs-v11/references/integration.md +310 -310
- package/skills/writing-docs/pdf/LICENSE.txt +30 -30
- package/skills/writing-docs/pdf/SKILL.md +294 -294
- package/skills/writing-docs/pdf/forms.md +205 -205
- package/skills/writing-docs/pdf/reference.md +611 -611
- package/skills/writing-docs/pdf/scripts/check_bounding_boxes.py +70 -70
- package/skills/writing-docs/pdf/scripts/check_bounding_boxes_test.py +226 -226
- package/skills/writing-docs/pdf/scripts/check_fillable_fields.py +12 -12
- package/skills/writing-docs/pdf/scripts/convert_pdf_to_images.py +35 -35
- package/skills/writing-docs/pdf/scripts/create_validation_image.py +41 -41
- package/skills/writing-docs/pdf/scripts/extract_form_field_info.py +152 -152
- package/skills/writing-docs/pdf/scripts/fill_fillable_fields.py +114 -114
- package/skills/writing-docs/pdf/scripts/fill_pdf_form_with_annotations.py +107 -107
- package/skills/writing-docs/pptx/LICENSE.txt +30 -30
- package/skills/writing-docs/pptx/SKILL.md +483 -483
- package/skills/writing-docs/pptx/html2pptx.md +624 -624
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chart.xsd +1499 -1499
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-chartDrawing.xsd +146 -146
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-diagram.xsd +1085 -1085
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-lockedCanvas.xsd +11 -11
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-main.xsd +3081 -3081
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-picture.xsd +23 -23
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-spreadsheetDrawing.xsd +185 -185
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/dml-wordprocessingDrawing.xsd +287 -287
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/pml.xsd +1676 -1676
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-additionalCharacteristics.xsd +28 -28
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-bibliography.xsd +144 -144
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-commonSimpleTypes.xsd +174 -174
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlDataProperties.xsd +25 -25
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-customXmlSchemaProperties.xsd +18 -18
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesCustom.xsd +59 -59
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesExtended.xsd +56 -56
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-documentPropertiesVariantTypes.xsd +195 -195
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-math.xsd +582 -582
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/shared-relationshipReference.xsd +25 -25
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/sml.xsd +4439 -4439
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-main.xsd +570 -570
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-officeDrawing.xsd +509 -509
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-presentationDrawing.xsd +12 -12
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-spreadsheetDrawing.xsd +108 -108
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/vml-wordprocessingDrawing.xsd +96 -96
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/wml.xsd +3646 -3646
- package/skills/writing-docs/pptx/ooxml/schemas/ISO-IEC29500-4_2016/xml.xsd +116 -116
- package/skills/writing-docs/pptx/ooxml/schemas/ecma/fouth-edition/opc-contentTypes.xsd +42 -42
- package/skills/writing-docs/pptx/ooxml/schemas/ecma/fouth-edition/opc-coreProperties.xsd +50 -50
- package/skills/writing-docs/pptx/ooxml/schemas/ecma/fouth-edition/opc-digSig.xsd +49 -49
- package/skills/writing-docs/pptx/ooxml/schemas/ecma/fouth-edition/opc-relationships.xsd +33 -33
- package/skills/writing-docs/pptx/ooxml/schemas/mce/mc.xsd +75 -75
- package/skills/writing-docs/pptx/ooxml/schemas/microsoft/wml-2010.xsd +560 -560
- package/skills/writing-docs/pptx/ooxml/schemas/microsoft/wml-2012.xsd +67 -67
- package/skills/writing-docs/pptx/ooxml/schemas/microsoft/wml-2018.xsd +14 -14
- package/skills/writing-docs/pptx/ooxml/schemas/microsoft/wml-cex-2018.xsd +20 -20
- package/skills/writing-docs/pptx/ooxml/schemas/microsoft/wml-cid-2016.xsd +13 -13
- package/skills/writing-docs/pptx/ooxml/schemas/microsoft/wml-sdtdatahash-2020.xsd +4 -4
- package/skills/writing-docs/pptx/ooxml/schemas/microsoft/wml-symex-2015.xsd +8 -8
- package/skills/writing-docs/pptx/ooxml/scripts/pack.py +159 -159
- package/skills/writing-docs/pptx/ooxml/scripts/unpack.py +29 -29
- package/skills/writing-docs/pptx/ooxml/scripts/validate.py +69 -69
- package/skills/writing-docs/pptx/ooxml/scripts/validation/__init__.py +15 -15
- package/skills/writing-docs/pptx/ooxml/scripts/validation/base.py +951 -951
- package/skills/writing-docs/pptx/ooxml/scripts/validation/docx.py +274 -274
- package/skills/writing-docs/pptx/ooxml/scripts/validation/pptx.py +315 -315
- package/skills/writing-docs/pptx/ooxml/scripts/validation/redlining.py +279 -279
- package/skills/writing-docs/pptx/ooxml.md +426 -426
- package/skills/writing-docs/pptx/scripts/html2pptx.js +978 -978
- package/skills/writing-docs/pptx/scripts/inventory.py +1020 -1020
- package/skills/writing-docs/pptx/scripts/rearrange.py +231 -231
- package/skills/writing-docs/pptx/scripts/replace.py +385 -385
- package/skills/writing-docs/pptx/scripts/thumbnail.py +450 -450
- package/skills/writing-docs/slides/LICENSE.txt +201 -201
- package/skills/writing-docs/slides/SKILL.md +71 -71
- package/skills/writing-docs/slides/agents/openai.yaml +6 -6
- package/skills/writing-docs/slides/assets/pptxgenjs_helpers/code.js +104 -104
- package/skills/writing-docs/slides/assets/pptxgenjs_helpers/image.js +333 -333
- package/skills/writing-docs/slides/assets/pptxgenjs_helpers/index.js +33 -33
- package/skills/writing-docs/slides/assets/pptxgenjs_helpers/latex.js +51 -51
- package/skills/writing-docs/slides/assets/pptxgenjs_helpers/layout.js +643 -643
- package/skills/writing-docs/slides/assets/pptxgenjs_helpers/layout_builders.js +358 -358
- package/skills/writing-docs/slides/assets/pptxgenjs_helpers/svg.js +36 -36
- package/skills/writing-docs/slides/assets/pptxgenjs_helpers/text.js +789 -789
- package/skills/writing-docs/slides/assets/pptxgenjs_helpers/util.js +24 -24
- package/skills/writing-docs/slides/assets/slides-small.svg +3 -3
- package/skills/writing-docs/slides/references/pptxgenjs-helpers.md +61 -61
- package/skills/writing-docs/slides/scripts/create_montage.py +300 -300
- package/skills/writing-docs/slides/scripts/detect_font.py +873 -873
- package/skills/writing-docs/slides/scripts/ensure_raster_image.py +202 -202
- package/skills/writing-docs/slides/scripts/render_slides.py +273 -273
- package/skills/writing-docs/slides/scripts/slides_test.py +201 -201
- package/skills/writing-docs/template-skill/SKILL.md +26 -26
- package/skills/writing-docs/xlsx/LICENSE.txt +30 -30
- package/skills/writing-docs/xlsx/SKILL.md +288 -288
- package/skills/writing-docs/xlsx/recalc.py +177 -177
- package/src/core/KILO_MASTER.md +448 -448
- package/src/tools/validate-skill.js +421 -421
|
@@ -1,421 +1,421 @@
|
|
|
1
|
-
"""
|
|
2
|
-
Tests for better_auth_init.py
|
|
3
|
-
|
|
4
|
-
Covers main functionality with mocked I/O and file operations.
|
|
5
|
-
Target: >80% coverage
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
import sys
|
|
9
|
-
import pytest
|
|
10
|
-
from pathlib import Path
|
|
11
|
-
from unittest.mock import Mock, patch, mock_open, MagicMock
|
|
12
|
-
from io import StringIO
|
|
13
|
-
|
|
14
|
-
# Add parent directory to path
|
|
15
|
-
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
16
|
-
|
|
17
|
-
from better_auth_init import BetterAuthInit, EnvConfig, main
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
@pytest.fixture
|
|
21
|
-
def mock_project_root(tmp_path):
|
|
22
|
-
"""Create mock project root with package.json."""
|
|
23
|
-
(tmp_path / "package.json").write_text("{}")
|
|
24
|
-
return tmp_path
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
@pytest.fixture
|
|
28
|
-
def auth_init(mock_project_root):
|
|
29
|
-
"""Create BetterAuthInit instance with mock project root."""
|
|
30
|
-
return BetterAuthInit(project_root=mock_project_root)
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
class TestBetterAuthInit:
|
|
34
|
-
"""Test BetterAuthInit class."""
|
|
35
|
-
|
|
36
|
-
def test_init_with_project_root(self, mock_project_root):
|
|
37
|
-
"""Test initialization with explicit project root."""
|
|
38
|
-
init = BetterAuthInit(project_root=mock_project_root)
|
|
39
|
-
assert init.project_root == mock_project_root
|
|
40
|
-
assert init.env_config is None
|
|
41
|
-
|
|
42
|
-
def test_find_project_root_success(self, mock_project_root, monkeypatch):
|
|
43
|
-
"""Test finding project root successfully."""
|
|
44
|
-
monkeypatch.chdir(mock_project_root)
|
|
45
|
-
init = BetterAuthInit()
|
|
46
|
-
assert init.project_root == mock_project_root
|
|
47
|
-
|
|
48
|
-
def test_find_project_root_failure(self, tmp_path, monkeypatch):
|
|
49
|
-
"""Test failure to find project root."""
|
|
50
|
-
# Create path without package.json
|
|
51
|
-
no_package_dir = tmp_path / "no-package"
|
|
52
|
-
no_package_dir.mkdir()
|
|
53
|
-
monkeypatch.chdir(no_package_dir)
|
|
54
|
-
|
|
55
|
-
# Mock parent to stop infinite loop
|
|
56
|
-
with patch.object(Path, "parent", new_callable=lambda: property(lambda self: self)):
|
|
57
|
-
with pytest.raises(RuntimeError, match="Could not find project root"):
|
|
58
|
-
BetterAuthInit()
|
|
59
|
-
|
|
60
|
-
def test_generate_secret(self):
|
|
61
|
-
"""Test secret generation."""
|
|
62
|
-
secret = BetterAuthInit.generate_secret()
|
|
63
|
-
assert len(secret) == 64 # 32 bytes = 64 hex chars
|
|
64
|
-
assert all(c in "0123456789abcdef" for c in secret)
|
|
65
|
-
|
|
66
|
-
# Test custom length
|
|
67
|
-
secret = BetterAuthInit.generate_secret(length=16)
|
|
68
|
-
assert len(secret) == 32 # 16 bytes = 32 hex chars
|
|
69
|
-
|
|
70
|
-
def test_parse_env_file(self, tmp_path):
|
|
71
|
-
"""Test parsing .env file."""
|
|
72
|
-
env_content = """
|
|
73
|
-
# Comment
|
|
74
|
-
KEY1=value1
|
|
75
|
-
KEY2="value2"
|
|
76
|
-
KEY3='value3'
|
|
77
|
-
INVALID LINE
|
|
78
|
-
KEY4=value=with=equals
|
|
79
|
-
"""
|
|
80
|
-
env_file = tmp_path / ".env"
|
|
81
|
-
env_file.write_text(env_content)
|
|
82
|
-
|
|
83
|
-
result = BetterAuthInit._parse_env_file(env_file)
|
|
84
|
-
|
|
85
|
-
assert result["KEY1"] == "value1"
|
|
86
|
-
assert result["KEY2"] == "value2"
|
|
87
|
-
assert result["KEY3"] == "value3"
|
|
88
|
-
assert result["KEY4"] == "value=with=equals"
|
|
89
|
-
assert "INVALID" not in result
|
|
90
|
-
|
|
91
|
-
def test_parse_env_file_missing(self, tmp_path):
|
|
92
|
-
"""Test parsing missing .env file."""
|
|
93
|
-
result = BetterAuthInit._parse_env_file(tmp_path / "nonexistent.env")
|
|
94
|
-
assert result == {}
|
|
95
|
-
|
|
96
|
-
def test_load_env_files(self, auth_init, mock_project_root):
|
|
97
|
-
"""Test loading environment variables from multiple files."""
|
|
98
|
-
# Create .env files
|
|
99
|
-
claude_env = mock_project_root / ".claude" / ".env"
|
|
100
|
-
claude_env.parent.mkdir(parents=True, exist_ok=True)
|
|
101
|
-
claude_env.write_text("BASE_VAR=base\nOVERRIDE=claude")
|
|
102
|
-
|
|
103
|
-
skills_env = mock_project_root / ".claude" / "skills" / ".env"
|
|
104
|
-
skills_env.parent.mkdir(parents=True, exist_ok=True)
|
|
105
|
-
skills_env.write_text("OVERRIDE=skills\nSKILLS_VAR=skills")
|
|
106
|
-
|
|
107
|
-
# Mock process env (highest priority)
|
|
108
|
-
with patch.dict("os.environ", {"OVERRIDE": "process", "PROCESS_VAR": "process"}):
|
|
109
|
-
result = auth_init._load_env_files()
|
|
110
|
-
|
|
111
|
-
assert result["BASE_VAR"] == "base"
|
|
112
|
-
assert result["SKILLS_VAR"] == "skills"
|
|
113
|
-
assert result["OVERRIDE"] == "process" # Process env wins
|
|
114
|
-
assert result["PROCESS_VAR"] == "process"
|
|
115
|
-
|
|
116
|
-
def test_prompt_direct_db_sqlite(self, auth_init):
|
|
117
|
-
"""Test prompting for SQLite database."""
|
|
118
|
-
with patch("builtins.input", side_effect=["3", "./test.db"]):
|
|
119
|
-
config = auth_init._prompt_direct_db()
|
|
120
|
-
|
|
121
|
-
assert config["type"] == "sqlite"
|
|
122
|
-
assert "better-sqlite3" in config["import"]
|
|
123
|
-
assert "./test.db" in config["config"]
|
|
124
|
-
|
|
125
|
-
def test_prompt_direct_db_postgresql(self, auth_init):
|
|
126
|
-
"""Test prompting for PostgreSQL database."""
|
|
127
|
-
with patch("builtins.input", side_effect=["1", "postgresql://localhost/test"]):
|
|
128
|
-
config = auth_init._prompt_direct_db()
|
|
129
|
-
|
|
130
|
-
assert config["type"] == "postgresql"
|
|
131
|
-
assert "pg" in config["import"]
|
|
132
|
-
assert config["env_var"] == ("DATABASE_URL", "postgresql://localhost/test")
|
|
133
|
-
|
|
134
|
-
def test_prompt_direct_db_mysql(self, auth_init):
|
|
135
|
-
"""Test prompting for MySQL database."""
|
|
136
|
-
with patch("builtins.input", side_effect=["2", "mysql://localhost/test"]):
|
|
137
|
-
config = auth_init._prompt_direct_db()
|
|
138
|
-
|
|
139
|
-
assert config["type"] == "mysql"
|
|
140
|
-
assert "mysql2" in config["import"]
|
|
141
|
-
assert config["env_var"][0] == "DATABASE_URL"
|
|
142
|
-
|
|
143
|
-
def test_prompt_drizzle(self, auth_init):
|
|
144
|
-
"""Test prompting for Drizzle ORM."""
|
|
145
|
-
with patch("builtins.input", return_value="1"):
|
|
146
|
-
config = auth_init._prompt_drizzle()
|
|
147
|
-
|
|
148
|
-
assert config["type"] == "drizzle"
|
|
149
|
-
assert config["provider"] == "pg"
|
|
150
|
-
assert "drizzleAdapter" in config["import"]
|
|
151
|
-
assert "drizzleAdapter" in config["config"]
|
|
152
|
-
|
|
153
|
-
def test_prompt_prisma(self, auth_init):
|
|
154
|
-
"""Test prompting for Prisma."""
|
|
155
|
-
with patch("builtins.input", return_value="2"):
|
|
156
|
-
config = auth_init._prompt_prisma()
|
|
157
|
-
|
|
158
|
-
assert config["type"] == "prisma"
|
|
159
|
-
assert config["provider"] == "mysql"
|
|
160
|
-
assert "prismaAdapter" in config["import"]
|
|
161
|
-
assert "PrismaClient" in config["import"]
|
|
162
|
-
|
|
163
|
-
def test_prompt_kysely(self, auth_init):
|
|
164
|
-
"""Test prompting for Kysely."""
|
|
165
|
-
config = auth_init._prompt_kysely()
|
|
166
|
-
|
|
167
|
-
assert config["type"] == "kysely"
|
|
168
|
-
assert "kyselyAdapter" in config["import"]
|
|
169
|
-
|
|
170
|
-
def test_prompt_mongodb(self, auth_init):
|
|
171
|
-
"""Test prompting for MongoDB."""
|
|
172
|
-
with patch("builtins.input", side_effect=["mongodb://localhost/test", "mydb"]):
|
|
173
|
-
config = auth_init._prompt_mongodb()
|
|
174
|
-
|
|
175
|
-
assert config["type"] == "mongodb"
|
|
176
|
-
assert "mongodbAdapter" in config["import"]
|
|
177
|
-
assert "mydb" in config["config"]
|
|
178
|
-
assert config["env_var"] == ("MONGODB_URI", "mongodb://localhost/test")
|
|
179
|
-
|
|
180
|
-
def test_prompt_database(self, auth_init):
|
|
181
|
-
"""Test database prompting with different choices."""
|
|
182
|
-
# Test valid choice
|
|
183
|
-
with patch("builtins.input", side_effect=["3", "1"]):
|
|
184
|
-
config = auth_init.prompt_database()
|
|
185
|
-
assert config["type"] == "prisma"
|
|
186
|
-
|
|
187
|
-
# Test invalid choice (defaults to direct DB)
|
|
188
|
-
with patch("builtins.input", side_effect=["99", "1", "postgresql://localhost/test"]):
|
|
189
|
-
with patch("builtins.print"):
|
|
190
|
-
config = auth_init.prompt_database()
|
|
191
|
-
assert config["type"] == "postgresql"
|
|
192
|
-
|
|
193
|
-
def test_prompt_auth_methods(self, auth_init):
|
|
194
|
-
"""Test prompting for authentication methods."""
|
|
195
|
-
with patch("builtins.input", return_value="1 2 3 5 8"):
|
|
196
|
-
with patch("builtins.print"):
|
|
197
|
-
methods = auth_init.prompt_auth_methods()
|
|
198
|
-
|
|
199
|
-
assert methods == ["1", "2", "3", "5", "8"]
|
|
200
|
-
|
|
201
|
-
def test_prompt_auth_methods_invalid(self, auth_init):
|
|
202
|
-
"""Test filtering invalid auth method choices."""
|
|
203
|
-
with patch("builtins.input", return_value="1 99 abc 3"):
|
|
204
|
-
with patch("builtins.print"):
|
|
205
|
-
methods = auth_init.prompt_auth_methods()
|
|
206
|
-
|
|
207
|
-
assert methods == ["1", "3"]
|
|
208
|
-
|
|
209
|
-
def test_generate_auth_config_basic(self, auth_init):
|
|
210
|
-
"""Test generating basic auth config."""
|
|
211
|
-
db_config = {
|
|
212
|
-
"import": "import Database from 'better-sqlite3';",
|
|
213
|
-
"config": "database: new Database('./dev.db')"
|
|
214
|
-
}
|
|
215
|
-
auth_methods = ["1"] # Email/password only
|
|
216
|
-
|
|
217
|
-
config = auth_init.generate_auth_config(db_config, auth_methods)
|
|
218
|
-
|
|
219
|
-
assert "import { betterAuth }" in config
|
|
220
|
-
assert "emailAndPassword" in config
|
|
221
|
-
assert "enabled: true" in config
|
|
222
|
-
assert "better-sqlite3" in config
|
|
223
|
-
|
|
224
|
-
def test_generate_auth_config_with_oauth(self, auth_init):
|
|
225
|
-
"""Test generating config with OAuth providers."""
|
|
226
|
-
db_config = {
|
|
227
|
-
"import": "import { Pool } from 'pg';",
|
|
228
|
-
"config": "database: new Pool()"
|
|
229
|
-
}
|
|
230
|
-
auth_methods = ["1", "2", "3", "4"] # Email + GitHub + Google + Discord
|
|
231
|
-
|
|
232
|
-
config = auth_init.generate_auth_config(db_config, auth_methods)
|
|
233
|
-
|
|
234
|
-
assert "socialProviders" in config
|
|
235
|
-
assert "github:" in config
|
|
236
|
-
assert "google:" in config
|
|
237
|
-
assert "discord:" in config
|
|
238
|
-
assert "GITHUB_CLIENT_ID" in config
|
|
239
|
-
assert "GOOGLE_CLIENT_ID" in config
|
|
240
|
-
assert "DISCORD_CLIENT_ID" in config
|
|
241
|
-
|
|
242
|
-
def test_generate_auth_config_with_plugins(self, auth_init):
|
|
243
|
-
"""Test generating config with plugins."""
|
|
244
|
-
db_config = {"import": "", "config": "database: db"}
|
|
245
|
-
auth_methods = ["5", "6", "7", "8"] # 2FA, Passkey, Magic Link, Username
|
|
246
|
-
|
|
247
|
-
config = auth_init.generate_auth_config(db_config, auth_methods)
|
|
248
|
-
|
|
249
|
-
assert "plugins:" in config
|
|
250
|
-
assert "twoFactor" in config
|
|
251
|
-
assert "passkey" in config
|
|
252
|
-
assert "magicLink" in config
|
|
253
|
-
assert "username" in config
|
|
254
|
-
assert "from 'better-auth/plugins'" in config
|
|
255
|
-
|
|
256
|
-
def test_generate_env_file_basic(self, auth_init):
|
|
257
|
-
"""Test generating basic .env file."""
|
|
258
|
-
db_config = {"type": "sqlite"}
|
|
259
|
-
auth_methods = ["1"]
|
|
260
|
-
|
|
261
|
-
env_content = auth_init.generate_env_file(db_config, auth_methods)
|
|
262
|
-
|
|
263
|
-
assert "BETTER_AUTH_SECRET=" in env_content
|
|
264
|
-
assert "BETTER_AUTH_URL=http://localhost:3000" in env_content
|
|
265
|
-
assert len(env_content.split("\n")) >= 2
|
|
266
|
-
|
|
267
|
-
def test_generate_env_file_with_database_url(self, auth_init):
|
|
268
|
-
"""Test generating .env with database URL."""
|
|
269
|
-
db_config = {
|
|
270
|
-
"env_var": ("DATABASE_URL", "postgresql://localhost/test")
|
|
271
|
-
}
|
|
272
|
-
auth_methods = []
|
|
273
|
-
|
|
274
|
-
env_content = auth_init.generate_env_file(db_config, auth_methods)
|
|
275
|
-
|
|
276
|
-
assert "DATABASE_URL=postgresql://localhost/test" in env_content
|
|
277
|
-
|
|
278
|
-
def test_generate_env_file_with_oauth(self, auth_init):
|
|
279
|
-
"""Test generating .env with OAuth credentials."""
|
|
280
|
-
db_config = {}
|
|
281
|
-
auth_methods = ["2", "3", "4"] # GitHub, Google, Discord
|
|
282
|
-
|
|
283
|
-
env_content = auth_init.generate_env_file(db_config, auth_methods)
|
|
284
|
-
|
|
285
|
-
assert "GITHUB_CLIENT_ID=" in env_content
|
|
286
|
-
assert "GITHUB_CLIENT_SECRET=" in env_content
|
|
287
|
-
assert "GOOGLE_CLIENT_ID=" in env_content
|
|
288
|
-
assert "GOOGLE_CLIENT_SECRET=" in env_content
|
|
289
|
-
assert "DISCORD_CLIENT_ID=" in env_content
|
|
290
|
-
assert "DISCORD_CLIENT_SECRET=" in env_content
|
|
291
|
-
|
|
292
|
-
def test_save_files(self, auth_init, mock_project_root):
|
|
293
|
-
"""Test saving configuration files."""
|
|
294
|
-
auth_config = "// auth config"
|
|
295
|
-
env_content = "SECRET=test"
|
|
296
|
-
|
|
297
|
-
with patch("builtins.input", side_effect=["1"]):
|
|
298
|
-
auth_init._save_files(auth_config, env_content)
|
|
299
|
-
|
|
300
|
-
# Check auth.ts was saved
|
|
301
|
-
auth_path = mock_project_root / "lib" / "auth.ts"
|
|
302
|
-
assert auth_path.exists()
|
|
303
|
-
assert auth_path.read_text() == auth_config
|
|
304
|
-
|
|
305
|
-
# Check .env was saved
|
|
306
|
-
env_path = mock_project_root / ".env"
|
|
307
|
-
assert env_path.exists()
|
|
308
|
-
assert env_path.read_text() == env_content
|
|
309
|
-
|
|
310
|
-
def test_save_files_custom_path(self, auth_init, mock_project_root):
|
|
311
|
-
"""Test saving with custom path."""
|
|
312
|
-
auth_config = "// config"
|
|
313
|
-
env_content = "SECRET=test"
|
|
314
|
-
|
|
315
|
-
custom_path = str(mock_project_root / "custom" / "auth.ts")
|
|
316
|
-
with patch("builtins.input", side_effect=["5", custom_path]):
|
|
317
|
-
auth_init._save_files(auth_config, env_content)
|
|
318
|
-
|
|
319
|
-
assert Path(custom_path).exists()
|
|
320
|
-
|
|
321
|
-
def test_save_files_backup_existing_env(self, auth_init, mock_project_root):
|
|
322
|
-
"""Test backing up existing .env file."""
|
|
323
|
-
# Create existing .env
|
|
324
|
-
env_path = mock_project_root / ".env"
|
|
325
|
-
env_path.write_text("OLD_SECRET=old")
|
|
326
|
-
|
|
327
|
-
auth_config = "// config"
|
|
328
|
-
env_content = "NEW_SECRET=new"
|
|
329
|
-
|
|
330
|
-
with patch("builtins.input", return_value="1"):
|
|
331
|
-
auth_init._save_files(auth_config, env_content)
|
|
332
|
-
|
|
333
|
-
# Check backup was created
|
|
334
|
-
backup_path = mock_project_root / ".env.backup"
|
|
335
|
-
assert backup_path.exists()
|
|
336
|
-
assert backup_path.read_text() == "OLD_SECRET=old"
|
|
337
|
-
|
|
338
|
-
# Check new .env
|
|
339
|
-
assert env_path.read_text() == "NEW_SECRET=new"
|
|
340
|
-
|
|
341
|
-
def test_run_full_flow(self, auth_init, mock_project_root):
|
|
342
|
-
"""Test complete run flow."""
|
|
343
|
-
inputs = [
|
|
344
|
-
"1", # Direct DB
|
|
345
|
-
"1", # PostgreSQL
|
|
346
|
-
"postgresql://localhost/test",
|
|
347
|
-
"1 2", # Email + GitHub
|
|
348
|
-
"n" # Don't save
|
|
349
|
-
]
|
|
350
|
-
|
|
351
|
-
with patch("builtins.input", side_effect=inputs):
|
|
352
|
-
with patch("builtins.print"):
|
|
353
|
-
auth_init.run()
|
|
354
|
-
|
|
355
|
-
# Should complete without errors
|
|
356
|
-
# Files not saved because user chose 'n'
|
|
357
|
-
assert not (mock_project_root / "auth.ts").exists()
|
|
358
|
-
|
|
359
|
-
def test_run_save_files(self, auth_init, mock_project_root):
|
|
360
|
-
"""Test run flow with file saving."""
|
|
361
|
-
inputs = [
|
|
362
|
-
"1", # Direct DB
|
|
363
|
-
"3", # SQLite
|
|
364
|
-
"", # Default path
|
|
365
|
-
"1", # Email only
|
|
366
|
-
"y", # Save
|
|
367
|
-
"1" # Save location
|
|
368
|
-
]
|
|
369
|
-
|
|
370
|
-
with patch("builtins.input", side_effect=inputs):
|
|
371
|
-
with patch("builtins.print"):
|
|
372
|
-
auth_init.run()
|
|
373
|
-
|
|
374
|
-
# Check files were created
|
|
375
|
-
assert (mock_project_root / "lib" / "auth.ts").exists()
|
|
376
|
-
assert (mock_project_root / ".env").exists()
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
class TestMainFunction:
|
|
380
|
-
"""Test main entry point."""
|
|
381
|
-
|
|
382
|
-
def test_main_success(self, tmp_path, monkeypatch):
|
|
383
|
-
"""Test successful main execution."""
|
|
384
|
-
(tmp_path / "package.json").write_text("{}")
|
|
385
|
-
monkeypatch.chdir(tmp_path)
|
|
386
|
-
|
|
387
|
-
inputs = ["1", "3", "", "1", "n"]
|
|
388
|
-
|
|
389
|
-
with patch("builtins.input", side_effect=inputs):
|
|
390
|
-
with patch("builtins.print"):
|
|
391
|
-
exit_code = main()
|
|
392
|
-
|
|
393
|
-
assert exit_code == 0
|
|
394
|
-
|
|
395
|
-
def test_main_keyboard_interrupt(self, tmp_path, monkeypatch):
|
|
396
|
-
"""Test main with keyboard interrupt."""
|
|
397
|
-
(tmp_path / "package.json").write_text("{}")
|
|
398
|
-
monkeypatch.chdir(tmp_path)
|
|
399
|
-
|
|
400
|
-
with patch("builtins.input", side_effect=KeyboardInterrupt()):
|
|
401
|
-
with patch("builtins.print"):
|
|
402
|
-
exit_code = main()
|
|
403
|
-
|
|
404
|
-
assert exit_code == 1
|
|
405
|
-
|
|
406
|
-
def test_main_error(self, tmp_path, monkeypatch):
|
|
407
|
-
"""Test main with error."""
|
|
408
|
-
# No package.json - should fail
|
|
409
|
-
no_package = tmp_path / "no-package"
|
|
410
|
-
no_package.mkdir()
|
|
411
|
-
monkeypatch.chdir(no_package)
|
|
412
|
-
|
|
413
|
-
with patch.object(Path, "parent", new_callable=lambda: property(lambda self: self)):
|
|
414
|
-
with patch("sys.stderr", new_callable=StringIO):
|
|
415
|
-
exit_code = main()
|
|
416
|
-
|
|
417
|
-
assert exit_code == 1
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
if __name__ == "__main__":
|
|
421
|
-
pytest.main([__file__, "-v", "--cov=better_auth_init", "--cov-report=term-missing"])
|
|
1
|
+
"""
|
|
2
|
+
Tests for better_auth_init.py
|
|
3
|
+
|
|
4
|
+
Covers main functionality with mocked I/O and file operations.
|
|
5
|
+
Target: >80% coverage
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import sys
|
|
9
|
+
import pytest
|
|
10
|
+
from pathlib import Path
|
|
11
|
+
from unittest.mock import Mock, patch, mock_open, MagicMock
|
|
12
|
+
from io import StringIO
|
|
13
|
+
|
|
14
|
+
# Add parent directory to path
|
|
15
|
+
sys.path.insert(0, str(Path(__file__).parent.parent))
|
|
16
|
+
|
|
17
|
+
from better_auth_init import BetterAuthInit, EnvConfig, main
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
@pytest.fixture
|
|
21
|
+
def mock_project_root(tmp_path):
|
|
22
|
+
"""Create mock project root with package.json."""
|
|
23
|
+
(tmp_path / "package.json").write_text("{}")
|
|
24
|
+
return tmp_path
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
@pytest.fixture
|
|
28
|
+
def auth_init(mock_project_root):
|
|
29
|
+
"""Create BetterAuthInit instance with mock project root."""
|
|
30
|
+
return BetterAuthInit(project_root=mock_project_root)
|
|
31
|
+
|
|
32
|
+
|
|
33
|
+
class TestBetterAuthInit:
|
|
34
|
+
"""Test BetterAuthInit class."""
|
|
35
|
+
|
|
36
|
+
def test_init_with_project_root(self, mock_project_root):
|
|
37
|
+
"""Test initialization with explicit project root."""
|
|
38
|
+
init = BetterAuthInit(project_root=mock_project_root)
|
|
39
|
+
assert init.project_root == mock_project_root
|
|
40
|
+
assert init.env_config is None
|
|
41
|
+
|
|
42
|
+
def test_find_project_root_success(self, mock_project_root, monkeypatch):
|
|
43
|
+
"""Test finding project root successfully."""
|
|
44
|
+
monkeypatch.chdir(mock_project_root)
|
|
45
|
+
init = BetterAuthInit()
|
|
46
|
+
assert init.project_root == mock_project_root
|
|
47
|
+
|
|
48
|
+
def test_find_project_root_failure(self, tmp_path, monkeypatch):
|
|
49
|
+
"""Test failure to find project root."""
|
|
50
|
+
# Create path without package.json
|
|
51
|
+
no_package_dir = tmp_path / "no-package"
|
|
52
|
+
no_package_dir.mkdir()
|
|
53
|
+
monkeypatch.chdir(no_package_dir)
|
|
54
|
+
|
|
55
|
+
# Mock parent to stop infinite loop
|
|
56
|
+
with patch.object(Path, "parent", new_callable=lambda: property(lambda self: self)):
|
|
57
|
+
with pytest.raises(RuntimeError, match="Could not find project root"):
|
|
58
|
+
BetterAuthInit()
|
|
59
|
+
|
|
60
|
+
def test_generate_secret(self):
|
|
61
|
+
"""Test secret generation."""
|
|
62
|
+
secret = BetterAuthInit.generate_secret()
|
|
63
|
+
assert len(secret) == 64 # 32 bytes = 64 hex chars
|
|
64
|
+
assert all(c in "0123456789abcdef" for c in secret)
|
|
65
|
+
|
|
66
|
+
# Test custom length
|
|
67
|
+
secret = BetterAuthInit.generate_secret(length=16)
|
|
68
|
+
assert len(secret) == 32 # 16 bytes = 32 hex chars
|
|
69
|
+
|
|
70
|
+
def test_parse_env_file(self, tmp_path):
|
|
71
|
+
"""Test parsing .env file."""
|
|
72
|
+
env_content = """
|
|
73
|
+
# Comment
|
|
74
|
+
KEY1=value1
|
|
75
|
+
KEY2="value2"
|
|
76
|
+
KEY3='value3'
|
|
77
|
+
INVALID LINE
|
|
78
|
+
KEY4=value=with=equals
|
|
79
|
+
"""
|
|
80
|
+
env_file = tmp_path / ".env"
|
|
81
|
+
env_file.write_text(env_content)
|
|
82
|
+
|
|
83
|
+
result = BetterAuthInit._parse_env_file(env_file)
|
|
84
|
+
|
|
85
|
+
assert result["KEY1"] == "value1"
|
|
86
|
+
assert result["KEY2"] == "value2"
|
|
87
|
+
assert result["KEY3"] == "value3"
|
|
88
|
+
assert result["KEY4"] == "value=with=equals"
|
|
89
|
+
assert "INVALID" not in result
|
|
90
|
+
|
|
91
|
+
def test_parse_env_file_missing(self, tmp_path):
|
|
92
|
+
"""Test parsing missing .env file."""
|
|
93
|
+
result = BetterAuthInit._parse_env_file(tmp_path / "nonexistent.env")
|
|
94
|
+
assert result == {}
|
|
95
|
+
|
|
96
|
+
def test_load_env_files(self, auth_init, mock_project_root):
|
|
97
|
+
"""Test loading environment variables from multiple files."""
|
|
98
|
+
# Create .env files
|
|
99
|
+
claude_env = mock_project_root / ".claude" / ".env"
|
|
100
|
+
claude_env.parent.mkdir(parents=True, exist_ok=True)
|
|
101
|
+
claude_env.write_text("BASE_VAR=base\nOVERRIDE=claude")
|
|
102
|
+
|
|
103
|
+
skills_env = mock_project_root / ".claude" / "skills" / ".env"
|
|
104
|
+
skills_env.parent.mkdir(parents=True, exist_ok=True)
|
|
105
|
+
skills_env.write_text("OVERRIDE=skills\nSKILLS_VAR=skills")
|
|
106
|
+
|
|
107
|
+
# Mock process env (highest priority)
|
|
108
|
+
with patch.dict("os.environ", {"OVERRIDE": "process", "PROCESS_VAR": "process"}):
|
|
109
|
+
result = auth_init._load_env_files()
|
|
110
|
+
|
|
111
|
+
assert result["BASE_VAR"] == "base"
|
|
112
|
+
assert result["SKILLS_VAR"] == "skills"
|
|
113
|
+
assert result["OVERRIDE"] == "process" # Process env wins
|
|
114
|
+
assert result["PROCESS_VAR"] == "process"
|
|
115
|
+
|
|
116
|
+
def test_prompt_direct_db_sqlite(self, auth_init):
|
|
117
|
+
"""Test prompting for SQLite database."""
|
|
118
|
+
with patch("builtins.input", side_effect=["3", "./test.db"]):
|
|
119
|
+
config = auth_init._prompt_direct_db()
|
|
120
|
+
|
|
121
|
+
assert config["type"] == "sqlite"
|
|
122
|
+
assert "better-sqlite3" in config["import"]
|
|
123
|
+
assert "./test.db" in config["config"]
|
|
124
|
+
|
|
125
|
+
def test_prompt_direct_db_postgresql(self, auth_init):
|
|
126
|
+
"""Test prompting for PostgreSQL database."""
|
|
127
|
+
with patch("builtins.input", side_effect=["1", "postgresql://localhost/test"]):
|
|
128
|
+
config = auth_init._prompt_direct_db()
|
|
129
|
+
|
|
130
|
+
assert config["type"] == "postgresql"
|
|
131
|
+
assert "pg" in config["import"]
|
|
132
|
+
assert config["env_var"] == ("DATABASE_URL", "postgresql://localhost/test")
|
|
133
|
+
|
|
134
|
+
def test_prompt_direct_db_mysql(self, auth_init):
|
|
135
|
+
"""Test prompting for MySQL database."""
|
|
136
|
+
with patch("builtins.input", side_effect=["2", "mysql://localhost/test"]):
|
|
137
|
+
config = auth_init._prompt_direct_db()
|
|
138
|
+
|
|
139
|
+
assert config["type"] == "mysql"
|
|
140
|
+
assert "mysql2" in config["import"]
|
|
141
|
+
assert config["env_var"][0] == "DATABASE_URL"
|
|
142
|
+
|
|
143
|
+
def test_prompt_drizzle(self, auth_init):
|
|
144
|
+
"""Test prompting for Drizzle ORM."""
|
|
145
|
+
with patch("builtins.input", return_value="1"):
|
|
146
|
+
config = auth_init._prompt_drizzle()
|
|
147
|
+
|
|
148
|
+
assert config["type"] == "drizzle"
|
|
149
|
+
assert config["provider"] == "pg"
|
|
150
|
+
assert "drizzleAdapter" in config["import"]
|
|
151
|
+
assert "drizzleAdapter" in config["config"]
|
|
152
|
+
|
|
153
|
+
def test_prompt_prisma(self, auth_init):
|
|
154
|
+
"""Test prompting for Prisma."""
|
|
155
|
+
with patch("builtins.input", return_value="2"):
|
|
156
|
+
config = auth_init._prompt_prisma()
|
|
157
|
+
|
|
158
|
+
assert config["type"] == "prisma"
|
|
159
|
+
assert config["provider"] == "mysql"
|
|
160
|
+
assert "prismaAdapter" in config["import"]
|
|
161
|
+
assert "PrismaClient" in config["import"]
|
|
162
|
+
|
|
163
|
+
def test_prompt_kysely(self, auth_init):
|
|
164
|
+
"""Test prompting for Kysely."""
|
|
165
|
+
config = auth_init._prompt_kysely()
|
|
166
|
+
|
|
167
|
+
assert config["type"] == "kysely"
|
|
168
|
+
assert "kyselyAdapter" in config["import"]
|
|
169
|
+
|
|
170
|
+
def test_prompt_mongodb(self, auth_init):
|
|
171
|
+
"""Test prompting for MongoDB."""
|
|
172
|
+
with patch("builtins.input", side_effect=["mongodb://localhost/test", "mydb"]):
|
|
173
|
+
config = auth_init._prompt_mongodb()
|
|
174
|
+
|
|
175
|
+
assert config["type"] == "mongodb"
|
|
176
|
+
assert "mongodbAdapter" in config["import"]
|
|
177
|
+
assert "mydb" in config["config"]
|
|
178
|
+
assert config["env_var"] == ("MONGODB_URI", "mongodb://localhost/test")
|
|
179
|
+
|
|
180
|
+
def test_prompt_database(self, auth_init):
|
|
181
|
+
"""Test database prompting with different choices."""
|
|
182
|
+
# Test valid choice
|
|
183
|
+
with patch("builtins.input", side_effect=["3", "1"]):
|
|
184
|
+
config = auth_init.prompt_database()
|
|
185
|
+
assert config["type"] == "prisma"
|
|
186
|
+
|
|
187
|
+
# Test invalid choice (defaults to direct DB)
|
|
188
|
+
with patch("builtins.input", side_effect=["99", "1", "postgresql://localhost/test"]):
|
|
189
|
+
with patch("builtins.print"):
|
|
190
|
+
config = auth_init.prompt_database()
|
|
191
|
+
assert config["type"] == "postgresql"
|
|
192
|
+
|
|
193
|
+
def test_prompt_auth_methods(self, auth_init):
|
|
194
|
+
"""Test prompting for authentication methods."""
|
|
195
|
+
with patch("builtins.input", return_value="1 2 3 5 8"):
|
|
196
|
+
with patch("builtins.print"):
|
|
197
|
+
methods = auth_init.prompt_auth_methods()
|
|
198
|
+
|
|
199
|
+
assert methods == ["1", "2", "3", "5", "8"]
|
|
200
|
+
|
|
201
|
+
def test_prompt_auth_methods_invalid(self, auth_init):
|
|
202
|
+
"""Test filtering invalid auth method choices."""
|
|
203
|
+
with patch("builtins.input", return_value="1 99 abc 3"):
|
|
204
|
+
with patch("builtins.print"):
|
|
205
|
+
methods = auth_init.prompt_auth_methods()
|
|
206
|
+
|
|
207
|
+
assert methods == ["1", "3"]
|
|
208
|
+
|
|
209
|
+
def test_generate_auth_config_basic(self, auth_init):
|
|
210
|
+
"""Test generating basic auth config."""
|
|
211
|
+
db_config = {
|
|
212
|
+
"import": "import Database from 'better-sqlite3';",
|
|
213
|
+
"config": "database: new Database('./dev.db')"
|
|
214
|
+
}
|
|
215
|
+
auth_methods = ["1"] # Email/password only
|
|
216
|
+
|
|
217
|
+
config = auth_init.generate_auth_config(db_config, auth_methods)
|
|
218
|
+
|
|
219
|
+
assert "import { betterAuth }" in config
|
|
220
|
+
assert "emailAndPassword" in config
|
|
221
|
+
assert "enabled: true" in config
|
|
222
|
+
assert "better-sqlite3" in config
|
|
223
|
+
|
|
224
|
+
def test_generate_auth_config_with_oauth(self, auth_init):
|
|
225
|
+
"""Test generating config with OAuth providers."""
|
|
226
|
+
db_config = {
|
|
227
|
+
"import": "import { Pool } from 'pg';",
|
|
228
|
+
"config": "database: new Pool()"
|
|
229
|
+
}
|
|
230
|
+
auth_methods = ["1", "2", "3", "4"] # Email + GitHub + Google + Discord
|
|
231
|
+
|
|
232
|
+
config = auth_init.generate_auth_config(db_config, auth_methods)
|
|
233
|
+
|
|
234
|
+
assert "socialProviders" in config
|
|
235
|
+
assert "github:" in config
|
|
236
|
+
assert "google:" in config
|
|
237
|
+
assert "discord:" in config
|
|
238
|
+
assert "GITHUB_CLIENT_ID" in config
|
|
239
|
+
assert "GOOGLE_CLIENT_ID" in config
|
|
240
|
+
assert "DISCORD_CLIENT_ID" in config
|
|
241
|
+
|
|
242
|
+
def test_generate_auth_config_with_plugins(self, auth_init):
|
|
243
|
+
"""Test generating config with plugins."""
|
|
244
|
+
db_config = {"import": "", "config": "database: db"}
|
|
245
|
+
auth_methods = ["5", "6", "7", "8"] # 2FA, Passkey, Magic Link, Username
|
|
246
|
+
|
|
247
|
+
config = auth_init.generate_auth_config(db_config, auth_methods)
|
|
248
|
+
|
|
249
|
+
assert "plugins:" in config
|
|
250
|
+
assert "twoFactor" in config
|
|
251
|
+
assert "passkey" in config
|
|
252
|
+
assert "magicLink" in config
|
|
253
|
+
assert "username" in config
|
|
254
|
+
assert "from 'better-auth/plugins'" in config
|
|
255
|
+
|
|
256
|
+
def test_generate_env_file_basic(self, auth_init):
|
|
257
|
+
"""Test generating basic .env file."""
|
|
258
|
+
db_config = {"type": "sqlite"}
|
|
259
|
+
auth_methods = ["1"]
|
|
260
|
+
|
|
261
|
+
env_content = auth_init.generate_env_file(db_config, auth_methods)
|
|
262
|
+
|
|
263
|
+
assert "BETTER_AUTH_SECRET=" in env_content
|
|
264
|
+
assert "BETTER_AUTH_URL=http://localhost:3000" in env_content
|
|
265
|
+
assert len(env_content.split("\n")) >= 2
|
|
266
|
+
|
|
267
|
+
def test_generate_env_file_with_database_url(self, auth_init):
|
|
268
|
+
"""Test generating .env with database URL."""
|
|
269
|
+
db_config = {
|
|
270
|
+
"env_var": ("DATABASE_URL", "postgresql://localhost/test")
|
|
271
|
+
}
|
|
272
|
+
auth_methods = []
|
|
273
|
+
|
|
274
|
+
env_content = auth_init.generate_env_file(db_config, auth_methods)
|
|
275
|
+
|
|
276
|
+
assert "DATABASE_URL=postgresql://localhost/test" in env_content
|
|
277
|
+
|
|
278
|
+
def test_generate_env_file_with_oauth(self, auth_init):
|
|
279
|
+
"""Test generating .env with OAuth credentials."""
|
|
280
|
+
db_config = {}
|
|
281
|
+
auth_methods = ["2", "3", "4"] # GitHub, Google, Discord
|
|
282
|
+
|
|
283
|
+
env_content = auth_init.generate_env_file(db_config, auth_methods)
|
|
284
|
+
|
|
285
|
+
assert "GITHUB_CLIENT_ID=" in env_content
|
|
286
|
+
assert "GITHUB_CLIENT_SECRET=" in env_content
|
|
287
|
+
assert "GOOGLE_CLIENT_ID=" in env_content
|
|
288
|
+
assert "GOOGLE_CLIENT_SECRET=" in env_content
|
|
289
|
+
assert "DISCORD_CLIENT_ID=" in env_content
|
|
290
|
+
assert "DISCORD_CLIENT_SECRET=" in env_content
|
|
291
|
+
|
|
292
|
+
def test_save_files(self, auth_init, mock_project_root):
|
|
293
|
+
"""Test saving configuration files."""
|
|
294
|
+
auth_config = "// auth config"
|
|
295
|
+
env_content = "SECRET=test"
|
|
296
|
+
|
|
297
|
+
with patch("builtins.input", side_effect=["1"]):
|
|
298
|
+
auth_init._save_files(auth_config, env_content)
|
|
299
|
+
|
|
300
|
+
# Check auth.ts was saved
|
|
301
|
+
auth_path = mock_project_root / "lib" / "auth.ts"
|
|
302
|
+
assert auth_path.exists()
|
|
303
|
+
assert auth_path.read_text() == auth_config
|
|
304
|
+
|
|
305
|
+
# Check .env was saved
|
|
306
|
+
env_path = mock_project_root / ".env"
|
|
307
|
+
assert env_path.exists()
|
|
308
|
+
assert env_path.read_text() == env_content
|
|
309
|
+
|
|
310
|
+
def test_save_files_custom_path(self, auth_init, mock_project_root):
|
|
311
|
+
"""Test saving with custom path."""
|
|
312
|
+
auth_config = "// config"
|
|
313
|
+
env_content = "SECRET=test"
|
|
314
|
+
|
|
315
|
+
custom_path = str(mock_project_root / "custom" / "auth.ts")
|
|
316
|
+
with patch("builtins.input", side_effect=["5", custom_path]):
|
|
317
|
+
auth_init._save_files(auth_config, env_content)
|
|
318
|
+
|
|
319
|
+
assert Path(custom_path).exists()
|
|
320
|
+
|
|
321
|
+
def test_save_files_backup_existing_env(self, auth_init, mock_project_root):
|
|
322
|
+
"""Test backing up existing .env file."""
|
|
323
|
+
# Create existing .env
|
|
324
|
+
env_path = mock_project_root / ".env"
|
|
325
|
+
env_path.write_text("OLD_SECRET=old")
|
|
326
|
+
|
|
327
|
+
auth_config = "// config"
|
|
328
|
+
env_content = "NEW_SECRET=new"
|
|
329
|
+
|
|
330
|
+
with patch("builtins.input", return_value="1"):
|
|
331
|
+
auth_init._save_files(auth_config, env_content)
|
|
332
|
+
|
|
333
|
+
# Check backup was created
|
|
334
|
+
backup_path = mock_project_root / ".env.backup"
|
|
335
|
+
assert backup_path.exists()
|
|
336
|
+
assert backup_path.read_text() == "OLD_SECRET=old"
|
|
337
|
+
|
|
338
|
+
# Check new .env
|
|
339
|
+
assert env_path.read_text() == "NEW_SECRET=new"
|
|
340
|
+
|
|
341
|
+
def test_run_full_flow(self, auth_init, mock_project_root):
|
|
342
|
+
"""Test complete run flow."""
|
|
343
|
+
inputs = [
|
|
344
|
+
"1", # Direct DB
|
|
345
|
+
"1", # PostgreSQL
|
|
346
|
+
"postgresql://localhost/test",
|
|
347
|
+
"1 2", # Email + GitHub
|
|
348
|
+
"n" # Don't save
|
|
349
|
+
]
|
|
350
|
+
|
|
351
|
+
with patch("builtins.input", side_effect=inputs):
|
|
352
|
+
with patch("builtins.print"):
|
|
353
|
+
auth_init.run()
|
|
354
|
+
|
|
355
|
+
# Should complete without errors
|
|
356
|
+
# Files not saved because user chose 'n'
|
|
357
|
+
assert not (mock_project_root / "auth.ts").exists()
|
|
358
|
+
|
|
359
|
+
def test_run_save_files(self, auth_init, mock_project_root):
|
|
360
|
+
"""Test run flow with file saving."""
|
|
361
|
+
inputs = [
|
|
362
|
+
"1", # Direct DB
|
|
363
|
+
"3", # SQLite
|
|
364
|
+
"", # Default path
|
|
365
|
+
"1", # Email only
|
|
366
|
+
"y", # Save
|
|
367
|
+
"1" # Save location
|
|
368
|
+
]
|
|
369
|
+
|
|
370
|
+
with patch("builtins.input", side_effect=inputs):
|
|
371
|
+
with patch("builtins.print"):
|
|
372
|
+
auth_init.run()
|
|
373
|
+
|
|
374
|
+
# Check files were created
|
|
375
|
+
assert (mock_project_root / "lib" / "auth.ts").exists()
|
|
376
|
+
assert (mock_project_root / ".env").exists()
|
|
377
|
+
|
|
378
|
+
|
|
379
|
+
class TestMainFunction:
|
|
380
|
+
"""Test main entry point."""
|
|
381
|
+
|
|
382
|
+
def test_main_success(self, tmp_path, monkeypatch):
|
|
383
|
+
"""Test successful main execution."""
|
|
384
|
+
(tmp_path / "package.json").write_text("{}")
|
|
385
|
+
monkeypatch.chdir(tmp_path)
|
|
386
|
+
|
|
387
|
+
inputs = ["1", "3", "", "1", "n"]
|
|
388
|
+
|
|
389
|
+
with patch("builtins.input", side_effect=inputs):
|
|
390
|
+
with patch("builtins.print"):
|
|
391
|
+
exit_code = main()
|
|
392
|
+
|
|
393
|
+
assert exit_code == 0
|
|
394
|
+
|
|
395
|
+
def test_main_keyboard_interrupt(self, tmp_path, monkeypatch):
|
|
396
|
+
"""Test main with keyboard interrupt."""
|
|
397
|
+
(tmp_path / "package.json").write_text("{}")
|
|
398
|
+
monkeypatch.chdir(tmp_path)
|
|
399
|
+
|
|
400
|
+
with patch("builtins.input", side_effect=KeyboardInterrupt()):
|
|
401
|
+
with patch("builtins.print"):
|
|
402
|
+
exit_code = main()
|
|
403
|
+
|
|
404
|
+
assert exit_code == 1
|
|
405
|
+
|
|
406
|
+
def test_main_error(self, tmp_path, monkeypatch):
|
|
407
|
+
"""Test main with error."""
|
|
408
|
+
# No package.json - should fail
|
|
409
|
+
no_package = tmp_path / "no-package"
|
|
410
|
+
no_package.mkdir()
|
|
411
|
+
monkeypatch.chdir(no_package)
|
|
412
|
+
|
|
413
|
+
with patch.object(Path, "parent", new_callable=lambda: property(lambda self: self)):
|
|
414
|
+
with patch("sys.stderr", new_callable=StringIO):
|
|
415
|
+
exit_code = main()
|
|
416
|
+
|
|
417
|
+
assert exit_code == 1
|
|
418
|
+
|
|
419
|
+
|
|
420
|
+
if __name__ == "__main__":
|
|
421
|
+
pytest.main([__file__, "-v", "--cov=better_auth_init", "--cov-report=term-missing"])
|