@base44-preview/cli 0.0.48-pr.445.4fa436f → 0.0.48-pr.445.a099d3a

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.
@@ -1068,7 +1068,7 @@
1068
1068
  "/**\n * Error thrown to signal a controlled CLI exit with a specific exit code.\n * This allows proper error propagation without calling process.exit() directly,\n * making the code more testable and maintaining a single exit point.\n */\nexport class CLIExitError extends Error {\n constructor(public readonly code: number) {\n super(`CLI exited with code ${code}`);\n this.name = \"CLIExitError\";\n }\n}\n",
1069
1069
  "import { cancel } from \"@clack/prompts\";\nimport { CLIExitError } from \"@/cli/errors.js\";\n\n/**\n * Standard onCancel handler for prompt groups.\ng * Throws CLIExitError(0) for graceful exit when the user cancels.\n */\nexport const onPromptCancel = () => {\n cancel(\"Operation cancelled.\");\n throw new CLIExitError(0);\n};\n",
1070
1070
  "import { spinner } from \"@clack/prompts\";\n\n/**\n * Wraps an async operation with automatic spinner management.\n * The spinner is automatically started, and stopped on both success and error.\n *\n * @param startMessage - Message to show when spinner starts\n * @param operation - The async operation to execute. Receives an updateMessage function\n * to update the spinner text during long-running operations.\n * @param options - Optional configuration for success/error messages\n * @returns The result of the operation\n *\n * @example\n * // Simple usage\n * const data = await runTask(\n * \"Fetching data...\",\n * async () => {\n * const response = await fetch(url);\n * return response.json();\n * },\n * {\n * successMessage: \"Data fetched successfully\",\n * errorMessage: \"Failed to fetch data\",\n * }\n * );\n *\n * @example\n * // With progress updates\n * const result = await runTask(\n * \"Processing files...\",\n * async (updateMessage) => {\n * for (const file of files) {\n * updateMessage(`Processing ${file.name}...`);\n * await process(file);\n * }\n * return files.length;\n * },\n * { successMessage: \"All files processed\" }\n * );\n */\nexport async function runTask<T>(\n startMessage: string,\n operation: (updateMessage: (message: string) => void) => Promise<T>,\n options?: {\n successMessage?: string;\n errorMessage?: string;\n },\n): Promise<T> {\n const s = spinner();\n s.start(startMessage);\n\n const updateMessage = (message: string) => s.message(message);\n\n try {\n const result = await operation(updateMessage);\n s.stop(options?.successMessage || startMessage);\n return result;\n } catch (error) {\n s.error(options?.errorMessage || \"Failed\");\n throw error;\n }\n}\n",
1071
- "import { isCancel, password } from \"@clack/prompts\";\nimport { CLIExitError } from \"@/cli/errors.js\";\nimport type { ErrorHint } from \"@/core/errors.js\";\nimport { InvalidInputError } from \"@/core/errors.js\";\n\nexport interface SecretInputOptions {\n /** Value from a CLI flag (e.g., --client-secret <value>) */\n flagValue?: string;\n /** Whether to read from stdin (e.g., --client-secret-stdin was set) */\n fromStdin?: boolean;\n /** Environment variable name to check (e.g., \"BASE44_GOOGLE_CLIENT_SECRET\") */\n envVar?: string;\n /** Prompt message for interactive fallback */\n promptMessage: string;\n /** Whether we're in non-interactive mode (from CLIContext) */\n isNonInteractive: boolean;\n /** Name of the secret for error messages (e.g., \"client secret\") */\n name: string;\n /** Hint commands to show in error when secret is missing in non-interactive mode */\n hints?: ErrorHint[];\n}\n\n/**\n * Resolves a secret value through a precedence chain:\n * stdin > flag value > environment variable > interactive masked prompt\n *\n * In non-interactive mode, throws InvalidInputError with hints if no value is available.\n * Reusable by any command that needs to collect a secret from the user.\n */\nexport async function resolveSecret(\n options: SecretInputOptions,\n): Promise<string> {\n // 1. Stdin (highest precedence — safest, no shell history)\n if (options.fromStdin) {\n const value = await readStdin();\n if (value) return value;\n }\n\n // 2. Flag value\n if (options.flagValue) {\n return options.flagValue;\n }\n\n // 3. Environment variable\n if (options.envVar) {\n const envValue = process.env[options.envVar];\n if (envValue) return envValue;\n }\n\n // 4. Interactive masked prompt (lowest precedence)\n if (!options.isNonInteractive) {\n const value = await password({\n message: options.promptMessage,\n validate: (v) => {\n if (!v || v.trim().length === 0) {\n return `${options.name} is required`;\n }\n },\n });\n\n if (isCancel(value)) {\n throw new CLIExitError(0);\n }\n\n return value;\n }\n\n // Non-interactive and no value resolved — throw with hints\n throw new InvalidInputError(`Missing required ${options.name}.`, {\n hints: options.hints ?? [\n {\n message: `Provide the ${options.name} via flag, stdin, or environment variable (${options.envVar ?? \"N/A\"})`,\n },\n ],\n });\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk);\n }\n return Buffer.concat(chunks).toString(\"utf-8\").trim();\n}\n",
1071
+ "import { isCancel, password } from \"@clack/prompts\";\nimport { CLIExitError } from \"@/cli/errors.js\";\nimport type { ErrorHint } from \"@/core/errors.js\";\nimport { InvalidInputError } from \"@/core/errors.js\";\n\ninterface SecretInputOptions {\n /** Value from a CLI flag (e.g., --client-secret <value>) */\n flagValue?: string;\n /** Whether to read from stdin (e.g., --client-secret-stdin was set) */\n fromStdin?: boolean;\n /** Environment variable name to check (e.g., \"BASE44_GOOGLE_CLIENT_SECRET\") */\n envVar?: string;\n /** Prompt message for interactive fallback */\n promptMessage: string;\n /** Whether we're in non-interactive mode (from CLIContext) */\n isNonInteractive: boolean;\n /** Name of the secret for error messages (e.g., \"client secret\") */\n name: string;\n /** Hint commands to show in error when secret is missing in non-interactive mode */\n hints?: ErrorHint[];\n}\n\n/**\n * Resolves a secret value through a precedence chain:\n * stdin > flag value > environment variable > interactive masked prompt\n *\n * In non-interactive mode, throws InvalidInputError with hints if no value is available.\n * Reusable by any command that needs to collect a secret from the user.\n */\nexport async function resolveSecret(\n options: SecretInputOptions,\n): Promise<string> {\n // 1. Stdin (highest precedence — safest, no shell history)\n if (options.fromStdin) {\n const value = await readStdin();\n if (value) return value;\n }\n\n // 2. Flag value\n if (options.flagValue) {\n return options.flagValue;\n }\n\n // 3. Environment variable\n if (options.envVar) {\n const envValue = process.env[options.envVar];\n if (envValue) return envValue;\n }\n\n // 4. Interactive masked prompt (lowest precedence)\n if (!options.isNonInteractive) {\n const value = await password({\n message: options.promptMessage,\n validate: (v) => {\n if (!v || v.trim().length === 0) {\n return `${options.name} is required`;\n }\n },\n });\n\n if (isCancel(value)) {\n throw new CLIExitError(0);\n }\n\n return value;\n }\n\n // Non-interactive and no value resolved — throw with hints\n throw new InvalidInputError(`Missing required ${options.name}.`, {\n hints: options.hints ?? [\n {\n message: `Provide the ${options.name} via flag, stdin, or environment variable (${options.envVar ?? \"N/A\"})`,\n },\n ],\n });\n}\n\nasync function readStdin(): Promise<string> {\n const chunks: Buffer[] = [];\n for await (const chunk of process.stdin) {\n chunks.push(chunk);\n }\n return Buffer.concat(chunks).toString(\"utf-8\").trim();\n}\n",
1072
1072
  "import { getBase44ApiUrl } from \"@/core/config.js\";\nimport { getAppConfig } from \"@/core/project/index.js\";\n\n/**\n * Gets the dashboard URL for a project.\n *\n * @param projectId - Optional project ID. If not provided, uses cached appId from getAppConfig().\n * @returns The dashboard URL\n * @throws Error if no projectId provided and app config is not initialized\n */\nexport function getDashboardUrl(projectId?: string): string {\n const id = projectId ?? getAppConfig().id;\n return `${getBase44ApiUrl()}/apps/${id}/editor/workspace/overview`;\n}\n\nexport function getConnectorsUrl(projectId?: string): string {\n const id = projectId ?? getAppConfig().id;\n return `${getBase44ApiUrl()}/apps/${id}/editor/workspace/app-connections`;\n}\n",
1073
1073
  "import { isEmpty } from \"lodash\";\nimport { stringify } from \"yaml\";\n\nexport const YAML_INDENT = 2;\n\ntype YamlReplacer = NonNullable<Parameters<typeof stringify>[1]>;\n\ninterface FormatYamlOptions {\n /** Strip keys whose value is null, undefined, or empty array/string (default: true) */\n stripEmpty?: boolean;\n}\n\nconst stripEmptyReplacer: YamlReplacer = (_key, value) => {\n if (typeof value === \"number\" || typeof value === \"boolean\") return value;\n if (isEmpty(value)) return undefined;\n return value;\n};\n\n/**\n * Format a data object as YAML, stripping empty values by default.\n */\nexport function formatYaml(\n data: unknown,\n options: FormatYamlOptions = {},\n): string {\n const { stripEmpty = true } = options;\n const replacer = stripEmpty ? stripEmptyReplacer : undefined;\n return stringify(data, replacer, { indent: YAML_INDENT }).trimEnd();\n}\n",
1074
1074
  "'use strict';\n\nvar composer = require('./compose/composer.js');\nvar Document = require('./doc/Document.js');\nvar Schema = require('./schema/Schema.js');\nvar errors = require('./errors.js');\nvar Alias = require('./nodes/Alias.js');\nvar identity = require('./nodes/identity.js');\nvar Pair = require('./nodes/Pair.js');\nvar Scalar = require('./nodes/Scalar.js');\nvar YAMLMap = require('./nodes/YAMLMap.js');\nvar YAMLSeq = require('./nodes/YAMLSeq.js');\nvar cst = require('./parse/cst.js');\nvar lexer = require('./parse/lexer.js');\nvar lineCounter = require('./parse/line-counter.js');\nvar parser = require('./parse/parser.js');\nvar publicApi = require('./public-api.js');\nvar visit = require('./visit.js');\n\n\n\nexports.Composer = composer.Composer;\nexports.Document = Document.Document;\nexports.Schema = Schema.Schema;\nexports.YAMLError = errors.YAMLError;\nexports.YAMLParseError = errors.YAMLParseError;\nexports.YAMLWarning = errors.YAMLWarning;\nexports.Alias = Alias.Alias;\nexports.isAlias = identity.isAlias;\nexports.isCollection = identity.isCollection;\nexports.isDocument = identity.isDocument;\nexports.isMap = identity.isMap;\nexports.isNode = identity.isNode;\nexports.isPair = identity.isPair;\nexports.isScalar = identity.isScalar;\nexports.isSeq = identity.isSeq;\nexports.Pair = Pair.Pair;\nexports.Scalar = Scalar.Scalar;\nexports.YAMLMap = YAMLMap.YAMLMap;\nexports.YAMLSeq = YAMLSeq.YAMLSeq;\nexports.CST = cst;\nexports.Lexer = lexer.Lexer;\nexports.LineCounter = lineCounter.LineCounter;\nexports.Parser = parser.Parser;\nexports.parse = publicApi.parse;\nexports.parseAllDocuments = publicApi.parseAllDocuments;\nexports.parseDocument = publicApi.parseDocument;\nexports.stringify = publicApi.stringify;\nexports.visit = visit.visit;\nexports.visitAsync = visit.visitAsync;\n",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@base44-preview/cli",
3
- "version": "0.0.48-pr.445.4fa436f",
3
+ "version": "0.0.48-pr.445.a099d3a",
4
4
  "description": "Base44 CLI - Unified interface for managing Base44 applications",
5
5
  "type": "module",
6
6
  "bin": {