auramaxx 0.0.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/LICENSE +26 -0
- package/README.md +77 -0
- package/apps/desktop-electron/main.js +428 -0
- package/bin/auramaxx.js +1063 -0
- package/docs/ADAPTERS.md +466 -0
- package/docs/AGENT_SETUP.md +159 -0
- package/docs/API.md +127 -0
- package/docs/APPS.md +199 -0
- package/docs/ARCHITECTURE.md +235 -0
- package/docs/AUTH.md +318 -0
- package/docs/BEST-PRACTICES.md +82 -0
- package/docs/CLI.md +141 -0
- package/docs/DESKTOP_ELECTRON.md +26 -0
- package/docs/DEVELOPING-APPS.md +453 -0
- package/docs/MCP.md +122 -0
- package/docs/PACKAGING_POLICY.md +19 -0
- package/docs/PERMISSION.md +137 -0
- package/docs/PROTOCOL.md +142 -0
- package/docs/README.md +50 -0
- package/docs/SKILLS.md +132 -0
- package/docs/TROUBLESHOOTING.md +376 -0
- package/docs/WORKSPACE.md +673 -0
- package/docs/agent-auth.md +14 -0
- package/docs/api/authentication.md +79 -0
- package/docs/api/secrets/api-keys.md +28 -0
- package/docs/api/secrets/credentials.md +80 -0
- package/docs/api/secrets/sharing.md +48 -0
- package/docs/api/system.md +41 -0
- package/docs/api/wallets/apps-strategies.md +66 -0
- package/docs/api/wallets/core.md +46 -0
- package/docs/api/wallets/data-portfolio.md +42 -0
- package/docs/aura-file.md +48 -0
- package/docs/core-concepts/FEATURES.md +114 -0
- package/docs/credentials.md +120 -0
- package/docs/external/HOW_TO_AURAMAXX/GETTING_SECRETS.md +33 -0
- package/docs/external/HOW_TO_AURAMAXX/README.md +45 -0
- package/docs/external/getting-started.md +10 -0
- package/docs/external/overview.md +19 -0
- package/docs/external/persona-paths.md +7 -0
- package/docs/external/share-secret.md +76 -0
- package/docs/external/why-aura.md +7 -0
- package/docs/security.md +227 -0
- package/docs/templates/RELEASE_NOTES_TEMPLATE.md +22 -0
- package/docs/wallet/AI.md +508 -0
- package/docs/wallet/DEVELOPING-STRATEGIES.md +713 -0
- package/docs/wallet/README.md +47 -0
- package/docs/wallet/STRATEGY.md +89 -0
- package/next.config.ts +28 -0
- package/package.json +167 -0
- package/postcss.config.mjs +8 -0
- package/prisma/migrations/20260214170000_baseline/migration.sql +511 -0
- package/prisma/migrations/20260216214537_add_passkey_model/migration.sql +18 -0
- package/prisma/migrations/20260217150500_add_credential_access_audit/migration.sql +31 -0
- package/prisma/migrations/20260222090000_update_admin_ttl_default/migration.sql +10 -0
- package/prisma/migrations/migration_lock.toml +3 -0
- package/prisma/schema.prisma +447 -0
- package/public/logo.webp +0 -0
- package/scripts/add-app.js +245 -0
- package/server/abi/SwapHelper.json +438 -0
- package/server/cli/approval.ts +447 -0
- package/server/cli/commands/actions.ts +474 -0
- package/server/cli/commands/api.ts +220 -0
- package/server/cli/commands/apikey.ts +277 -0
- package/server/cli/commands/app.ts +204 -0
- package/server/cli/commands/auth.ts +464 -0
- package/server/cli/commands/cron.ts +24 -0
- package/server/cli/commands/diary.ts +274 -0
- package/server/cli/commands/doctor.ts +1247 -0
- package/server/cli/commands/env.ts +476 -0
- package/server/cli/commands/experimental.ts +69 -0
- package/server/cli/commands/init.ts +798 -0
- package/server/cli/commands/lock.ts +157 -0
- package/server/cli/commands/mcp.ts +285 -0
- package/server/cli/commands/quickhack.ts +86 -0
- package/server/cli/commands/release-check.ts +231 -0
- package/server/cli/commands/restore.ts +314 -0
- package/server/cli/commands/service.ts +320 -0
- package/server/cli/commands/shell-hook.ts +512 -0
- package/server/cli/commands/skill.ts +216 -0
- package/server/cli/commands/start.ts +139 -0
- package/server/cli/commands/status.ts +59 -0
- package/server/cli/commands/stop.ts +36 -0
- package/server/cli/commands/token.ts +180 -0
- package/server/cli/commands/unlock.ts +50 -0
- package/server/cli/commands/vault.ts +1323 -0
- package/server/cli/commands/wallet.ts +209 -0
- package/server/cli/index.ts +280 -0
- package/server/cli/lib/approval-poll.ts +94 -0
- package/server/cli/lib/aura-parser.ts +64 -0
- package/server/cli/lib/credential-create.ts +74 -0
- package/server/cli/lib/credential-resolve.ts +280 -0
- package/server/cli/lib/dotenv-migrate.ts +116 -0
- package/server/cli/lib/dotenv-parser.ts +146 -0
- package/server/cli/lib/escalation.ts +57 -0
- package/server/cli/lib/http.ts +91 -0
- package/server/cli/lib/init-steps.ts +76 -0
- package/server/cli/lib/local-agent-trust.ts +45 -0
- package/server/cli/lib/lock-unlock-helper.ts +71 -0
- package/server/cli/lib/process.ts +162 -0
- package/server/cli/lib/prompt.ts +294 -0
- package/server/cli/lib/theme.ts +240 -0
- package/server/cli/socket.ts +579 -0
- package/server/cli/transport-client.ts +50 -0
- package/server/cron/index.ts +137 -0
- package/server/cron/job.ts +31 -0
- package/server/cron/jobs/balance-sync.ts +436 -0
- package/server/cron/jobs/incoming-scan.ts +506 -0
- package/server/cron/jobs/native-price.ts +70 -0
- package/server/cron/jobs/orphan-cleanup.ts +40 -0
- package/server/cron/jobs/strategy-runner.ts +175 -0
- package/server/cron/scheduler.ts +125 -0
- package/server/index.ts +420 -0
- package/server/lib/adapters/factory.ts +119 -0
- package/server/lib/adapters/index.ts +19 -0
- package/server/lib/adapters/router.ts +297 -0
- package/server/lib/adapters/telegram.ts +645 -0
- package/server/lib/adapters/types.ts +89 -0
- package/server/lib/adapters/webhook.ts +95 -0
- package/server/lib/address.ts +49 -0
- package/server/lib/agent-auth/contracts.ts +1194 -0
- package/server/lib/agent-profiles.ts +419 -0
- package/server/lib/ai.ts +285 -0
- package/server/lib/api-registry/contracts.ts +86 -0
- package/server/lib/api-registry/validation.ts +172 -0
- package/server/lib/apikey-migration.ts +258 -0
- package/server/lib/app-installer.ts +505 -0
- package/server/lib/app-tokens.ts +247 -0
- package/server/lib/approval-link.ts +27 -0
- package/server/lib/auth.ts +314 -0
- package/server/lib/auto-execute.ts +160 -0
- package/server/lib/batch.ts +242 -0
- package/server/lib/cold.ts +1048 -0
- package/server/lib/config.ts +408 -0
- package/server/lib/credential-access-audit.ts +85 -0
- package/server/lib/credential-access-policy.ts +111 -0
- package/server/lib/credential-health.ts +343 -0
- package/server/lib/credential-import.ts +608 -0
- package/server/lib/credential-scope.ts +102 -0
- package/server/lib/credential-shares.ts +190 -0
- package/server/lib/credential-transport.ts +533 -0
- package/server/lib/credential-vault.ts +77 -0
- package/server/lib/credentials.ts +422 -0
- package/server/lib/crypto.ts +8 -0
- package/server/lib/db.ts +58 -0
- package/server/lib/defaults.ts +386 -0
- package/server/lib/dex/index.ts +80 -0
- package/server/lib/dex/relay.ts +235 -0
- package/server/lib/dex/types.ts +59 -0
- package/server/lib/dex/uniswap.ts +370 -0
- package/server/lib/diary.ts +34 -0
- package/server/lib/dont-ask-again-policy.ts +41 -0
- package/server/lib/e2e-agent/artifacts.ts +36 -0
- package/server/lib/e2e-agent/contracts.ts +112 -0
- package/server/lib/e2e-agent/validation.ts +135 -0
- package/server/lib/encrypt.ts +114 -0
- package/server/lib/error.ts +20 -0
- package/server/lib/events.ts +217 -0
- package/server/lib/feature-flags.ts +93 -0
- package/server/lib/hot.ts +357 -0
- package/server/lib/human-action-summary.ts +80 -0
- package/server/lib/key-fingerprint.ts +28 -0
- package/server/lib/logger.ts +340 -0
- package/server/lib/network.ts +137 -0
- package/server/lib/notifications.ts +230 -0
- package/server/lib/oauth2-refresh.ts +241 -0
- package/server/lib/oursecret.ts +71 -0
- package/server/lib/passkey-credential.ts +360 -0
- package/server/lib/passkey.ts +68 -0
- package/server/lib/permissions.ts +299 -0
- package/server/lib/pino.ts +24 -0
- package/server/lib/policy-preview.ts +138 -0
- package/server/lib/price.ts +338 -0
- package/server/lib/prices.ts +34 -0
- package/server/lib/project-scope.ts +297 -0
- package/server/lib/resolve-action.ts +328 -0
- package/server/lib/resolve.ts +36 -0
- package/server/lib/secret-gist-share.ts +296 -0
- package/server/lib/sessions.ts +634 -0
- package/server/lib/socket-path.ts +56 -0
- package/server/lib/solana/connection.ts +26 -0
- package/server/lib/solana/jupiter.ts +128 -0
- package/server/lib/solana/transfer.ts +108 -0
- package/server/lib/solana/wallet.ts +136 -0
- package/server/lib/strategy/emits.ts +21 -0
- package/server/lib/strategy/engine.ts +1305 -0
- package/server/lib/strategy/executor.ts +115 -0
- package/server/lib/strategy/hook-context.ts +159 -0
- package/server/lib/strategy/hooks.ts +990 -0
- package/server/lib/strategy/index.ts +28 -0
- package/server/lib/strategy/installer.ts +305 -0
- package/server/lib/strategy/loader.ts +256 -0
- package/server/lib/strategy/message.ts +237 -0
- package/server/lib/strategy/repository.ts +218 -0
- package/server/lib/strategy/session-logger.ts +693 -0
- package/server/lib/strategy/sources.ts +288 -0
- package/server/lib/strategy/state.ts +189 -0
- package/server/lib/strategy/templates.ts +403 -0
- package/server/lib/strategy/tick.ts +404 -0
- package/server/lib/strategy/types.ts +230 -0
- package/server/lib/swap.ts +3 -0
- package/server/lib/temp.ts +86 -0
- package/server/lib/token-metadata.ts +86 -0
- package/server/lib/token-safety.ts +200 -0
- package/server/lib/token-search.ts +444 -0
- package/server/lib/totp.ts +194 -0
- package/server/lib/transactions.ts +123 -0
- package/server/lib/transport.ts +84 -0
- package/server/lib/txhistory/decoder.ts +262 -0
- package/server/lib/txhistory/enricher.ts +652 -0
- package/server/lib/txhistory/index.ts +391 -0
- package/server/lib/txhistory/signatures.ts +59 -0
- package/server/lib/update-check.ts +35 -0
- package/server/lib/verified-summary.ts +414 -0
- package/server/lib/view-registry.ts +80 -0
- package/server/mcp/profile-policy.ts +30 -0
- package/server/mcp/server.ts +1589 -0
- package/server/mcp/tools.ts +276 -0
- package/server/middleware/auth.ts +119 -0
- package/server/middleware/requestLogger.ts +84 -0
- package/server/routes/actions.ts +539 -0
- package/server/routes/adapters.ts +711 -0
- package/server/routes/addressbook.ts +113 -0
- package/server/routes/ai.ts +34 -0
- package/server/routes/apikeys.ts +343 -0
- package/server/routes/apps.ts +601 -0
- package/server/routes/auth.ts +406 -0
- package/server/routes/backup.ts +404 -0
- package/server/routes/batch.ts +270 -0
- package/server/routes/bookmarks.ts +162 -0
- package/server/routes/credential-shares.ts +380 -0
- package/server/routes/credential-vaults.ts +159 -0
- package/server/routes/credentials.ts +1782 -0
- package/server/routes/dashboard.ts +97 -0
- package/server/routes/defaults.ts +124 -0
- package/server/routes/flags.ts +11 -0
- package/server/routes/fund.ts +225 -0
- package/server/routes/heartbeat.ts +375 -0
- package/server/routes/import.ts +364 -0
- package/server/routes/launch.ts +665 -0
- package/server/routes/lock.ts +54 -0
- package/server/routes/logs.ts +68 -0
- package/server/routes/nuke.ts +111 -0
- package/server/routes/passkey-credentials.ts +99 -0
- package/server/routes/passkey.ts +366 -0
- package/server/routes/portfolio.ts +217 -0
- package/server/routes/price.ts +63 -0
- package/server/routes/resolve.ts +31 -0
- package/server/routes/security.ts +45 -0
- package/server/routes/send-evm.ts +241 -0
- package/server/routes/send-solana.ts +281 -0
- package/server/routes/send.ts +178 -0
- package/server/routes/setup.ts +210 -0
- package/server/routes/strategy.ts +894 -0
- package/server/routes/swap-evm.ts +352 -0
- package/server/routes/swap-solana.ts +176 -0
- package/server/routes/swap.ts +356 -0
- package/server/routes/token.ts +247 -0
- package/server/routes/unlock.ts +467 -0
- package/server/routes/views.ts +41 -0
- package/server/routes/wallet-assets.ts +361 -0
- package/server/routes/wallet-transactions.ts +515 -0
- package/server/routes/wallet.ts +709 -0
- package/server/types.ts +146 -0
- package/shared/credential-field-schema.ts +248 -0
- package/skills/auramaxx/HEARTBEAT.md +78 -0
- package/skills/auramaxx/SKILL.md +745 -0
- package/skills/auramaxx/docs/AGENT_SETUP.md +155 -0
- package/skills/auramaxx/docs/API.md +127 -0
- package/skills/auramaxx/docs/AUTH.md +318 -0
- package/skills/auramaxx/docs/CLI.md +130 -0
- package/skills/auramaxx/docs/MCP.md +122 -0
- package/skills/auramaxx/docs/TROUBLESHOOTING.md +357 -0
- package/skills/auramaxx/docs/WORKSPACE.md +673 -0
- package/skills/auramaxx/docs/security.md +227 -0
- package/skills/task-lifecycle/SKILL.md +378 -0
- package/src/app/api/[...doc]/page.tsx +36 -0
- package/src/app/api/agent-requests/route.ts +30 -0
- package/src/app/api/apps/install/route.ts +132 -0
- package/src/app/api/apps/manifests/route.ts +16 -0
- package/src/app/api/apps/static/[...path]/route.ts +57 -0
- package/src/app/api/docs/plain/route.ts +74 -0
- package/src/app/api/events/route.ts +92 -0
- package/src/app/api/page.tsx +290 -0
- package/src/app/api/workspace/[id]/apps/[wid]/route.ts +119 -0
- package/src/app/api/workspace/[id]/apps/route.ts +81 -0
- package/src/app/api/workspace/[id]/export/route.ts +67 -0
- package/src/app/api/workspace/[id]/route.ts +168 -0
- package/src/app/api/workspace/auth.ts +40 -0
- package/src/app/api/workspace/config/route.ts +121 -0
- package/src/app/api/workspace/import/route.ts +127 -0
- package/src/app/api/workspace/route.ts +116 -0
- package/src/app/app-legacy-do-not-use/page.tsx +2245 -0
- package/src/app/apple-icon.png +0 -0
- package/src/app/approve/[actionId]/page.tsx +409 -0
- package/src/app/docs/DocsPageContent.tsx +269 -0
- package/src/app/docs/[...doc]/page.tsx +41 -0
- package/src/app/docs/page.tsx +38 -0
- package/src/app/favicon.ico +0 -0
- package/src/app/globals.css +819 -0
- package/src/app/health/page.tsx +5 -0
- package/src/app/hello/page.tsx +102 -0
- package/src/app/icon.png +0 -0
- package/src/app/layout.tsx +39 -0
- package/src/app/page.tsx +1964 -0
- package/src/app/privacy/page.tsx +63 -0
- package/src/app/providers.tsx +87 -0
- package/src/app/share/[token]/page.tsx +295 -0
- package/src/app/terms/page.tsx +80 -0
- package/src/components/ChainSelector.tsx +44 -0
- package/src/components/HumanActionBar.tsx +697 -0
- package/src/components/NotificationDrawer.tsx +387 -0
- package/src/components/PasskeyEnrollmentPrompt.tsx +235 -0
- package/src/components/apps/AgentKeysApp.tsx +490 -0
- package/src/components/apps/App.tsx +153 -0
- package/src/components/apps/AppGrid.tsx +15 -0
- package/src/components/apps/DetailedAddressDrawer.tsx +325 -0
- package/src/components/apps/DraggableApp.tsx +562 -0
- package/src/components/apps/IFrameApp.tsx +73 -0
- package/src/components/apps/LogsApp.tsx +360 -0
- package/src/components/apps/SendApp.tsx +394 -0
- package/src/components/apps/SetupWizardApp.tsx +1004 -0
- package/src/components/apps/SystemDefaultsApp.tsx +845 -0
- package/src/components/apps/ThirdPartyApp.tsx +428 -0
- package/src/components/apps/TokenApp.tsx +319 -0
- package/src/components/apps/TransactionsApp.tsx +438 -0
- package/src/components/apps/WalletDetailApp.tsx +1505 -0
- package/src/components/apps/index.ts +13 -0
- package/src/components/design-system/Button.tsx +88 -0
- package/src/components/design-system/ChainIndicator.tsx +65 -0
- package/src/components/design-system/ChainSelector.tsx +147 -0
- package/src/components/design-system/ConfirmationModal.tsx +107 -0
- package/src/components/design-system/ConfirmationPopover.tsx +81 -0
- package/src/components/design-system/DownloadButton.tsx +149 -0
- package/src/components/design-system/Drawer.tsx +133 -0
- package/src/components/design-system/FilterDropdown.tsx +183 -0
- package/src/components/design-system/ItemPicker.tsx +157 -0
- package/src/components/design-system/Modal.tsx +296 -0
- package/src/components/design-system/Popover.tsx +142 -0
- package/src/components/design-system/TextInput.tsx +85 -0
- package/src/components/design-system/Toggle.tsx +65 -0
- package/src/components/design-system/TyvekCollapsibleSection.tsx +55 -0
- package/src/components/design-system/index.ts +14 -0
- package/src/components/docs/ClientSideMarkdown.tsx +51 -0
- package/src/components/docs/DocsSearchBar.tsx +118 -0
- package/src/components/docs/DocsThemeToggle.tsx +38 -0
- package/src/components/docs/PersistentDocGroup.tsx +91 -0
- package/src/components/docs/ShareUrlButton.tsx +33 -0
- package/src/components/docs/SidebarScrollMemory.tsx +56 -0
- package/src/components/health/CredentialHealthDashboard.tsx +214 -0
- package/src/components/icons/ChainIcons.tsx +72 -0
- package/src/components/layout/AppStoreDrawer.tsx +369 -0
- package/src/components/layout/ContentArea.tsx +21 -0
- package/src/components/layout/CreateViewModal.tsx +88 -0
- package/src/components/layout/LeftRail.tsx +114 -0
- package/src/components/layout/TabBar.tsx +284 -0
- package/src/components/layout/WalletSidebar.tsx +1030 -0
- package/src/components/layout/index.ts +6 -0
- package/src/components/marketing/AuraMaxxSpecOverlay.tsx +653 -0
- package/src/components/marketing/DeviceMorphExperience.tsx +216 -0
- package/src/components/vault/ApiKeysConsole.tsx +1272 -0
- package/src/components/vault/AuditConsole.tsx +600 -0
- package/src/components/vault/CredentialDetail.tsx +625 -0
- package/src/components/vault/CredentialEmpty.tsx +55 -0
- package/src/components/vault/CredentialField.tsx +583 -0
- package/src/components/vault/CredentialForm.tsx +1484 -0
- package/src/components/vault/CredentialList.tsx +265 -0
- package/src/components/vault/CredentialRow.tsx +130 -0
- package/src/components/vault/CredentialShareModal.tsx +273 -0
- package/src/components/vault/CredentialVault.tsx +1662 -0
- package/src/components/vault/CredentialWalletWidget.tsx +103 -0
- package/src/components/vault/DocsConsole.tsx +113 -0
- package/src/components/vault/ImportCredentialsModal.tsx +578 -0
- package/src/components/vault/LargeTypeModal.tsx +88 -0
- package/src/components/vault/PasswordGenerator.tsx +232 -0
- package/src/components/vault/TOTPDisplay.tsx +108 -0
- package/src/components/vault/TotpSetupPanel.tsx +198 -0
- package/src/components/vault/VaultSidebar.tsx +881 -0
- package/src/components/vault/credentialFormName.ts +91 -0
- package/src/components/vault/hooks/useVaultKeyboardShortcuts.ts +69 -0
- package/src/components/vault/types.ts +56 -0
- package/src/context/AuthContext.tsx +365 -0
- package/src/context/PriceContext.tsx +113 -0
- package/src/context/ThemeContext.tsx +164 -0
- package/src/context/WebSocketContext.tsx +269 -0
- package/src/context/WorkspaceContext.tsx +668 -0
- package/src/hooks/index.ts +4 -0
- package/src/hooks/useAgentActions.ts +552 -0
- package/src/hooks/useBalance.ts +103 -0
- package/src/hooks/useBalances.ts +129 -0
- package/src/hooks/useTheme.ts +156 -0
- package/src/instrumentation.ts +12 -0
- package/src/lib/api-docs.ts +154 -0
- package/src/lib/api.ts +474 -0
- package/src/lib/app-loader.ts +148 -0
- package/src/lib/app-registry.ts +178 -0
- package/src/lib/app-sdk.ts +157 -0
- package/src/lib/audit-console-adapter.ts +151 -0
- package/src/lib/auth-client.ts +75 -0
- package/src/lib/config.ts +74 -0
- package/src/lib/credential-field-schema.ts +11 -0
- package/src/lib/crypto.ts +112 -0
- package/src/lib/db.ts +21 -0
- package/src/lib/docs.ts +544 -0
- package/src/lib/events.ts +363 -0
- package/src/lib/pino.ts +24 -0
- package/src/lib/theme-handlers.ts +168 -0
- package/src/lib/theme.ts +351 -0
- package/src/lib/tokenData.ts +378 -0
- package/src/lib/totp-import.ts +57 -0
- package/src/lib/vault-crypto.ts +129 -0
- package/src/lib/view-registry.ts +57 -0
- package/src/lib/websocket-server.ts +302 -0
- package/src/lib/websocket-setup.ts +79 -0
- package/src/lib/wordlist.ts +2050 -0
- package/src/lib/workspace-handlers.ts +285 -0
- package/start.sh +170 -0
- package/tailwind.config.ts +99 -0
- package/tsconfig.json +42 -0
|
@@ -0,0 +1,476 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* auramaxx env — Load env vars from vault via .aura file
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* npx auramaxx env -- <cmd> [args] Run command with vault-injected env vars
|
|
6
|
+
* npx auramaxx env inject Write .env file from .aura mappings
|
|
7
|
+
* npx auramaxx env check Verify all mapped credentials exist
|
|
8
|
+
* npx auramaxx env list Show mappings without values
|
|
9
|
+
*/
|
|
10
|
+
|
|
11
|
+
import * as fs from 'fs';
|
|
12
|
+
import * as path from 'path';
|
|
13
|
+
import { spawn } from 'child_process';
|
|
14
|
+
import {
|
|
15
|
+
generateEphemeralKeypair,
|
|
16
|
+
bootstrapViaSocket,
|
|
17
|
+
bootstrapViaAuthRequest,
|
|
18
|
+
decryptWithPrivateKey,
|
|
19
|
+
createReadToken,
|
|
20
|
+
} from '../../lib/credential-transport';
|
|
21
|
+
import { serverUrl, fetchSetupStatus } from '../lib/http';
|
|
22
|
+
import { getErrorMessage } from '../../lib/error';
|
|
23
|
+
import { maybeHandleLockError } from '../lib/lock-unlock-helper';
|
|
24
|
+
import { createCredentialViaApi, getPrimaryVaultId } from '../lib/credential-create';
|
|
25
|
+
import { migrateDotenv } from '../lib/dotenv-migrate';
|
|
26
|
+
import { promptInput } from '../lib/prompt';
|
|
27
|
+
import {
|
|
28
|
+
type AuraMapping,
|
|
29
|
+
type CredentialMeta,
|
|
30
|
+
type DecryptedCredential,
|
|
31
|
+
searchCredential,
|
|
32
|
+
readCredential,
|
|
33
|
+
resolveMappings as sharedResolveMappings,
|
|
34
|
+
} from '../lib/credential-resolve';
|
|
35
|
+
import { parseAuraFile } from '../lib/aura-parser';
|
|
36
|
+
|
|
37
|
+
// ── Pre-flight check: server running + vault exists ──
|
|
38
|
+
|
|
39
|
+
function isConnectionError(err: unknown): boolean {
|
|
40
|
+
const msg = getErrorMessage(err).toLowerCase();
|
|
41
|
+
if (msg.includes('econnrefused') || msg.includes('fetch failed') || msg.includes('enoent')) return true;
|
|
42
|
+
|
|
43
|
+
const anyErr = err as { code?: unknown; errno?: unknown };
|
|
44
|
+
const code = typeof anyErr?.code === 'string' ? anyErr.code : undefined;
|
|
45
|
+
if (code === 'ECONNREFUSED' || code === 'ECONNRESET' || code === 'ENOTFOUND') return true;
|
|
46
|
+
const errno = typeof anyErr?.errno === 'number' ? anyErr.errno : undefined;
|
|
47
|
+
return errno === -61 || errno === -111; // macOS/WASI ECONNREFUSED codes
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
export async function checkServerAndVault(): Promise<void> {
|
|
51
|
+
let status: Awaited<ReturnType<typeof fetchSetupStatus>>;
|
|
52
|
+
try {
|
|
53
|
+
status = await fetchSetupStatus();
|
|
54
|
+
} catch (err: unknown) {
|
|
55
|
+
const msg = getErrorMessage(err);
|
|
56
|
+
if (isConnectionError(err)) {
|
|
57
|
+
console.error('Aura server not running. Run `npx auramaxx` first.');
|
|
58
|
+
} else {
|
|
59
|
+
console.error(`Cannot connect to Aura server: ${msg}`);
|
|
60
|
+
}
|
|
61
|
+
process.exit(1);
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
if (!status.hasWallet) {
|
|
66
|
+
console.error('No vault found. Run `npx auramaxx` to bootstrap setup.');
|
|
67
|
+
process.exit(1);
|
|
68
|
+
return;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// ── Ephemeral RSA keypair ──
|
|
73
|
+
|
|
74
|
+
const keypair = generateEphemeralKeypair();
|
|
75
|
+
|
|
76
|
+
// ── Auth: socket or AURA_TOKEN env var ──
|
|
77
|
+
|
|
78
|
+
async function getAuthToken(): Promise<string> {
|
|
79
|
+
const envToken = process.env.AURA_TOKEN;
|
|
80
|
+
if (envToken) return envToken;
|
|
81
|
+
try {
|
|
82
|
+
return await bootstrapViaSocket('cli-env', keypair);
|
|
83
|
+
} catch (socketErr) {
|
|
84
|
+
return bootstrapViaAuthRequest(serverUrl(), 'cli-env', keypair, {
|
|
85
|
+
onStatus: (message) => console.error(message),
|
|
86
|
+
}).catch((authErr) => {
|
|
87
|
+
throw new Error(`${getErrorMessage(socketErr)}\n${getErrorMessage(authErr)}`);
|
|
88
|
+
});
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
// ── .aura file parsing ──
|
|
93
|
+
|
|
94
|
+
function findAuraFile(): string | null {
|
|
95
|
+
let dir = process.cwd();
|
|
96
|
+
while (true) {
|
|
97
|
+
const candidate = path.join(dir, '.aura');
|
|
98
|
+
try {
|
|
99
|
+
if (fs.existsSync(candidate) && fs.statSync(candidate).isFile()) return candidate;
|
|
100
|
+
} catch { /* ignore stat errors */ }
|
|
101
|
+
const parent = path.dirname(dir);
|
|
102
|
+
if (parent === dir) return null;
|
|
103
|
+
dir = parent;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// parseAuraFile moved to ../lib/aura-parser.ts
|
|
108
|
+
export { parseAuraFile } from '../lib/aura-parser';
|
|
109
|
+
|
|
110
|
+
// ── Resolve mappings to env vars (delegates to shared module, audit finding #3) ──
|
|
111
|
+
|
|
112
|
+
async function resolveMappings(
|
|
113
|
+
mappings: AuraMapping[],
|
|
114
|
+
token: string,
|
|
115
|
+
readToken: string,
|
|
116
|
+
): Promise<{ resolved: Map<string, string>; errors: string[]; missing: AuraMapping[] }> {
|
|
117
|
+
const base = serverUrl();
|
|
118
|
+
const decryptFn = (encrypted: string) => decryptWithPrivateKey(encrypted, keypair.privateKeyPem);
|
|
119
|
+
return sharedResolveMappings(mappings, base, token, readToken, decryptFn);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// ── Env value escaping for .env file ──
|
|
123
|
+
|
|
124
|
+
/**
|
|
125
|
+
* Escape a value for safe inclusion in a .env file.
|
|
126
|
+
* Handles newlines, backslashes, dollar signs, and quotes.
|
|
127
|
+
*/
|
|
128
|
+
export function escapeEnvValue(value: string): string {
|
|
129
|
+
// Always double-quote and escape special chars
|
|
130
|
+
const escaped = value
|
|
131
|
+
.replace(/\\/g, '\\\\')
|
|
132
|
+
.replace(/\$/g, '\\$')
|
|
133
|
+
.replace(/"/g, '\\"')
|
|
134
|
+
.replace(/\n/g, '\\n')
|
|
135
|
+
.replace(/\r/g, '\\r');
|
|
136
|
+
return `"${escaped}"`;
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// ── Subcommands ──
|
|
140
|
+
|
|
141
|
+
function suggestFromDotenvIfPresent(): void {
|
|
142
|
+
const envPath = path.join(process.cwd(), '.env');
|
|
143
|
+
if (fs.existsSync(envPath)) {
|
|
144
|
+
console.error('Tip: Found a .env file in this directory. Run `npx auramaxx env init` to migrate it.');
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
export async function cmdRun(cmdArgs: string[]): Promise<void> {
|
|
149
|
+
if (cmdArgs.length === 0) {
|
|
150
|
+
console.error('Usage: npx auramaxx env -- <command> [args]');
|
|
151
|
+
process.exit(1);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
await checkServerAndVault();
|
|
155
|
+
|
|
156
|
+
const auraFile = findAuraFile();
|
|
157
|
+
if (!auraFile) {
|
|
158
|
+
console.error('No .aura file found in current or parent directories.');
|
|
159
|
+
suggestFromDotenvIfPresent();
|
|
160
|
+
process.exit(1);
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
const mappings = parseAuraFile(auraFile);
|
|
164
|
+
if (mappings.length === 0) {
|
|
165
|
+
console.error('No mappings found in .aura file.');
|
|
166
|
+
process.exit(1);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const token = await getAuthToken();
|
|
170
|
+
const readToken = await createReadToken(serverUrl(), token, keypair, 'cli-env-reader');
|
|
171
|
+
let { resolved, errors, missing } = await resolveMappings(mappings, token, readToken);
|
|
172
|
+
|
|
173
|
+
// Interactive creation for missing credentials (TTY only)
|
|
174
|
+
if (missing.length > 0 && process.stdin.isTTY) {
|
|
175
|
+
try {
|
|
176
|
+
const vaultId = await getPrimaryVaultId(token);
|
|
177
|
+
const created = await interactiveCreateMissing(missing, token, vaultId);
|
|
178
|
+
for (const [key, value] of created) {
|
|
179
|
+
resolved.set(key, value);
|
|
180
|
+
}
|
|
181
|
+
errors = errors.filter(e => !missing.some(m => e.includes(m.envVar) && created.has(m.envVar)));
|
|
182
|
+
missing = missing.filter(m => !created.has(m.envVar));
|
|
183
|
+
} catch (err) {
|
|
184
|
+
console.error(` Interactive setup failed: ${getErrorMessage(err)}`);
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
if (errors.length > 0 && missing.length > 0) {
|
|
189
|
+
for (const err of errors) console.error(` ✗ ${err}`);
|
|
190
|
+
console.error(`\n${errors.length} of ${mappings.length} credentials failed to resolve.`);
|
|
191
|
+
process.exit(1);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
console.error(`✓ Resolved ${resolved.size} credentials from vault`);
|
|
195
|
+
|
|
196
|
+
const env = { ...process.env };
|
|
197
|
+
for (const [key, value] of resolved) {
|
|
198
|
+
env[key] = value;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
const child = spawn(cmdArgs[0], cmdArgs.slice(1), {
|
|
202
|
+
stdio: 'inherit',
|
|
203
|
+
env,
|
|
204
|
+
shell: false,
|
|
205
|
+
});
|
|
206
|
+
|
|
207
|
+
const forwardSignal = (sig: NodeJS.Signals) => child.kill(sig);
|
|
208
|
+
process.on('SIGINT', forwardSignal);
|
|
209
|
+
process.on('SIGTERM', forwardSignal);
|
|
210
|
+
|
|
211
|
+
child.on('exit', (code, signal) => {
|
|
212
|
+
process.off('SIGINT', forwardSignal);
|
|
213
|
+
process.off('SIGTERM', forwardSignal);
|
|
214
|
+
if (signal) {
|
|
215
|
+
process.kill(process.pid, signal);
|
|
216
|
+
} else {
|
|
217
|
+
process.exit(code ?? 1);
|
|
218
|
+
}
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
export async function cmdInject(): Promise<void> {
|
|
223
|
+
await checkServerAndVault();
|
|
224
|
+
|
|
225
|
+
const auraFile = findAuraFile();
|
|
226
|
+
if (!auraFile) {
|
|
227
|
+
console.error('No .aura file found in current or parent directories.');
|
|
228
|
+
suggestFromDotenvIfPresent();
|
|
229
|
+
process.exit(1);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
const mappings = parseAuraFile(auraFile);
|
|
233
|
+
if (mappings.length === 0) {
|
|
234
|
+
console.error('No mappings found in .aura file.');
|
|
235
|
+
process.exit(1);
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
const token = await getAuthToken();
|
|
239
|
+
const readToken = await createReadToken(serverUrl(), token, keypair, 'cli-env-reader');
|
|
240
|
+
const { resolved, errors } = await resolveMappings(mappings, token, readToken);
|
|
241
|
+
|
|
242
|
+
if (errors.length > 0) {
|
|
243
|
+
for (const err of errors) console.error(` ✗ ${err}`);
|
|
244
|
+
console.error(`\n${errors.length} of ${mappings.length} credentials failed to resolve.`);
|
|
245
|
+
process.exit(1);
|
|
246
|
+
}
|
|
247
|
+
|
|
248
|
+
// Write .env in same directory as .aura
|
|
249
|
+
const envPath = path.join(path.dirname(auraFile), '.env');
|
|
250
|
+
const lines = ['# Generated by auramaxx env inject — DO NOT COMMIT'];
|
|
251
|
+
for (const [key, value] of resolved) {
|
|
252
|
+
lines.push(`${key}=${escapeEnvValue(value)}`);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Write with restrictive permissions (0600 — owner read/write only)
|
|
256
|
+
const fd = fs.openSync(envPath, 'w', 0o600);
|
|
257
|
+
fs.writeSync(fd, lines.join('\n') + '\n');
|
|
258
|
+
fs.closeSync(fd);
|
|
259
|
+
|
|
260
|
+
console.log(`✓ Resolved ${resolved.size} credentials from vault`);
|
|
261
|
+
console.log(`✓ Wrote .env (${resolved.size} variables, mode 0600)`);
|
|
262
|
+
|
|
263
|
+
// Check .gitignore
|
|
264
|
+
const gitignorePath = path.join(path.dirname(auraFile), '.gitignore');
|
|
265
|
+
if (fs.existsSync(gitignorePath)) {
|
|
266
|
+
const gitignore = fs.readFileSync(gitignorePath, 'utf-8');
|
|
267
|
+
if (!gitignore.includes('.env')) {
|
|
268
|
+
console.log('⚠ Make sure .env is in .gitignore!');
|
|
269
|
+
}
|
|
270
|
+
} else {
|
|
271
|
+
console.log('⚠ No .gitignore found — make sure .env is not committed!');
|
|
272
|
+
}
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
export async function cmdCheck(): Promise<void> {
|
|
276
|
+
await checkServerAndVault();
|
|
277
|
+
|
|
278
|
+
const auraFile = findAuraFile();
|
|
279
|
+
if (!auraFile) {
|
|
280
|
+
console.error('No .aura file found in current or parent directories.');
|
|
281
|
+
suggestFromDotenvIfPresent();
|
|
282
|
+
process.exit(1);
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
console.log(`.aura: ${auraFile}`);
|
|
286
|
+
|
|
287
|
+
const mappings = parseAuraFile(auraFile);
|
|
288
|
+
if (mappings.length === 0) {
|
|
289
|
+
console.log('No mappings found.');
|
|
290
|
+
return;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const token = await getAuthToken();
|
|
294
|
+
let allOk = true;
|
|
295
|
+
|
|
296
|
+
for (const mapping of mappings) {
|
|
297
|
+
const meta = await searchCredential(serverUrl(), token, mapping.credentialName);
|
|
298
|
+
if (meta) {
|
|
299
|
+
console.log(` ✓ ${mapping.envVar} → ${mapping.credentialName}/${mapping.field} (found)`);
|
|
300
|
+
} else {
|
|
301
|
+
console.log(` ✗ ${mapping.envVar} → ${mapping.credentialName}/${mapping.field} (not found)`);
|
|
302
|
+
allOk = false;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
console.log('');
|
|
307
|
+
if (allOk) {
|
|
308
|
+
console.log(`All ${mappings.length} credentials resolved successfully.`);
|
|
309
|
+
} else {
|
|
310
|
+
console.log('Some credentials could not be found.');
|
|
311
|
+
process.exit(1);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
function cmdList(): void {
|
|
316
|
+
const auraFile = findAuraFile();
|
|
317
|
+
if (!auraFile) {
|
|
318
|
+
console.error('No .aura file found in current or parent directories.');
|
|
319
|
+
suggestFromDotenvIfPresent();
|
|
320
|
+
process.exit(1);
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
console.log(`.aura: ${auraFile}`);
|
|
324
|
+
const mappings = parseAuraFile(auraFile);
|
|
325
|
+
|
|
326
|
+
if (mappings.length === 0) {
|
|
327
|
+
console.log('No mappings found.');
|
|
328
|
+
return;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
for (const m of mappings) {
|
|
332
|
+
const ref = m.vault ? `@${m.vault}/${m.credentialName}/${m.field}` : `${m.credentialName}/${m.field}`;
|
|
333
|
+
console.log(` ${m.envVar} → ${ref}`);
|
|
334
|
+
}
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
// ── Init (from-dotenv migration) ──
|
|
338
|
+
|
|
339
|
+
async function cmdInit(): Promise<void> {
|
|
340
|
+
await checkServerAndVault();
|
|
341
|
+
|
|
342
|
+
const args = process.argv.slice(2);
|
|
343
|
+
const fromIdx = args.indexOf('--from');
|
|
344
|
+
const fromPath = fromIdx >= 0 && fromIdx + 1 < args.length ? args[fromIdx + 1] : undefined;
|
|
345
|
+
const dryRun = args.includes('--dry-run');
|
|
346
|
+
const noGroup = args.includes('--no-group');
|
|
347
|
+
|
|
348
|
+
const envPath = fromPath || path.join(process.cwd(), '.env');
|
|
349
|
+
|
|
350
|
+
const token = await getAuthToken();
|
|
351
|
+
|
|
352
|
+
await migrateDotenv({
|
|
353
|
+
token,
|
|
354
|
+
envPath,
|
|
355
|
+
noGroup,
|
|
356
|
+
dryRun,
|
|
357
|
+
});
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
// ── Interactive credential creation for missing entries ──
|
|
361
|
+
|
|
362
|
+
async function interactiveCreateMissing(
|
|
363
|
+
missingMappings: AuraMapping[],
|
|
364
|
+
token: string,
|
|
365
|
+
vaultId: string,
|
|
366
|
+
): Promise<Map<string, string>> {
|
|
367
|
+
const resolved = new Map<string, string>();
|
|
368
|
+
|
|
369
|
+
const byCredential = new Map<string, AuraMapping[]>();
|
|
370
|
+
for (const m of missingMappings) {
|
|
371
|
+
const list = byCredential.get(m.credentialName) || [];
|
|
372
|
+
list.push(m);
|
|
373
|
+
byCredential.set(m.credentialName, list);
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
console.log(`\n ${missingMappings.length} credential(s) not found. Let's create them:\n`);
|
|
377
|
+
|
|
378
|
+
for (const [credName, mappings] of byCredential) {
|
|
379
|
+
const fields: Array<{ key: string; value: string }> = [];
|
|
380
|
+
|
|
381
|
+
for (const m of mappings) {
|
|
382
|
+
const value = await promptInput(` Enter value for ${m.envVar} (→ ${credName}/${m.field})`);
|
|
383
|
+
if (!value) {
|
|
384
|
+
console.log(` Skipped ${m.envVar}`);
|
|
385
|
+
continue;
|
|
386
|
+
}
|
|
387
|
+
fields.push({ key: m.field, value });
|
|
388
|
+
resolved.set(m.envVar, value);
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
if (fields.length > 0) {
|
|
392
|
+
const result = await createCredentialViaApi({ token, vaultId, name: credName, fields });
|
|
393
|
+
if (result.success) {
|
|
394
|
+
console.log(` ✓ Created credential: ${credName}`);
|
|
395
|
+
} else {
|
|
396
|
+
console.error(` ✗ Failed to create ${credName}: ${result.error}`);
|
|
397
|
+
for (const f of fields) {
|
|
398
|
+
const mapping = mappings.find(m => m.field === f.key);
|
|
399
|
+
if (mapping) resolved.delete(mapping.envVar);
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
return resolved;
|
|
406
|
+
}
|
|
407
|
+
|
|
408
|
+
// ── Help ──
|
|
409
|
+
|
|
410
|
+
function showHelp(): void {
|
|
411
|
+
console.log(`
|
|
412
|
+
auramaxx env — Load env vars from vault
|
|
413
|
+
|
|
414
|
+
Usage:
|
|
415
|
+
npx auramaxx env -- <cmd> [args] Run command with vault-injected env vars
|
|
416
|
+
npx auramaxx env inject Write .env file from .aura mappings
|
|
417
|
+
npx auramaxx env check Verify all mapped credentials exist
|
|
418
|
+
npx auramaxx env list Show mappings without values
|
|
419
|
+
npx auramaxx env init Migrate .env to vault + .aura
|
|
420
|
+
[--from <path>] [--dry-run] [--no-group]
|
|
421
|
+
|
|
422
|
+
Auth: Uses Unix socket by default. Falls back to /auth polling when strict local mode disables auto-approve.
|
|
423
|
+
Set AURA_TOKEN env var for headless/CI.
|
|
424
|
+
|
|
425
|
+
The .aura file maps env var names to vault credential references:
|
|
426
|
+
|
|
427
|
+
# .aura
|
|
428
|
+
DATABASE_URL=database-prod/url
|
|
429
|
+
STRIPE_KEY=stripe/secret_key
|
|
430
|
+
AGENT_TOKEN=@agent/openai/api_key # from 'agent' vault
|
|
431
|
+
`);
|
|
432
|
+
}
|
|
433
|
+
|
|
434
|
+
// ── Main ──
|
|
435
|
+
|
|
436
|
+
async function main(): Promise<void> {
|
|
437
|
+
const args = process.argv.slice(2);
|
|
438
|
+
|
|
439
|
+
const dashIdx = args.indexOf('--');
|
|
440
|
+
if (dashIdx !== -1) {
|
|
441
|
+
const cmdArgs = args.slice(dashIdx + 1);
|
|
442
|
+
return cmdRun(cmdArgs);
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
const subcommand = args[0];
|
|
446
|
+
|
|
447
|
+
if (!subcommand || subcommand === '--help' || subcommand === '-h') {
|
|
448
|
+
showHelp();
|
|
449
|
+
process.exit(0);
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
switch (subcommand) {
|
|
453
|
+
case 'init':
|
|
454
|
+
return cmdInit();
|
|
455
|
+
case 'inject':
|
|
456
|
+
return cmdInject();
|
|
457
|
+
case 'check':
|
|
458
|
+
return cmdCheck();
|
|
459
|
+
case 'list':
|
|
460
|
+
return cmdList();
|
|
461
|
+
default:
|
|
462
|
+
console.error(`Unknown subcommand: ${subcommand}`);
|
|
463
|
+
showHelp();
|
|
464
|
+
process.exit(1);
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
if (require.main === module) {
|
|
469
|
+
main().catch(async (err) => {
|
|
470
|
+
const handledLock = await maybeHandleLockError({ context: 'env command', error: err });
|
|
471
|
+
if (!handledLock) {
|
|
472
|
+
console.error(`Error: ${getErrorMessage(err)}`);
|
|
473
|
+
}
|
|
474
|
+
process.exit(1);
|
|
475
|
+
});
|
|
476
|
+
}
|
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* npx auramaxx experimental — toggle dev feature flags
|
|
3
|
+
*
|
|
4
|
+
* Usage:
|
|
5
|
+
* npx auramaxx experimental List all flags
|
|
6
|
+
* npx auramaxx experimental <FLAG> <on|off> Toggle a flag
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import { readFlags, writeFlag, getKnownFlagNames, ensureDefaults } from '../../lib/feature-flags';
|
|
10
|
+
|
|
11
|
+
function usage() {
|
|
12
|
+
console.log('Usage: npx auramaxx experimental [FLAG] [on|off]');
|
|
13
|
+
console.log('');
|
|
14
|
+
console.log(' No args List all feature flags and current values');
|
|
15
|
+
console.log(' FLAG on Enable a feature flag');
|
|
16
|
+
console.log(' FLAG off Disable a feature flag');
|
|
17
|
+
console.log('');
|
|
18
|
+
console.log(`Known flags: ${getKnownFlagNames().join(', ')}`);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
function listFlags() {
|
|
22
|
+
const flags = readFlags();
|
|
23
|
+
console.log('Feature flags:');
|
|
24
|
+
for (const [name, value] of Object.entries(flags)) {
|
|
25
|
+
console.log(` ${name}: ${value ? 'on' : 'off'}`);
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
function main() {
|
|
30
|
+
const args = process.argv.slice(2);
|
|
31
|
+
|
|
32
|
+
if (args.includes('--help') || args.includes('-h')) {
|
|
33
|
+
usage();
|
|
34
|
+
process.exit(0);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Ensure config file exists
|
|
38
|
+
ensureDefaults();
|
|
39
|
+
|
|
40
|
+
if (args.length === 0) {
|
|
41
|
+
listFlags();
|
|
42
|
+
process.exit(0);
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (args.length === 1) {
|
|
46
|
+
console.error(`Missing value. Usage: npx auramaxx experimental ${args[0]} <on|off>`);
|
|
47
|
+
process.exit(1);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
const flagName = args[0];
|
|
51
|
+
const rawValue = args[1].toLowerCase();
|
|
52
|
+
|
|
53
|
+
if (rawValue !== 'on' && rawValue !== 'off') {
|
|
54
|
+
console.error(`Invalid value "${args[1]}". Use "on" or "off".`);
|
|
55
|
+
process.exit(1);
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
const value = rawValue === 'on';
|
|
59
|
+
const result = writeFlag(flagName, value);
|
|
60
|
+
|
|
61
|
+
if (!result.ok) {
|
|
62
|
+
console.error(result.error);
|
|
63
|
+
process.exit(1);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
console.log(`${flagName}: ${value ? 'on' : 'off'}`);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
main();
|