@omega.js/manager 0.1.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/.claude-plugin/marketplace.json +14 -0
- package/LICENSE +98 -0
- package/README.md +165 -0
- package/bin/omega +2 -0
- package/bin/omg +2 -0
- package/claude-plugin/.claude-plugin/plugin.json +11 -0
- package/claude-plugin/.mcp.json +9 -0
- package/claude-plugin/README.md +139 -0
- package/claude-plugin/hooks/gate/mark.sh +58 -0
- package/claude-plugin/hooks/gate/run.sh +97 -0
- package/claude-plugin/hooks/guard/run.sh +249 -0
- package/claude-plugin/hooks/hooks.json +63 -0
- package/claude-plugin/hooks/inject/run.sh +127 -0
- package/claude-plugin/hooks/lib/omega-gate.sh +20 -0
- package/claude-plugin/hooks/lib/omega-scope.sh +41 -0
- package/claude-plugin/hooks/lib/omega-skills.sh +209 -0
- package/claude-plugin/hooks/quality/run.sh +132 -0
- package/claude-plugin/hooks/shape/run.sh +45 -0
- package/claude-plugin/mcp-router-launch.js +29 -0
- package/claude-plugin/skills/README.md +48 -0
- package/claude-plugin/skills/accessibility/SKILL.md +31 -0
- package/claude-plugin/skills/analytics/SKILL.md +30 -0
- package/claude-plugin/skills/backend/SKILL.md +25 -0
- package/claude-plugin/skills/brandcheck/SKILL.md +29 -0
- package/claude-plugin/skills/browser/SKILL.md +64 -0
- package/claude-plugin/skills/client/SKILL.md +24 -0
- package/claude-plugin/skills/desktop/SKILL.md +25 -0
- package/claude-plugin/skills/extension/SKILL.md +25 -0
- package/claude-plugin/skills/main/SKILL.md +54 -0
- package/claude-plugin/skills/manager/SKILL.md +25 -0
- package/claude-plugin/skills/seo/SKILL.md +36 -0
- package/claude-plugin/skills/theme/SKILL.md +33 -0
- package/claude-plugin/skills/web/SKILL.md +29 -0
- package/dist/cli-run.js +34 -0
- package/dist/cli.js +29 -0
- package/dist/commands/build.js +17 -0
- package/dist/commands/clean.js +16 -0
- package/dist/commands/company.js +46 -0
- package/dist/commands/deploy.js +143 -0
- package/dist/commands/dev.js +437 -0
- package/dist/commands/devlog.js +25 -0
- package/dist/commands/help.js +48 -0
- package/dist/commands/manage.js +53 -0
- package/dist/commands/migrate.js +76 -0
- package/dist/commands/onboard.js +31 -0
- package/dist/commands/pipeline.js +319 -0
- package/dist/commands/test.js +380 -0
- package/dist/commands/update.js +128 -0
- package/dist/commands/version.js +8 -0
- package/dist/company-init.js +167 -0
- package/dist/company.js +283 -0
- package/dist/config.js +1359 -0
- package/dist/devlog/index.js +226 -0
- package/dist/devlog/lib/collect-commits.js +136 -0
- package/dist/devlog/lib/generate-post.js +201 -0
- package/dist/devlog/lib/ghostii.js +122 -0
- package/dist/devlog/lib/project-map.js +98 -0
- package/dist/devlog/lib/publish-website.js +88 -0
- package/dist/index.js +45 -0
- package/dist/lib/agents-md.js +201 -0
- package/dist/lib/analytics-secret.js +22 -0
- package/dist/lib/argv.js +21 -0
- package/dist/lib/auth-admin.js +120 -0
- package/dist/lib/automation-client.js +210 -0
- package/dist/lib/backend-marketing.js +49 -0
- package/dist/lib/brand.js +240 -0
- package/dist/lib/bundle-id.js +53 -0
- package/dist/lib/claude-settings.js +125 -0
- package/dist/lib/company-scaffold.js +213 -0
- package/dist/lib/company.js +227 -0
- package/dist/lib/config-flow.js +350 -0
- package/dist/lib/config-write.js +41 -0
- package/dist/lib/custom-target.js +75 -0
- package/dist/lib/domain-utils.js +19 -0
- package/dist/lib/duration.js +39 -0
- package/dist/lib/env-order.js +236 -0
- package/dist/lib/env-secret.js +78 -0
- package/dist/lib/firestore-rest.js +326 -0
- package/dist/lib/framework-bin.js +156 -0
- package/dist/lib/gitignore.js +63 -0
- package/dist/lib/google-auth.js +495 -0
- package/dist/lib/google-token.js +66 -0
- package/dist/lib/jwt.js +31 -0
- package/dist/lib/legacy-oauth.js +59 -0
- package/dist/lib/node-version.js +127 -0
- package/dist/lib/owner-plan.js +78 -0
- package/dist/lib/package-scripts.js +152 -0
- package/dist/lib/preflight.js +470 -0
- package/dist/lib/product-create.js +144 -0
- package/dist/lib/run-command.js +74 -0
- package/dist/lib/run-gates.js +70 -0
- package/dist/lib/run-output.js +42 -0
- package/dist/lib/run-summary.js +384 -0
- package/dist/lib/scaffold.js +427 -0
- package/dist/lib/service-input.js +207 -0
- package/dist/lib/service-runner.js +466 -0
- package/dist/lib/stale.js +24 -0
- package/dist/lib/target-selection.js +155 -0
- package/dist/lib/verb-fanout.js +128 -0
- package/dist/lib/verify-live.js +188 -0
- package/dist/manage.js +311 -0
- package/dist/omega-bin.js +7 -0
- package/dist/onboard.js +532 -0
- package/dist/services/account/ensure/users.js +259 -0
- package/dist/services/account/index.js +97 -0
- package/dist/services/account/lib/backend-client.js +107 -0
- package/dist/services/account/lib/password.js +36 -0
- package/dist/services/account/lib/resolve-password.js +100 -0
- package/dist/services/advertising/ensure/sites.js +101 -0
- package/dist/services/advertising/index.js +101 -0
- package/dist/services/advertising/lib/adsense-api.js +41 -0
- package/dist/services/ai/ensure/keys.js +21 -0
- package/dist/services/ai/index.js +36 -0
- package/dist/services/analytics/ensure/google-firebase-link.js +230 -0
- package/dist/services/analytics/ensure/google-streams.js +256 -0
- package/dist/services/analytics/ensure/meta-pixel.js +22 -0
- package/dist/services/analytics/ensure/tiktok-pixel.js +22 -0
- package/dist/services/analytics/index.js +134 -0
- package/dist/services/analytics/lib/analytics-api.js +156 -0
- package/dist/services/analytics/lib/meta-api.js +83 -0
- package/dist/services/analytics/lib/pixel-account.js +78 -0
- package/dist/services/analytics/lib/pixel-provision.js +152 -0
- package/dist/services/analytics/lib/pixel-specs.js +57 -0
- package/dist/services/analytics/lib/pixel-token.js +88 -0
- package/dist/services/analytics/lib/property-flow.js +77 -0
- package/dist/services/analytics/lib/tiktok-api.js +157 -0
- package/dist/services/analytics/lib/tiktok-auth.js +153 -0
- package/dist/services/assets/ensure/logo-gen.js +68 -0
- package/dist/services/assets/index.js +109 -0
- package/dist/services/assets/lib/assets-config.js +168 -0
- package/dist/services/assets/lib/brandmark-api.js +160 -0
- package/dist/services/assets/lib/derived.js +113 -0
- package/dist/services/assets/lib/font-loader.js +67 -0
- package/dist/services/assets/lib/reconcile.js +122 -0
- package/dist/services/assets/lib/reset.js +118 -0
- package/dist/services/assets/lib/svg-logo-generator.js +154 -0
- package/dist/services/assets/lib/svg-to-black.js +32 -0
- package/dist/services/assets/write/favicons.js +82 -0
- package/dist/services/assets/write/icons.js +64 -0
- package/dist/services/assets/write/process.js +96 -0
- package/dist/services/assets/write/reconcile.js +30 -0
- package/dist/services/assets/write/social-icons.js +108 -0
- package/dist/services/assets/write/templates.js +345 -0
- package/dist/services/bookmark/ensure/sync.js +255 -0
- package/dist/services/bookmark/index.js +17 -0
- package/dist/services/campaigns/ensure/contact-person.js +40 -0
- package/dist/services/campaigns/ensure/custom-fields.js +84 -0
- package/dist/services/campaigns/ensure/domain-auth.js +92 -0
- package/dist/services/campaigns/ensure/event-webhook.js +89 -0
- package/dist/services/campaigns/ensure/link-branding.js +187 -0
- package/dist/services/campaigns/ensure/list.js +50 -0
- package/dist/services/campaigns/ensure/segments.js +109 -0
- package/dist/services/campaigns/ensure/sender-identity.js +153 -0
- package/dist/services/campaigns/ensure/unsubscribe-groups.js +116 -0
- package/dist/services/campaigns/index.js +79 -0
- package/dist/services/campaigns/lib/dns-sync.js +81 -0
- package/dist/services/campaigns/lib/segment-query.js +138 -0
- package/dist/services/campaigns/lib/sendgrid-api.js +287 -0
- package/dist/services/captcha/ensure/site-key.js +83 -0
- package/dist/services/captcha/index.js +78 -0
- package/dist/services/captcha/lib/console-url.js +45 -0
- package/dist/services/captcha/lib/recaptcha-api.js +36 -0
- package/dist/services/certificates/ensure/api-key.js +22 -0
- package/dist/services/certificates/ensure/bundle-ids.js +115 -0
- package/dist/services/certificates/ensure/certificates.js +187 -0
- package/dist/services/certificates/ensure/profiles.js +143 -0
- package/dist/services/certificates/index.js +225 -0
- package/dist/services/certificates/lib/apple-api.js +183 -0
- package/dist/services/certificates/lib/certificate-manager.js +252 -0
- package/dist/services/certificates/lib/identifier-manager.js +107 -0
- package/dist/services/certificates/lib/keychain.js +135 -0
- package/dist/services/certificates/lib/manual-walkthrough.js +165 -0
- package/dist/services/certificates/lib/profile-manager.js +115 -0
- package/dist/services/chat/data/baseline-knowledge.md +96 -0
- package/dist/services/chat/ensure/chat.js +106 -0
- package/dist/services/chat/ensure/user.js +45 -0
- package/dist/services/chat/index.js +139 -0
- package/dist/services/chat/lib/baseline-knowledge.js +137 -0
- package/dist/services/cloud/ensure/authentication.js +267 -0
- package/dist/services/cloud/ensure/billing.js +120 -0
- package/dist/services/cloud/ensure/cloud-messaging.js +105 -0
- package/dist/services/cloud/ensure/database.js +60 -0
- package/dist/services/cloud/ensure/firestore.js +79 -0
- package/dist/services/cloud/ensure/functions.js +49 -0
- package/dist/services/cloud/ensure/hosting.js +398 -0
- package/dist/services/cloud/ensure/oauth-consent.js +248 -0
- package/dist/services/cloud/ensure/project-settings.js +72 -0
- package/dist/services/cloud/ensure/sdk-config.js +95 -0
- package/dist/services/cloud/ensure/service-account.js +152 -0
- package/dist/services/cloud/ensure/services.js +103 -0
- package/dist/services/cloud/ensure/storage.js +47 -0
- package/dist/services/cloud/index.js +130 -0
- package/dist/services/cloud/lib/access-heal.js +130 -0
- package/dist/services/cloud/lib/firebase-api.js +662 -0
- package/dist/services/cloud/lib/project-flow.js +102 -0
- package/dist/services/directory/ensure/entry.js +48 -0
- package/dist/services/directory/index.js +64 -0
- package/dist/services/directory/lib/blocks.js +104 -0
- package/dist/services/disperse/index.js +45 -0
- package/dist/services/disperse/write/certs.js +117 -0
- package/dist/services/domain/ensure/nameservers.js +179 -0
- package/dist/services/domain/index.js +69 -0
- package/dist/services/domain/lib/namecheap-api.js +167 -0
- package/dist/services/domain/lib/registrars.js +46 -0
- package/dist/services/domain/lib/whitelist-walkthrough.js +76 -0
- package/dist/services/edge/ensure/cache-rules.js +105 -0
- package/dist/services/edge/ensure/dns-records.js +304 -0
- package/dist/services/edge/ensure/email-routing.js +292 -0
- package/dist/services/edge/ensure/rules-configuration.js +98 -0
- package/dist/services/edge/ensure/rules-managed-transforms.js +101 -0
- package/dist/services/edge/ensure/rules-redirect.js +107 -0
- package/dist/services/edge/ensure/rules-response-headers.js +90 -0
- package/dist/services/edge/ensure/rules-security.js +142 -0
- package/dist/services/edge/ensure/speed-scheduled-tests.js +98 -0
- package/dist/services/edge/ensure/workers.js +219 -0
- package/dist/services/edge/ensure/zone-settings.js +108 -0
- package/dist/services/edge/ensure/zone.js +183 -0
- package/dist/services/edge/index.js +73 -0
- package/dist/services/edge/lib/cloudflare-api.js +84 -0
- package/dist/services/edge/lib/dns-records-helpers.js +518 -0
- package/dist/services/edge/lib/read-cache.js +16 -0
- package/dist/services/edge/lib/ruleset-helper.js +108 -0
- package/dist/services/edge/workers/omega-api-proxy.js +43 -0
- package/dist/services/email/data/baseline-filter.md +4 -0
- package/dist/services/email/data/baseline-knowledge.md +86 -0
- package/dist/services/email/ensure/agent.js +107 -0
- package/dist/services/email/ensure/user.js +45 -0
- package/dist/services/email/index.js +138 -0
- package/dist/services/email/lib/baseline.js +82 -0
- package/dist/services/email/lib/knowledge-file.js +53 -0
- package/dist/services/forms/ensure/form.js +46 -0
- package/dist/services/forms/ensure/user.js +45 -0
- package/dist/services/forms/index.js +138 -0
- package/dist/services/migrations/ensure/notifications.js +189 -0
- package/dist/services/migrations/ensure/orders.js +34 -0
- package/dist/services/migrations/ensure/payment-provider.js +132 -0
- package/dist/services/migrations/ensure/payments-intents.js +34 -0
- package/dist/services/migrations/ensure/state-retirement.js +266 -0
- package/dist/services/migrations/ensure/targets-rename.js +124 -0
- package/dist/services/migrations/ensure/users.js +1176 -0
- package/dist/services/migrations/index.js +101 -0
- package/dist/services/migrations/lib/attribution-touch.js +64 -0
- package/dist/services/migrations/lib/ensure-metadata.js +144 -0
- package/dist/services/migrations/lib/migration-runner.js +473 -0
- package/dist/services/migrations/lib/sanitize-strings.js +112 -0
- package/dist/services/migrations/lib/schema-validator.js +154 -0
- package/dist/services/monitoring/ensure/dsn.js +54 -0
- package/dist/services/monitoring/ensure/projects.js +135 -0
- package/dist/services/monitoring/index.js +54 -0
- package/dist/services/monitoring/lib/sentry-api.js +94 -0
- package/dist/services/newsletter/ensure/custom-fields.js +90 -0
- package/dist/services/newsletter/ensure/publication.js +94 -0
- package/dist/services/newsletter/ensure/segments.js +140 -0
- package/dist/services/newsletter/ensure/webhook.js +108 -0
- package/dist/services/newsletter/index.js +64 -0
- package/dist/services/newsletter/lib/beehiiv-api.js +124 -0
- package/dist/services/newsletter/lib/segment-automation.js +577 -0
- package/dist/services/payment/ensure/chargebee-account.js +30 -0
- package/dist/services/payment/ensure/chargebee-products.js +359 -0
- package/dist/services/payment/ensure/chargebee-webhook.js +113 -0
- package/dist/services/payment/ensure/paypal-account.js +36 -0
- package/dist/services/payment/ensure/paypal-products.js +374 -0
- package/dist/services/payment/ensure/paypal-webhook.js +128 -0
- package/dist/services/payment/ensure/stripe-account.js +93 -0
- package/dist/services/payment/ensure/stripe-disputes.js +56 -0
- package/dist/services/payment/ensure/stripe-products.js +245 -0
- package/dist/services/payment/ensure/stripe-radar.js +74 -0
- package/dist/services/payment/ensure/stripe-webhook.js +130 -0
- package/dist/services/payment/index.js +163 -0
- package/dist/services/payment/lib/chargebee-api.js +338 -0
- package/dist/services/payment/lib/payment-utils.js +116 -0
- package/dist/services/payment/lib/paypal-api.js +354 -0
- package/dist/services/payment/lib/provider-setup.js +134 -0
- package/dist/services/payment/lib/stripe-api.js +152 -0
- package/dist/services/repo/ensure/org.js +70 -0
- package/dist/services/repo/ensure/pages.js +72 -0
- package/dist/services/repo/ensure/repo.js +90 -0
- package/dist/services/repo/index.js +52 -0
- package/dist/services/repo/lib/github-api.js +196 -0
- package/dist/services/search/ensure/ga-link.js +57 -0
- package/dist/services/search/ensure/property.js +137 -0
- package/dist/services/search/ensure/sitemaps.js +70 -0
- package/dist/services/search/index.js +61 -0
- package/dist/services/search/lib/search-console-api.js +92 -0
- package/dist/services/seo/ensure/github-repos.js +271 -0
- package/dist/services/seo/index.js +55 -0
- package/dist/services/seo/lib/gh-api.js +161 -0
- package/dist/services/seo/templates/developer-tool/.github/workflows/maintenance.yml +25 -0
- package/dist/services/seo/templates/developer-tool/.nvmrc +1 -0
- package/dist/services/seo/templates/developer-tool/_README.md.js +121 -0
- package/dist/services/seo/templates/developer-tool/_package.json.js +33 -0
- package/dist/services/seo/templates/developer-tool/src/index.js +120 -0
- package/dist/services/seo/templates/index.js +57 -0
- package/dist/services/server/ensure/brands.js +63 -0
- package/dist/services/server/index.js +42 -0
- package/dist/services/testing/ensure/target-checks.js +97 -0
- package/dist/services/testing/index.js +11 -0
- package/dist/services/testing/lib/checks.js +467 -0
- package/dist/services/update/index.js +20 -0
- package/dist/services/update/lib/cache.js +59 -0
- package/dist/services/update/lib/fingerprint.js +157 -0
- package/dist/services/update/write/targets.js +206 -0
- package/dist/services/workspace/ensure/agents.js +42 -0
- package/dist/services/workspace/ensure/claude-settings.js +34 -0
- package/dist/services/workspace/ensure/config.js +54 -0
- package/dist/services/workspace/ensure/defaults.js +60 -0
- package/dist/services/workspace/ensure/env-keys.js +55 -0
- package/dist/services/workspace/ensure/env-order.js +66 -0
- package/dist/services/workspace/ensure/env-rules.js +97 -0
- package/dist/services/workspace/ensure/gitignore.js +18 -0
- package/dist/services/workspace/ensure/scripts.js +126 -0
- package/dist/services/workspace/ensure/structure.js +97 -0
- package/dist/services/workspace/ensure/translation-sdk.js +148 -0
- package/dist/services/workspace/ensure/workflows.js +54 -0
- package/dist/services/workspace/index.js +8 -0
- package/dist/vendor/account/engine.js +182 -0
- package/dist/vendor/account/features.js +220 -0
- package/dist/vendor/account/index.js +53 -0
- package/dist/vendor/account/schema.js +272 -0
- package/dist/vendor/account/subscription.js +38 -0
- package/dist/vendor/config/company.js +31 -0
- package/dist/vendor/config/defaults.js +173 -0
- package/dist/vendor/config/demo.js +18 -0
- package/dist/vendor/config/desktop-artifacts.js +110 -0
- package/dist/vendor/config/edit.js +769 -0
- package/dist/vendor/config/env-delivery.js +145 -0
- package/dist/vendor/config/env-rules.js +93 -0
- package/dist/vendor/config/env-schema.js +1078 -0
- package/dist/vendor/config/env.js +445 -0
- package/dist/vendor/config/hooks.js +97 -0
- package/dist/vendor/config/index.js +237 -0
- package/dist/vendor/config/instances.js +208 -0
- package/dist/vendor/config/load.js +490 -0
- package/dist/vendor/config/merge.js +68 -0
- package/dist/vendor/config/order.js +139 -0
- package/dist/vendor/config/ports.js +374 -0
- package/dist/vendor/config/providers.js +32 -0
- package/dist/vendor/config/repo.js +142 -0
- package/dist/vendor/config/retired-keys.js +430 -0
- package/dist/vendor/config/schema.js +1610 -0
- package/dist/vendor/config/secrets.js +50 -0
- package/dist/vendor/config/seed.js +34 -0
- package/dist/vendor/config/site-global.js +205 -0
- package/dist/vendor/config/validate.js +554 -0
- package/dist/vendor/config/winback.js +61 -0
- package/dist/vendor/devkit/attach-log-file.js +262 -0
- package/dist/vendor/devkit/certs.js +199 -0
- package/dist/vendor/devkit/ci-workflows.js +520 -0
- package/dist/vendor/devkit/cli-router.js +156 -0
- package/dist/vendor/devkit/command-path.js +46 -0
- package/dist/vendor/devkit/deploy-record.js +180 -0
- package/dist/vendor/devkit/flows.js +317 -0
- package/dist/vendor/devkit/local-https.js +360 -0
- package/dist/vendor/devkit/local.js +1905 -0
- package/dist/vendor/devkit/logger.js +128 -0
- package/dist/vendor/devkit/omega-bin.js +345 -0
- package/dist/vendor/devkit/prompt.js +187 -0
- package/dist/vendor/devkit/safe-install.js +18 -0
- package/dist/vendor/devkit/stop-signals.js +28 -0
- package/dist/vendor/devkit/test/scope.js +162 -0
- package/dist/vendor/devkit/translate/cache.js +84 -0
- package/dist/vendor/devkit/translate/engine.js +243 -0
- package/dist/vendor/devkit/translate/index.js +49 -0
- package/dist/vendor/devkit/translate/languages.js +134 -0
- package/dist/vendor/devkit/translate/providers.js +188 -0
- package/dist/vendor/devkit/update.js +569 -0
- package/docs/AGENTS.md +200 -0
- package/docs/account.md +45 -0
- package/docs/advertising.md +46 -0
- package/docs/ai.md +34 -0
- package/docs/analytics.md +69 -0
- package/docs/assets.md +57 -0
- package/docs/bookmark.md +26 -0
- package/docs/brand.md +151 -0
- package/docs/campaigns.md +96 -0
- package/docs/captcha.md +46 -0
- package/docs/certificates.md +68 -0
- package/docs/chat.md +47 -0
- package/docs/cloud.md +110 -0
- package/docs/company.md +64 -0
- package/docs/directory.md +140 -0
- package/docs/disperse.md +46 -0
- package/docs/domain.md +56 -0
- package/docs/edge.md +234 -0
- package/docs/email.md +42 -0
- package/docs/forms.md +48 -0
- package/docs/index.md +109 -0
- package/docs/migration.md +203 -0
- package/docs/migrations.md +56 -0
- package/docs/monitoring.md +41 -0
- package/docs/newsletter.md +48 -0
- package/docs/payment.md +83 -0
- package/docs/repo.md +48 -0
- package/docs/search.md +44 -0
- package/docs/seo.md +34 -0
- package/docs/server.md +37 -0
- package/docs/shared/agent-docs.md +89 -0
- package/docs/shared/analytics.md +612 -0
- package/docs/shared/brands.md +51 -0
- package/docs/shared/breaking-changes.md +497 -0
- package/docs/shared/config.md +1387 -0
- package/docs/shared/deploys.md +215 -0
- package/docs/shared/icons.md +201 -0
- package/docs/shared/local-dev.md +147 -0
- package/docs/shared/logging.md +202 -0
- package/docs/shared/monitoring.md +153 -0
- package/docs/shared/publishing.md +183 -0
- package/docs/shared/rulings.md +34 -0
- package/docs/shared/testing.md +147 -0
- package/docs/shared/theming.md +604 -0
- package/docs/shared/translation.md +291 -0
- package/docs/shared/updates.md +61 -0
- package/docs/testing.md +34 -0
- package/docs/update.md +36 -0
- package/docs/workspace.md +64 -0
- package/package.json +88 -0
|
@@ -0,0 +1,360 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Local HTTPS for dev servers (mkcert) — the shared mechanism behind
|
|
3
|
+
* `omega serve` / `omega emulator` (backend) and `omega dev` (web):
|
|
4
|
+
* the PUBLIC port speaks TLS through a forwarding proxy while the real
|
|
5
|
+
* server sits on an internal plain-http port.
|
|
6
|
+
*
|
|
7
|
+
* - ensureLocalHttpsCerts({ certsDir, log }) → { key, cert } | null
|
|
8
|
+
* Reuses mkcert certificates from certsDir when they're usable; stale
|
|
9
|
+
* ones (expired, or issued by a DIFFERENT machine's mkcert CA — e.g. a
|
|
10
|
+
* .temp copied over from another Mac) are wiped and regenerated against
|
|
11
|
+
* THIS machine's trusted CA. No mkcert installed → null, and callers
|
|
12
|
+
* fall back to plain http.
|
|
13
|
+
*
|
|
14
|
+
* - startLocalHttpsProxy({ port, targetPort, certs, log }) → net.Server
|
|
15
|
+
* TLS terminator forwarding every request to localhost:targetPort with
|
|
16
|
+
* x-forwarded-proto/host set. WebSocket upgrades tunnel as raw sockets
|
|
17
|
+
* (dev-server live-reload keeps working through the proxy). The public
|
|
18
|
+
* port is polyglot: the first byte decides TLS vs plain http, and plain
|
|
19
|
+
* http gets a 307 redirect to https on the same host — anyone typing
|
|
20
|
+
* http://localhost:<port> lands in the right place instead of a browser
|
|
21
|
+
* connection error.
|
|
22
|
+
*
|
|
23
|
+
* - mkcertCaRootPem() → '<mkcert -CAROOT>/rootCA.pem' | null
|
|
24
|
+
* The root certificate a spawned Node process TRUSTS through
|
|
25
|
+
* NODE_EXTRA_CA_CERTS, so a child calling the public https port verifies it
|
|
26
|
+
* instead of bypassing verification (#795). Memoised per process.
|
|
27
|
+
*/
|
|
28
|
+
const fs = require('fs');
|
|
29
|
+
const path = require('path');
|
|
30
|
+
const os = require('os');
|
|
31
|
+
const net = require('net');
|
|
32
|
+
const http = require('http');
|
|
33
|
+
const https = require('https');
|
|
34
|
+
const { execSync } = require('child_process');
|
|
35
|
+
const jetpack = require('fs-jetpack');
|
|
36
|
+
const { commandOnPath } = require('./command-path.js');
|
|
37
|
+
|
|
38
|
+
const NOOP = () => {};
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
* The install line to print when mkcert is absent, for THIS host.
|
|
42
|
+
*
|
|
43
|
+
* mkcert ships through a different manager on every platform — its README
|
|
44
|
+
* (https://github.com/FiloSottile/mkcert#installation) names Homebrew on
|
|
45
|
+
* macOS, Chocolatey or Scoop on Windows, and on Linux certutil from apt plus
|
|
46
|
+
* mkcert itself from the release binary or Linuxbrew. One home for the string,
|
|
47
|
+
* since `omega serve`, `omega emulator`, web's `omega dev` and the generator
|
|
48
|
+
* below all print it.
|
|
49
|
+
*
|
|
50
|
+
* Every line OPENS with something pasteable — an alternative belongs in a
|
|
51
|
+
* sentence after it, never spliced into the command a reader will copy.
|
|
52
|
+
*
|
|
53
|
+
* @param {string} [platform] - Host platform (test seam)
|
|
54
|
+
* @returns {string} The command to run, then any alternative
|
|
55
|
+
*/
|
|
56
|
+
function mkcertInstallHint(platform = process.platform) {
|
|
57
|
+
if (platform === 'darwin') {
|
|
58
|
+
return 'brew install mkcert && mkcert -install';
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (platform === 'win32') {
|
|
62
|
+
return 'choco install mkcert && mkcert -install. Scoop works too: scoop bucket add extras, then scoop install mkcert.';
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return 'sudo apt install libnss3-tools, then install mkcert itself from https://github.com/FiloSottile/mkcert/releases (or Linuxbrew) and run mkcert -install.';
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
// One CAROOT lookup per process — mkcert's root does not move under a running
|
|
69
|
+
// stack, and three call sites ask for it. Keyed by the exec that answered, so a
|
|
70
|
+
// test seam never inherits (or poisons) the real host's answer.
|
|
71
|
+
const caRootPemCache = new Map();
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* The absolute path to THIS machine's mkcert root CA certificate.
|
|
75
|
+
*
|
|
76
|
+
* A Node child reads no system trust store, so a process calling the public
|
|
77
|
+
* https port (the proxy above) fails the certificate. Handing it this path as
|
|
78
|
+
* NODE_EXTRA_CA_CERTS makes it VERIFY the local certificate — the reason it is
|
|
79
|
+
* not NODE_TLS_REJECT_UNAUTHORIZED=0, which disables verification wholesale and
|
|
80
|
+
* makes Node print a warning (#795).
|
|
81
|
+
*
|
|
82
|
+
* The `mkcert -CAROOT` call IS the on-PATH probe: mkcert missing means the
|
|
83
|
+
* shell exits nonzero, which is the null answer.
|
|
84
|
+
*
|
|
85
|
+
* @param {object} [options]
|
|
86
|
+
* @param {function} [options.exec] - execSync (test seam)
|
|
87
|
+
* @returns {string|null} The rootCA.pem path, or null when mkcert or its root is absent
|
|
88
|
+
*/
|
|
89
|
+
function mkcertCaRootPem({ exec = execSync } = {}) {
|
|
90
|
+
if (caRootPemCache.has(exec)) {
|
|
91
|
+
return caRootPemCache.get(exec);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
let pem = null;
|
|
95
|
+
try {
|
|
96
|
+
// A host without mkcert answers with a nonzero exit, the expected null, so
|
|
97
|
+
// the child's stderr stays quiet (no "command not found" in the dev banner).
|
|
98
|
+
const caRoot = String(exec('mkcert -CAROOT', { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'] })).trim();
|
|
99
|
+
const candidate = caRoot ? path.join(caRoot, 'rootCA.pem') : null;
|
|
100
|
+
pem = candidate && fs.existsSync(candidate) ? candidate : null;
|
|
101
|
+
} catch (e) {
|
|
102
|
+
// No mkcert on this host — callers fall back (plain http, or no trust var).
|
|
103
|
+
pem = null;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
caRootPemCache.set(exec, pem);
|
|
107
|
+
return pem;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Find-or-generate mkcert certificates in certsDir.
|
|
112
|
+
* @param {object} options
|
|
113
|
+
* @param {string} options.certsDir - Where the localhost*.pem pair lives
|
|
114
|
+
* @param {function} [options.log] - Line logger
|
|
115
|
+
* @returns {Promise<{ key: string, cert: string } | null>} Cert file paths, or null when unobtainable
|
|
116
|
+
*/
|
|
117
|
+
async function ensureLocalHttpsCerts({ certsDir, log = NOOP }) {
|
|
118
|
+
jetpack.dir(certsDir);
|
|
119
|
+
|
|
120
|
+
// Check if mkcert certificates already exist
|
|
121
|
+
const existing = findCertPair(certsDir);
|
|
122
|
+
|
|
123
|
+
if (existing) {
|
|
124
|
+
const problem = checkCertProblem(existing.cert);
|
|
125
|
+
|
|
126
|
+
if (!problem) {
|
|
127
|
+
log(`Using existing mkcert certificates from ${path.basename(path.dirname(certsDir))}/${path.basename(certsDir)}/`);
|
|
128
|
+
return existing;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Unusable certs make browsers reject the proxy outright — wipe and
|
|
132
|
+
// regenerate against this machine's trusted CA.
|
|
133
|
+
log(`Existing certificates are not usable (${problem}) — regenerating...`);
|
|
134
|
+
jetpack.remove(certsDir);
|
|
135
|
+
jetpack.dir(certsDir);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
return generateMkcertCerts(certsDir, log);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/**
|
|
142
|
+
* Locate the mkcert localhost pair in a directory.
|
|
143
|
+
* @param {string} certsDir
|
|
144
|
+
* @returns {{ key: string, cert: string } | null}
|
|
145
|
+
*/
|
|
146
|
+
function findCertPair(certsDir) {
|
|
147
|
+
const certFiles = (jetpack.find(certsDir, { matching: 'localhost*.pem' }) || []);
|
|
148
|
+
const key = certFiles.find((f) => f.includes('-key.pem'));
|
|
149
|
+
const cert = certFiles.find((f) => !f.includes('-key.pem'));
|
|
150
|
+
|
|
151
|
+
return key && cert ? { key, cert } : null;
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
/**
|
|
155
|
+
* Returns a reason string when the existing cert must be regenerated, or null
|
|
156
|
+
* when it's usable: unexpired AND signed by this machine's trusted mkcert root CA.
|
|
157
|
+
* @param {string} certFile
|
|
158
|
+
* @returns {string | null}
|
|
159
|
+
*/
|
|
160
|
+
function checkCertProblem(certFile) {
|
|
161
|
+
const { X509Certificate } = require('crypto');
|
|
162
|
+
|
|
163
|
+
let cert;
|
|
164
|
+
try {
|
|
165
|
+
cert = new X509Certificate(fs.readFileSync(certFile));
|
|
166
|
+
} catch (e) {
|
|
167
|
+
return 'unreadable certificate';
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
if (new Date(cert.validTo) <= new Date()) {
|
|
171
|
+
return `expired ${cert.validTo}`;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Verify the signature chains to the CURRENT mkcert root CA. If mkcert (or
|
|
175
|
+
// its root) isn't available we can't verify — keep the existing certs rather
|
|
176
|
+
// than breaking the no-mkcert fallback path.
|
|
177
|
+
const caPem = mkcertCaRootPem();
|
|
178
|
+
if (!caPem) {
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
try {
|
|
183
|
+
const ca = new X509Certificate(fs.readFileSync(caPem));
|
|
184
|
+
|
|
185
|
+
if (!cert.verify(ca.publicKey)) {
|
|
186
|
+
const issuerCN = cert.issuer.split('\n').find((line) => line.startsWith('CN=')) || cert.issuer;
|
|
187
|
+
return `issued by a different CA (${issuerCN})`;
|
|
188
|
+
}
|
|
189
|
+
} catch (e) {
|
|
190
|
+
return null;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
return null;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
/**
|
|
197
|
+
* Generate a fresh localhost cert pair with mkcert (SANs: localhost,
|
|
198
|
+
* loopbacks, and the machine's LAN IPv4s so phones on the same network work).
|
|
199
|
+
* @param {string} certsDir
|
|
200
|
+
* @param {function} log
|
|
201
|
+
* @returns {{ key: string, cert: string } | null}
|
|
202
|
+
*/
|
|
203
|
+
function generateMkcertCerts(certsDir, log = NOOP) {
|
|
204
|
+
if (!commandOnPath('mkcert')) {
|
|
205
|
+
log(`mkcert not found. Install with: ${mkcertInstallHint()}`);
|
|
206
|
+
return null;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
try {
|
|
210
|
+
execSync('mkcert -install', { stdio: 'pipe' });
|
|
211
|
+
} catch (e) {
|
|
212
|
+
// CA may already be installed
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
log('Generating mkcert certificates...');
|
|
216
|
+
|
|
217
|
+
const hosts = ['localhost', '127.0.0.1', '::1'];
|
|
218
|
+
const interfaces = os.networkInterfaces();
|
|
219
|
+
|
|
220
|
+
for (const name of Object.keys(interfaces)) {
|
|
221
|
+
for (const iface of interfaces[name]) {
|
|
222
|
+
if (!iface.internal && iface.family === 'IPv4') {
|
|
223
|
+
hosts.push(iface.address);
|
|
224
|
+
break;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
try {
|
|
230
|
+
execSync(`mkcert ${hosts.join(' ')}`, { cwd: certsDir, stdio: 'pipe' });
|
|
231
|
+
|
|
232
|
+
const pair = findCertPair(certsDir);
|
|
233
|
+
if (pair) {
|
|
234
|
+
log('Trusted HTTPS certificates generated');
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
return pair;
|
|
238
|
+
} catch (e) {
|
|
239
|
+
log(`Failed to generate certificates: ${e.message}`);
|
|
240
|
+
return null;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Start the TLS-terminating forwarder: https://localhost:port →
|
|
246
|
+
* http://localhost:targetPort. Handles plain requests AND WebSocket
|
|
247
|
+
* upgrades (raw tunnel), so dev-server live-reload sockets survive.
|
|
248
|
+
* The listener is a polyglot front: TLS handshakes (first byte 0x16) go to
|
|
249
|
+
* the TLS server, plain http gets a 307 to https on the same host.
|
|
250
|
+
* @param {object} options
|
|
251
|
+
* @param {number} options.port - Public TLS port
|
|
252
|
+
* @param {number} options.targetPort - Internal plain-http port
|
|
253
|
+
* @param {{ key: string, cert: string }} options.certs - Cert file paths
|
|
254
|
+
* @param {function} [options.log] - Line logger
|
|
255
|
+
* @returns {import('net').Server}
|
|
256
|
+
*/
|
|
257
|
+
function startLocalHttpsProxy({ port, targetPort, certs, log = NOOP }) {
|
|
258
|
+
const options = {
|
|
259
|
+
key: fs.readFileSync(certs.key),
|
|
260
|
+
cert: fs.readFileSync(certs.cert),
|
|
261
|
+
};
|
|
262
|
+
|
|
263
|
+
const proxy = https.createServer(options, (clientReq, clientRes) => {
|
|
264
|
+
const proxyOpts = {
|
|
265
|
+
hostname: 'localhost',
|
|
266
|
+
port: targetPort,
|
|
267
|
+
path: clientReq.url,
|
|
268
|
+
method: clientReq.method,
|
|
269
|
+
headers: {
|
|
270
|
+
...clientReq.headers,
|
|
271
|
+
'x-forwarded-proto': 'https',
|
|
272
|
+
'x-forwarded-host': clientReq.headers.host,
|
|
273
|
+
},
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
const proxyReq = http.request(proxyOpts, (proxyRes) => {
|
|
277
|
+
clientRes.writeHead(proxyRes.statusCode, proxyRes.headers);
|
|
278
|
+
proxyRes.pipe(clientRes, { end: true });
|
|
279
|
+
});
|
|
280
|
+
|
|
281
|
+
proxyReq.on('error', (err) => {
|
|
282
|
+
clientRes.writeHead(502);
|
|
283
|
+
clientRes.end(`Proxy error: ${err.message}`);
|
|
284
|
+
});
|
|
285
|
+
|
|
286
|
+
clientReq.pipe(proxyReq, { end: true });
|
|
287
|
+
});
|
|
288
|
+
|
|
289
|
+
// WebSocket upgrades (dev-server live-reload): replay the handshake at the
|
|
290
|
+
// target and splice the sockets — rawHeaders preserves case + duplicates.
|
|
291
|
+
proxy.on('upgrade', (req, socket, head) => {
|
|
292
|
+
const upstream = net.connect(targetPort, 'localhost', () => {
|
|
293
|
+
const lines = [`${req.method} ${req.url} HTTP/1.1`];
|
|
294
|
+
for (let i = 0; i < req.rawHeaders.length; i += 2) {
|
|
295
|
+
lines.push(`${req.rawHeaders[i]}: ${req.rawHeaders[i + 1]}`);
|
|
296
|
+
}
|
|
297
|
+
upstream.write(`${lines.join('\r\n')}\r\n\r\n`);
|
|
298
|
+
|
|
299
|
+
if (head && head.length) {
|
|
300
|
+
upstream.write(head);
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
socket.pipe(upstream);
|
|
304
|
+
upstream.pipe(socket);
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
// Either side going away (error OR clean close) releases the other —
|
|
308
|
+
// without this, half-open tunnels strand sockets on every closed tab
|
|
309
|
+
upstream.on('error', () => socket.destroy());
|
|
310
|
+
socket.on('error', () => upstream.destroy());
|
|
311
|
+
upstream.on('close', () => socket.destroy());
|
|
312
|
+
socket.on('close', () => upstream.destroy());
|
|
313
|
+
});
|
|
314
|
+
|
|
315
|
+
// Plain-http answers on the SAME port: whatever the path, bounce the
|
|
316
|
+
// browser to https on the host it asked for (Host carries the port).
|
|
317
|
+
const redirect = http.createServer((req, res) => {
|
|
318
|
+
const host = req.headers.host || `localhost:${port}`;
|
|
319
|
+
res.writeHead(307, { Location: `https://${host}${req.url}` });
|
|
320
|
+
res.end();
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
// Polyglot front — peek the first byte without consuming it: a TLS
|
|
324
|
+
// handshake record starts with 0x16, anything else is treated as plain
|
|
325
|
+
// http. The byte goes back via unshift before the real server takes over.
|
|
326
|
+
const front = net.createServer((socket) => {
|
|
327
|
+
socket.on('error', () => socket.destroy());
|
|
328
|
+
|
|
329
|
+
socket.once('data', (firstChunk) => {
|
|
330
|
+
socket.pause();
|
|
331
|
+
socket.unshift(firstChunk);
|
|
332
|
+
|
|
333
|
+
const target = firstChunk[0] === 0x16 ? proxy : redirect;
|
|
334
|
+
target.emit('connection', socket);
|
|
335
|
+
|
|
336
|
+
process.nextTick(() => socket.resume());
|
|
337
|
+
});
|
|
338
|
+
});
|
|
339
|
+
|
|
340
|
+
front.listen(port, () => {
|
|
341
|
+
log(`HTTPS proxy listening on https://localhost:${port}`);
|
|
342
|
+
log(`Forwarding to http://localhost:${targetPort} (plain http redirects to https)`);
|
|
343
|
+
});
|
|
344
|
+
|
|
345
|
+
front.on('error', (err) => {
|
|
346
|
+
log(`HTTPS proxy error: ${err.message}`);
|
|
347
|
+
});
|
|
348
|
+
|
|
349
|
+
return front;
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
module.exports = {
|
|
353
|
+
ensureLocalHttpsCerts,
|
|
354
|
+
startLocalHttpsProxy,
|
|
355
|
+
checkCertProblem,
|
|
356
|
+
findCertPair,
|
|
357
|
+
generateMkcertCerts,
|
|
358
|
+
mkcertInstallHint,
|
|
359
|
+
mkcertCaRootPem,
|
|
360
|
+
};
|