@bedrock-rbx/core 0.1.0-beta.1 → 0.1.0-beta.2
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/dist/cli/run.mjs +22 -14
- package/dist/cli/run.mjs.map +1 -1
- package/dist/config.d.mts +1 -1
- package/dist/{define-config-D-LAhfSJ.d.mts → define-config-87u2jqjM.d.mts} +8 -16
- package/dist/{define-config-D-LAhfSJ.d.mts.map → define-config-87u2jqjM.d.mts.map} +1 -1
- package/dist/index.d.mts +10 -33
- package/dist/index.d.mts.map +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{migrate-mantle-state-DqbJ1TLq.mjs → migrate-mantle-state-_7Tkn0hG.mjs} +256 -344
- package/dist/migrate-mantle-state-_7Tkn0hG.mjs.map +1 -0
- package/package.json +4 -4
- package/dist/migrate-mantle-state-DqbJ1TLq.mjs.map +0 -1
package/dist/cli/run.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"run.mjs","names":["RECOGNIZED_FLAGS","SADE_RESERVED","readProcessEnvironment","defaultDeploy","defaultLoadConfig","loadOptionsFor","dispatchEnvironments","buildGetEnvironment","cancelAsFailed","defaultLoadConfig","readFile","nodeReadFile","defaultLoadConfig","defaultPreviewDiff","defaultIsCancel","defaultPath","defaultSelect","defaultText","defaultBuildStatePort","defaultMigrateMantleState","nodeMkdir","nodeWriteFile","cancel","manifest.version"],"sources":["../../package.json","../../src/cli/parse-options.ts","../../src/cli/render.ts","../../src/cli/commands/deploy.ts","../../src/shell/preview-diff.ts","../../src/cli/commands/diff.ts","../../src/cli/default-migrate-prompt-port.ts","../../src/cli/parse-migrate-options.ts","../../src/cli/commands/describe-unknown.ts","../../src/cli/commands/write-migrated-states.ts","../../src/core/migrate/render-migration-report-md.ts","../../src/core/migrate/serialize-migration-report.ts","../../src/cli/commands/write-migration-report.ts","../../src/cli/commands/finalize-migration.ts","../../src/cli/commands/resolve-migrate-inputs.ts","../../src/cli/commands/migrate.ts","../../src/cli/index.ts","../../src/cli/run.ts"],"sourcesContent":["","import type { Result } from \"@bedrock-rbx/ocale\";\n\nimport process from \"node:process\";\n\n/**\n * Typed shape command actions consume after the raw sade options object has\n * been validated and normalized.\n */\nexport interface CommonOptions {\n\t/** Roblox Open Cloud API key override; falls back to ROBLOX_API_KEY when undefined. */\n\treadonly apiKey?: string;\n\t/** Explicit config file path; when undefined the loader's discovery rules apply. */\n\treadonly configFile?: string;\n\t/** Target environment names. Sade collects `--env` repeatedly into this list. */\n\treadonly environments: ReadonlyArray<string>;\n\t/** GitHub token override; falls back to GITHUB_TOKEN when undefined. */\n\treadonly githubToken?: string;\n}\n\n/**\n * Failure modes surfaced by `parseCommonOptions`. Every variant names the\n * offending flag so callers can render a precise diagnostic.\n */\nexport type ParseOptionsError =\n\t| { readonly flag: string; readonly kind: \"invalidValue\" }\n\t| { readonly flag: string; readonly kind: \"missingRequired\" }\n\t| { readonly flag: string; readonly kind: \"unknownFlag\" };\n\nconst RECOGNIZED_FLAGS: ReadonlySet<string> = new Set([\n\t\"api-key\",\n\t\"apiKey\",\n\t\"config\",\n\t\"env\",\n\t\"github-token\",\n\t\"githubToken\",\n]);\n\nconst SADE_RESERVED: ReadonlySet<string> = new Set([\"--\", \"_\", \"h\", \"help\", \"v\", \"version\"]);\n\n/**\n * Translate the raw sade options POJO into a typed `CommonOptions`. Reads\n * `BEDROCK_ENVIRONMENT` from `process.env` as a fallback when `--env` is\n * absent; inject `getEnvironment` to redirect or isolate the lookup. No\n * clack, no sade types. Reused by `bedrock deploy` and `bedrock diff`.\n * @param rawOptions - The options object sade hands the action callback.\n * @param getEnvironment - Reads an environment variable; consulted as a\n * fallback for `--env` when no flag was supplied. Defaults to a\n * `process.env` reader.\n * @returns `Ok(CommonOptions)` on success, or `Err(ParseOptionsError)` when a\n * required flag is missing or an unrecognized flag was supplied.\n */\nexport function parseCommonOptions(\n\trawOptions: Readonly<Record<string, unknown>>,\n\tgetEnvironment: (name: string) => string | undefined = readProcessEnvironment,\n): Result<CommonOptions, ParseOptionsError> {\n\tfor (const key of Object.keys(rawOptions)) {\n\t\tif (!RECOGNIZED_FLAGS.has(key) && !SADE_RESERVED.has(key)) {\n\t\t\treturn { err: { flag: key, kind: \"unknownFlag\" }, success: false };\n\t\t}\n\t}\n\n\tconst environments = resolveEnvironments(rawOptions[\"env\"], getEnvironment);\n\tif (!environments.success) {\n\t\treturn environments;\n\t}\n\n\tconst apiKey = pickString(rawOptions, \"apiKey\", \"api-key\");\n\tconst configFile = pickString(rawOptions, \"config\");\n\tconst githubToken = pickString(rawOptions, \"githubToken\", \"github-token\");\n\n\treturn {\n\t\tdata: {\n\t\t\tenvironments: environments.data,\n\t\t\t...(apiKey === undefined ? {} : { apiKey }),\n\t\t\t...(configFile === undefined ? {} : { configFile }),\n\t\t\t...(githubToken === undefined ? {} : { githubToken }),\n\t\t},\n\t\tsuccess: true,\n\t};\n}\n\nfunction resolveEnvironments(\n\traw: unknown,\n\tgetEnvironment: (name: string) => string | undefined,\n): Result<ReadonlyArray<string>, ParseOptionsError> {\n\tif (raw === undefined) {\n\t\tconst fallback = getEnvironment(\"BEDROCK_ENVIRONMENT\");\n\t\tif (fallback === undefined) {\n\t\t\treturn { err: { flag: \"env\", kind: \"missingRequired\" }, success: false };\n\t\t}\n\n\t\treturn { data: [fallback], success: true };\n\t}\n\n\tconst candidates = Array.isArray(raw) ? raw : [raw];\n\tconst environments: Array<string> = [];\n\tfor (const candidate of candidates) {\n\t\tif (typeof candidate !== \"string\") {\n\t\t\treturn { err: { flag: \"env\", kind: \"invalidValue\" }, success: false };\n\t\t}\n\n\t\tenvironments.push(candidate);\n\t}\n\n\treturn { data: environments, success: true };\n}\n\nfunction readProcessEnvironment(name: string): string | undefined {\n\treturn process.env[name];\n}\n\nfunction pickString(\n\trawOptions: Readonly<Record<string, unknown>>,\n\t...keys: ReadonlyArray<string>\n): string | undefined {\n\tfor (const key of keys) {\n\t\tconst value = rawOptions[key];\n\t\tif (typeof value === \"string\") {\n\t\t\treturn value;\n\t\t}\n\t}\n\n\treturn undefined;\n}\n","import { PermissionError } from \"@bedrock-rbx/ocale\";\nimport { cancel, intro, log, outro } from \"@clack/prompts\";\n\nimport type { ConfigError } from \"../core/config-error.ts\";\nimport type { MigrateError, MigrationSummary } from \"../core/migrate/migration-report.ts\";\nimport type { StateError } from \"../core/state.ts\";\nimport type { ApplyError } from \"../shell/apply-ops.ts\";\nimport type { BuildDesiredError } from \"../shell/build-desired.ts\";\nimport type { MissingCredentialError, UnsupportedBackendError } from \"../shell/build-state-port.ts\";\nimport type { DeployError } from \"../shell/deploy.ts\";\nimport type { ParseMigrateError } from \"./parse-migrate-options.ts\";\nimport type { ParseOptionsError } from \"./parse-options.ts\";\n\n/**\n * Output port the CLI renders through. Mirrors the subset of `@clack/prompts`\n * the bedrock CLI uses today; tests inject a fake to assert what was rendered.\n */\nexport interface ClackPort {\n\t/** End an interactive flow with a cancellation marker. */\n\tcancel(message: string): void;\n\t/** Open a framed section with a title (used for command intros). */\n\tintro(message: string): void;\n\t/** Render a single error line inside an open frame. */\n\tlogError(message: string): void;\n\t/** Render a single neutral line inside an open frame. */\n\tlogMessage(message: string): void;\n\t/** Render a single success line inside an open frame. */\n\tlogSuccess(message: string): void;\n\t/** Close the current framed section with a final message. */\n\toutro(message: string): void;\n}\n\n/** Inputs for {@link renderStateWriteError}. */\ninterface StateWriteErrorRender {\n\t/** Environment whose state could not be written. */\n\treadonly environment: string;\n\t/** The state-error returned by the adapter. */\n\treadonly err: StateError;\n}\n\n/** Inputs for {@link renderMigrationSummary}. */\ninterface MigrationSummaryRender {\n\t/** Path to the Markdown report on disk. Pointed at from the action-required and review-needed lines. */\n\treadonly reportPath: string;\n\t/** Aggregate counts from a `MigrationReport`. */\n\treadonly summary: MigrationSummary;\n}\n\n/**\n * Render a `DeployError` to the supplied `ClackPort` as a single error line.\n * Each variant produces a distinct, terse diagnostic; wrapped variants\n * (`applyFailed`, `buildDesiredFailed`, `configLoadFailed`, `stateReadFailed`,\n * `stateWriteFailed`) surface the inner cause's actionable detail (file path,\n * resource key, parser message, HTTP failure, validator issue) so the reader\n * does not have to inspect the full cause to act.\n * @param err - The deploy error to describe.\n * @param port - The output port the diagnostic is written to.\n */\nexport function renderDeployError(err: DeployError, port: ClackPort): void {\n\tport.logError(deployErrorMessage(err));\n}\n\n/**\n * Render a `ParseOptionsError` to the supplied `ClackPort` as a single\n * error line. Each variant names the offending flag so the diagnostic\n * pinpoints what the caller needs to change.\n * @param err - The parse error to describe.\n * @param port - The output port the diagnostic is written to.\n */\nexport function renderParseError(err: ParseOptionsError, port: ClackPort): void {\n\tport.logError(parseErrorMessage(err));\n}\n\n/**\n * Construct a `ClackPort` whose methods delegate to `@clack/prompts`. The\n * resulting port writes to `process.stdout` via clack's defaults.\n * @returns A port whose six methods each invoke the matching clack helper.\n */\nexport function createClackPort(): ClackPort {\n\treturn {\n\t\tcancel: (message) => {\n\t\t\tcancel(message);\n\t\t},\n\t\tintro: (message) => {\n\t\t\tintro(message);\n\t\t},\n\t\tlogError: (message) => {\n\t\t\tlog.error(message);\n\t\t},\n\t\tlogMessage: (message) => {\n\t\t\tlog.message(message);\n\t\t},\n\t\tlogSuccess: (message) => {\n\t\t\tlog.success(message);\n\t\t},\n\t\toutro: (message) => {\n\t\t\toutro(message);\n\t\t},\n\t};\n}\n\n/**\n * Render a `ParseMigrateError` to the supplied `ClackPort`. Reuses\n * `parseErrorMessage` for the three flag-shape variants and adds a\n * dedicated message for `unknownSource` listing the supported sources.\n * @param err - The parse error to describe.\n * @param port - The output port the diagnostic is written to.\n */\nexport function renderMigrateParseError(err: ParseMigrateError, port: ClackPort): void {\n\tport.logError(migrateParseErrorMessage(err));\n}\n\n/**\n * Render a `MigrateError` to the supplied `ClackPort` as a single error\n * line. Each variant points at the offending Mantle state file path,\n * primary-environment input, or wrapped `ConfigError` so the reader can\n * act without inspecting the raw error object.\n * @param err - The migrate error to describe.\n * @param port - The output port the diagnostic is written to.\n */\nexport function renderMigrateError(err: MigrateError, port: ClackPort): void {\n\tport.logError(migrateErrorMessage(err));\n}\n\n/**\n * Render a `MissingCredentialError` or `UnsupportedBackendError`\n * surfaced when the migrate command tried to default-construct the\n * configured `StatePort` and was missing its inputs.\n * @param err - The error returned by `buildStatePort`.\n * @param port - The output port the diagnostic is written to.\n */\nexport function renderBuildStatePortError(\n\terr: MissingCredentialError | UnsupportedBackendError,\n\tport: ClackPort,\n): void {\n\tport.logError(buildStatePortErrorMessage(err));\n}\n\n/**\n * Render the post-migrate review prompt to the supplied `ClackPort`.\n * Three outcomes:\n *\n * - Any `ambiguous` warnings exist: emit a single error line directing\n * the user to the report. The migration ran but there are decisions\n * the user still needs to make before deploy will be meaningful.\n * - No `ambiguous` warnings but non-zero `blocked` / `deferred` /\n * `interpretive`: emit a single success line pointing at the report\n * for auditing.\n * - All counts zero: silent. The closing `outro(\"migrate succeeded\")`\n * already speaks for the run.\n * @param input - Counts plus the path of the Markdown report.\n * @param port - The output port the line is written to.\n */\nexport function renderMigrationSummary(input: MigrationSummaryRender, port: ClackPort): void {\n\tconst { ambiguousCount, blockedCount, deferredCount, interpretiveCount } = input.summary;\n\tif (ambiguousCount > 0) {\n\t\tport.logError(\n\t\t\t`action required: ${String(ambiguousCount)} fields need your input. See ${input.reportPath}`,\n\t\t);\n\t\treturn;\n\t}\n\n\tconst reviewable = blockedCount + deferredCount + interpretiveCount;\n\tif (reviewable > 0) {\n\t\tport.logSuccess(\n\t\t\t`migration complete; see ${input.reportPath} for ${String(reviewable)} auto-mapped or skipped fields`,\n\t\t);\n\t}\n}\n\n/**\n * Render a `StateError` produced when the migrator wrote a per-environment\n * state through the `StatePort`. Names the environment alongside the\n * adapter's failure reason so the reader knows which write failed.\n * @param input - Environment + state-error to describe.\n * @param port - The output port the diagnostic is written to.\n */\nexport function renderStateWriteError(input: StateWriteErrorRender, port: ClackPort): void {\n\tport.logError(\n\t\t`state write failed for '${input.environment}' (${input.err.file}): ${input.err.reason}`,\n\t);\n}\n\nfunction permissionDetail(err: PermissionError): string {\n\tconst isPlural = err.requiredScopes.length > 1;\n\tconst label = isPlural ? \"scopes\" : \"scope\";\n\tconst pronoun = isPlural ? \"them\" : \"it\";\n\tconst scopeList = err.requiredScopes.map((scope) => `'${scope}'`).join(\", \");\n\treturn `${err.message} on ${err.operationKey}: missing required ${label} ${scopeList}. Grant ${pronoun} on the API key at https://create.roblox.com/credentials`;\n}\n\nfunction applyCauseDetail(cause: ApplyError): string {\n\tswitch (cause.kind) {\n\t\tcase \"driverFailure\": {\n\t\t\tif (cause.cause instanceof PermissionError) {\n\t\t\t\treturn permissionDetail(cause.cause);\n\t\t\t}\n\n\t\t\treturn cause.cause.message;\n\t\t}\n\t\tcase \"updateUnsupported\": {\n\t\t\treturn \"update not supported\";\n\t\t}\n\t}\n}\n\nfunction buildDesiredDetail(cause: BuildDesiredError): string {\n\tswitch (cause.kind) {\n\t\tcase \"fileReadFailed\": {\n\t\t\treturn `(${cause.filePath}): ${cause.reason}`;\n\t\t}\n\t\tcase \"iconRemovalRejected\": {\n\t\t\treturn `: ${cause.message}`;\n\t\t}\n\t}\n}\n\nfunction configErrorDetail(err: ConfigError): string {\n\tswitch (err.kind) {\n\t\tcase \"configFunctionFailed\": {\n\t\t\treturn `${err.sourceFile}: config function threw: ${err.message}`;\n\t\t}\n\t\tcase \"fileNotFound\": {\n\t\t\treturn `no bedrock config under ${err.searchedFrom}`;\n\t\t}\n\t\tcase \"luauRuntimeMissing\": {\n\t\t\treturn `${err.sourceFile}: ${err.hint}`;\n\t\t}\n\t\tcase \"parseFailed\": {\n\t\t\treturn `${err.sourceFile}: ${err.message}`;\n\t\t}\n\t\tcase \"validationFailed\": {\n\t\t\tconst first = err.issues[0];\n\t\t\treturn first === undefined\n\t\t\t\t? `${err.sourceFile}: invalid`\n\t\t\t\t: `${err.sourceFile}: ${first.path.join(\".\")} ${first.message}`;\n\t\t}\n\t}\n}\n\nfunction stateErrorDetail(cause: StateError): string {\n\treturn `(${cause.file}): ${cause.reason}`;\n}\n\n/* eslint-disable-next-line max-lines-per-function -- single exhaustive switch over every DeployError variant is clearer than splitting into a wrapped-vs-unwrapped predicate plus a parallel prefix table. */\nfunction deployErrorMessage(err: DeployError): string {\n\tswitch (err.kind) {\n\t\tcase \"applyFailed\": {\n\t\t\treturn `apply failed for '${err.cause.key}': ${applyCauseDetail(err.cause)}`;\n\t\t}\n\t\tcase \"buildDesiredFailed\": {\n\t\t\treturn `build desired state failed for '${err.cause.key}' ${buildDesiredDetail(err.cause)}`;\n\t\t}\n\t\tcase \"configLoadFailed\": {\n\t\t\treturn `config load failed: ${configErrorDetail(err.cause)}`;\n\t\t}\n\t\tcase \"incompletePlaceEntry\": {\n\t\t\treturn `place '${err.key}' is missing '${err.missingField}' under environment '${err.environment}'`;\n\t\t}\n\t\tcase \"incompleteUniverseEntry\": {\n\t\t\treturn `universe is missing '${err.missingField}' under environment '${err.environment}'`;\n\t\t}\n\t\tcase \"missingCredential\": {\n\t\t\treturn `missing credential: environment variable ${err.variable} is not set`;\n\t\t}\n\t\tcase \"registryConfigMissing\": {\n\t\t\treturn `registry config missing '${err.missing}' (${err.hint})`;\n\t\t}\n\t\tcase \"stateNotConfigured\": {\n\t\t\treturn `state not configured for environment '${err.environment}'`;\n\t\t}\n\t\tcase \"stateReadFailed\": {\n\t\t\treturn `state read failed ${stateErrorDetail(err.cause)}`;\n\t\t}\n\t\tcase \"stateWriteFailed\": {\n\t\t\treturn `state write failed ${stateErrorDetail(err.cause)}`;\n\t\t}\n\t\tcase \"unknownEnvironment\": {\n\t\t\treturn `unknown environment '${err.environment}' (declared: ${err.declared.join(\", \")})`;\n\t\t}\n\t\tcase \"unsupportedBackend\": {\n\t\t\treturn `unsupported state backend '${err.backend}' (${err.hint})`;\n\t\t}\n\t}\n}\n\nfunction parseErrorMessage(err: ParseOptionsError): string {\n\tswitch (err.kind) {\n\t\tcase \"invalidValue\": {\n\t\t\treturn `invalid value for flag '--${err.flag}' (expected a string)`;\n\t\t}\n\t\tcase \"missingRequired\": {\n\t\t\treturn `missing required flag --${err.flag}`;\n\t\t}\n\t\tcase \"unknownFlag\": {\n\t\t\treturn `unknown flag '--${err.flag}'`;\n\t\t}\n\t}\n}\n\nfunction migrateParseErrorMessage(err: ParseMigrateError): string {\n\tif (err.kind === \"unknownSource\") {\n\t\treturn `unknown migration source '${err.received}' (supported: ${err.supported.join(\", \")})`;\n\t}\n\n\treturn parseErrorMessage(err);\n}\n\nfunction migrateErrorMessage(err: MigrateError): string {\n\tswitch (err.kind) {\n\t\tcase \"internalError\": {\n\t\t\treturn `migrate internal error: ${err.reason} (${configErrorDetail(err.cause)})`;\n\t\t}\n\t\tcase \"primaryEnvironmentNotFound\": {\n\t\t\treturn `primary environment '${err.primary}' not found (available: ${err.available.join(\", \")})`;\n\t\t}\n\t\tcase \"primaryEnvironmentRequired\": {\n\t\t\treturn `primary environment required (available: ${err.available.join(\", \")})`;\n\t\t}\n\t\tcase \"stateFileNotFound\": {\n\t\t\treturn `Mantle state file not found at '${err.path}'`;\n\t\t}\n\t\tcase \"stateParseFailed\": {\n\t\t\treturn `Mantle state file at '${err.path}' could not be parsed: ${err.reason}`;\n\t\t}\n\t\tcase \"unsupportedMantleStateVersion\": {\n\t\t\treturn `unsupported Mantle state version '${err.found}' (supported: ${err.supported.join(\", \")})`;\n\t\t}\n\t}\n}\n\nfunction buildStatePortErrorMessage(err: MissingCredentialError | UnsupportedBackendError): string {\n\tswitch (err.kind) {\n\t\tcase \"missingCredential\": {\n\t\t\treturn `missing credential: environment variable ${err.variable} is not set`;\n\t\t}\n\t\tcase \"unsupportedBackend\": {\n\t\t\treturn `unsupported state backend '${err.backend}' (${err.hint})`;\n\t\t}\n\t}\n}\n","import process from \"node:process\";\n\nimport type { Config } from \"../../core/schema.ts\";\nimport { deploy as defaultDeploy } from \"../../shell/deploy.ts\";\nimport {\n\tloadConfig as defaultLoadConfig,\n\ttype LoadConfigOptions,\n} from \"../../shell/load-config.ts\";\nimport { EXIT_ERROR, EXIT_OK } from \"../exit-codes.ts\";\nimport type { ProgDeps } from \"../index.ts\";\nimport { type CommonOptions, parseCommonOptions } from \"../parse-options.ts\";\nimport { type ClackPort, createClackPort, renderDeployError, renderParseError } from \"../render.ts\";\n\ninterface ResolvedDeploy {\n\treadonly clack: ClackPort;\n\treadonly deploy: typeof defaultDeploy;\n\treadonly exit: (code: number) => void;\n\treadonly loadConfig: typeof defaultLoadConfig;\n}\n\ninterface DispatchInputs {\n\treadonly config: Config;\n\treadonly environments: ReadonlyArray<string>;\n\treadonly getEnv: (name: string) => string | undefined;\n\treadonly resolved: ResolvedDeploy;\n}\n\n/**\n * Build the sade action for `bedrock deploy`. The returned function consumes\n * the raw options object sade hands the action callback, parses it via\n * `parseCommonOptions`, loads the project config once, and dispatches\n * `deploy()` for each `--env` value in order. Per-env successes and failures\n * render through clack as a single line each; the aggregated exit code is\n * `EXIT_OK` only when every env succeeded.\n * @param deps - Dependency overrides; missing slots are default-constructed\n * from real implementations.\n * @returns An async sade action that returns once `deps.exit` was invoked.\n */\nexport function deployCommand(\n\tdeps: ProgDeps,\n): (rawOptions: Record<string, unknown>) => Promise<void> {\n\tconst resolved = resolveDeploy(deps);\n\treturn async (rawOptions) => {\n\t\tconst code = await runDeploy(rawOptions, resolved);\n\t\tresolved.exit(code);\n\t};\n}\n\nfunction resolveDeploy(deps: ProgDeps): ResolvedDeploy {\n\treturn {\n\t\tclack: deps.clack ?? createClackPort(),\n\t\tdeploy: deps.deploy ?? defaultDeploy,\n\t\texit: deps.exit ?? ((code: number) => process.exit(code)),\n\t\tloadConfig: deps.loadConfig ?? defaultLoadConfig,\n\t};\n}\n\nfunction loadOptionsFor(parsed: CommonOptions): LoadConfigOptions | undefined {\n\treturn parsed.configFile === undefined ? undefined : { configFile: parsed.configFile };\n}\n\nasync function dispatchEnvironments(inputs: DispatchInputs): Promise<ReadonlyArray<string>> {\n\tconst { config, environments, getEnv, resolved } = inputs;\n\tconst failed: Array<string> = [];\n\tfor (const environment of environments) {\n\t\tconst result = await resolved.deploy({\n\t\t\tconfig,\n\t\t\tenvironment,\n\t\t\tgetEnv,\n\t\t});\n\t\tif (result.success) {\n\t\t\tresolved.clack.logSuccess(\n\t\t\t\t`${environment}: ${result.data.resources.length} resources reconciled`,\n\t\t\t);\n\t\t} else {\n\t\t\trenderDeployError(result.err, resolved.clack);\n\t\t\tfailed.push(environment);\n\t\t}\n\t}\n\n\treturn failed;\n}\n\nfunction buildGetEnvironment(parsed: CommonOptions): (name: string) => string | undefined {\n\treturn (name) => {\n\t\tif (name === \"ROBLOX_API_KEY\" && parsed.apiKey !== undefined) {\n\t\t\treturn parsed.apiKey;\n\t\t}\n\n\t\tif (name === \"GITHUB_TOKEN\" && parsed.githubToken !== undefined) {\n\t\t\treturn parsed.githubToken;\n\t\t}\n\n\t\treturn process.env[name];\n\t};\n}\n\nfunction cancelAsFailed(clack: ClackPort): void {\n\tclack.cancel(\"deploy failed\");\n}\n\nasync function runDeploy(\n\trawOptions: Record<string, unknown>,\n\tresolved: ResolvedDeploy,\n): Promise<number> {\n\tresolved.clack.intro(\"bedrock deploy\");\n\n\tconst parsed = parseCommonOptions(rawOptions);\n\tif (!parsed.success) {\n\t\trenderParseError(parsed.err, resolved.clack);\n\t\tcancelAsFailed(resolved.clack);\n\t\treturn EXIT_ERROR;\n\t}\n\n\tconst loaded = await resolved.loadConfig(loadOptionsFor(parsed.data));\n\tif (!loaded.success) {\n\t\trenderDeployError({ cause: loaded.err, kind: \"configLoadFailed\" }, resolved.clack);\n\t\tcancelAsFailed(resolved.clack);\n\t\treturn EXIT_ERROR;\n\t}\n\n\tconst failures = await dispatchEnvironments({\n\t\tconfig: loaded.data,\n\t\tenvironments: parsed.data.environments,\n\t\tgetEnv: buildGetEnvironment(parsed.data),\n\t\tresolved,\n\t});\n\tif (failures.length > 0) {\n\t\tcancelAsFailed(resolved.clack);\n\t\treturn EXIT_ERROR;\n\t}\n\n\tresolved.clack.outro(\"deploy succeeded\");\n\treturn EXIT_OK;\n}\n","import type { Result } from \"@bedrock-rbx/ocale\";\n\nimport { readFile as nodeReadFile } from \"node:fs/promises\";\nimport process from \"node:process\";\n\nimport type { GistFetch } from \"../adapters/gist-state-adapter.ts\";\nimport type { ConfigError } from \"../core/config-error.ts\";\nimport { diff } from \"../core/diff.ts\";\nimport { flattenConfig } from \"../core/flatten.ts\";\nimport type { Operation } from \"../core/operations.ts\";\nimport { resolveStateConfig, type StateNotConfiguredError } from \"../core/resolve-state-config.ts\";\nimport type { Config, ResolvedConfig } from \"../core/schema.ts\";\nimport {\n\ttype IncompletePlaceEntryError,\n\ttype IncompleteUniverseEntryError,\n\tselectEnvironment,\n\ttype UnknownEnvironmentError,\n} from \"../core/select-environment.ts\";\nimport type { StateError } from \"../core/state.ts\";\nimport { validatePlan } from \"../core/validate-plan.ts\";\nimport type { StatePort } from \"../ports/state-port.ts\";\nimport { buildDesired, type BuildDesiredError } from \"./build-desired.ts\";\nimport {\n\tbuildStatePort,\n\ttype MissingCredentialError,\n\ttype UnsupportedBackendError,\n} from \"./build-state-port.ts\";\nimport { loadConfig as defaultLoadConfig, type LoadConfigOptions } from \"./load-config.ts\";\n\n/**\n * Inputs for `previewDiff`. Mirrors `DeployOptions` minus the apply-side\n * dependencies (`registry`); every field except `environment` is optional\n * and default-constructed from the project config and the environment\n * variables `GITHUB_TOKEN` (gist state backend) when omitted.\n */\nexport interface PreviewDiffOptions {\n\t/** Pre-loaded, optionally-mutated project config. Omit to call `loadConfig()` automatically. */\n\treadonly config?: Config;\n\t/** Environment name; threaded into `StatePort.read`. */\n\treadonly environment: string;\n\t/** `fetch` override plumbed into the default-constructed gist adapter when `statePort` is omitted. */\n\treadonly fetch?: GistFetch;\n\t/** Reads an environment variable; defaults to `(name) => process.env[name]`. */\n\treadonly getEnv?: (name: string) => string | undefined;\n\t/** Loader invoked when `config` is omitted; defaults to `loadConfig` from this package. */\n\treadonly loadConfig?: (options?: LoadConfigOptions) => Promise<Result<Config, ConfigError>>;\n\t/** Reads file bytes for resources that have file-backed inputs. Defaults to `node:fs/promises.readFile`. */\n\treadonly readFile?: (path: string) => Promise<Uint8Array>;\n\t/** Backend used to read the prior snapshot. Default-constructed from `config.state` and `GITHUB_TOKEN` when omitted. */\n\treadonly statePort?: StatePort;\n}\n\n/**\n * Failure surfaced by `previewDiff`. Stage-tagged so callers can branch on\n * `kind`. Strict subset of `DeployError`: every variant here is also a\n * `DeployError` variant, but the apply-side variants (`applyFailed`,\n * `stateWriteFailed`) cannot occur because `previewDiff` is read-only.\n */\nexport type PreviewDiffError =\n\t| IncompletePlaceEntryError\n\t| IncompleteUniverseEntryError\n\t| MissingCredentialError\n\t| StateNotConfiguredError\n\t| UnknownEnvironmentError\n\t| UnsupportedBackendError\n\t| { readonly cause: BuildDesiredError; readonly kind: \"buildDesiredFailed\" }\n\t| { readonly cause: ConfigError; readonly kind: \"configLoadFailed\" }\n\t| { readonly cause: StateError; readonly kind: \"stateReadFailed\" };\n\n/** Successful preview output. */\nexport interface DiffPreview {\n\t/** Environment the preview was computed against; matches `options.environment`. */\n\treadonly environment: string;\n\t/** Operations `diff` would apply during a deploy. */\n\treadonly ops: ReadonlyArray<Operation>;\n}\n\ninterface ResolvedDeps {\n\treadonly config: ResolvedConfig;\n\treadonly readFile: (path: string) => Promise<Uint8Array>;\n\treadonly statePort: StatePort;\n}\n\n/**\n * Compute the operations `deploy` would apply for a target environment\n * without writing state. Default-constructs missing deps from the project\n * config and `GITHUB_TOKEN`; never reads `process.env` when `statePort`\n * and `config` are both supplied explicitly.\n *\n * @param options - Target environment plus optional overrides.\n * @returns The computed operations on success, or a stage-tagged\n * `PreviewDiffError` on failure.\n */\nexport async function previewDiff(\n\toptions: PreviewDiffOptions,\n): Promise<Result<DiffPreview, PreviewDiffError>> {\n\tconst resolved = await resolveDeps(options);\n\tif (!resolved.success) {\n\t\treturn resolved;\n\t}\n\n\treturn runPreview(options.environment, resolved.data);\n}\n\nasync function pickConfig(options: PreviewDiffOptions): Promise<Result<Config, PreviewDiffError>> {\n\tif (options.config !== undefined) {\n\t\treturn { data: options.config, success: true };\n\t}\n\n\tconst loader = options.loadConfig ?? defaultLoadConfig;\n\tconst loaded = await loader();\n\tif (!loaded.success) {\n\t\treturn { err: { cause: loaded.err, kind: \"configLoadFailed\" }, success: false };\n\t}\n\n\treturn { data: loaded.data, success: true };\n}\n\nfunction readProcessEnvironment(name: string): string | undefined {\n\treturn process.env[name];\n}\n\nfunction getEnvironmentOf(options: PreviewDiffOptions): (name: string) => string | undefined {\n\treturn options.getEnv ?? readProcessEnvironment;\n}\n\nfunction pickStatePort(\n\toptions: PreviewDiffOptions,\n\tconfig: ResolvedConfig,\n): Result<StatePort, PreviewDiffError> {\n\tif (options.statePort !== undefined) {\n\t\treturn { data: options.statePort, success: true };\n\t}\n\n\tconst stateConfig = resolveStateConfig(config, options.environment);\n\tif (!stateConfig.success) {\n\t\treturn { err: stateConfig.err, success: false };\n\t}\n\n\treturn buildStatePort({\n\t\tfetch: options.fetch,\n\t\tgetEnv: getEnvironmentOf(options),\n\t\tstateConfig: stateConfig.data,\n\t});\n}\n\nasync function resolveDeps(\n\toptions: PreviewDiffOptions,\n): Promise<Result<ResolvedDeps, PreviewDiffError>> {\n\tconst config = await pickConfig(options);\n\tif (!config.success) {\n\t\treturn config;\n\t}\n\n\tconst selected = selectEnvironment(config.data, options.environment);\n\tif (!selected.success) {\n\t\treturn { err: selected.err, success: false };\n\t}\n\n\tconst effective = selected.data;\n\tconst readFile = options.readFile ?? nodeReadFile;\n\n\tconst statePort = pickStatePort(options, effective);\n\tif (!statePort.success) {\n\t\treturn statePort;\n\t}\n\n\treturn {\n\t\tdata: {\n\t\t\tconfig: effective,\n\t\t\treadFile,\n\t\t\tstatePort: statePort.data,\n\t\t},\n\t\tsuccess: true,\n\t};\n}\n\nasync function runPreview(\n\tenvironment: string,\n\tdeps: ResolvedDeps,\n): Promise<Result<DiffPreview, PreviewDiffError>> {\n\tconst desired = await buildDesired(flattenConfig(deps.config), deps.readFile);\n\tif (!desired.success) {\n\t\treturn { err: { cause: desired.err, kind: \"buildDesiredFailed\" }, success: false };\n\t}\n\n\tconst prior = await deps.statePort.read(environment);\n\tif (!prior.success) {\n\t\treturn { err: { cause: prior.err, kind: \"stateReadFailed\" }, success: false };\n\t}\n\n\tconst priorResources = prior.data?.resources ?? [];\n\tconst validated = validatePlan(desired.data, priorResources);\n\tif (!validated.success) {\n\t\treturn { err: { cause: validated.err, kind: \"buildDesiredFailed\" }, success: false };\n\t}\n\n\tconst ops = diff(desired.data, priorResources);\n\treturn { data: { environment, ops }, success: true };\n}\n","import process from \"node:process\";\n\nimport type { CreateOperation, Operation, UpdateOperation } from \"../../core/operations.ts\";\nimport type { Config } from \"../../core/schema.ts\";\nimport {\n\tloadConfig as defaultLoadConfig,\n\ttype LoadConfigOptions,\n} from \"../../shell/load-config.ts\";\nimport { previewDiff as defaultPreviewDiff, type DiffPreview } from \"../../shell/preview-diff.ts\";\nimport { EXIT_ERROR, EXIT_OK } from \"../exit-codes.ts\";\nimport type { ProgDeps } from \"../index.ts\";\nimport { type CommonOptions, parseCommonOptions } from \"../parse-options.ts\";\nimport { type ClackPort, createClackPort, renderDeployError, renderParseError } from \"../render.ts\";\n\ninterface ResolvedDiff {\n\treadonly clack: ClackPort;\n\treadonly exit: (code: number) => void;\n\treadonly loadConfig: typeof defaultLoadConfig;\n\treadonly previewDiff: typeof defaultPreviewDiff;\n}\n\ninterface DispatchInputs {\n\treadonly config: Config;\n\treadonly environments: ReadonlyArray<string>;\n\treadonly getEnv: (name: string) => string | undefined;\n\treadonly resolved: ResolvedDiff;\n}\n\ninterface DispatchOutcome {\n\treadonly failed: ReadonlyArray<string>;\n\treadonly hasDrift: boolean;\n}\n\n/**\n * Build the sade action for `bedrock diff`. The returned function consumes\n * the raw options object sade hands the action callback, parses it via\n * `parseCommonOptions`, loads the project config once, and dispatches\n * `previewDiff()` for each `--env` value in order. Per-env successes render\n * the operations list (or a `No drift` line when every op is a noop);\n * failures render via `renderDeployError`. The aggregated exit code is\n * `EXIT_OK` only when every env succeeded.\n * @param deps - Dependency overrides; missing slots are default-constructed\n * from real implementations.\n * @returns An async sade action that returns once `deps.exit` was invoked.\n */\nexport function diffCommand(\n\tdeps: ProgDeps,\n): (rawOptions: Record<string, unknown>) => Promise<void> {\n\tconst resolved = resolveDiff(deps);\n\treturn async (rawOptions) => {\n\t\tconst code = await runDiff(rawOptions, resolved);\n\t\tresolved.exit(code);\n\t};\n}\n\nfunction resolveDiff(deps: ProgDeps): ResolvedDiff {\n\treturn {\n\t\tclack: deps.clack ?? createClackPort(),\n\t\texit: deps.exit ?? ((code: number) => process.exit(code)),\n\t\tloadConfig: deps.loadConfig ?? defaultLoadConfig,\n\t\tpreviewDiff: deps.previewDiff ?? defaultPreviewDiff,\n\t};\n}\n\nfunction loadOptionsFor(parsed: CommonOptions): LoadConfigOptions | undefined {\n\treturn parsed.configFile === undefined ? undefined : { configFile: parsed.configFile };\n}\n\nfunction buildGetEnvironment(parsed: CommonOptions): (name: string) => string | undefined {\n\treturn (name) => {\n\t\tif (name === \"ROBLOX_API_KEY\" && parsed.apiKey !== undefined) {\n\t\t\treturn parsed.apiKey;\n\t\t}\n\n\t\tif (name === \"GITHUB_TOKEN\" && parsed.githubToken !== undefined) {\n\t\t\treturn parsed.githubToken;\n\t\t}\n\n\t\treturn process.env[name];\n\t};\n}\n\nfunction cancelAsFailed(clack: ClackPort): void {\n\tclack.cancel(\"diff failed\");\n}\n\nfunction describeOp(op: CreateOperation | UpdateOperation): string {\n\tswitch (op.type) {\n\t\tcase \"create\": {\n\t\t\treturn `+ ${op.desired.kind}:${op.key}`;\n\t\t}\n\t\tcase \"update\": {\n\t\t\treturn `~ ${op.desired.kind}:${op.key}`;\n\t\t}\n\t}\n}\n\nfunction isDriftOp(op: Operation): op is CreateOperation | UpdateOperation {\n\treturn op.type !== \"noop\";\n}\n\nfunction renderPreview(preview: DiffPreview, clack: ClackPort): boolean {\n\tconst drift = preview.ops.filter(isDriftOp);\n\tif (drift.length === 0) {\n\t\tclack.logSuccess(`No drift for \"${preview.environment}\"`);\n\t\treturn false;\n\t}\n\n\tclack.logMessage(`Pending changes for \"${preview.environment}\":`);\n\tfor (const op of drift) {\n\t\tclack.logMessage(describeOp(op));\n\t}\n\n\treturn true;\n}\n\nasync function dispatchEnvironments(inputs: DispatchInputs): Promise<DispatchOutcome> {\n\tconst { config, environments, getEnv, resolved } = inputs;\n\tconst failed: Array<string> = [];\n\tlet hasDrift = false;\n\tfor (const environment of environments) {\n\t\tconst result = await resolved.previewDiff({\n\t\t\tconfig,\n\t\t\tenvironment,\n\t\t\tgetEnv,\n\t\t});\n\t\tif (result.success) {\n\t\t\tif (renderPreview(result.data, resolved.clack)) {\n\t\t\t\thasDrift = true;\n\t\t\t}\n\t\t} else {\n\t\t\trenderDeployError(result.err, resolved.clack);\n\t\t\tfailed.push(environment);\n\t\t}\n\t}\n\n\treturn { failed, hasDrift };\n}\n\nfunction outroFor(hasDrift: boolean): string {\n\treturn hasDrift\n\t\t? \"run bedrock deploy to apply pending changes\"\n\t\t: \"all environments are up to date\";\n}\n\nasync function runDiff(\n\trawOptions: Record<string, unknown>,\n\tresolved: ResolvedDiff,\n): Promise<number> {\n\tresolved.clack.intro(\"bedrock diff\");\n\n\tconst parsed = parseCommonOptions(rawOptions);\n\tif (!parsed.success) {\n\t\trenderParseError(parsed.err, resolved.clack);\n\t\tcancelAsFailed(resolved.clack);\n\t\treturn EXIT_ERROR;\n\t}\n\n\tconst loaded = await resolved.loadConfig(loadOptionsFor(parsed.data));\n\tif (!loaded.success) {\n\t\trenderDeployError({ cause: loaded.err, kind: \"configLoadFailed\" }, resolved.clack);\n\t\tcancelAsFailed(resolved.clack);\n\t\treturn EXIT_ERROR;\n\t}\n\n\tconst outcome = await dispatchEnvironments({\n\t\tconfig: loaded.data,\n\t\tenvironments: parsed.data.environments,\n\t\tgetEnv: buildGetEnvironment(parsed.data),\n\t\tresolved,\n\t});\n\tif (outcome.failed.length > 0) {\n\t\tcancelAsFailed(resolved.clack);\n\t\treturn EXIT_ERROR;\n\t}\n\n\tresolved.clack.outro(outroFor(outcome.hasDrift));\n\treturn EXIT_OK;\n}\n","import {\n\tisCancel as defaultIsCancel,\n\tpath as defaultPath,\n\tselect as defaultSelect,\n\ttext as defaultText,\n\ttype PathOptions,\n\ttype SelectOptions,\n\ttype TextOptions,\n} from \"@clack/prompts\";\n\nimport type {\n\tMigrateConfigFormat,\n\tMigratePromptPort,\n\tMigratePromptResult,\n\tMigrateStateBackend,\n} from \"./migrate-prompt-port.ts\";\nimport type { MigrationSource } from \"./parse-migrate-options.ts\";\n\n/**\n * Test seam for {@link createDefaultMigratePromptPort}. Production callers\n * omit `helpers` and the port delegates straight to `@clack/prompts`;\n * tests substitute scripted, non-generic stand-ins so each prompt method\n * can be exercised without spawning a real terminal.\n *\n * Slot signatures use clack's own types pinned to `string`-valued options\n * so a `vi.fn` instance is assignable: vitest cannot construct a `Mock`\n * that satisfies a polymorphic `<Value>(...)` signature, but it can\n * satisfy this concrete shape.\n */\nexport interface MigratePromptClackHelpers {\n\t/** Cancel predicate; defaults to `@clack/prompts`'s `isCancel`. */\n\treadonly isCancel: (value: unknown) => value is symbol;\n\t/**\n\t * Path-prompt fn with filesystem tab-completion; defaults to\n\t * `@clack/prompts`'s `path`.\n\t */\n\treadonly path: (options: PathOptions) => Promise<string | symbol>;\n\t/** Select-prompt fn; defaults to `@clack/prompts`'s `select`. */\n\treadonly select: (options: SelectOptions<string>) => Promise<string | symbol>;\n\t/** Text-prompt fn; defaults to `@clack/prompts`'s `text`. */\n\treadonly text: (options: TextOptions) => Promise<string | symbol>;\n}\n\nconst FORMAT_OPTIONS: ReadonlyArray<{ hint?: string; label: string; value: MigrateConfigFormat }> =\n\t[\n\t\t{ hint: \"recommended\", label: \"TypeScript\", value: \"typescript\" },\n\t\t{ label: \"YAML\", value: \"yaml\" },\n\t];\n\nconst BACKEND_OPTIONS: ReadonlyArray<{ hint?: string; label: string; value: MigrateStateBackend }> =\n\t[\n\t\t{ label: \"GitHub Gist\", value: \"gist\" },\n\t\t{\n\t\t\thint: \"writes .bedrock/state/<env>.json next to bedrock.config\",\n\t\t\tlabel: \"Local files\",\n\t\t\tvalue: \"local\",\n\t\t},\n\t];\n\nconst SOURCE_LABELS: Record<MigrationSource, string> = {\n\tmantle: \"Mantle\",\n};\n\nconst defaultHelpers: MigratePromptClackHelpers = {\n\tisCancel: defaultIsCancel,\n\tpath: defaultPath,\n\tselect: defaultSelect,\n\ttext: defaultText,\n};\n\ninterface FromSelectInputs<T extends string> {\n\treadonly initialValue?: T;\n\treadonly message: string;\n\treadonly options: ReadonlyArray<{ hint?: string; label: string; value: T }>;\n}\n\n/**\n * Construct a `MigratePromptPort` whose methods delegate to\n * `@clack/prompts`. Each prompt translates clack's cancel sentinel into\n * a typed `Err({ kind: \"cancelled\" })` so the migrate command branches\n * on `Result` like every other shell call.\n *\n * @param helpers - Test-only seam for swapping the three clack\n * primitives. Production callers omit this argument.\n * @returns A live `MigratePromptPort` ready to drive interactively.\n */\nexport function createDefaultMigratePromptPort(\n\thelpers: MigratePromptClackHelpers = defaultHelpers,\n): MigratePromptPort {\n\treturn {\n\t\tpromptConfigFormat: async () => promptConfigFormatFrom(helpers),\n\t\tpromptGistId: async () => promptGistIdFrom(helpers),\n\t\tpromptMigrationSource: async (sources) => selectMigrationSource(helpers, sources),\n\t\tpromptPrimaryEnvironment: async (environments) =>\n\t\t\tselectPrimaryEnvironment(helpers, environments),\n\t\tpromptStateBackend: async () => promptStateBackendFrom(helpers),\n\t\tpromptStateFilePath: async () => promptStateFilePathFrom(helpers),\n\t};\n}\n\nasync function fromSelect<T extends string>(\n\thelpers: MigratePromptClackHelpers,\n\tinputs: FromSelectInputs<T>,\n): Promise<MigratePromptResult<T>> {\n\tconst result = await helpers.select({\n\t\tmessage: inputs.message,\n\t\toptions: inputs.options.map((option) => {\n\t\t\treturn {\n\t\t\t\t...(option.hint === undefined ? {} : { hint: option.hint }),\n\t\t\t\tlabel: option.label,\n\t\t\t\tvalue: option.value,\n\t\t\t};\n\t\t}),\n\t\t...(inputs.initialValue === undefined ? {} : { initialValue: inputs.initialValue }),\n\t});\n\tif (helpers.isCancel(result)) {\n\t\treturn { err: { kind: \"cancelled\" }, success: false };\n\t}\n\n\treturn { data: result as T, success: true };\n}\n\nasync function selectMigrationSource(\n\thelpers: MigratePromptClackHelpers,\n\tsources: readonly [MigrationSource, ...ReadonlyArray<MigrationSource>],\n): Promise<MigratePromptResult<MigrationSource>> {\n\treturn fromSelect<MigrationSource>(helpers, {\n\t\tinitialValue: sources[0],\n\t\tmessage: \"Migrate from?\",\n\t\toptions: sources.map((source) => ({ label: SOURCE_LABELS[source], value: source })),\n\t});\n}\n\nasync function promptConfigFormatFrom(\n\thelpers: MigratePromptClackHelpers,\n): Promise<MigratePromptResult<MigrateConfigFormat>> {\n\treturn fromSelect(helpers, {\n\t\tinitialValue: \"typescript\",\n\t\tmessage: \"Output config format?\",\n\t\toptions: FORMAT_OPTIONS,\n\t});\n}\n\nfunction validateNonEmpty(value: string | undefined): string | undefined {\n\tif (value === undefined || value.trim() === \"\") {\n\t\treturn \"Required\";\n\t}\n\n\treturn undefined;\n}\n\nasync function fromText(\n\thelpers: MigratePromptClackHelpers,\n\toptions: TextOptions,\n): Promise<MigratePromptResult<string>> {\n\tconst result = await helpers.text(options);\n\tif (helpers.isCancel(result)) {\n\t\treturn { err: { kind: \"cancelled\" }, success: false };\n\t}\n\n\treturn { data: result, success: true };\n}\n\nasync function promptGistIdFrom(\n\thelpers: MigratePromptClackHelpers,\n): Promise<MigratePromptResult<string>> {\n\treturn fromText(helpers, {\n\t\tmessage: \"Gist ID for state storage?\",\n\t\tplaceholder: \"abc123\",\n\t\tvalidate: validateNonEmpty,\n\t});\n}\n\nasync function selectPrimaryEnvironment(\n\thelpers: MigratePromptClackHelpers,\n\tenvironments: ReadonlyArray<string>,\n): Promise<MigratePromptResult<string>> {\n\treturn fromSelect(helpers, {\n\t\tmessage:\n\t\t\t\"Which environment should be the primary?\\nThe migrator uses it as the baseline for the generated config.\",\n\t\toptions: environments.map((name) => ({ label: name, value: name })),\n\t});\n}\n\nasync function promptStateBackendFrom(\n\thelpers: MigratePromptClackHelpers,\n): Promise<MigratePromptResult<MigrateStateBackend>> {\n\treturn fromSelect(helpers, {\n\t\tinitialValue: \"gist\",\n\t\tmessage: \"State backend?\",\n\t\toptions: BACKEND_OPTIONS,\n\t});\n}\n\nasync function fromPath(\n\thelpers: MigratePromptClackHelpers,\n\toptions: PathOptions,\n): Promise<MigratePromptResult<string>> {\n\tconst result = await helpers.path(options);\n\tif (helpers.isCancel(result)) {\n\t\treturn { err: { kind: \"cancelled\" }, success: false };\n\t}\n\n\treturn { data: result, success: true };\n}\n\nasync function promptStateFilePathFrom(\n\thelpers: MigratePromptClackHelpers,\n): Promise<MigratePromptResult<string>> {\n\treturn fromPath(helpers, {\n\t\tinitialValue: \".mantle-state.yml\",\n\t\tmessage: \"Path to the Mantle state file?\",\n\t\tvalidate: validateNonEmpty,\n\t});\n}\n","import type { Result } from \"@bedrock-rbx/ocale\";\n\nimport type { ParseOptionsError } from \"./parse-options.ts\";\n\n/**\n * Sources `bedrock migrate --from <source>` accepts. Today only `\"mantle\"`\n * is wired up; widening this tuple turns on additional sources without\n * touching the parser.\n */\nexport const SUPPORTED_MIGRATION_SOURCES = [\"mantle\"] as const;\n\n/**\n * Failure surfaced by `parseMigrateOptions`. Reuses the three flag-shape\n * variants from `ParseOptionsError` (so the existing `renderParseError`\n * messages stay consistent) and adds `unknownSource` for `--from` values\n * outside {@link SUPPORTED_MIGRATION_SOURCES}.\n */\nexport type ParseMigrateError =\n\t| ParseOptionsError\n\t| {\n\t\t\treadonly kind: \"unknownSource\";\n\t\t\treadonly received: string;\n\t\t\treadonly supported: ReadonlyArray<string>;\n\t };\n\n/** One element of {@link SUPPORTED_MIGRATION_SOURCES}. */\nexport type MigrationSource = (typeof SUPPORTED_MIGRATION_SOURCES)[number];\n\n/** Typed shape the migrate command consumes after `--from` has been validated. */\ninterface MigrateOptions {\n\t/**\n\t * Validated source to migrate from, or `undefined` when the flag was\n\t * omitted. The command falls back to an interactive picker in that\n\t * case, mirroring how the positional state-file path is handled.\n\t */\n\treadonly from: MigrationSource | undefined;\n}\n\nconst RECOGNIZED_FLAGS: ReadonlySet<string> = new Set([\"from\"]);\n\nconst SADE_RESERVED: ReadonlySet<string> = new Set([\"--\", \"_\", \"h\", \"help\", \"v\", \"version\"]);\n\n/**\n * Translate the raw sade options POJO into a typed `MigrateOptions`. The\n * positional `<stateFilePath>` argument is not handled here: sade hands\n * positional values to the action callback ahead of the options object,\n * and the migrate command falls back to an interactive prompt when it\n * is absent. This parser only covers the `--from` flag, which is also\n * optional and prompted for when omitted.\n *\n * @param rawOptions - The options object sade hands the action callback.\n * @returns `Ok(MigrateOptions)` on success, or `Err(ParseMigrateError)`\n * describing the offending flag or value.\n */\nexport function parseMigrateOptions(\n\trawOptions: Readonly<Record<string, unknown>>,\n): Result<MigrateOptions, ParseMigrateError> {\n\tfor (const key of Object.keys(rawOptions)) {\n\t\tif (!RECOGNIZED_FLAGS.has(key) && !SADE_RESERVED.has(key)) {\n\t\t\treturn { err: { flag: key, kind: \"unknownFlag\" }, success: false };\n\t\t}\n\t}\n\n\tconst fromRaw = rawOptions[\"from\"];\n\tif (fromRaw === undefined) {\n\t\treturn { data: { from: undefined }, success: true };\n\t}\n\n\tif (typeof fromRaw !== \"string\") {\n\t\treturn { err: { flag: \"from\", kind: \"invalidValue\" }, success: false };\n\t}\n\n\tif (!isMigrationSource(fromRaw)) {\n\t\treturn {\n\t\t\terr: {\n\t\t\t\tkind: \"unknownSource\",\n\t\t\t\treceived: fromRaw,\n\t\t\t\tsupported: SUPPORTED_MIGRATION_SOURCES,\n\t\t\t},\n\t\t\tsuccess: false,\n\t\t};\n\t}\n\n\treturn { data: { from: fromRaw }, success: true };\n}\n\nfunction isMigrationSource(value: string): value is MigrationSource {\n\treturn (SUPPORTED_MIGRATION_SOURCES as ReadonlyArray<string>).includes(value);\n}\n","/**\n * Format a thrown value as a human-readable string for clack diagnostic\n * lines. Native `Error` instances surface their `message`; everything\n * else is coerced via `String()` so non-Error throws (rejection of a\n * primitive, for example) still render legibly.\n *\n * @param value - The caught value to describe.\n * @returns A short string suitable for inlining into a CLI error line.\n */\nexport function describeUnknown(value: unknown): string {\n\treturn value instanceof Error ? value.message : String(value);\n}\n","import type { Result } from \"@bedrock-rbx/ocale\";\n\nimport { join } from \"node:path\";\nimport process from \"node:process\";\n\nimport type { MigrationReport } from \"../../core/migrate/migration-report.ts\";\nimport type { GistStateConfig } from \"../../core/schema.ts\";\nimport { serializeStateFile } from \"../../core/state-file.ts\";\nimport type { buildStatePort as defaultBuildStatePort } from \"../../shell/build-state-port.ts\";\nimport type { ClackPort } from \"../render.ts\";\nimport { renderBuildStatePortError, renderStateWriteError } from \"../render.ts\";\nimport { describeUnknown } from \"./describe-unknown.ts\";\n\n/**\n * Where the migrate command persists per-environment states. The `gist`\n * arm carries the resolved {@link GistStateConfig} that gets written to\n * the bedrock config; the `local` arm carries the on-disk directory used\n * for the JSON-per-environment dump.\n */\nexport type ResolvedStateTarget =\n\t| { readonly backend: \"gist\"; readonly stateConfig: GistStateConfig }\n\t| { readonly backend: \"local\"; readonly outputDir: string };\n\n/** Subset of the migrate command's resolved deps the writers need. */\ninterface WriterDeps {\n\treadonly buildStatePort: typeof defaultBuildStatePort;\n\treadonly clack: ClackPort;\n\treadonly mkdir: (path: string) => Promise<void>;\n\treadonly writeFile: (path: string, contents: string) => Promise<void>;\n}\n\ninterface WriteInputs {\n\treadonly deps: WriterDeps;\n\treadonly report: MigrationReport;\n\treadonly target: ResolvedStateTarget;\n}\n\n/**\n * Persist every per-environment state in the migration report to the\n * resolved target. Dispatches to the GitHub Gist `StatePort` adapter or\n * to a local-file dump under `target.outputDir`. On failure the writer\n * has already rendered the error to `deps.clack`; the caller only needs\n * to translate the Err into an exit code.\n *\n * @param inputs - Resolved deps, the migration report, and the target\n * the writer should dispatch on.\n * @returns `Ok(void)` once every environment has been written; `Err(void)`\n * on the first failure (already rendered to clack).\n */\nexport async function writeMigratedStates(inputs: WriteInputs): Promise<Result<void, void>> {\n\tif (inputs.target.backend === \"local\") {\n\t\treturn writeStatesToLocal({ ...inputs, target: inputs.target });\n\t}\n\n\treturn writeStatesToGist({ ...inputs, target: inputs.target });\n}\n\nasync function writeStatesToGist(\n\tinputs: WriteInputs & { readonly target: { readonly stateConfig: GistStateConfig } },\n): Promise<Result<void, void>> {\n\tconst { deps, report, target } = inputs;\n\tconst portResult = deps.buildStatePort({\n\t\tgetEnv: (name) => process.env[name],\n\t\tstateConfig: target.stateConfig,\n\t});\n\tif (!portResult.success) {\n\t\trenderBuildStatePortError(portResult.err, deps.clack);\n\t\treturn { err: undefined, success: false };\n\t}\n\n\tfor (const [environment, state] of Object.entries(report.statesByEnvironment)) {\n\t\tconst writeResult = await portResult.data.write(state);\n\t\tif (!writeResult.success) {\n\t\t\trenderStateWriteError({ environment, err: writeResult.err }, deps.clack);\n\t\t\treturn { err: undefined, success: false };\n\t\t}\n\n\t\tdeps.clack.logSuccess(`${environment}: ${state.resources.length} resources migrated`);\n\t}\n\n\treturn { data: undefined, success: true };\n}\n\nasync function writeStatesToLocal(\n\tinputs: WriteInputs & { readonly target: { readonly outputDir: string } },\n): Promise<Result<void, void>> {\n\tconst { deps, report, target } = inputs;\n\ttry {\n\t\tawait deps.mkdir(target.outputDir);\n\t} catch (err) {\n\t\tdeps.clack.logError(\n\t\t\t`local state directory create failed (${target.outputDir}): ${describeUnknown(err)}`,\n\t\t);\n\t\treturn { err: undefined, success: false };\n\t}\n\n\tfor (const [environment, state] of Object.entries(report.statesByEnvironment)) {\n\t\tconst filePath = join(target.outputDir, `${environment}.json`);\n\t\ttry {\n\t\t\tawait deps.writeFile(filePath, serializeStateFile(state));\n\t\t} catch (err) {\n\t\t\tdeps.clack.logError(`local state write failed (${filePath}): ${describeUnknown(err)}`);\n\t\t\treturn { err: undefined, success: false };\n\t\t}\n\n\t\tdeps.clack.logSuccess(`${environment}: ${state.resources.length} resources migrated`);\n\t}\n\n\treturn { data: undefined, success: true };\n}\n","import type { MigrationReportFile, MigrationWarning } from \"./migration-report.ts\";\n\ninterface SectionInput<W extends { readonly mantlePath: string }> {\n\treadonly groupKey: (warning: W) => string;\n\t/**\n\t * Subject the entry collapses by. For ambiguous/blocked/deferred this is\n\t * the mantle-path suffix (env stripped); for interpretive it is suffix\n\t * plus `-> bedrockPath` so distinct mappings remain distinct bullets.\n\t */\n\treadonly subject: (warning: W) => string;\n\treadonly title: string;\n\treadonly warnings: ReadonlyArray<W>;\n}\n\n/**\n * Render a {@link MigrationReportFile} as the Markdown body written to\n * `.bedrock/migration-report.md`. Pure derivation: the same input shape\n * the JSON serializer consumes feeds this renderer, so the Markdown view\n * round-trips through the JSON file.\n *\n * Output structure:\n * - Header with the four counts.\n * - Sections in user-action priority order (Action required, Blocked,\n * Deferred, Interpretive). Sections with no matching warnings are\n * omitted entirely.\n * - Within each section, warnings are grouped by their non-path\n * discriminator (`hint` for ambiguous, `reason` for blocked/deferred,\n * `rule` for interpretive). First-appearance order is preserved.\n * - Interpretive entries render as `mantlePath -> bedrockPath` so the\n * user can verify the auto-applied mapping at a glance.\n *\n * @param file - The summary plus warnings to render.\n * @returns Markdown source ending with a trailing newline.\n */\nexport function renderMigrationReportMarkdown(file: MigrationReportFile): string {\n\tconst sections = [\n\t\trenderActionRequired(file.warnings),\n\t\trenderBlocked(file.warnings),\n\t\trenderDeferred(file.warnings),\n\t\trenderInterpretive(file.warnings),\n\t].filter((section) => section !== \"\");\n\n\tconst header = renderHeader(file);\n\treturn [header, ...sections].join(\"\\n\");\n}\n\nfunction renderHeader(file: MigrationReportFile): string {\n\treturn [\n\t\t\"# Migration report\",\n\t\t\"\",\n\t\t`ambiguous: ${String(file.summary.ambiguousCount)}`,\n\t\t`blocked: ${String(file.summary.blockedCount)}`,\n\t\t`deferred: ${String(file.summary.deferredCount)}`,\n\t\t`interpretive: ${String(file.summary.interpretiveCount)}`,\n\t\t\"\",\n\t].join(\"\\n\");\n}\n\nfunction suffixOf(mantlePath: string): string {\n\t// `indexOf(\".\") === -1` becomes `slice(0)` so no branch is needed.\n\treturn mantlePath.slice(mantlePath.indexOf(\".\") + 1);\n}\n\nfunction groupByKey<W>(\n\twarnings: ReadonlyArray<W>,\n\tkey: (warning: W) => string,\n): ReadonlyMap<string, ReadonlyArray<W>> {\n\tconst orderedKeys = [...new Set(warnings.map(key))];\n\treturn new Map(\n\t\torderedKeys.map((groupKey) => [\n\t\t\tgroupKey,\n\t\t\twarnings.filter((warning) => key(warning) === groupKey),\n\t\t]),\n\t);\n}\n\nfunction environmentOf(mantlePath: string): string | undefined {\n\tconst dot = mantlePath.indexOf(\".\");\n\treturn dot === -1 ? undefined : mantlePath.slice(0, dot);\n}\n\nfunction environmentsOf(\n\tmembers: ReadonlyArray<{ readonly mantlePath: string }>,\n): ReadonlyArray<string> {\n\tconst environments = members\n\t\t.map((warning) => environmentOf(warning.mantlePath))\n\t\t.filter((environment): environment is string => environment !== undefined);\n\treturn [...new Set(environments)];\n}\n\nfunction renderBullet(\n\tsubject: string,\n\tmembers: ReadonlyArray<{ readonly mantlePath: string }>,\n): string {\n\tconst environments = environmentsOf(members);\n\treturn environments.length === 0 ? `- ${subject}` : `- ${subject} (${environments.join(\", \")})`;\n}\n\nfunction renderSection<W extends { readonly mantlePath: string }>(input: SectionInput<W>): string {\n\tif (input.warnings.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst groups = groupByKey(input.warnings, input.groupKey);\n\tconst blocks = [...groups].map(([heading, members]) => {\n\t\tconst bySubject = groupByKey(members, input.subject);\n\t\tconst lines = [...bySubject].map(([key, subjectMembers]) =>\n\t\t\trenderBullet(key, subjectMembers),\n\t\t);\n\t\treturn [`### ${heading}`, \"\", ...lines, \"\"].join(\"\\n\");\n\t});\n\n\treturn [`## ${input.title}`, \"\", ...blocks].join(\"\\n\");\n}\n\nfunction renderActionRequired(warnings: ReadonlyArray<MigrationWarning>): string {\n\treturn renderSection({\n\t\tgroupKey: (warning) => warning.hint,\n\t\tsubject: (warning) => suffixOf(warning.mantlePath),\n\t\ttitle: \"Action required\",\n\t\twarnings: warnings.filter(\n\t\t\t(warning): warning is Extract<MigrationWarning, { kind: \"ambiguous\" }> => {\n\t\t\t\treturn warning.kind === \"ambiguous\";\n\t\t\t},\n\t\t),\n\t});\n}\n\nfunction renderBlocked(warnings: ReadonlyArray<MigrationWarning>): string {\n\treturn renderSection({\n\t\tgroupKey: (warning) => warning.reason,\n\t\tsubject: (warning) => suffixOf(warning.mantlePath),\n\t\ttitle: \"Won't migrate (no Open Cloud equivalent)\",\n\t\twarnings: warnings.filter(\n\t\t\t(warning): warning is Extract<MigrationWarning, { kind: \"blocked\" }> => {\n\t\t\t\treturn warning.kind === \"blocked\";\n\t\t\t},\n\t\t),\n\t});\n}\n\nfunction renderDeferred(warnings: ReadonlyArray<MigrationWarning>): string {\n\treturn renderSection({\n\t\tgroupKey: (warning) => warning.reason,\n\t\tsubject: (warning) => suffixOf(warning.mantlePath),\n\t\ttitle: \"Coming later (skipped for now)\",\n\t\twarnings: warnings.filter(\n\t\t\t(warning): warning is Extract<MigrationWarning, { kind: \"deferred\" }> => {\n\t\t\t\treturn warning.kind === \"deferred\";\n\t\t\t},\n\t\t),\n\t});\n}\n\nfunction renderInterpretive(warnings: ReadonlyArray<MigrationWarning>): string {\n\treturn renderSection({\n\t\tgroupKey: (warning) => warning.rule,\n\t\tsubject: (warning) => `${suffixOf(warning.mantlePath)} -> ${warning.bedrockPath}`,\n\t\ttitle: \"Auto-mapped (please verify)\",\n\t\twarnings: warnings.filter(\n\t\t\t(warning): warning is Extract<MigrationWarning, { kind: \"interpretive\" }> => {\n\t\t\t\treturn warning.kind === \"interpretive\";\n\t\t\t},\n\t\t),\n\t});\n}\n","import type { MigrationReportFile } from \"./migration-report.ts\";\n\n/**\n * Serialize a {@link MigrationReportFile} as the bytes written to\n * `.bedrock/migration-report.json`. The output is canonical JSON:\n * pretty-printed with two-space indentation, terminated with a trailing newline.\n *\n * @param file - The summary plus warnings to serialize.\n * @returns A UTF-8 source string ending with a trailing newline.\n */\nexport function serializeMigrationReport(file: MigrationReportFile): string {\n\treturn `${JSON.stringify(file, undefined, 2)}\\n`;\n}\n","import type { Result } from \"@bedrock-rbx/ocale\";\n\nimport { dirname, join } from \"node:path\";\n\nimport type { MigrationReport } from \"../../core/migrate/migration-report.ts\";\nimport { renderMigrationReportMarkdown } from \"../../core/migrate/render-migration-report-md.ts\";\nimport { serializeMigrationReport } from \"../../core/migrate/serialize-migration-report.ts\";\nimport type { ClackPort } from \"../render.ts\";\nimport { describeUnknown } from \"./describe-unknown.ts\";\n\nconst REPORT_DIR_NAME = \".bedrock\";\nconst JSON_FILE_NAME = \"migration-report.json\";\nconst MD_FILE_NAME = \"migration-report.md\";\n\n/** Paths the writer produced. The Markdown path is reported to the user. */\ninterface MigrationReportPaths {\n\t/** Path to `.bedrock/migration-report.json`. */\n\treadonly jsonPath: string;\n\t/** Path to `.bedrock/migration-report.md`. */\n\treadonly mdPath: string;\n}\n\n/** Subset of the migrate command's deps the report writer touches. */\ninterface WriterDeps {\n\treadonly clack: ClackPort;\n\treadonly mkdir: (path: string) => Promise<void>;\n\treadonly writeFile: (path: string, contents: string) => Promise<void>;\n}\n\ninterface WriteInputs {\n\treadonly deps: WriterDeps;\n\treadonly report: MigrationReport;\n\treadonly stateFilePath: string;\n}\n\n/**\n * Persist the migration report as `.bedrock/migration-report.json` and a\n * pure derivation `.bedrock/migration-report.md` next to the per-environment\n * state files. Always written so the user can compare runs even when no\n * warnings were emitted; the CLI summary line that points at the Markdown\n * file is gated on warning count separately.\n *\n * @param input - Resolved deps, the migration report, and the path of the\n * Mantle state file the report describes.\n * @returns `Ok` with both file paths once both writes succeed; `Err` on the\n * first failure (already rendered to clack).\n */\nexport async function writeMigrationReport(\n\tinput: WriteInputs,\n): Promise<Result<MigrationReportPaths, void>> {\n\tconst { deps, report, stateFilePath } = input;\n\tconst reportDirectory = join(dirname(stateFilePath), REPORT_DIR_NAME);\n\tconst jsonPath = join(reportDirectory, JSON_FILE_NAME);\n\tconst mdPath = join(reportDirectory, MD_FILE_NAME);\n\tconst file = { summary: report.summary, warnings: report.warnings };\n\n\ttry {\n\t\tawait deps.mkdir(reportDirectory);\n\t} catch (err) {\n\t\tdeps.clack.logError(\n\t\t\t`migration report directory create failed (${reportDirectory}): ${describeUnknown(err)}`,\n\t\t);\n\t\treturn { err: undefined, success: false };\n\t}\n\n\ttry {\n\t\tawait deps.writeFile(jsonPath, serializeMigrationReport(file));\n\t} catch (err) {\n\t\tdeps.clack.logError(`migration report write failed (${jsonPath}): ${describeUnknown(err)}`);\n\t\treturn { err: undefined, success: false };\n\t}\n\n\ttry {\n\t\tawait deps.writeFile(mdPath, renderMigrationReportMarkdown(file));\n\t} catch (err) {\n\t\tdeps.clack.logError(`migration report write failed (${mdPath}): ${describeUnknown(err)}`);\n\t\treturn { err: undefined, success: false };\n\t}\n\n\treturn { data: { jsonPath, mdPath }, success: true };\n}\n","import type { Result } from \"@bedrock-rbx/ocale\";\n\nimport type { MigrationReport } from \"../../core/migrate/migration-report.ts\";\nimport { serializeConfig } from \"../../core/migrate/serialize-config.ts\";\nimport type { Config } from \"../../core/schema.ts\";\nimport type { buildStatePort as defaultBuildStatePort } from \"../../shell/build-state-port.ts\";\nimport type { MigrateConfigFormat } from \"../migrate-prompt-port.ts\";\nimport type { ClackPort } from \"../render.ts\";\nimport { describeUnknown } from \"./describe-unknown.ts\";\nimport { type ResolvedStateTarget, writeMigratedStates } from \"./write-migrated-states.ts\";\nimport { writeMigrationReport } from \"./write-migration-report.ts\";\n\n/** Subset of the migrate command's resolved deps the finalize step touches. */\nexport interface FinalizeDeps {\n\t/** Default-constructs a `StatePort` once the gist target is resolved. */\n\treadonly buildStatePort: typeof defaultBuildStatePort;\n\t/** Output port for diagnostics and success lines. */\n\treadonly clack: ClackPort;\n\t/** Recursively creates a directory; used for the local-dump and report dirs. */\n\treadonly mkdir: (path: string) => Promise<void>;\n\t/** Writes a file's UTF-8 contents in one shot. */\n\treadonly writeFile: (path: string, contents: string) => Promise<void>;\n}\n\n/** Inputs for {@link persistMigration} and the inner config-write helper. */\nexport interface FinalizeInputs {\n\t/** Path to the bedrock config file to emit. */\n\treadonly configFilePath: string;\n\t/** Output format for the bedrock config (`typescript` or `yaml`). */\n\treadonly configFormat: MigrateConfigFormat;\n\t/** Resolved deps the writers dispatch through. */\n\treadonly deps: FinalizeDeps;\n\t/** Migration report whose state, config, and warnings are persisted. */\n\treadonly report: MigrationReport;\n\t/** Path to the Mantle state file the migration consumed. */\n\treadonly stateFilePath: string;\n\t/** Resolved state target picked by the user (gist or local). */\n\treadonly target: ResolvedStateTarget;\n}\n\n/**\n * Persist the migration's per-environment state, the bedrock config, and\n * the migration report (JSON + Markdown) in that order. Each failure\n * surface has already been rendered to clack by its respective writer; on\n * the first failure the function returns `Err` so the caller can exit\n * after a single shared `cancel(\"migrate failed\")` line.\n *\n * @param inputs - Resolved deps, the migration report, and the resolved\n * state-target plus paths the writers consume.\n * @returns `Ok` carrying the on-disk Markdown report path (used by the\n * terminal summary line) once every writer succeeded; `Err(void)` once\n * any writer reported failure.\n */\nexport async function persistMigration(inputs: FinalizeInputs): Promise<Result<string, void>> {\n\tconst stateConfigWritten = await persistStateAndConfig(inputs);\n\tif (!stateConfigWritten.success) {\n\t\treturn { err: undefined, success: false };\n\t}\n\n\tconst reportPaths = await writeMigrationReport({\n\t\tdeps: {\n\t\t\tclack: inputs.deps.clack,\n\t\t\tmkdir: inputs.deps.mkdir,\n\t\t\twriteFile: inputs.deps.writeFile,\n\t\t},\n\t\treport: inputs.report,\n\t\tstateFilePath: inputs.stateFilePath,\n\t});\n\treturn reportPaths.success\n\t\t? { data: reportPaths.data.mdPath, success: true }\n\t\t: { err: undefined, success: false };\n}\n\nasync function writeBedrockConfig(inputs: FinalizeInputs): Promise<Result<void, void>> {\n\tconst { configFilePath, configFormat, deps, report, target } = inputs;\n\tconst { state: _ignoredState, ...configWithoutState } = report.config;\n\tconst enrichedConfig: Config =\n\t\ttarget.backend === \"gist\"\n\t\t\t? { ...configWithoutState, state: target.stateConfig }\n\t\t\t: configWithoutState;\n\tconst bytes = serializeConfig({ config: enrichedConfig, configFormat });\n\ttry {\n\t\tawait deps.writeFile(configFilePath, bytes);\n\t} catch (err) {\n\t\tdeps.clack.logError(\n\t\t\t`config file write failed (${configFilePath}): ${describeUnknown(err)}`,\n\t\t);\n\t\treturn { err: undefined, success: false };\n\t}\n\n\tdeps.clack.logSuccess(`wrote ${configFilePath}`);\n\treturn { data: undefined, success: true };\n}\n\nasync function persistStateAndConfig(inputs: FinalizeInputs): Promise<Result<void, void>> {\n\tconst stateWritten = await writeMigratedStates({\n\t\tdeps: inputs.deps,\n\t\treport: inputs.report,\n\t\ttarget: inputs.target,\n\t});\n\tif (!stateWritten.success) {\n\t\treturn { err: undefined, success: false };\n\t}\n\n\tconst written = await writeBedrockConfig(inputs);\n\treturn written.success\n\t\t? { data: undefined, success: true }\n\t\t: { err: undefined, success: false };\n}\n","import type { Result } from \"@bedrock-rbx/ocale\";\n\nimport type { MigratePromptPort } from \"../migrate-prompt-port.ts\";\nimport { type MigrationSource, SUPPORTED_MIGRATION_SOURCES } from \"../parse-migrate-options.ts\";\n\n/**\n * Resolve the path to the input Mantle state file. The positional CLI\n * argument wins; when it is absent the user is asked through the prompt\n * port. Cancelling the prompt surfaces as `Err(\"cancelled\")`.\n *\n * @param pathArgument - The positional `<stateFilePath>` value sade\n * handed the action callback, or `undefined` when omitted.\n * @param promptPort - The migrate prompt port whose `promptStateFilePath`\n * is used as the interactive fallback.\n * @returns `Ok(path)` on success, or `Err(\"cancelled\")` if the user\n * aborted the prompt.\n */\nexport async function resolveStateFilePath(\n\tpathArgument: string | undefined,\n\tpromptPort: MigratePromptPort,\n): Promise<Result<string, \"cancelled\">> {\n\tif (pathArgument !== undefined) {\n\t\treturn { data: pathArgument, success: true };\n\t}\n\n\tconst promptResult = await promptPort.promptStateFilePath();\n\tif (!promptResult.success) {\n\t\treturn { err: \"cancelled\", success: false };\n\t}\n\n\treturn { data: promptResult.data, success: true };\n}\n\n/**\n * Resolve which source format to migrate from. A validated `--from`\n * value wins; when it is absent the user picks from\n * {@link SUPPORTED_MIGRATION_SOURCES} through the prompt port.\n * Cancelling the prompt surfaces as `Err(\"cancelled\")`.\n *\n * @param from - The validated `--from` value, or `undefined` when the\n * flag was omitted.\n * @param promptPort - The migrate prompt port whose\n * `promptMigrationSource` is used as the interactive fallback.\n * @returns `Ok(source)` on success, or `Err(\"cancelled\")` if the user\n * aborted the prompt.\n */\nexport async function resolveMigrationSource(\n\tfrom: MigrationSource | undefined,\n\tpromptPort: MigratePromptPort,\n): Promise<Result<MigrationSource, \"cancelled\">> {\n\tif (from !== undefined) {\n\t\treturn { data: from, success: true };\n\t}\n\n\tconst promptResult = await promptPort.promptMigrationSource(SUPPORTED_MIGRATION_SOURCES);\n\tif (!promptResult.success) {\n\t\treturn { err: \"cancelled\", success: false };\n\t}\n\n\treturn { data: promptResult.data, success: true };\n}\n","import type { Result } from \"@bedrock-rbx/ocale\";\n\nimport { mkdir as nodeMkdir, writeFile as nodeWriteFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport process from \"node:process\";\n\nimport type { MigrateError, MigrationReport } from \"../../core/migrate/migration-report.ts\";\nimport { buildStatePort as defaultBuildStatePort } from \"../../shell/build-state-port.ts\";\nimport {\n\tmigrateMantleState as defaultMigrateMantleState,\n\ttype MigrateMantleStateDeps,\n} from \"../../shell/migrate-mantle-state.ts\";\nimport { createDefaultMigratePromptPort } from \"../default-migrate-prompt-port.ts\";\nimport { EXIT_ERROR, EXIT_OK } from \"../exit-codes.ts\";\nimport type { ProgDeps } from \"../index.ts\";\nimport type { MigrateConfigFormat, MigratePromptPort } from \"../migrate-prompt-port.ts\";\nimport { type MigrationSource, parseMigrateOptions } from \"../parse-migrate-options.ts\";\nimport {\n\ttype ClackPort,\n\tcreateClackPort,\n\trenderMigrateError,\n\trenderMigrateParseError,\n\trenderMigrationSummary,\n} from \"../render.ts\";\nimport { describeUnknown } from \"./describe-unknown.ts\";\nimport { type FinalizeDeps, type FinalizeInputs, persistMigration } from \"./finalize-migration.ts\";\nimport { resolveMigrationSource, resolveStateFilePath } from \"./resolve-migrate-inputs.ts\";\nimport type { ResolvedStateTarget } from \"./write-migrated-states.ts\";\n\nconst FAILED_OUTRO = \"migrate failed\";\n\nconst CANCELLED_OUTRO = \"migrate cancelled\";\n\n/**\n * Sentinel returned by inner orchestration helpers when they could not\n * produce a `MigrationReport`. `cancelled` means the user aborted a\n * prompt; `rendered` means the failure was already described to the\n * user via `renderMigrateError` and the caller should exit\n * unconditionally without re-rendering.\n */\ntype MigrateRunError = \"cancelled\" | \"rendered\";\n\ninterface ResolvedMigrate {\n\treadonly buildStatePort: typeof defaultBuildStatePort;\n\treadonly clack: ClackPort;\n\treadonly exit: (code: number) => void;\n\treadonly migrateMantleState: typeof defaultMigrateMantleState;\n\treadonly mkdir: (path: string) => Promise<void>;\n\treadonly promptPort: MigratePromptPort;\n\treadonly writeFile: (path: string, contents: string) => Promise<void>;\n}\n\ninterface RunMigrateInputs {\n\treadonly pathArg: string | undefined;\n\treadonly rawOptions: Readonly<Record<string, unknown>>;\n\treadonly resolved: ResolvedMigrate;\n}\n\ninterface RunMigratorInputs {\n\treadonly configFormat: MigrateConfigFormat;\n\treadonly resolved: ResolvedMigrate;\n\treadonly stateFilePath: string;\n}\n\ninterface MigratorIoError {\n\treadonly cause: unknown;\n\treadonly kind: \"ioError\";\n\treadonly path: string;\n}\n\ninterface DispatchInputs {\n\treadonly resolved: ResolvedMigrate;\n\treadonly source: MigrationSource;\n\treadonly stateFilePath: string;\n}\n\n/**\n * Build the sade action for `bedrock migrate`. The returned function\n * consumes the optional positional path argument and the raw options\n * object sade hands the action callback. The command parses `--from`,\n * resolves the state file path (positional or interactive), prompts for\n * the output config format, runs the migrator, prompts for the state\n * backend coordinates, writes the per-environment states through the\n * configured `StatePort`, and emits an enriched bedrock config to disk.\n *\n * @param deps - Dependency overrides; missing slots are default-constructed\n * from real implementations.\n * @returns An async sade action that returns once `deps.exit` was invoked.\n */\nexport function migrateCommand(\n\tdeps: ProgDeps,\n): (\n\tpathArgument: string | undefined,\n\trawOptions: Readonly<Record<string, unknown>>,\n) => Promise<void> {\n\tconst resolved = resolveMigrate(deps);\n\treturn async (pathArgument, rawOptions) => {\n\t\tconst code = await runMigrate({ pathArg: pathArgument, rawOptions, resolved });\n\t\tresolved.exit(code);\n\t};\n}\n\nfunction resolveMigrate(deps: ProgDeps): ResolvedMigrate {\n\treturn {\n\t\tbuildStatePort: deps.buildStatePort ?? defaultBuildStatePort,\n\t\tclack: deps.clack ?? createClackPort(),\n\t\texit: deps.exit ?? ((code) => process.exit(code)),\n\t\tmigrateMantleState: deps.migrateMantleState ?? defaultMigrateMantleState,\n\t\tmkdir: deps.mkdir ?? (async (path) => void (await nodeMkdir(path, { recursive: true }))),\n\t\tpromptPort: deps.migratePromptPort ?? createDefaultMigratePromptPort(),\n\t\twriteFile:\n\t\t\tdeps.writeFile ?? (async (path, contents) => nodeWriteFile(path, contents, \"utf8\")),\n\t};\n}\n\nfunction cancel(resolved: ResolvedMigrate): number {\n\tresolved.clack.cancel(CANCELLED_OUTRO);\n\treturn EXIT_ERROR;\n}\n\nfunction failAfterRender(resolved: ResolvedMigrate): number {\n\tresolved.clack.cancel(FAILED_OUTRO);\n\treturn EXIT_ERROR;\n}\n\nfunction renderedFailure(\n\terr: MigrateError,\n\tresolved: ResolvedMigrate,\n): Result<MigrationReport, MigrateRunError> {\n\trenderMigrateError(err, resolved.clack);\n\tresolved.clack.cancel(FAILED_OUTRO);\n\treturn { err: \"rendered\", success: false };\n}\n\nasync function callMigrator(\n\tinputs: RunMigratorInputs & { readonly primaryEnvironment?: string },\n): Promise<Result<MigrationReport, MigrateError | MigratorIoError>> {\n\tconst callDeps: MigrateMantleStateDeps = {\n\t\tconfigFormat: inputs.configFormat,\n\t\tstateFilePath: inputs.stateFilePath,\n\t\t...(inputs.primaryEnvironment === undefined\n\t\t\t? {}\n\t\t\t: { primaryEnvironment: inputs.primaryEnvironment }),\n\t};\n\ttry {\n\t\treturn await inputs.resolved.migrateMantleState(callDeps);\n\t} catch (err) {\n\t\treturn { err: { cause: err, kind: \"ioError\", path: inputs.stateFilePath }, success: false };\n\t}\n}\n\nfunction renderIoFailure(\n\terr: MigratorIoError,\n\tresolved: ResolvedMigrate,\n): Result<MigrationReport, MigrateRunError> {\n\tresolved.clack.logError(\n\t\t`failed to read Mantle state file '${err.path}': ${describeUnknown(err.cause)}`,\n\t);\n\tresolved.clack.cancel(FAILED_OUTRO);\n\treturn { err: \"rendered\", success: false };\n}\n\nasync function runMigratorWithPrompt(\n\tinputs: RunMigratorInputs,\n): Promise<Result<MigrationReport, MigrateRunError>> {\n\tconst first = await callMigrator(inputs);\n\tif (first.success) {\n\t\treturn { data: first.data, success: true };\n\t}\n\n\tif (first.err.kind === \"ioError\") {\n\t\treturn renderIoFailure(first.err, inputs.resolved);\n\t}\n\n\tif (first.err.kind !== \"primaryEnvironmentRequired\") {\n\t\treturn renderedFailure(first.err, inputs.resolved);\n\t}\n\n\tconst primary = await inputs.resolved.promptPort.promptPrimaryEnvironment(first.err.available);\n\tif (!primary.success) {\n\t\treturn { err: \"cancelled\", success: false };\n\t}\n\n\tconst second = await callMigrator({ ...inputs, primaryEnvironment: primary.data });\n\tif (second.success) {\n\t\treturn { data: second.data, success: true };\n\t}\n\n\tif (second.err.kind === \"ioError\") {\n\t\treturn renderIoFailure(second.err, inputs.resolved);\n\t}\n\n\treturn renderedFailure(second.err, inputs.resolved);\n}\n\nasync function finalize(inputs: FinalizeInputs): Promise<number> {\n\tconst persisted = await persistMigration(inputs);\n\tif (!persisted.success) {\n\t\tinputs.deps.clack.cancel(FAILED_OUTRO);\n\t\treturn EXIT_ERROR;\n\t}\n\n\trenderMigrationSummary(\n\t\t{ reportPath: persisted.data, summary: inputs.report.summary },\n\t\tinputs.deps.clack,\n\t);\n\tinputs.deps.clack.outro(\"migrate succeeded\");\n\treturn EXIT_OK;\n}\n\nfunction configFileFor(stateFilePath: string, format: MigrateConfigFormat): string {\n\tconst extension = format === \"typescript\" ? \"ts\" : \"yaml\";\n\treturn join(dirname(stateFilePath), `bedrock.config.${extension}`);\n}\n\nasync function promptForStateTarget(\n\tresolved: ResolvedMigrate,\n\tstateFilePath: string,\n): Promise<Result<ResolvedStateTarget, \"cancelled\">> {\n\tconst backend = await resolved.promptPort.promptStateBackend();\n\tif (!backend.success) {\n\t\treturn { err: \"cancelled\", success: false };\n\t}\n\n\tif (backend.data === \"local\") {\n\t\treturn {\n\t\t\tdata: {\n\t\t\t\tbackend: \"local\",\n\t\t\t\toutputDir: join(dirname(stateFilePath), \".bedrock\", \"state\"),\n\t\t\t},\n\t\t\tsuccess: true,\n\t\t};\n\t}\n\n\tconst gistId = await resolved.promptPort.promptGistId();\n\tif (!gistId.success) {\n\t\treturn { err: \"cancelled\", success: false };\n\t}\n\n\treturn {\n\t\tdata: { backend: \"gist\", stateConfig: { backend: \"gist\", gistId: gistId.data } },\n\t\tsuccess: true,\n\t};\n}\n\nfunction finalizeDeps(resolved: ResolvedMigrate): FinalizeDeps {\n\treturn {\n\t\tbuildStatePort: resolved.buildStatePort,\n\t\tclack: resolved.clack,\n\t\tmkdir: resolved.mkdir,\n\t\twriteFile: resolved.writeFile,\n\t};\n}\n\nasync function runWithStateFilePath(\n\tstateFilePath: string,\n\tresolved: ResolvedMigrate,\n): Promise<number> {\n\tconst formatResult = await resolved.promptPort.promptConfigFormat();\n\tif (!formatResult.success) {\n\t\treturn cancel(resolved);\n\t}\n\n\tconst reportResult = await runMigratorWithPrompt({\n\t\tconfigFormat: formatResult.data,\n\t\tresolved,\n\t\tstateFilePath,\n\t});\n\tif (!reportResult.success) {\n\t\treturn reportResult.err === \"cancelled\" ? cancel(resolved) : EXIT_ERROR;\n\t}\n\n\tconst targetResult = await promptForStateTarget(resolved, stateFilePath);\n\tif (!targetResult.success) {\n\t\treturn cancel(resolved);\n\t}\n\n\treturn finalize({\n\t\tconfigFilePath: configFileFor(stateFilePath, formatResult.data),\n\t\tconfigFormat: formatResult.data,\n\t\tdeps: finalizeDeps(resolved),\n\t\treport: reportResult.data,\n\t\tstateFilePath,\n\t\ttarget: targetResult.data,\n\t});\n}\n\nasync function dispatchBySource(inputs: DispatchInputs): Promise<number> {\n\tconst { resolved, source, stateFilePath } = inputs;\n\tconst dispatch: Record<MigrationSource, () => Promise<number>> = {\n\t\tmantle: async () => runWithStateFilePath(stateFilePath, resolved),\n\t};\n\tconst handler = dispatch[source];\n\treturn handler();\n}\n\nasync function runMigrate(inputs: RunMigrateInputs): Promise<number> {\n\tconst { pathArg, rawOptions, resolved } = inputs;\n\tresolved.clack.intro(\"bedrock migrate\");\n\n\tconst parsed = parseMigrateOptions(rawOptions);\n\tif (!parsed.success) {\n\t\trenderMigrateParseError(parsed.err, resolved.clack);\n\t\treturn failAfterRender(resolved);\n\t}\n\n\tconst source = await resolveMigrationSource(parsed.data.from, resolved.promptPort);\n\tif (!source.success) {\n\t\treturn cancel(resolved);\n\t}\n\n\tconst stateFilePath = await resolveStateFilePath(pathArg, resolved.promptPort);\n\tif (!stateFilePath.success) {\n\t\treturn cancel(resolved);\n\t}\n\n\treturn dispatchBySource({\n\t\tresolved,\n\t\tsource: source.data,\n\t\tstateFilePath: stateFilePath.data,\n\t});\n}\n","import sade from \"sade\";\nimport type { Sade } from \"sade\";\n\nimport manifest from \"../../package.json\" with { type: \"json\" };\nimport type { buildStatePort as defaultBuildStatePort } from \"../shell/build-state-port.ts\";\nimport type { deploy as defaultDeploy } from \"../shell/deploy.ts\";\nimport type { loadConfig as defaultLoadConfig } from \"../shell/load-config.ts\";\nimport type { migrateMantleState as defaultMigrateMantleState } from \"../shell/migrate-mantle-state.ts\";\nimport type { previewDiff as defaultPreviewDiff } from \"../shell/preview-diff.ts\";\nimport { deployCommand } from \"./commands/deploy.ts\";\nimport { diffCommand } from \"./commands/diff.ts\";\nimport { migrateCommand } from \"./commands/migrate.ts\";\nimport type { MigratePromptPort } from \"./migrate-prompt-port.ts\";\nimport type { ClackPort } from \"./render.ts\";\n\nexport { createClackPort } from \"./render.ts\";\n\nconst PROGRAM_NAME = \"bedrock\";\nconst PROGRAM_DESCRIBE = \"Infrastructure-as-Code deployment tool for Roblox\";\n\n/**\n * Dependency seam for the bedrock CLI program. Every slot is optional;\n * command actions resolve a real default when a slot is omitted.\n */\nexport interface ProgDeps {\n\t/** Builds a `StatePort` from a resolved state config; defaults to the public `buildStatePort`. */\n\treadonly buildStatePort?: typeof defaultBuildStatePort;\n\t/** Output port; defaults to a real `@clack/prompts` adapter inside command actions. */\n\treadonly clack?: ClackPort;\n\t/** Reconciles config to live state; defaults to the public `deploy`. */\n\treadonly deploy?: typeof defaultDeploy;\n\t/** Process exit handle; defaults to `process.exit` so tests can intercept termination. The production default never returns; test stubs are free to return void. */\n\treadonly exit?: (code: number) => void;\n\t/** Project config loader; defaults to the public `loadConfig`. */\n\treadonly loadConfig?: typeof defaultLoadConfig;\n\t/** Mantle state migrator; defaults to the public `migrateMantleState`. */\n\treadonly migrateMantleState?: typeof defaultMigrateMantleState;\n\t/** Domain-specific prompt port for the migrate command; defaults to `createDefaultMigratePromptPort()`. */\n\treadonly migratePromptPort?: MigratePromptPort;\n\t/** Directory-create seam used by the migrate command for the local-dump backend; defaults to `node:fs/promises.mkdir` with `recursive: true`. */\n\treadonly mkdir?: (path: string) => Promise<void>;\n\t/** Read-only preview of operations; defaults to the internal `previewDiff` shell helper. */\n\treadonly previewDiff?: typeof defaultPreviewDiff;\n\t/** File-write seam used by the migrate command to emit the bedrock config file; defaults to `node:fs/promises.writeFile`. */\n\treadonly writeFile?: (path: string, contents: string) => Promise<void>;\n}\n\n/**\n * Construct the bedrock CLI program. Pure factory: no `process.argv` parsing,\n * no clack output, no exits. Callers (the `run.ts` shim, integration tests)\n * call `.parse()` on the returned sade instance.\n * @param deps - Dependency overrides for command actions. Each command\n * resolves its own defaults from any omitted slots.\n * @returns A configured sade program with the bedrock name, description, and\n * the currently installed `@bedrock-rbx/core` version, plus the registered\n * `deploy`, `diff`, and `migrate` commands.\n */\nexport function createProg(deps: ProgDeps = {}): Sade {\n\tconst prog = sade(PROGRAM_NAME).describe(PROGRAM_DESCRIBE).version(manifest.version);\n\n\tprog.command(\"deploy\")\n\t\t.describe(\"Reconcile a project's resources against the configured environment(s)\")\n\t\t.option(\"--env\", \"Target environment (repeat for multiple)\")\n\t\t.option(\"--config\", \"Config file path (overrides discovery)\")\n\t\t.option(\"--api-key\", \"Override the ROBLOX_API_KEY environment variable\")\n\t\t.option(\"--github-token\", \"Override the GITHUB_TOKEN environment variable\")\n\t\t.action(deployCommand(deps));\n\n\tprog.command(\"diff\")\n\t\t.describe(\"Preview the operations a deploy would apply, without writing state\")\n\t\t.option(\"--env\", \"Target environment (repeat for multiple)\")\n\t\t.option(\"--config\", \"Config file path (overrides discovery)\")\n\t\t.option(\"--api-key\", \"Override the ROBLOX_API_KEY environment variable\")\n\t\t.option(\"--github-token\", \"Override the GITHUB_TOKEN environment variable\")\n\t\t.action(diffCommand(deps));\n\n\tprog.command(\"migrate [stateFilePath]\")\n\t\t.describe(\"Translate a state file from another tool into a bedrock project\")\n\t\t.option(\"--from\", \"Source format to migrate from (mantle; prompted if omitted)\")\n\t\t.action(migrateCommand(deps));\n\n\treturn prog;\n}\n","#!/usr/bin/env node\nimport process from \"node:process\";\n\nimport { createProg } from \"./index.ts\";\n\ncreateProg().parse(process.argv);\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"run.mjs","names":["RECOGNIZED_FLAGS","SADE_RESERVED","readProcessEnvironment","defaultDeploy","defaultLoadConfig","loadOptionsFor","dispatchEnvironments","buildGetEnvironment","cancelAsFailed","defaultLoadConfig","readFile","nodeReadFile","defaultLoadConfig","defaultPreviewDiff","defaultIsCancel","defaultPath","defaultSelect","defaultText","defaultBuildStatePort","defaultMigrateMantleState","nodeMkdir","nodeWriteFile","cancel","manifest.version"],"sources":["../../package.json","../../src/cli/credential-environment-overrides.ts","../../src/cli/parse-options.ts","../../src/cli/render.ts","../../src/cli/commands/deploy.ts","../../src/shell/preview-diff.ts","../../src/cli/commands/diff.ts","../../src/cli/default-migrate-prompt-port.ts","../../src/cli/parse-migrate-options.ts","../../src/cli/commands/describe-unknown.ts","../../src/cli/commands/write-migrated-states.ts","../../src/core/migrate/render-migration-report-md.ts","../../src/core/migrate/serialize-migration-report.ts","../../src/cli/commands/write-migration-report.ts","../../src/cli/commands/finalize-migration.ts","../../src/cli/commands/resolve-migrate-inputs.ts","../../src/cli/commands/migrate.ts","../../src/cli/index.ts","../../src/cli/run.ts"],"sourcesContent":["","/** Credential flags that may be supplied on the CLI and translated to env-var overrides. */\ninterface CredentialFlags {\n\t/** Roblox Open Cloud API key override; translates to BEDROCK_API_KEY when defined. */\n\treadonly apiKey?: string;\n\t/** GitHub token override; translates to GITHUB_TOKEN when defined. */\n\treadonly githubToken?: string;\n}\n\n/**\n * Map CLI credential flags to their corresponding env-var names, omitting\n * entries whose flag is `undefined`.\n * @param flags - CLI credential flag values to translate.\n * @returns An immutable record of env-var names to their override values.\n */\nexport function buildCredentialOverrides(flags: CredentialFlags): Readonly<Record<string, string>> {\n\tconst overrides: Record<string, string> = {};\n\tif (flags.apiKey !== undefined) {\n\t\toverrides[\"BEDROCK_API_KEY\"] = flags.apiKey;\n\t}\n\n\tif (flags.githubToken !== undefined) {\n\t\toverrides[\"GITHUB_TOKEN\"] = flags.githubToken;\n\t}\n\n\treturn overrides;\n}\n","import type { Result } from \"@bedrock-rbx/ocale\";\n\nimport process from \"node:process\";\n\n/**\n * Typed shape command actions consume after the raw sade options object has\n * been validated and normalized.\n */\nexport interface CommonOptions {\n\t/** Roblox Open Cloud API key override; falls back to BEDROCK_API_KEY when undefined. */\n\treadonly apiKey?: string;\n\t/** Explicit config file path; when undefined the loader's discovery rules apply. */\n\treadonly configFile?: string;\n\t/** Target environment names. Sade collects `--env` repeatedly into this list. */\n\treadonly environments: ReadonlyArray<string>;\n\t/** GitHub token override; falls back to GITHUB_TOKEN when undefined. */\n\treadonly githubToken?: string;\n}\n\n/**\n * Failure modes surfaced by `parseCommonOptions`. Every variant names the\n * offending flag so callers can render a precise diagnostic.\n */\nexport type ParseOptionsError =\n\t| { readonly flag: string; readonly kind: \"invalidValue\" }\n\t| { readonly flag: string; readonly kind: \"missingRequired\" }\n\t| { readonly flag: string; readonly kind: \"unknownFlag\" };\n\nconst RECOGNIZED_FLAGS: ReadonlySet<string> = new Set([\n\t\"api-key\",\n\t\"apiKey\",\n\t\"config\",\n\t\"env\",\n\t\"github-token\",\n\t\"githubToken\",\n]);\n\nconst SADE_RESERVED: ReadonlySet<string> = new Set([\"--\", \"_\", \"h\", \"help\", \"v\", \"version\"]);\n\n/**\n * Translate the raw sade options POJO into a typed `CommonOptions`. Reads\n * `BEDROCK_ENVIRONMENT` from `process.env` as a fallback when `--env` is\n * absent; inject `getEnvironment` to redirect or isolate the lookup. No\n * clack, no sade types. Reused by `bedrock deploy` and `bedrock diff`.\n * @param rawOptions - The options object sade hands the action callback.\n * @param getEnvironment - Reads an environment variable; consulted as a\n * fallback for `--env` when no flag was supplied. Defaults to a\n * `process.env` reader.\n * @returns `Ok(CommonOptions)` on success, or `Err(ParseOptionsError)` when a\n * required flag is missing or an unrecognized flag was supplied.\n */\nexport function parseCommonOptions(\n\trawOptions: Readonly<Record<string, unknown>>,\n\tgetEnvironment: (name: string) => string | undefined = readProcessEnvironment,\n): Result<CommonOptions, ParseOptionsError> {\n\tfor (const key of Object.keys(rawOptions)) {\n\t\tif (!RECOGNIZED_FLAGS.has(key) && !SADE_RESERVED.has(key)) {\n\t\t\treturn { err: { flag: key, kind: \"unknownFlag\" }, success: false };\n\t\t}\n\t}\n\n\tconst environments = resolveEnvironments(rawOptions[\"env\"], getEnvironment);\n\tif (!environments.success) {\n\t\treturn environments;\n\t}\n\n\tconst apiKey = pickString(rawOptions, \"apiKey\", \"api-key\");\n\tconst configFile = pickString(rawOptions, \"config\");\n\tconst githubToken = pickString(rawOptions, \"githubToken\", \"github-token\");\n\n\treturn {\n\t\tdata: {\n\t\t\tenvironments: environments.data,\n\t\t\t...(apiKey === undefined ? {} : { apiKey }),\n\t\t\t...(configFile === undefined ? {} : { configFile }),\n\t\t\t...(githubToken === undefined ? {} : { githubToken }),\n\t\t},\n\t\tsuccess: true,\n\t};\n}\n\nfunction resolveEnvironments(\n\traw: unknown,\n\tgetEnvironment: (name: string) => string | undefined,\n): Result<ReadonlyArray<string>, ParseOptionsError> {\n\tif (raw === undefined) {\n\t\tconst fallback = getEnvironment(\"BEDROCK_ENVIRONMENT\");\n\t\tif (fallback === undefined) {\n\t\t\treturn { err: { flag: \"env\", kind: \"missingRequired\" }, success: false };\n\t\t}\n\n\t\treturn { data: [fallback], success: true };\n\t}\n\n\tconst candidates = Array.isArray(raw) ? raw : [raw];\n\tconst environments: Array<string> = [];\n\tfor (const candidate of candidates) {\n\t\tif (typeof candidate !== \"string\") {\n\t\t\treturn { err: { flag: \"env\", kind: \"invalidValue\" }, success: false };\n\t\t}\n\n\t\tenvironments.push(candidate);\n\t}\n\n\treturn { data: environments, success: true };\n}\n\nfunction readProcessEnvironment(name: string): string | undefined {\n\treturn process.env[name];\n}\n\nfunction pickString(\n\trawOptions: Readonly<Record<string, unknown>>,\n\t...keys: ReadonlyArray<string>\n): string | undefined {\n\tfor (const key of keys) {\n\t\tconst value = rawOptions[key];\n\t\tif (typeof value === \"string\") {\n\t\t\treturn value;\n\t\t}\n\t}\n\n\treturn undefined;\n}\n","import { PermissionError } from \"@bedrock-rbx/ocale\";\nimport { cancel, intro, log, outro } from \"@clack/prompts\";\n\nimport type { ConfigError } from \"../core/config-error.ts\";\nimport type { MigrateError, MigrationSummary } from \"../core/migrate/migration-report.ts\";\nimport type { StateError } from \"../core/state.ts\";\nimport type { ApplyError } from \"../shell/apply-ops.ts\";\nimport type { BuildDesiredError } from \"../shell/build-desired.ts\";\nimport type { MissingCredentialError, UnsupportedBackendError } from \"../shell/build-state-port.ts\";\nimport type { DeployError } from \"../shell/deploy.ts\";\nimport type { ParseMigrateError } from \"./parse-migrate-options.ts\";\nimport type { ParseOptionsError } from \"./parse-options.ts\";\n\n/**\n * Output port the CLI renders through. Mirrors the subset of `@clack/prompts`\n * the bedrock CLI uses today; tests inject a fake to assert what was rendered.\n */\nexport interface ClackPort {\n\t/** End an interactive flow with a cancellation marker. */\n\tcancel(message: string): void;\n\t/** Open a framed section with a title (used for command intros). */\n\tintro(message: string): void;\n\t/** Render a single error line inside an open frame. */\n\tlogError(message: string): void;\n\t/** Render a single neutral line inside an open frame. */\n\tlogMessage(message: string): void;\n\t/** Render a single success line inside an open frame. */\n\tlogSuccess(message: string): void;\n\t/** Close the current framed section with a final message. */\n\toutro(message: string): void;\n}\n\n/** Inputs for {@link renderStateWriteError}. */\ninterface StateWriteErrorRender {\n\t/** Environment whose state could not be written. */\n\treadonly environment: string;\n\t/** The state-error returned by the adapter. */\n\treadonly err: StateError;\n}\n\n/** Inputs for {@link renderMigrationSummary}. */\ninterface MigrationSummaryRender {\n\t/** Path to the Markdown report on disk. Pointed at from the action-required and review-needed lines. */\n\treadonly reportPath: string;\n\t/** Aggregate counts from a `MigrationReport`. */\n\treadonly summary: MigrationSummary;\n}\n\n/**\n * Render a `DeployError` to the supplied `ClackPort` as a single error line.\n * Each variant produces a distinct, terse diagnostic; wrapped variants\n * (`applyFailed`, `buildDesiredFailed`, `configLoadFailed`, `stateReadFailed`,\n * `stateWriteFailed`) surface the inner cause's actionable detail (file path,\n * resource key, parser message, HTTP failure, validator issue) so the reader\n * does not have to inspect the full cause to act.\n * @param err - The deploy error to describe.\n * @param port - The output port the diagnostic is written to.\n */\nexport function renderDeployError(err: DeployError, port: ClackPort): void {\n\tport.logError(deployErrorMessage(err));\n}\n\n/**\n * Render a `ParseOptionsError` to the supplied `ClackPort` as a single\n * error line. Each variant names the offending flag so the diagnostic\n * pinpoints what the caller needs to change.\n * @param err - The parse error to describe.\n * @param port - The output port the diagnostic is written to.\n */\nexport function renderParseError(err: ParseOptionsError, port: ClackPort): void {\n\tport.logError(parseErrorMessage(err));\n}\n\n/**\n * Construct a `ClackPort` whose methods delegate to `@clack/prompts`. The\n * resulting port writes to `process.stdout` via clack's defaults.\n * @returns A port whose six methods each invoke the matching clack helper.\n */\nexport function createClackPort(): ClackPort {\n\treturn {\n\t\tcancel: (message) => {\n\t\t\tcancel(message);\n\t\t},\n\t\tintro: (message) => {\n\t\t\tintro(message);\n\t\t},\n\t\tlogError: (message) => {\n\t\t\tlog.error(message);\n\t\t},\n\t\tlogMessage: (message) => {\n\t\t\tlog.message(message);\n\t\t},\n\t\tlogSuccess: (message) => {\n\t\t\tlog.success(message);\n\t\t},\n\t\toutro: (message) => {\n\t\t\toutro(message);\n\t\t},\n\t};\n}\n\n/**\n * Render a `ParseMigrateError` to the supplied `ClackPort`. Reuses\n * `parseErrorMessage` for the three flag-shape variants and adds a\n * dedicated message for `unknownSource` listing the supported sources.\n * @param err - The parse error to describe.\n * @param port - The output port the diagnostic is written to.\n */\nexport function renderMigrateParseError(err: ParseMigrateError, port: ClackPort): void {\n\tport.logError(migrateParseErrorMessage(err));\n}\n\n/**\n * Render a `MigrateError` to the supplied `ClackPort` as a single error\n * line. Each variant points at the offending Mantle state file path,\n * primary-environment input, or wrapped `ConfigError` so the reader can\n * act without inspecting the raw error object.\n * @param err - The migrate error to describe.\n * @param port - The output port the diagnostic is written to.\n */\nexport function renderMigrateError(err: MigrateError, port: ClackPort): void {\n\tport.logError(migrateErrorMessage(err));\n}\n\n/**\n * Render a `MissingCredentialError` or `UnsupportedBackendError`\n * surfaced when the migrate command tried to default-construct the\n * configured `StatePort` and was missing its inputs.\n * @param err - The error returned by `buildStatePort`.\n * @param port - The output port the diagnostic is written to.\n */\nexport function renderBuildStatePortError(\n\terr: MissingCredentialError | UnsupportedBackendError,\n\tport: ClackPort,\n): void {\n\tport.logError(buildStatePortErrorMessage(err));\n}\n\n/**\n * Render the post-migrate review prompt to the supplied `ClackPort`.\n * Three outcomes:\n *\n * - Any `ambiguous` warnings exist: emit a single error line directing\n * the user to the report. The migration ran but there are decisions\n * the user still needs to make before deploy will be meaningful.\n * - No `ambiguous` warnings but non-zero `blocked` / `deferred` /\n * `interpretive`: emit a single success line pointing at the report\n * for auditing.\n * - All counts zero: silent. The closing `outro(\"migrate succeeded\")`\n * already speaks for the run.\n * @param input - Counts plus the path of the Markdown report.\n * @param port - The output port the line is written to.\n */\nexport function renderMigrationSummary(input: MigrationSummaryRender, port: ClackPort): void {\n\tconst { ambiguousCount, blockedCount, deferredCount, interpretiveCount } = input.summary;\n\tif (ambiguousCount > 0) {\n\t\tport.logError(\n\t\t\t`action required: ${String(ambiguousCount)} fields need your input. See ${input.reportPath}`,\n\t\t);\n\t\treturn;\n\t}\n\n\tconst reviewable = blockedCount + deferredCount + interpretiveCount;\n\tif (reviewable > 0) {\n\t\tport.logSuccess(\n\t\t\t`migration complete; see ${input.reportPath} for ${String(reviewable)} auto-mapped or skipped fields`,\n\t\t);\n\t}\n}\n\n/**\n * Render a `StateError` produced when the migrator wrote a per-environment\n * state through the `StatePort`. Names the environment alongside the\n * adapter's failure reason so the reader knows which write failed.\n * @param input - Environment + state-error to describe.\n * @param port - The output port the diagnostic is written to.\n */\nexport function renderStateWriteError(input: StateWriteErrorRender, port: ClackPort): void {\n\tport.logError(\n\t\t`state write failed for '${input.environment}' (${input.err.file}): ${input.err.reason}`,\n\t);\n}\n\nfunction permissionDetail(err: PermissionError): string {\n\tconst isPlural = err.requiredScopes.length > 1;\n\tconst label = isPlural ? \"scopes\" : \"scope\";\n\tconst pronoun = isPlural ? \"them\" : \"it\";\n\tconst scopeList = err.requiredScopes.map((scope) => `'${scope}'`).join(\", \");\n\treturn `${err.message} on ${err.operationKey}: missing required ${label} ${scopeList}. Grant ${pronoun} on the API key at https://create.roblox.com/credentials`;\n}\n\nfunction applyCauseDetail(cause: ApplyError): string {\n\tswitch (cause.kind) {\n\t\tcase \"driverFailure\": {\n\t\t\tif (cause.cause instanceof PermissionError) {\n\t\t\t\treturn permissionDetail(cause.cause);\n\t\t\t}\n\n\t\t\treturn cause.cause.message;\n\t\t}\n\t\tcase \"updateUnsupported\": {\n\t\t\treturn \"update not supported\";\n\t\t}\n\t}\n}\n\nfunction buildDesiredDetail(cause: BuildDesiredError): string {\n\tswitch (cause.kind) {\n\t\tcase \"fileReadFailed\": {\n\t\t\treturn `(${cause.filePath}): ${cause.reason}`;\n\t\t}\n\t\tcase \"iconRemovalRejected\": {\n\t\t\treturn `: ${cause.message}`;\n\t\t}\n\t}\n}\n\nfunction configErrorDetail(err: ConfigError): string {\n\tswitch (err.kind) {\n\t\tcase \"configFunctionFailed\": {\n\t\t\treturn `${err.sourceFile}: config function threw: ${err.message}`;\n\t\t}\n\t\tcase \"fileNotFound\": {\n\t\t\treturn `no bedrock config under ${err.searchedFrom}`;\n\t\t}\n\t\tcase \"luauRuntimeMissing\": {\n\t\t\treturn `${err.sourceFile}: ${err.hint}`;\n\t\t}\n\t\tcase \"parseFailed\": {\n\t\t\treturn `${err.sourceFile}: ${err.message}`;\n\t\t}\n\t\tcase \"validationFailed\": {\n\t\t\tconst first = err.issues[0];\n\t\t\treturn first === undefined\n\t\t\t\t? `${err.sourceFile}: invalid`\n\t\t\t\t: `${err.sourceFile}: ${first.path.join(\".\")} ${first.message}`;\n\t\t}\n\t}\n}\n\nfunction stateErrorDetail(cause: StateError): string {\n\treturn `(${cause.file}): ${cause.reason}`;\n}\n\n/* eslint-disable-next-line max-lines-per-function -- single exhaustive switch over every DeployError variant is clearer than splitting into a wrapped-vs-unwrapped predicate plus a parallel prefix table. */\nfunction deployErrorMessage(err: DeployError): string {\n\tswitch (err.kind) {\n\t\tcase \"applyFailed\": {\n\t\t\treturn `apply failed for '${err.cause.key}': ${applyCauseDetail(err.cause)}`;\n\t\t}\n\t\tcase \"buildDesiredFailed\": {\n\t\t\treturn `build desired state failed for '${err.cause.key}' ${buildDesiredDetail(err.cause)}`;\n\t\t}\n\t\tcase \"configLoadFailed\": {\n\t\t\treturn `config load failed: ${configErrorDetail(err.cause)}`;\n\t\t}\n\t\tcase \"incompletePlaceEntry\": {\n\t\t\treturn `place '${err.key}' is missing '${err.missingField}' under environment '${err.environment}'`;\n\t\t}\n\t\tcase \"incompleteUniverseEntry\": {\n\t\t\treturn `universe is missing '${err.missingField}' under environment '${err.environment}'`;\n\t\t}\n\t\tcase \"missingCredential\": {\n\t\t\treturn `missing credential: environment variable ${err.variable} is not set`;\n\t\t}\n\t\tcase \"registryConfigMissing\": {\n\t\t\treturn `registry config missing '${err.missing}' (${err.hint})`;\n\t\t}\n\t\tcase \"stateNotConfigured\": {\n\t\t\treturn `state not configured for environment '${err.environment}'`;\n\t\t}\n\t\tcase \"stateReadFailed\": {\n\t\t\treturn `state read failed ${stateErrorDetail(err.cause)}`;\n\t\t}\n\t\tcase \"stateWriteFailed\": {\n\t\t\treturn `state write failed ${stateErrorDetail(err.cause)}`;\n\t\t}\n\t\tcase \"unknownEnvironment\": {\n\t\t\treturn `unknown environment '${err.environment}' (declared: ${err.declared.join(\", \")})`;\n\t\t}\n\t\tcase \"unsupportedBackend\": {\n\t\t\treturn `unsupported state backend '${err.backend}' (${err.hint})`;\n\t\t}\n\t}\n}\n\nfunction parseErrorMessage(err: ParseOptionsError): string {\n\tswitch (err.kind) {\n\t\tcase \"invalidValue\": {\n\t\t\treturn `invalid value for flag '--${err.flag}' (expected a string)`;\n\t\t}\n\t\tcase \"missingRequired\": {\n\t\t\treturn `missing required flag --${err.flag}`;\n\t\t}\n\t\tcase \"unknownFlag\": {\n\t\t\treturn `unknown flag '--${err.flag}'`;\n\t\t}\n\t}\n}\n\nfunction migrateParseErrorMessage(err: ParseMigrateError): string {\n\tif (err.kind === \"unknownSource\") {\n\t\treturn `unknown migration source '${err.received}' (supported: ${err.supported.join(\", \")})`;\n\t}\n\n\treturn parseErrorMessage(err);\n}\n\nfunction migrateErrorMessage(err: MigrateError): string {\n\tswitch (err.kind) {\n\t\tcase \"internalError\": {\n\t\t\treturn `migrate internal error: ${err.reason} (${configErrorDetail(err.cause)})`;\n\t\t}\n\t\tcase \"primaryEnvironmentNotFound\": {\n\t\t\treturn `primary environment '${err.primary}' not found (available: ${err.available.join(\", \")})`;\n\t\t}\n\t\tcase \"primaryEnvironmentRequired\": {\n\t\t\treturn `primary environment required (available: ${err.available.join(\", \")})`;\n\t\t}\n\t\tcase \"stateFileNotFound\": {\n\t\t\treturn `Mantle state file not found at '${err.path}'`;\n\t\t}\n\t\tcase \"stateParseFailed\": {\n\t\t\treturn `Mantle state file at '${err.path}' could not be parsed: ${err.reason}`;\n\t\t}\n\t\tcase \"unsupportedMantleStateVersion\": {\n\t\t\treturn `unsupported Mantle state version '${err.found}' (supported: ${err.supported.join(\", \")})`;\n\t\t}\n\t}\n}\n\nfunction buildStatePortErrorMessage(err: MissingCredentialError | UnsupportedBackendError): string {\n\tswitch (err.kind) {\n\t\tcase \"missingCredential\": {\n\t\t\treturn `missing credential: environment variable ${err.variable} is not set`;\n\t\t}\n\t\tcase \"unsupportedBackend\": {\n\t\t\treturn `unsupported state backend '${err.backend}' (${err.hint})`;\n\t\t}\n\t}\n}\n","import process from \"node:process\";\n\nimport type { Config } from \"../../core/schema.ts\";\nimport { deploy as defaultDeploy } from \"../../shell/deploy.ts\";\nimport {\n\tloadConfig as defaultLoadConfig,\n\ttype LoadConfigOptions,\n} from \"../../shell/load-config.ts\";\nimport { buildCredentialOverrides } from \"../credential-environment-overrides.ts\";\nimport { EXIT_ERROR, EXIT_OK } from \"../exit-codes.ts\";\nimport type { ProgDeps } from \"../index.ts\";\nimport { type CommonOptions, parseCommonOptions } from \"../parse-options.ts\";\nimport { type ClackPort, createClackPort, renderDeployError, renderParseError } from \"../render.ts\";\n\ninterface ResolvedDeploy {\n\treadonly clack: ClackPort;\n\treadonly deploy: typeof defaultDeploy;\n\treadonly exit: (code: number) => void;\n\treadonly loadConfig: typeof defaultLoadConfig;\n}\n\ninterface DispatchInputs {\n\treadonly config: Config;\n\treadonly environments: ReadonlyArray<string>;\n\treadonly getEnv: (name: string) => string | undefined;\n\treadonly resolved: ResolvedDeploy;\n}\n\n/**\n * Build the sade action for `bedrock deploy`. The returned function consumes\n * the raw options object sade hands the action callback, parses it via\n * `parseCommonOptions`, loads the project config once, and dispatches\n * `deploy()` for each `--env` value in order. Per-env successes and failures\n * render through clack as a single line each; the aggregated exit code is\n * `EXIT_OK` only when every env succeeded.\n * @param deps - Dependency overrides; missing slots are default-constructed\n * from real implementations.\n * @returns An async sade action that returns once `deps.exit` was invoked.\n */\nexport function deployCommand(\n\tdeps: ProgDeps,\n): (rawOptions: Record<string, unknown>) => Promise<void> {\n\tconst resolved = resolveDeploy(deps);\n\treturn async (rawOptions) => {\n\t\tconst code = await runDeploy(rawOptions, resolved);\n\t\tresolved.exit(code);\n\t};\n}\n\nfunction resolveDeploy(deps: ProgDeps): ResolvedDeploy {\n\treturn {\n\t\tclack: deps.clack ?? createClackPort(),\n\t\tdeploy: deps.deploy ?? defaultDeploy,\n\t\texit: deps.exit ?? ((code: number) => process.exit(code)),\n\t\tloadConfig: deps.loadConfig ?? defaultLoadConfig,\n\t};\n}\n\nfunction loadOptionsFor(parsed: CommonOptions): LoadConfigOptions | undefined {\n\treturn parsed.configFile === undefined ? undefined : { configFile: parsed.configFile };\n}\n\nasync function dispatchEnvironments(inputs: DispatchInputs): Promise<ReadonlyArray<string>> {\n\tconst { config, environments, getEnv, resolved } = inputs;\n\tconst failed: Array<string> = [];\n\tfor (const environment of environments) {\n\t\tconst result = await resolved.deploy({\n\t\t\tconfig,\n\t\t\tenvironment,\n\t\t\tgetEnv,\n\t\t});\n\t\tif (result.success) {\n\t\t\tresolved.clack.logSuccess(\n\t\t\t\t`${environment}: ${result.data.resources.length} resources reconciled`,\n\t\t\t);\n\t\t} else {\n\t\t\trenderDeployError(result.err, resolved.clack);\n\t\t\tfailed.push(environment);\n\t\t}\n\t}\n\n\treturn failed;\n}\n\nfunction buildGetEnvironment(parsed: CommonOptions): (name: string) => string | undefined {\n\tconst overrides = buildCredentialOverrides(parsed);\n\treturn (name) => overrides[name] ?? process.env[name];\n}\n\nfunction cancelAsFailed(clack: ClackPort): void {\n\tclack.cancel(\"deploy failed\");\n}\n\nasync function runDeploy(\n\trawOptions: Record<string, unknown>,\n\tresolved: ResolvedDeploy,\n): Promise<number> {\n\tresolved.clack.intro(\"bedrock deploy\");\n\n\tconst parsed = parseCommonOptions(rawOptions);\n\tif (!parsed.success) {\n\t\trenderParseError(parsed.err, resolved.clack);\n\t\tcancelAsFailed(resolved.clack);\n\t\treturn EXIT_ERROR;\n\t}\n\n\tconst loaded = await resolved.loadConfig(loadOptionsFor(parsed.data));\n\tif (!loaded.success) {\n\t\trenderDeployError({ cause: loaded.err, kind: \"configLoadFailed\" }, resolved.clack);\n\t\tcancelAsFailed(resolved.clack);\n\t\treturn EXIT_ERROR;\n\t}\n\n\tconst failures = await dispatchEnvironments({\n\t\tconfig: loaded.data,\n\t\tenvironments: parsed.data.environments,\n\t\tgetEnv: buildGetEnvironment(parsed.data),\n\t\tresolved,\n\t});\n\tif (failures.length > 0) {\n\t\tcancelAsFailed(resolved.clack);\n\t\treturn EXIT_ERROR;\n\t}\n\n\tresolved.clack.outro(\"deploy succeeded\");\n\treturn EXIT_OK;\n}\n","import type { Result } from \"@bedrock-rbx/ocale\";\n\nimport { readFile as nodeReadFile } from \"node:fs/promises\";\nimport process from \"node:process\";\n\nimport type { GistFetch } from \"../adapters/gist-state-adapter.ts\";\nimport type { ConfigError } from \"../core/config-error.ts\";\nimport { diff } from \"../core/diff.ts\";\nimport { flattenConfig } from \"../core/flatten.ts\";\nimport type { Operation } from \"../core/operations.ts\";\nimport { resolveStateConfig, type StateNotConfiguredError } from \"../core/resolve-state-config.ts\";\nimport type { Config, ResolvedConfig } from \"../core/schema.ts\";\nimport {\n\ttype IncompletePlaceEntryError,\n\ttype IncompleteUniverseEntryError,\n\tselectEnvironment,\n\ttype UnknownEnvironmentError,\n} from \"../core/select-environment.ts\";\nimport type { StateError } from \"../core/state.ts\";\nimport { validatePlan } from \"../core/validate-plan.ts\";\nimport type { StatePort } from \"../ports/state-port.ts\";\nimport { buildDesired, type BuildDesiredError } from \"./build-desired.ts\";\nimport {\n\tbuildStatePort,\n\ttype MissingCredentialError,\n\ttype UnsupportedBackendError,\n} from \"./build-state-port.ts\";\nimport { loadConfig as defaultLoadConfig, type LoadConfigOptions } from \"./load-config.ts\";\n\n/**\n * Inputs for `previewDiff`. Mirrors `DeployOptions` minus the apply-side\n * dependencies (`registry`); every field except `environment` is optional\n * and default-constructed from the project config and the environment\n * variables `GITHUB_TOKEN` (gist state backend) when omitted.\n */\nexport interface PreviewDiffOptions {\n\t/** Pre-loaded, optionally-mutated project config. Omit to call `loadConfig()` automatically. */\n\treadonly config?: Config;\n\t/** Environment name; threaded into `StatePort.read`. */\n\treadonly environment: string;\n\t/** `fetch` override plumbed into the default-constructed gist adapter when `statePort` is omitted. */\n\treadonly fetch?: GistFetch;\n\t/** Reads an environment variable; defaults to `(name) => process.env[name]`. */\n\treadonly getEnv?: (name: string) => string | undefined;\n\t/** Loader invoked when `config` is omitted; defaults to `loadConfig` from this package. */\n\treadonly loadConfig?: (options?: LoadConfigOptions) => Promise<Result<Config, ConfigError>>;\n\t/** Reads file bytes for resources that have file-backed inputs. Defaults to `node:fs/promises.readFile`. */\n\treadonly readFile?: (path: string) => Promise<Uint8Array>;\n\t/** Backend used to read the prior snapshot. Default-constructed from `config.state` and `GITHUB_TOKEN` when omitted. */\n\treadonly statePort?: StatePort;\n}\n\n/**\n * Failure surfaced by `previewDiff`. Stage-tagged so callers can branch on\n * `kind`. Strict subset of `DeployError`: every variant here is also a\n * `DeployError` variant, but the apply-side variants (`applyFailed`,\n * `stateWriteFailed`) cannot occur because `previewDiff` is read-only.\n */\nexport type PreviewDiffError =\n\t| IncompletePlaceEntryError\n\t| IncompleteUniverseEntryError\n\t| MissingCredentialError\n\t| StateNotConfiguredError\n\t| UnknownEnvironmentError\n\t| UnsupportedBackendError\n\t| { readonly cause: BuildDesiredError; readonly kind: \"buildDesiredFailed\" }\n\t| { readonly cause: ConfigError; readonly kind: \"configLoadFailed\" }\n\t| { readonly cause: StateError; readonly kind: \"stateReadFailed\" };\n\n/** Successful preview output. */\nexport interface DiffPreview {\n\t/** Environment the preview was computed against; matches `options.environment`. */\n\treadonly environment: string;\n\t/** Operations `diff` would apply during a deploy. */\n\treadonly ops: ReadonlyArray<Operation>;\n}\n\ninterface ResolvedDeps {\n\treadonly config: ResolvedConfig;\n\treadonly readFile: (path: string) => Promise<Uint8Array>;\n\treadonly statePort: StatePort;\n}\n\n/**\n * Compute the operations `deploy` would apply for a target environment\n * without writing state. Default-constructs missing deps from the project\n * config and `GITHUB_TOKEN`; never reads `process.env` when `statePort`\n * and `config` are both supplied explicitly.\n *\n * @param options - Target environment plus optional overrides.\n * @returns The computed operations on success, or a stage-tagged\n * `PreviewDiffError` on failure.\n */\nexport async function previewDiff(\n\toptions: PreviewDiffOptions,\n): Promise<Result<DiffPreview, PreviewDiffError>> {\n\tconst resolved = await resolveDeps(options);\n\tif (!resolved.success) {\n\t\treturn resolved;\n\t}\n\n\treturn runPreview(options.environment, resolved.data);\n}\n\nasync function pickConfig(options: PreviewDiffOptions): Promise<Result<Config, PreviewDiffError>> {\n\tif (options.config !== undefined) {\n\t\treturn { data: options.config, success: true };\n\t}\n\n\tconst loader = options.loadConfig ?? defaultLoadConfig;\n\tconst loaded = await loader();\n\tif (!loaded.success) {\n\t\treturn { err: { cause: loaded.err, kind: \"configLoadFailed\" }, success: false };\n\t}\n\n\treturn { data: loaded.data, success: true };\n}\n\nfunction readProcessEnvironment(name: string): string | undefined {\n\treturn process.env[name];\n}\n\nfunction getEnvironmentOf(options: PreviewDiffOptions): (name: string) => string | undefined {\n\treturn options.getEnv ?? readProcessEnvironment;\n}\n\nfunction pickStatePort(\n\toptions: PreviewDiffOptions,\n\tconfig: ResolvedConfig,\n): Result<StatePort, PreviewDiffError> {\n\tif (options.statePort !== undefined) {\n\t\treturn { data: options.statePort, success: true };\n\t}\n\n\tconst stateConfig = resolveStateConfig(config, options.environment);\n\tif (!stateConfig.success) {\n\t\treturn { err: stateConfig.err, success: false };\n\t}\n\n\treturn buildStatePort({\n\t\tfetch: options.fetch,\n\t\tgetEnv: getEnvironmentOf(options),\n\t\tstateConfig: stateConfig.data,\n\t});\n}\n\nasync function resolveDeps(\n\toptions: PreviewDiffOptions,\n): Promise<Result<ResolvedDeps, PreviewDiffError>> {\n\tconst config = await pickConfig(options);\n\tif (!config.success) {\n\t\treturn config;\n\t}\n\n\tconst selected = selectEnvironment(config.data, options.environment);\n\tif (!selected.success) {\n\t\treturn { err: selected.err, success: false };\n\t}\n\n\tconst effective = selected.data;\n\tconst readFile = options.readFile ?? nodeReadFile;\n\n\tconst statePort = pickStatePort(options, effective);\n\tif (!statePort.success) {\n\t\treturn statePort;\n\t}\n\n\treturn {\n\t\tdata: {\n\t\t\tconfig: effective,\n\t\t\treadFile,\n\t\t\tstatePort: statePort.data,\n\t\t},\n\t\tsuccess: true,\n\t};\n}\n\nasync function runPreview(\n\tenvironment: string,\n\tdeps: ResolvedDeps,\n): Promise<Result<DiffPreview, PreviewDiffError>> {\n\tconst desired = await buildDesired(flattenConfig(deps.config), deps.readFile);\n\tif (!desired.success) {\n\t\treturn { err: { cause: desired.err, kind: \"buildDesiredFailed\" }, success: false };\n\t}\n\n\tconst prior = await deps.statePort.read(environment);\n\tif (!prior.success) {\n\t\treturn { err: { cause: prior.err, kind: \"stateReadFailed\" }, success: false };\n\t}\n\n\tconst priorResources = prior.data?.resources ?? [];\n\tconst validated = validatePlan(desired.data, priorResources);\n\tif (!validated.success) {\n\t\treturn { err: { cause: validated.err, kind: \"buildDesiredFailed\" }, success: false };\n\t}\n\n\tconst ops = diff(desired.data, priorResources);\n\treturn { data: { environment, ops }, success: true };\n}\n","import process from \"node:process\";\n\nimport type { CreateOperation, Operation, UpdateOperation } from \"../../core/operations.ts\";\nimport type { Config } from \"../../core/schema.ts\";\nimport {\n\tloadConfig as defaultLoadConfig,\n\ttype LoadConfigOptions,\n} from \"../../shell/load-config.ts\";\nimport { previewDiff as defaultPreviewDiff, type DiffPreview } from \"../../shell/preview-diff.ts\";\nimport { buildCredentialOverrides } from \"../credential-environment-overrides.ts\";\nimport { EXIT_ERROR, EXIT_OK } from \"../exit-codes.ts\";\nimport type { ProgDeps } from \"../index.ts\";\nimport { type CommonOptions, parseCommonOptions } from \"../parse-options.ts\";\nimport { type ClackPort, createClackPort, renderDeployError, renderParseError } from \"../render.ts\";\n\ninterface ResolvedDiff {\n\treadonly clack: ClackPort;\n\treadonly exit: (code: number) => void;\n\treadonly loadConfig: typeof defaultLoadConfig;\n\treadonly previewDiff: typeof defaultPreviewDiff;\n}\n\ninterface DispatchInputs {\n\treadonly config: Config;\n\treadonly environments: ReadonlyArray<string>;\n\treadonly getEnv: (name: string) => string | undefined;\n\treadonly resolved: ResolvedDiff;\n}\n\ninterface DispatchOutcome {\n\treadonly failed: ReadonlyArray<string>;\n\treadonly hasDrift: boolean;\n}\n\n/**\n * Build the sade action for `bedrock diff`. The returned function consumes\n * the raw options object sade hands the action callback, parses it via\n * `parseCommonOptions`, loads the project config once, and dispatches\n * `previewDiff()` for each `--env` value in order. Per-env successes render\n * the operations list (or a `No drift` line when every op is a noop);\n * failures render via `renderDeployError`. The aggregated exit code is\n * `EXIT_OK` only when every env succeeded.\n * @param deps - Dependency overrides; missing slots are default-constructed\n * from real implementations.\n * @returns An async sade action that returns once `deps.exit` was invoked.\n */\nexport function diffCommand(\n\tdeps: ProgDeps,\n): (rawOptions: Record<string, unknown>) => Promise<void> {\n\tconst resolved = resolveDiff(deps);\n\treturn async (rawOptions) => {\n\t\tconst code = await runDiff(rawOptions, resolved);\n\t\tresolved.exit(code);\n\t};\n}\n\nfunction resolveDiff(deps: ProgDeps): ResolvedDiff {\n\treturn {\n\t\tclack: deps.clack ?? createClackPort(),\n\t\texit: deps.exit ?? ((code: number) => process.exit(code)),\n\t\tloadConfig: deps.loadConfig ?? defaultLoadConfig,\n\t\tpreviewDiff: deps.previewDiff ?? defaultPreviewDiff,\n\t};\n}\n\nfunction loadOptionsFor(parsed: CommonOptions): LoadConfigOptions | undefined {\n\treturn parsed.configFile === undefined ? undefined : { configFile: parsed.configFile };\n}\n\nfunction buildGetEnvironment(parsed: CommonOptions): (name: string) => string | undefined {\n\tconst overrides = buildCredentialOverrides(parsed);\n\treturn (name) => overrides[name] ?? process.env[name];\n}\n\nfunction cancelAsFailed(clack: ClackPort): void {\n\tclack.cancel(\"diff failed\");\n}\n\nfunction describeOp(op: CreateOperation | UpdateOperation): string {\n\tswitch (op.type) {\n\t\tcase \"create\": {\n\t\t\treturn `+ ${op.desired.kind}:${op.key}`;\n\t\t}\n\t\tcase \"update\": {\n\t\t\treturn `~ ${op.desired.kind}:${op.key}`;\n\t\t}\n\t}\n}\n\nfunction isDriftOp(op: Operation): op is CreateOperation | UpdateOperation {\n\treturn op.type !== \"noop\";\n}\n\nfunction renderPreview(preview: DiffPreview, clack: ClackPort): boolean {\n\tconst drift = preview.ops.filter(isDriftOp);\n\tif (drift.length === 0) {\n\t\tclack.logSuccess(`No drift for \"${preview.environment}\"`);\n\t\treturn false;\n\t}\n\n\tclack.logMessage(`Pending changes for \"${preview.environment}\":`);\n\tfor (const op of drift) {\n\t\tclack.logMessage(describeOp(op));\n\t}\n\n\treturn true;\n}\n\nasync function dispatchEnvironments(inputs: DispatchInputs): Promise<DispatchOutcome> {\n\tconst { config, environments, getEnv, resolved } = inputs;\n\tconst failed: Array<string> = [];\n\tlet hasDrift = false;\n\tfor (const environment of environments) {\n\t\tconst result = await resolved.previewDiff({\n\t\t\tconfig,\n\t\t\tenvironment,\n\t\t\tgetEnv,\n\t\t});\n\t\tif (result.success) {\n\t\t\tif (renderPreview(result.data, resolved.clack)) {\n\t\t\t\thasDrift = true;\n\t\t\t}\n\t\t} else {\n\t\t\trenderDeployError(result.err, resolved.clack);\n\t\t\tfailed.push(environment);\n\t\t}\n\t}\n\n\treturn { failed, hasDrift };\n}\n\nfunction outroFor(hasDrift: boolean): string {\n\treturn hasDrift\n\t\t? \"run bedrock deploy to apply pending changes\"\n\t\t: \"all environments are up to date\";\n}\n\nasync function runDiff(\n\trawOptions: Record<string, unknown>,\n\tresolved: ResolvedDiff,\n): Promise<number> {\n\tresolved.clack.intro(\"bedrock diff\");\n\n\tconst parsed = parseCommonOptions(rawOptions);\n\tif (!parsed.success) {\n\t\trenderParseError(parsed.err, resolved.clack);\n\t\tcancelAsFailed(resolved.clack);\n\t\treturn EXIT_ERROR;\n\t}\n\n\tconst loaded = await resolved.loadConfig(loadOptionsFor(parsed.data));\n\tif (!loaded.success) {\n\t\trenderDeployError({ cause: loaded.err, kind: \"configLoadFailed\" }, resolved.clack);\n\t\tcancelAsFailed(resolved.clack);\n\t\treturn EXIT_ERROR;\n\t}\n\n\tconst outcome = await dispatchEnvironments({\n\t\tconfig: loaded.data,\n\t\tenvironments: parsed.data.environments,\n\t\tgetEnv: buildGetEnvironment(parsed.data),\n\t\tresolved,\n\t});\n\tif (outcome.failed.length > 0) {\n\t\tcancelAsFailed(resolved.clack);\n\t\treturn EXIT_ERROR;\n\t}\n\n\tresolved.clack.outro(outroFor(outcome.hasDrift));\n\treturn EXIT_OK;\n}\n","import {\n\tisCancel as defaultIsCancel,\n\tpath as defaultPath,\n\tselect as defaultSelect,\n\ttext as defaultText,\n\ttype PathOptions,\n\ttype SelectOptions,\n\ttype TextOptions,\n} from \"@clack/prompts\";\n\nimport type {\n\tMigrateConfigFormat,\n\tMigratePromptPort,\n\tMigratePromptResult,\n\tMigrateStateBackend,\n} from \"./migrate-prompt-port.ts\";\nimport type { MigrationSource } from \"./parse-migrate-options.ts\";\n\n/**\n * Test seam for {@link createDefaultMigratePromptPort}. Production callers\n * omit `helpers` and the port delegates straight to `@clack/prompts`;\n * tests substitute scripted, non-generic stand-ins so each prompt method\n * can be exercised without spawning a real terminal.\n *\n * Slot signatures use clack's own types pinned to `string`-valued options\n * so a `vi.fn` instance is assignable: vitest cannot construct a `Mock`\n * that satisfies a polymorphic `<Value>(...)` signature, but it can\n * satisfy this concrete shape.\n */\nexport interface MigratePromptClackHelpers {\n\t/** Cancel predicate; defaults to `@clack/prompts`'s `isCancel`. */\n\treadonly isCancel: (value: unknown) => value is symbol;\n\t/**\n\t * Path-prompt fn with filesystem tab-completion; defaults to\n\t * `@clack/prompts`'s `path`.\n\t */\n\treadonly path: (options: PathOptions) => Promise<string | symbol>;\n\t/** Select-prompt fn; defaults to `@clack/prompts`'s `select`. */\n\treadonly select: (options: SelectOptions<string>) => Promise<string | symbol>;\n\t/** Text-prompt fn; defaults to `@clack/prompts`'s `text`. */\n\treadonly text: (options: TextOptions) => Promise<string | symbol>;\n}\n\nconst FORMAT_OPTIONS: ReadonlyArray<{ hint?: string; label: string; value: MigrateConfigFormat }> =\n\t[\n\t\t{ hint: \"recommended\", label: \"TypeScript\", value: \"typescript\" },\n\t\t{ label: \"YAML\", value: \"yaml\" },\n\t];\n\nconst BACKEND_OPTIONS: ReadonlyArray<{ hint?: string; label: string; value: MigrateStateBackend }> =\n\t[\n\t\t{ label: \"GitHub Gist\", value: \"gist\" },\n\t\t{\n\t\t\thint: \"writes .bedrock/state/<env>.json next to bedrock.config\",\n\t\t\tlabel: \"Local files\",\n\t\t\tvalue: \"local\",\n\t\t},\n\t];\n\nconst SOURCE_LABELS: Record<MigrationSource, string> = {\n\tmantle: \"Mantle\",\n};\n\nconst defaultHelpers: MigratePromptClackHelpers = {\n\tisCancel: defaultIsCancel,\n\tpath: defaultPath,\n\tselect: defaultSelect,\n\ttext: defaultText,\n};\n\ninterface FromSelectInputs<T extends string> {\n\treadonly initialValue?: T;\n\treadonly message: string;\n\treadonly options: ReadonlyArray<{ hint?: string; label: string; value: T }>;\n}\n\n/**\n * Construct a `MigratePromptPort` whose methods delegate to\n * `@clack/prompts`. Each prompt translates clack's cancel sentinel into\n * a typed `Err({ kind: \"cancelled\" })` so the migrate command branches\n * on `Result` like every other shell call.\n *\n * @param helpers - Test-only seam for swapping the three clack\n * primitives. Production callers omit this argument.\n * @returns A live `MigratePromptPort` ready to drive interactively.\n */\nexport function createDefaultMigratePromptPort(\n\thelpers: MigratePromptClackHelpers = defaultHelpers,\n): MigratePromptPort {\n\treturn {\n\t\tpromptConfigFormat: async () => promptConfigFormatFrom(helpers),\n\t\tpromptGistId: async () => promptGistIdFrom(helpers),\n\t\tpromptMigrationSource: async (sources) => selectMigrationSource(helpers, sources),\n\t\tpromptPrimaryEnvironment: async (environments) =>\n\t\t\tselectPrimaryEnvironment(helpers, environments),\n\t\tpromptStateBackend: async () => promptStateBackendFrom(helpers),\n\t\tpromptStateFilePath: async () => promptStateFilePathFrom(helpers),\n\t};\n}\n\nasync function fromSelect<T extends string>(\n\thelpers: MigratePromptClackHelpers,\n\tinputs: FromSelectInputs<T>,\n): Promise<MigratePromptResult<T>> {\n\tconst result = await helpers.select({\n\t\tmessage: inputs.message,\n\t\toptions: inputs.options.map((option) => {\n\t\t\treturn {\n\t\t\t\t...(option.hint === undefined ? {} : { hint: option.hint }),\n\t\t\t\tlabel: option.label,\n\t\t\t\tvalue: option.value,\n\t\t\t};\n\t\t}),\n\t\t...(inputs.initialValue === undefined ? {} : { initialValue: inputs.initialValue }),\n\t});\n\tif (helpers.isCancel(result)) {\n\t\treturn { err: { kind: \"cancelled\" }, success: false };\n\t}\n\n\treturn { data: result as T, success: true };\n}\n\nasync function selectMigrationSource(\n\thelpers: MigratePromptClackHelpers,\n\tsources: readonly [MigrationSource, ...ReadonlyArray<MigrationSource>],\n): Promise<MigratePromptResult<MigrationSource>> {\n\treturn fromSelect<MigrationSource>(helpers, {\n\t\tinitialValue: sources[0],\n\t\tmessage: \"Migrate from?\",\n\t\toptions: sources.map((source) => ({ label: SOURCE_LABELS[source], value: source })),\n\t});\n}\n\nasync function promptConfigFormatFrom(\n\thelpers: MigratePromptClackHelpers,\n): Promise<MigratePromptResult<MigrateConfigFormat>> {\n\treturn fromSelect(helpers, {\n\t\tinitialValue: \"typescript\",\n\t\tmessage: \"Output config format?\",\n\t\toptions: FORMAT_OPTIONS,\n\t});\n}\n\nfunction validateNonEmpty(value: string | undefined): string | undefined {\n\tif (value === undefined || value.trim() === \"\") {\n\t\treturn \"Required\";\n\t}\n\n\treturn undefined;\n}\n\nasync function fromText(\n\thelpers: MigratePromptClackHelpers,\n\toptions: TextOptions,\n): Promise<MigratePromptResult<string>> {\n\tconst result = await helpers.text(options);\n\tif (helpers.isCancel(result)) {\n\t\treturn { err: { kind: \"cancelled\" }, success: false };\n\t}\n\n\treturn { data: result, success: true };\n}\n\nasync function promptGistIdFrom(\n\thelpers: MigratePromptClackHelpers,\n): Promise<MigratePromptResult<string>> {\n\treturn fromText(helpers, {\n\t\tmessage: \"Gist ID for state storage?\",\n\t\tplaceholder: \"abc123\",\n\t\tvalidate: validateNonEmpty,\n\t});\n}\n\nasync function selectPrimaryEnvironment(\n\thelpers: MigratePromptClackHelpers,\n\tenvironments: ReadonlyArray<string>,\n): Promise<MigratePromptResult<string>> {\n\treturn fromSelect(helpers, {\n\t\tmessage:\n\t\t\t\"Which environment should be the primary?\\nThe migrator uses it as the baseline for the generated config.\",\n\t\toptions: environments.map((name) => ({ label: name, value: name })),\n\t});\n}\n\nasync function promptStateBackendFrom(\n\thelpers: MigratePromptClackHelpers,\n): Promise<MigratePromptResult<MigrateStateBackend>> {\n\treturn fromSelect(helpers, {\n\t\tinitialValue: \"gist\",\n\t\tmessage: \"State backend?\",\n\t\toptions: BACKEND_OPTIONS,\n\t});\n}\n\nasync function fromPath(\n\thelpers: MigratePromptClackHelpers,\n\toptions: PathOptions,\n): Promise<MigratePromptResult<string>> {\n\tconst result = await helpers.path(options);\n\tif (helpers.isCancel(result)) {\n\t\treturn { err: { kind: \"cancelled\" }, success: false };\n\t}\n\n\treturn { data: result, success: true };\n}\n\nasync function promptStateFilePathFrom(\n\thelpers: MigratePromptClackHelpers,\n): Promise<MigratePromptResult<string>> {\n\treturn fromPath(helpers, {\n\t\tinitialValue: \".mantle-state.yml\",\n\t\tmessage: \"Path to the Mantle state file?\",\n\t\tvalidate: validateNonEmpty,\n\t});\n}\n","import type { Result } from \"@bedrock-rbx/ocale\";\n\nimport type { ParseOptionsError } from \"./parse-options.ts\";\n\n/**\n * Sources `bedrock migrate --from <source>` accepts. Today only `\"mantle\"`\n * is wired up; widening this tuple turns on additional sources without\n * touching the parser.\n */\nexport const SUPPORTED_MIGRATION_SOURCES = [\"mantle\"] as const;\n\n/**\n * Failure surfaced by `parseMigrateOptions`. Reuses the three flag-shape\n * variants from `ParseOptionsError` (so the existing `renderParseError`\n * messages stay consistent) and adds `unknownSource` for `--from` values\n * outside {@link SUPPORTED_MIGRATION_SOURCES}.\n */\nexport type ParseMigrateError =\n\t| ParseOptionsError\n\t| {\n\t\t\treadonly kind: \"unknownSource\";\n\t\t\treadonly received: string;\n\t\t\treadonly supported: ReadonlyArray<string>;\n\t };\n\n/** One element of {@link SUPPORTED_MIGRATION_SOURCES}. */\nexport type MigrationSource = (typeof SUPPORTED_MIGRATION_SOURCES)[number];\n\n/** Typed shape the migrate command consumes after `--from` has been validated. */\ninterface MigrateOptions {\n\t/**\n\t * Validated source to migrate from, or `undefined` when the flag was\n\t * omitted. The command falls back to an interactive picker in that\n\t * case, mirroring how the positional state-file path is handled.\n\t */\n\treadonly from: MigrationSource | undefined;\n}\n\nconst RECOGNIZED_FLAGS: ReadonlySet<string> = new Set([\"from\"]);\n\nconst SADE_RESERVED: ReadonlySet<string> = new Set([\"--\", \"_\", \"h\", \"help\", \"v\", \"version\"]);\n\n/**\n * Translate the raw sade options POJO into a typed `MigrateOptions`. The\n * positional `<stateFilePath>` argument is not handled here: sade hands\n * positional values to the action callback ahead of the options object,\n * and the migrate command falls back to an interactive prompt when it\n * is absent. This parser only covers the `--from` flag, which is also\n * optional and prompted for when omitted.\n *\n * @param rawOptions - The options object sade hands the action callback.\n * @returns `Ok(MigrateOptions)` on success, or `Err(ParseMigrateError)`\n * describing the offending flag or value.\n */\nexport function parseMigrateOptions(\n\trawOptions: Readonly<Record<string, unknown>>,\n): Result<MigrateOptions, ParseMigrateError> {\n\tfor (const key of Object.keys(rawOptions)) {\n\t\tif (!RECOGNIZED_FLAGS.has(key) && !SADE_RESERVED.has(key)) {\n\t\t\treturn { err: { flag: key, kind: \"unknownFlag\" }, success: false };\n\t\t}\n\t}\n\n\tconst fromRaw = rawOptions[\"from\"];\n\tif (fromRaw === undefined) {\n\t\treturn { data: { from: undefined }, success: true };\n\t}\n\n\tif (typeof fromRaw !== \"string\") {\n\t\treturn { err: { flag: \"from\", kind: \"invalidValue\" }, success: false };\n\t}\n\n\tif (!isMigrationSource(fromRaw)) {\n\t\treturn {\n\t\t\terr: {\n\t\t\t\tkind: \"unknownSource\",\n\t\t\t\treceived: fromRaw,\n\t\t\t\tsupported: SUPPORTED_MIGRATION_SOURCES,\n\t\t\t},\n\t\t\tsuccess: false,\n\t\t};\n\t}\n\n\treturn { data: { from: fromRaw }, success: true };\n}\n\nfunction isMigrationSource(value: string): value is MigrationSource {\n\treturn (SUPPORTED_MIGRATION_SOURCES as ReadonlyArray<string>).includes(value);\n}\n","/**\n * Format a thrown value as a human-readable string for clack diagnostic\n * lines. Native `Error` instances surface their `message`; everything\n * else is coerced via `String()` so non-Error throws (rejection of a\n * primitive, for example) still render legibly.\n *\n * @param value - The caught value to describe.\n * @returns A short string suitable for inlining into a CLI error line.\n */\nexport function describeUnknown(value: unknown): string {\n\treturn value instanceof Error ? value.message : String(value);\n}\n","import type { Result } from \"@bedrock-rbx/ocale\";\n\nimport { join } from \"node:path\";\nimport process from \"node:process\";\n\nimport type { MigrationReport } from \"../../core/migrate/migration-report.ts\";\nimport type { GistStateConfig } from \"../../core/schema.ts\";\nimport { serializeStateFile } from \"../../core/state-file.ts\";\nimport type { buildStatePort as defaultBuildStatePort } from \"../../shell/build-state-port.ts\";\nimport type { ClackPort } from \"../render.ts\";\nimport { renderBuildStatePortError, renderStateWriteError } from \"../render.ts\";\nimport { describeUnknown } from \"./describe-unknown.ts\";\n\n/**\n * Where the migrate command persists per-environment states. The `gist`\n * arm carries the resolved {@link GistStateConfig} that gets written to\n * the bedrock config; the `local` arm carries the on-disk directory used\n * for the JSON-per-environment dump.\n */\nexport type ResolvedStateTarget =\n\t| { readonly backend: \"gist\"; readonly stateConfig: GistStateConfig }\n\t| { readonly backend: \"local\"; readonly outputDir: string };\n\n/** Subset of the migrate command's resolved deps the writers need. */\ninterface WriterDeps {\n\treadonly buildStatePort: typeof defaultBuildStatePort;\n\treadonly clack: ClackPort;\n\treadonly mkdir: (path: string) => Promise<void>;\n\treadonly writeFile: (path: string, contents: string) => Promise<void>;\n}\n\ninterface WriteInputs {\n\treadonly deps: WriterDeps;\n\treadonly report: MigrationReport;\n\treadonly target: ResolvedStateTarget;\n}\n\n/**\n * Persist every per-environment state in the migration report to the\n * resolved target. Dispatches to the GitHub Gist `StatePort` adapter or\n * to a local-file dump under `target.outputDir`. On failure the writer\n * has already rendered the error to `deps.clack`; the caller only needs\n * to translate the Err into an exit code.\n *\n * @param inputs - Resolved deps, the migration report, and the target\n * the writer should dispatch on.\n * @returns `Ok(void)` once every environment has been written; `Err(void)`\n * on the first failure (already rendered to clack).\n */\nexport async function writeMigratedStates(inputs: WriteInputs): Promise<Result<void, void>> {\n\tif (inputs.target.backend === \"local\") {\n\t\treturn writeStatesToLocal({ ...inputs, target: inputs.target });\n\t}\n\n\treturn writeStatesToGist({ ...inputs, target: inputs.target });\n}\n\nasync function writeStatesToGist(\n\tinputs: WriteInputs & { readonly target: { readonly stateConfig: GistStateConfig } },\n): Promise<Result<void, void>> {\n\tconst { deps, report, target } = inputs;\n\tconst portResult = deps.buildStatePort({\n\t\tgetEnv: (name) => process.env[name],\n\t\tstateConfig: target.stateConfig,\n\t});\n\tif (!portResult.success) {\n\t\trenderBuildStatePortError(portResult.err, deps.clack);\n\t\treturn { err: undefined, success: false };\n\t}\n\n\tfor (const [environment, state] of Object.entries(report.statesByEnvironment)) {\n\t\tconst writeResult = await portResult.data.write(state);\n\t\tif (!writeResult.success) {\n\t\t\trenderStateWriteError({ environment, err: writeResult.err }, deps.clack);\n\t\t\treturn { err: undefined, success: false };\n\t\t}\n\n\t\tdeps.clack.logSuccess(`${environment}: ${state.resources.length} resources migrated`);\n\t}\n\n\treturn { data: undefined, success: true };\n}\n\nasync function writeStatesToLocal(\n\tinputs: WriteInputs & { readonly target: { readonly outputDir: string } },\n): Promise<Result<void, void>> {\n\tconst { deps, report, target } = inputs;\n\ttry {\n\t\tawait deps.mkdir(target.outputDir);\n\t} catch (err) {\n\t\tdeps.clack.logError(\n\t\t\t`local state directory create failed (${target.outputDir}): ${describeUnknown(err)}`,\n\t\t);\n\t\treturn { err: undefined, success: false };\n\t}\n\n\tfor (const [environment, state] of Object.entries(report.statesByEnvironment)) {\n\t\tconst filePath = join(target.outputDir, `${environment}.json`);\n\t\ttry {\n\t\t\tawait deps.writeFile(filePath, serializeStateFile(state));\n\t\t} catch (err) {\n\t\t\tdeps.clack.logError(`local state write failed (${filePath}): ${describeUnknown(err)}`);\n\t\t\treturn { err: undefined, success: false };\n\t\t}\n\n\t\tdeps.clack.logSuccess(`${environment}: ${state.resources.length} resources migrated`);\n\t}\n\n\treturn { data: undefined, success: true };\n}\n","import type { MigrationReportFile, MigrationWarning } from \"./migration-report.ts\";\n\ninterface SectionInput<W extends { readonly mantlePath: string }> {\n\treadonly groupKey: (warning: W) => string;\n\t/**\n\t * Subject the entry collapses by. For ambiguous/blocked/deferred this is\n\t * the mantle-path suffix (env stripped); for interpretive it is suffix\n\t * plus `-> bedrockPath` so distinct mappings remain distinct bullets.\n\t */\n\treadonly subject: (warning: W) => string;\n\treadonly title: string;\n\treadonly warnings: ReadonlyArray<W>;\n}\n\n/**\n * Render a {@link MigrationReportFile} as the Markdown body written to\n * `.bedrock/migration-report.md`. Pure derivation: the same input shape\n * the JSON serializer consumes feeds this renderer, so the Markdown view\n * round-trips through the JSON file.\n *\n * Output structure:\n * - Header with the four counts.\n * - Sections in user-action priority order (Action required, Blocked,\n * Deferred, Interpretive). Sections with no matching warnings are\n * omitted entirely.\n * - Within each section, warnings are grouped by their non-path\n * discriminator (`hint` for ambiguous, `reason` for blocked/deferred,\n * `rule` for interpretive). First-appearance order is preserved.\n * - Interpretive entries render as `mantlePath -> bedrockPath` so the\n * user can verify the auto-applied mapping at a glance.\n *\n * @param file - The summary plus warnings to render.\n * @returns Markdown source ending with a trailing newline.\n */\nexport function renderMigrationReportMarkdown(file: MigrationReportFile): string {\n\tconst sections = [\n\t\trenderActionRequired(file.warnings),\n\t\trenderBlocked(file.warnings),\n\t\trenderDeferred(file.warnings),\n\t\trenderInterpretive(file.warnings),\n\t].filter((section) => section !== \"\");\n\n\tconst header = renderHeader(file);\n\treturn [header, ...sections].join(\"\\n\");\n}\n\nfunction renderHeader(file: MigrationReportFile): string {\n\treturn [\n\t\t\"# Migration report\",\n\t\t\"\",\n\t\t`ambiguous: ${String(file.summary.ambiguousCount)}`,\n\t\t`blocked: ${String(file.summary.blockedCount)}`,\n\t\t`deferred: ${String(file.summary.deferredCount)}`,\n\t\t`interpretive: ${String(file.summary.interpretiveCount)}`,\n\t\t\"\",\n\t].join(\"\\n\");\n}\n\nfunction suffixOf(mantlePath: string): string {\n\t// `indexOf(\".\") === -1` becomes `slice(0)` so no branch is needed.\n\treturn mantlePath.slice(mantlePath.indexOf(\".\") + 1);\n}\n\nfunction groupByKey<W>(\n\twarnings: ReadonlyArray<W>,\n\tkey: (warning: W) => string,\n): ReadonlyMap<string, ReadonlyArray<W>> {\n\tconst orderedKeys = [...new Set(warnings.map(key))];\n\treturn new Map(\n\t\torderedKeys.map((groupKey) => [\n\t\t\tgroupKey,\n\t\t\twarnings.filter((warning) => key(warning) === groupKey),\n\t\t]),\n\t);\n}\n\nfunction environmentOf(mantlePath: string): string | undefined {\n\tconst dot = mantlePath.indexOf(\".\");\n\treturn dot === -1 ? undefined : mantlePath.slice(0, dot);\n}\n\nfunction environmentsOf(\n\tmembers: ReadonlyArray<{ readonly mantlePath: string }>,\n): ReadonlyArray<string> {\n\tconst environments = members\n\t\t.map((warning) => environmentOf(warning.mantlePath))\n\t\t.filter((environment): environment is string => environment !== undefined);\n\treturn [...new Set(environments)];\n}\n\nfunction renderBullet(\n\tsubject: string,\n\tmembers: ReadonlyArray<{ readonly mantlePath: string }>,\n): string {\n\tconst environments = environmentsOf(members);\n\treturn environments.length === 0 ? `- ${subject}` : `- ${subject} (${environments.join(\", \")})`;\n}\n\nfunction renderSection<W extends { readonly mantlePath: string }>(input: SectionInput<W>): string {\n\tif (input.warnings.length === 0) {\n\t\treturn \"\";\n\t}\n\n\tconst groups = groupByKey(input.warnings, input.groupKey);\n\tconst blocks = [...groups].map(([heading, members]) => {\n\t\tconst bySubject = groupByKey(members, input.subject);\n\t\tconst lines = [...bySubject].map(([key, subjectMembers]) =>\n\t\t\trenderBullet(key, subjectMembers),\n\t\t);\n\t\treturn [`### ${heading}`, \"\", ...lines, \"\"].join(\"\\n\");\n\t});\n\n\treturn [`## ${input.title}`, \"\", ...blocks].join(\"\\n\");\n}\n\nfunction renderActionRequired(warnings: ReadonlyArray<MigrationWarning>): string {\n\treturn renderSection({\n\t\tgroupKey: (warning) => warning.hint,\n\t\tsubject: (warning) => suffixOf(warning.mantlePath),\n\t\ttitle: \"Action required\",\n\t\twarnings: warnings.filter(\n\t\t\t(warning): warning is Extract<MigrationWarning, { kind: \"ambiguous\" }> => {\n\t\t\t\treturn warning.kind === \"ambiguous\";\n\t\t\t},\n\t\t),\n\t});\n}\n\nfunction renderBlocked(warnings: ReadonlyArray<MigrationWarning>): string {\n\treturn renderSection({\n\t\tgroupKey: (warning) => warning.reason,\n\t\tsubject: (warning) => suffixOf(warning.mantlePath),\n\t\ttitle: \"Won't migrate (no Open Cloud equivalent)\",\n\t\twarnings: warnings.filter(\n\t\t\t(warning): warning is Extract<MigrationWarning, { kind: \"blocked\" }> => {\n\t\t\t\treturn warning.kind === \"blocked\";\n\t\t\t},\n\t\t),\n\t});\n}\n\nfunction renderDeferred(warnings: ReadonlyArray<MigrationWarning>): string {\n\treturn renderSection({\n\t\tgroupKey: (warning) => warning.reason,\n\t\tsubject: (warning) => suffixOf(warning.mantlePath),\n\t\ttitle: \"Coming later (skipped for now)\",\n\t\twarnings: warnings.filter(\n\t\t\t(warning): warning is Extract<MigrationWarning, { kind: \"deferred\" }> => {\n\t\t\t\treturn warning.kind === \"deferred\";\n\t\t\t},\n\t\t),\n\t});\n}\n\nfunction renderInterpretive(warnings: ReadonlyArray<MigrationWarning>): string {\n\treturn renderSection({\n\t\tgroupKey: (warning) => warning.rule,\n\t\tsubject: (warning) => `${suffixOf(warning.mantlePath)} -> ${warning.bedrockPath}`,\n\t\ttitle: \"Auto-mapped (please verify)\",\n\t\twarnings: warnings.filter(\n\t\t\t(warning): warning is Extract<MigrationWarning, { kind: \"interpretive\" }> => {\n\t\t\t\treturn warning.kind === \"interpretive\";\n\t\t\t},\n\t\t),\n\t});\n}\n","import type { MigrationReportFile } from \"./migration-report.ts\";\n\n/**\n * Serialize a {@link MigrationReportFile} as the bytes written to\n * `.bedrock/migration-report.json`. The output is canonical JSON:\n * pretty-printed with two-space indentation, terminated with a trailing newline.\n *\n * @param file - The summary plus warnings to serialize.\n * @returns A UTF-8 source string ending with a trailing newline.\n */\nexport function serializeMigrationReport(file: MigrationReportFile): string {\n\treturn `${JSON.stringify(file, undefined, 2)}\\n`;\n}\n","import type { Result } from \"@bedrock-rbx/ocale\";\n\nimport { dirname, join } from \"node:path\";\n\nimport type { MigrationReport } from \"../../core/migrate/migration-report.ts\";\nimport { renderMigrationReportMarkdown } from \"../../core/migrate/render-migration-report-md.ts\";\nimport { serializeMigrationReport } from \"../../core/migrate/serialize-migration-report.ts\";\nimport type { ClackPort } from \"../render.ts\";\nimport { describeUnknown } from \"./describe-unknown.ts\";\n\nconst REPORT_DIR_NAME = \".bedrock\";\nconst JSON_FILE_NAME = \"migration-report.json\";\nconst MD_FILE_NAME = \"migration-report.md\";\n\n/** Paths the writer produced. The Markdown path is reported to the user. */\ninterface MigrationReportPaths {\n\t/** Path to `.bedrock/migration-report.json`. */\n\treadonly jsonPath: string;\n\t/** Path to `.bedrock/migration-report.md`. */\n\treadonly mdPath: string;\n}\n\n/** Subset of the migrate command's deps the report writer touches. */\ninterface WriterDeps {\n\treadonly clack: ClackPort;\n\treadonly mkdir: (path: string) => Promise<void>;\n\treadonly writeFile: (path: string, contents: string) => Promise<void>;\n}\n\ninterface WriteInputs {\n\treadonly deps: WriterDeps;\n\treadonly report: MigrationReport;\n\treadonly stateFilePath: string;\n}\n\n/**\n * Persist the migration report as `.bedrock/migration-report.json` and a\n * pure derivation `.bedrock/migration-report.md` next to the per-environment\n * state files. Always written so the user can compare runs even when no\n * warnings were emitted; the CLI summary line that points at the Markdown\n * file is gated on warning count separately.\n *\n * @param input - Resolved deps, the migration report, and the path of the\n * Mantle state file the report describes.\n * @returns `Ok` with both file paths once both writes succeed; `Err` on the\n * first failure (already rendered to clack).\n */\nexport async function writeMigrationReport(\n\tinput: WriteInputs,\n): Promise<Result<MigrationReportPaths, void>> {\n\tconst { deps, report, stateFilePath } = input;\n\tconst reportDirectory = join(dirname(stateFilePath), REPORT_DIR_NAME);\n\tconst jsonPath = join(reportDirectory, JSON_FILE_NAME);\n\tconst mdPath = join(reportDirectory, MD_FILE_NAME);\n\tconst file = { summary: report.summary, warnings: report.warnings };\n\n\ttry {\n\t\tawait deps.mkdir(reportDirectory);\n\t} catch (err) {\n\t\tdeps.clack.logError(\n\t\t\t`migration report directory create failed (${reportDirectory}): ${describeUnknown(err)}`,\n\t\t);\n\t\treturn { err: undefined, success: false };\n\t}\n\n\ttry {\n\t\tawait deps.writeFile(jsonPath, serializeMigrationReport(file));\n\t} catch (err) {\n\t\tdeps.clack.logError(`migration report write failed (${jsonPath}): ${describeUnknown(err)}`);\n\t\treturn { err: undefined, success: false };\n\t}\n\n\ttry {\n\t\tawait deps.writeFile(mdPath, renderMigrationReportMarkdown(file));\n\t} catch (err) {\n\t\tdeps.clack.logError(`migration report write failed (${mdPath}): ${describeUnknown(err)}`);\n\t\treturn { err: undefined, success: false };\n\t}\n\n\treturn { data: { jsonPath, mdPath }, success: true };\n}\n","import type { Result } from \"@bedrock-rbx/ocale\";\n\nimport type { MigrationReport } from \"../../core/migrate/migration-report.ts\";\nimport { serializeConfig } from \"../../core/migrate/serialize-config.ts\";\nimport type { Config } from \"../../core/schema.ts\";\nimport type { buildStatePort as defaultBuildStatePort } from \"../../shell/build-state-port.ts\";\nimport type { MigrateConfigFormat } from \"../migrate-prompt-port.ts\";\nimport type { ClackPort } from \"../render.ts\";\nimport { describeUnknown } from \"./describe-unknown.ts\";\nimport { type ResolvedStateTarget, writeMigratedStates } from \"./write-migrated-states.ts\";\nimport { writeMigrationReport } from \"./write-migration-report.ts\";\n\n/** Subset of the migrate command's resolved deps the finalize step touches. */\nexport interface FinalizeDeps {\n\t/** Default-constructs a `StatePort` once the gist target is resolved. */\n\treadonly buildStatePort: typeof defaultBuildStatePort;\n\t/** Output port for diagnostics and success lines. */\n\treadonly clack: ClackPort;\n\t/** Recursively creates a directory; used for the local-dump and report dirs. */\n\treadonly mkdir: (path: string) => Promise<void>;\n\t/** Writes a file's UTF-8 contents in one shot. */\n\treadonly writeFile: (path: string, contents: string) => Promise<void>;\n}\n\n/** Inputs for {@link persistMigration} and the inner config-write helper. */\nexport interface FinalizeInputs {\n\t/** Path to the bedrock config file to emit. */\n\treadonly configFilePath: string;\n\t/** Output format for the bedrock config (`typescript` or `yaml`). */\n\treadonly configFormat: MigrateConfigFormat;\n\t/** Resolved deps the writers dispatch through. */\n\treadonly deps: FinalizeDeps;\n\t/** Migration report whose state, config, and warnings are persisted. */\n\treadonly report: MigrationReport;\n\t/** Path to the Mantle state file the migration consumed. */\n\treadonly stateFilePath: string;\n\t/** Resolved state target picked by the user (gist or local). */\n\treadonly target: ResolvedStateTarget;\n}\n\n/**\n * Persist the migration's per-environment state, the bedrock config, and\n * the migration report (JSON + Markdown) in that order. Each failure\n * surface has already been rendered to clack by its respective writer; on\n * the first failure the function returns `Err` so the caller can exit\n * after a single shared `cancel(\"migrate failed\")` line.\n *\n * @param inputs - Resolved deps, the migration report, and the resolved\n * state-target plus paths the writers consume.\n * @returns `Ok` carrying the on-disk Markdown report path (used by the\n * terminal summary line) once every writer succeeded; `Err(void)` once\n * any writer reported failure.\n */\nexport async function persistMigration(inputs: FinalizeInputs): Promise<Result<string, void>> {\n\tconst stateConfigWritten = await persistStateAndConfig(inputs);\n\tif (!stateConfigWritten.success) {\n\t\treturn { err: undefined, success: false };\n\t}\n\n\tconst reportPaths = await writeMigrationReport({\n\t\tdeps: {\n\t\t\tclack: inputs.deps.clack,\n\t\t\tmkdir: inputs.deps.mkdir,\n\t\t\twriteFile: inputs.deps.writeFile,\n\t\t},\n\t\treport: inputs.report,\n\t\tstateFilePath: inputs.stateFilePath,\n\t});\n\treturn reportPaths.success\n\t\t? { data: reportPaths.data.mdPath, success: true }\n\t\t: { err: undefined, success: false };\n}\n\nasync function writeBedrockConfig(inputs: FinalizeInputs): Promise<Result<void, void>> {\n\tconst { configFilePath, configFormat, deps, report, target } = inputs;\n\tconst { state: _ignoredState, ...configWithoutState } = report.config;\n\tconst enrichedConfig: Config =\n\t\ttarget.backend === \"gist\"\n\t\t\t? { ...configWithoutState, state: target.stateConfig }\n\t\t\t: configWithoutState;\n\tconst bytes = serializeConfig({ config: enrichedConfig, configFormat });\n\ttry {\n\t\tawait deps.writeFile(configFilePath, bytes);\n\t} catch (err) {\n\t\tdeps.clack.logError(\n\t\t\t`config file write failed (${configFilePath}): ${describeUnknown(err)}`,\n\t\t);\n\t\treturn { err: undefined, success: false };\n\t}\n\n\tdeps.clack.logSuccess(`wrote ${configFilePath}`);\n\treturn { data: undefined, success: true };\n}\n\nasync function persistStateAndConfig(inputs: FinalizeInputs): Promise<Result<void, void>> {\n\tconst stateWritten = await writeMigratedStates({\n\t\tdeps: inputs.deps,\n\t\treport: inputs.report,\n\t\ttarget: inputs.target,\n\t});\n\tif (!stateWritten.success) {\n\t\treturn { err: undefined, success: false };\n\t}\n\n\tconst written = await writeBedrockConfig(inputs);\n\treturn written.success\n\t\t? { data: undefined, success: true }\n\t\t: { err: undefined, success: false };\n}\n","import type { Result } from \"@bedrock-rbx/ocale\";\n\nimport type { MigratePromptPort } from \"../migrate-prompt-port.ts\";\nimport { type MigrationSource, SUPPORTED_MIGRATION_SOURCES } from \"../parse-migrate-options.ts\";\n\n/**\n * Resolve the path to the input Mantle state file. The positional CLI\n * argument wins; when it is absent the user is asked through the prompt\n * port. Cancelling the prompt surfaces as `Err(\"cancelled\")`.\n *\n * @param pathArgument - The positional `<stateFilePath>` value sade\n * handed the action callback, or `undefined` when omitted.\n * @param promptPort - The migrate prompt port whose `promptStateFilePath`\n * is used as the interactive fallback.\n * @returns `Ok(path)` on success, or `Err(\"cancelled\")` if the user\n * aborted the prompt.\n */\nexport async function resolveStateFilePath(\n\tpathArgument: string | undefined,\n\tpromptPort: MigratePromptPort,\n): Promise<Result<string, \"cancelled\">> {\n\tif (pathArgument !== undefined) {\n\t\treturn { data: pathArgument, success: true };\n\t}\n\n\tconst promptResult = await promptPort.promptStateFilePath();\n\tif (!promptResult.success) {\n\t\treturn { err: \"cancelled\", success: false };\n\t}\n\n\treturn { data: promptResult.data, success: true };\n}\n\n/**\n * Resolve which source format to migrate from. A validated `--from`\n * value wins; when it is absent the user picks from\n * {@link SUPPORTED_MIGRATION_SOURCES} through the prompt port.\n * Cancelling the prompt surfaces as `Err(\"cancelled\")`.\n *\n * @param from - The validated `--from` value, or `undefined` when the\n * flag was omitted.\n * @param promptPort - The migrate prompt port whose\n * `promptMigrationSource` is used as the interactive fallback.\n * @returns `Ok(source)` on success, or `Err(\"cancelled\")` if the user\n * aborted the prompt.\n */\nexport async function resolveMigrationSource(\n\tfrom: MigrationSource | undefined,\n\tpromptPort: MigratePromptPort,\n): Promise<Result<MigrationSource, \"cancelled\">> {\n\tif (from !== undefined) {\n\t\treturn { data: from, success: true };\n\t}\n\n\tconst promptResult = await promptPort.promptMigrationSource(SUPPORTED_MIGRATION_SOURCES);\n\tif (!promptResult.success) {\n\t\treturn { err: \"cancelled\", success: false };\n\t}\n\n\treturn { data: promptResult.data, success: true };\n}\n","import type { Result } from \"@bedrock-rbx/ocale\";\n\nimport { mkdir as nodeMkdir, writeFile as nodeWriteFile } from \"node:fs/promises\";\nimport { dirname, join } from \"node:path\";\nimport process from \"node:process\";\n\nimport type { MigrateError, MigrationReport } from \"../../core/migrate/migration-report.ts\";\nimport { buildStatePort as defaultBuildStatePort } from \"../../shell/build-state-port.ts\";\nimport {\n\tmigrateMantleState as defaultMigrateMantleState,\n\ttype MigrateMantleStateDeps,\n} from \"../../shell/migrate-mantle-state.ts\";\nimport { createDefaultMigratePromptPort } from \"../default-migrate-prompt-port.ts\";\nimport { EXIT_ERROR, EXIT_OK } from \"../exit-codes.ts\";\nimport type { ProgDeps } from \"../index.ts\";\nimport type { MigrateConfigFormat, MigratePromptPort } from \"../migrate-prompt-port.ts\";\nimport { type MigrationSource, parseMigrateOptions } from \"../parse-migrate-options.ts\";\nimport {\n\ttype ClackPort,\n\tcreateClackPort,\n\trenderMigrateError,\n\trenderMigrateParseError,\n\trenderMigrationSummary,\n} from \"../render.ts\";\nimport { describeUnknown } from \"./describe-unknown.ts\";\nimport { type FinalizeDeps, type FinalizeInputs, persistMigration } from \"./finalize-migration.ts\";\nimport { resolveMigrationSource, resolveStateFilePath } from \"./resolve-migrate-inputs.ts\";\nimport type { ResolvedStateTarget } from \"./write-migrated-states.ts\";\n\nconst FAILED_OUTRO = \"migrate failed\";\n\nconst CANCELLED_OUTRO = \"migrate cancelled\";\n\n/**\n * Sentinel returned by inner orchestration helpers when they could not\n * produce a `MigrationReport`. `cancelled` means the user aborted a\n * prompt; `rendered` means the failure was already described to the\n * user via `renderMigrateError` and the caller should exit\n * unconditionally without re-rendering.\n */\ntype MigrateRunError = \"cancelled\" | \"rendered\";\n\ninterface ResolvedMigrate {\n\treadonly buildStatePort: typeof defaultBuildStatePort;\n\treadonly clack: ClackPort;\n\treadonly exit: (code: number) => void;\n\treadonly migrateMantleState: typeof defaultMigrateMantleState;\n\treadonly mkdir: (path: string) => Promise<void>;\n\treadonly promptPort: MigratePromptPort;\n\treadonly writeFile: (path: string, contents: string) => Promise<void>;\n}\n\ninterface RunMigrateInputs {\n\treadonly pathArg: string | undefined;\n\treadonly rawOptions: Readonly<Record<string, unknown>>;\n\treadonly resolved: ResolvedMigrate;\n}\n\ninterface RunMigratorInputs {\n\treadonly configFormat: MigrateConfigFormat;\n\treadonly resolved: ResolvedMigrate;\n\treadonly stateFilePath: string;\n}\n\ninterface MigratorIoError {\n\treadonly cause: unknown;\n\treadonly kind: \"ioError\";\n\treadonly path: string;\n}\n\ninterface DispatchInputs {\n\treadonly resolved: ResolvedMigrate;\n\treadonly source: MigrationSource;\n\treadonly stateFilePath: string;\n}\n\n/**\n * Build the sade action for `bedrock migrate`. The returned function\n * consumes the optional positional path argument and the raw options\n * object sade hands the action callback. The command parses `--from`,\n * resolves the state file path (positional or interactive), prompts for\n * the output config format, runs the migrator, prompts for the state\n * backend coordinates, writes the per-environment states through the\n * configured `StatePort`, and emits an enriched bedrock config to disk.\n *\n * @param deps - Dependency overrides; missing slots are default-constructed\n * from real implementations.\n * @returns An async sade action that returns once `deps.exit` was invoked.\n */\nexport function migrateCommand(\n\tdeps: ProgDeps,\n): (\n\tpathArgument: string | undefined,\n\trawOptions: Readonly<Record<string, unknown>>,\n) => Promise<void> {\n\tconst resolved = resolveMigrate(deps);\n\treturn async (pathArgument, rawOptions) => {\n\t\tconst code = await runMigrate({ pathArg: pathArgument, rawOptions, resolved });\n\t\tresolved.exit(code);\n\t};\n}\n\nfunction resolveMigrate(deps: ProgDeps): ResolvedMigrate {\n\treturn {\n\t\tbuildStatePort: deps.buildStatePort ?? defaultBuildStatePort,\n\t\tclack: deps.clack ?? createClackPort(),\n\t\texit: deps.exit ?? ((code) => process.exit(code)),\n\t\tmigrateMantleState: deps.migrateMantleState ?? defaultMigrateMantleState,\n\t\tmkdir: deps.mkdir ?? (async (path) => void (await nodeMkdir(path, { recursive: true }))),\n\t\tpromptPort: deps.migratePromptPort ?? createDefaultMigratePromptPort(),\n\t\twriteFile:\n\t\t\tdeps.writeFile ?? (async (path, contents) => nodeWriteFile(path, contents, \"utf8\")),\n\t};\n}\n\nfunction cancel(resolved: ResolvedMigrate): number {\n\tresolved.clack.cancel(CANCELLED_OUTRO);\n\treturn EXIT_ERROR;\n}\n\nfunction failAfterRender(resolved: ResolvedMigrate): number {\n\tresolved.clack.cancel(FAILED_OUTRO);\n\treturn EXIT_ERROR;\n}\n\nfunction renderedFailure(\n\terr: MigrateError,\n\tresolved: ResolvedMigrate,\n): Result<MigrationReport, MigrateRunError> {\n\trenderMigrateError(err, resolved.clack);\n\tresolved.clack.cancel(FAILED_OUTRO);\n\treturn { err: \"rendered\", success: false };\n}\n\nasync function callMigrator(\n\tinputs: RunMigratorInputs & { readonly primaryEnvironment?: string },\n): Promise<Result<MigrationReport, MigrateError | MigratorIoError>> {\n\tconst callDeps: MigrateMantleStateDeps = {\n\t\tconfigFormat: inputs.configFormat,\n\t\tstateFilePath: inputs.stateFilePath,\n\t\t...(inputs.primaryEnvironment === undefined\n\t\t\t? {}\n\t\t\t: { primaryEnvironment: inputs.primaryEnvironment }),\n\t};\n\ttry {\n\t\treturn await inputs.resolved.migrateMantleState(callDeps);\n\t} catch (err) {\n\t\treturn { err: { cause: err, kind: \"ioError\", path: inputs.stateFilePath }, success: false };\n\t}\n}\n\nfunction renderIoFailure(\n\terr: MigratorIoError,\n\tresolved: ResolvedMigrate,\n): Result<MigrationReport, MigrateRunError> {\n\tresolved.clack.logError(\n\t\t`failed to read Mantle state file '${err.path}': ${describeUnknown(err.cause)}`,\n\t);\n\tresolved.clack.cancel(FAILED_OUTRO);\n\treturn { err: \"rendered\", success: false };\n}\n\nasync function runMigratorWithPrompt(\n\tinputs: RunMigratorInputs,\n): Promise<Result<MigrationReport, MigrateRunError>> {\n\tconst first = await callMigrator(inputs);\n\tif (first.success) {\n\t\treturn { data: first.data, success: true };\n\t}\n\n\tif (first.err.kind === \"ioError\") {\n\t\treturn renderIoFailure(first.err, inputs.resolved);\n\t}\n\n\tif (first.err.kind !== \"primaryEnvironmentRequired\") {\n\t\treturn renderedFailure(first.err, inputs.resolved);\n\t}\n\n\tconst primary = await inputs.resolved.promptPort.promptPrimaryEnvironment(first.err.available);\n\tif (!primary.success) {\n\t\treturn { err: \"cancelled\", success: false };\n\t}\n\n\tconst second = await callMigrator({ ...inputs, primaryEnvironment: primary.data });\n\tif (second.success) {\n\t\treturn { data: second.data, success: true };\n\t}\n\n\tif (second.err.kind === \"ioError\") {\n\t\treturn renderIoFailure(second.err, inputs.resolved);\n\t}\n\n\treturn renderedFailure(second.err, inputs.resolved);\n}\n\nasync function finalize(inputs: FinalizeInputs): Promise<number> {\n\tconst persisted = await persistMigration(inputs);\n\tif (!persisted.success) {\n\t\tinputs.deps.clack.cancel(FAILED_OUTRO);\n\t\treturn EXIT_ERROR;\n\t}\n\n\trenderMigrationSummary(\n\t\t{ reportPath: persisted.data, summary: inputs.report.summary },\n\t\tinputs.deps.clack,\n\t);\n\tinputs.deps.clack.outro(\"migrate succeeded\");\n\treturn EXIT_OK;\n}\n\nfunction configFileFor(stateFilePath: string, format: MigrateConfigFormat): string {\n\tconst extension = format === \"typescript\" ? \"ts\" : \"yaml\";\n\treturn join(dirname(stateFilePath), `bedrock.config.${extension}`);\n}\n\nasync function promptForStateTarget(\n\tresolved: ResolvedMigrate,\n\tstateFilePath: string,\n): Promise<Result<ResolvedStateTarget, \"cancelled\">> {\n\tconst backend = await resolved.promptPort.promptStateBackend();\n\tif (!backend.success) {\n\t\treturn { err: \"cancelled\", success: false };\n\t}\n\n\tif (backend.data === \"local\") {\n\t\treturn {\n\t\t\tdata: {\n\t\t\t\tbackend: \"local\",\n\t\t\t\toutputDir: join(dirname(stateFilePath), \".bedrock\", \"state\"),\n\t\t\t},\n\t\t\tsuccess: true,\n\t\t};\n\t}\n\n\tconst gistId = await resolved.promptPort.promptGistId();\n\tif (!gistId.success) {\n\t\treturn { err: \"cancelled\", success: false };\n\t}\n\n\treturn {\n\t\tdata: { backend: \"gist\", stateConfig: { backend: \"gist\", gistId: gistId.data } },\n\t\tsuccess: true,\n\t};\n}\n\nfunction finalizeDeps(resolved: ResolvedMigrate): FinalizeDeps {\n\treturn {\n\t\tbuildStatePort: resolved.buildStatePort,\n\t\tclack: resolved.clack,\n\t\tmkdir: resolved.mkdir,\n\t\twriteFile: resolved.writeFile,\n\t};\n}\n\nasync function runWithStateFilePath(\n\tstateFilePath: string,\n\tresolved: ResolvedMigrate,\n): Promise<number> {\n\tconst formatResult = await resolved.promptPort.promptConfigFormat();\n\tif (!formatResult.success) {\n\t\treturn cancel(resolved);\n\t}\n\n\tconst reportResult = await runMigratorWithPrompt({\n\t\tconfigFormat: formatResult.data,\n\t\tresolved,\n\t\tstateFilePath,\n\t});\n\tif (!reportResult.success) {\n\t\treturn reportResult.err === \"cancelled\" ? cancel(resolved) : EXIT_ERROR;\n\t}\n\n\tconst targetResult = await promptForStateTarget(resolved, stateFilePath);\n\tif (!targetResult.success) {\n\t\treturn cancel(resolved);\n\t}\n\n\treturn finalize({\n\t\tconfigFilePath: configFileFor(stateFilePath, formatResult.data),\n\t\tconfigFormat: formatResult.data,\n\t\tdeps: finalizeDeps(resolved),\n\t\treport: reportResult.data,\n\t\tstateFilePath,\n\t\ttarget: targetResult.data,\n\t});\n}\n\nasync function dispatchBySource(inputs: DispatchInputs): Promise<number> {\n\tconst { resolved, source, stateFilePath } = inputs;\n\tconst dispatch: Record<MigrationSource, () => Promise<number>> = {\n\t\tmantle: async () => runWithStateFilePath(stateFilePath, resolved),\n\t};\n\tconst handler = dispatch[source];\n\treturn handler();\n}\n\nasync function runMigrate(inputs: RunMigrateInputs): Promise<number> {\n\tconst { pathArg, rawOptions, resolved } = inputs;\n\tresolved.clack.intro(\"bedrock migrate\");\n\n\tconst parsed = parseMigrateOptions(rawOptions);\n\tif (!parsed.success) {\n\t\trenderMigrateParseError(parsed.err, resolved.clack);\n\t\treturn failAfterRender(resolved);\n\t}\n\n\tconst source = await resolveMigrationSource(parsed.data.from, resolved.promptPort);\n\tif (!source.success) {\n\t\treturn cancel(resolved);\n\t}\n\n\tconst stateFilePath = await resolveStateFilePath(pathArg, resolved.promptPort);\n\tif (!stateFilePath.success) {\n\t\treturn cancel(resolved);\n\t}\n\n\treturn dispatchBySource({\n\t\tresolved,\n\t\tsource: source.data,\n\t\tstateFilePath: stateFilePath.data,\n\t});\n}\n","import sade from \"sade\";\nimport type { Sade } from \"sade\";\n\nimport manifest from \"../../package.json\" with { type: \"json\" };\nimport type { buildStatePort as defaultBuildStatePort } from \"../shell/build-state-port.ts\";\nimport type { deploy as defaultDeploy } from \"../shell/deploy.ts\";\nimport type { loadConfig as defaultLoadConfig } from \"../shell/load-config.ts\";\nimport type { migrateMantleState as defaultMigrateMantleState } from \"../shell/migrate-mantle-state.ts\";\nimport type { previewDiff as defaultPreviewDiff } from \"../shell/preview-diff.ts\";\nimport { deployCommand } from \"./commands/deploy.ts\";\nimport { diffCommand } from \"./commands/diff.ts\";\nimport { migrateCommand } from \"./commands/migrate.ts\";\nimport type { MigratePromptPort } from \"./migrate-prompt-port.ts\";\nimport type { ClackPort } from \"./render.ts\";\n\nexport { createClackPort } from \"./render.ts\";\n\nconst PROGRAM_NAME = \"bedrock\";\nconst PROGRAM_DESCRIBE = \"Infrastructure-as-Code deployment tool for Roblox\";\n\n/**\n * Dependency seam for the bedrock CLI program. Every slot is optional;\n * command actions resolve a real default when a slot is omitted.\n */\nexport interface ProgDeps {\n\t/** Builds a `StatePort` from a resolved state config; defaults to the public `buildStatePort`. */\n\treadonly buildStatePort?: typeof defaultBuildStatePort;\n\t/** Output port; defaults to a real `@clack/prompts` adapter inside command actions. */\n\treadonly clack?: ClackPort;\n\t/** Reconciles config to live state; defaults to the public `deploy`. */\n\treadonly deploy?: typeof defaultDeploy;\n\t/** Process exit handle; defaults to `process.exit` so tests can intercept termination. The production default never returns; test stubs are free to return void. */\n\treadonly exit?: (code: number) => void;\n\t/** Project config loader; defaults to the public `loadConfig`. */\n\treadonly loadConfig?: typeof defaultLoadConfig;\n\t/** Mantle state migrator; defaults to the public `migrateMantleState`. */\n\treadonly migrateMantleState?: typeof defaultMigrateMantleState;\n\t/** Domain-specific prompt port for the migrate command; defaults to `createDefaultMigratePromptPort()`. */\n\treadonly migratePromptPort?: MigratePromptPort;\n\t/** Directory-create seam used by the migrate command for the local-dump backend; defaults to `node:fs/promises.mkdir` with `recursive: true`. */\n\treadonly mkdir?: (path: string) => Promise<void>;\n\t/** Read-only preview of operations; defaults to the internal `previewDiff` shell helper. */\n\treadonly previewDiff?: typeof defaultPreviewDiff;\n\t/** File-write seam used by the migrate command to emit the bedrock config file; defaults to `node:fs/promises.writeFile`. */\n\treadonly writeFile?: (path: string, contents: string) => Promise<void>;\n}\n\n/**\n * Construct the bedrock CLI program. Pure factory: no `process.argv` parsing,\n * no clack output, no exits. Callers (the `run.ts` shim, integration tests)\n * call `.parse()` on the returned sade instance.\n * @param deps - Dependency overrides for command actions. Each command\n * resolves its own defaults from any omitted slots.\n * @returns A configured sade program with the bedrock name, description, and\n * the currently installed `@bedrock-rbx/core` version, plus the registered\n * `deploy`, `diff`, and `migrate` commands.\n */\nexport function createProg(deps: ProgDeps = {}): Sade {\n\tconst prog = sade(PROGRAM_NAME).describe(PROGRAM_DESCRIBE).version(manifest.version);\n\n\tprog.command(\"deploy\")\n\t\t.describe(\"Reconcile a project's resources against the configured environment(s)\")\n\t\t.option(\"--env\", \"Target environment (repeat for multiple)\")\n\t\t.option(\"--config\", \"Config file path (overrides discovery)\")\n\t\t.option(\"--api-key\", \"Override the BEDROCK_API_KEY environment variable\")\n\t\t.option(\"--github-token\", \"Override the GITHUB_TOKEN environment variable\")\n\t\t.action(deployCommand(deps));\n\n\tprog.command(\"diff\")\n\t\t.describe(\"Preview the operations a deploy would apply, without writing state\")\n\t\t.option(\"--env\", \"Target environment (repeat for multiple)\")\n\t\t.option(\"--config\", \"Config file path (overrides discovery)\")\n\t\t.option(\"--api-key\", \"Override the BEDROCK_API_KEY environment variable\")\n\t\t.option(\"--github-token\", \"Override the GITHUB_TOKEN environment variable\")\n\t\t.action(diffCommand(deps));\n\n\tprog.command(\"migrate [stateFilePath]\")\n\t\t.describe(\"Translate a state file from another tool into a bedrock project\")\n\t\t.option(\"--from\", \"Source format to migrate from (mantle; prompted if omitted)\")\n\t\t.action(migrateCommand(deps));\n\n\treturn prog;\n}\n","#!/usr/bin/env node\nimport process from \"node:process\";\n\nimport { createProg } from \"./index.ts\";\n\ncreateProg().parse(process.argv);\n"],"mappings":";;;;;;;;;;;;;;;;;;ACcA,SAAgB,yBAAyB,OAA0D;CAClG,MAAM,YAAoC,EAAE;AAC5C,KAAI,MAAM,WAAW,KAAA,EACpB,WAAU,qBAAqB,MAAM;AAGtC,KAAI,MAAM,gBAAgB,KAAA,EACzB,WAAU,kBAAkB,MAAM;AAGnC,QAAO;;;;ACIR,MAAMA,qBAAwC,IAAI,IAAI;CACrD;CACA;CACA;CACA;CACA;CACA;CACA,CAAC;AAEF,MAAMC,kBAAqC,IAAI,IAAI;CAAC;CAAM;CAAK;CAAK;CAAQ;CAAK;CAAU,CAAC;;;;;;;;;;;;;AAc5F,SAAgB,mBACf,YACA,iBAAuDC,0BACZ;AAC3C,MAAK,MAAM,OAAO,OAAO,KAAK,WAAW,CACxC,KAAI,CAACF,mBAAiB,IAAI,IAAI,IAAI,CAACC,gBAAc,IAAI,IAAI,CACxD,QAAO;EAAE,KAAK;GAAE,MAAM;GAAK,MAAM;GAAe;EAAE,SAAS;EAAO;CAIpE,MAAM,eAAe,oBAAoB,WAAW,QAAQ,eAAe;AAC3E,KAAI,CAAC,aAAa,QACjB,QAAO;CAGR,MAAM,SAAS,WAAW,YAAY,UAAU,UAAU;CAC1D,MAAM,aAAa,WAAW,YAAY,SAAS;CACnD,MAAM,cAAc,WAAW,YAAY,eAAe,eAAe;AAEzE,QAAO;EACN,MAAM;GACL,cAAc,aAAa;GAC3B,GAAI,WAAW,KAAA,IAAY,EAAE,GAAG,EAAE,QAAQ;GAC1C,GAAI,eAAe,KAAA,IAAY,EAAE,GAAG,EAAE,YAAY;GAClD,GAAI,gBAAgB,KAAA,IAAY,EAAE,GAAG,EAAE,aAAa;GACpD;EACD,SAAS;EACT;;AAGF,SAAS,oBACR,KACA,gBACmD;AACnD,KAAI,QAAQ,KAAA,GAAW;EACtB,MAAM,WAAW,eAAe,sBAAsB;AACtD,MAAI,aAAa,KAAA,EAChB,QAAO;GAAE,KAAK;IAAE,MAAM;IAAO,MAAM;IAAmB;GAAE,SAAS;GAAO;AAGzE,SAAO;GAAE,MAAM,CAAC,SAAS;GAAE,SAAS;GAAM;;CAG3C,MAAM,aAAa,MAAM,QAAQ,IAAI,GAAG,MAAM,CAAC,IAAI;CACnD,MAAM,eAA8B,EAAE;AACtC,MAAK,MAAM,aAAa,YAAY;AACnC,MAAI,OAAO,cAAc,SACxB,QAAO;GAAE,KAAK;IAAE,MAAM;IAAO,MAAM;IAAgB;GAAE,SAAS;GAAO;AAGtE,eAAa,KAAK,UAAU;;AAG7B,QAAO;EAAE,MAAM;EAAc,SAAS;EAAM;;AAG7C,SAASC,yBAAuB,MAAkC;AACjE,QAAO,QAAQ,IAAI;;AAGpB,SAAS,WACR,YACA,GAAG,MACkB;AACrB,MAAK,MAAM,OAAO,MAAM;EACvB,MAAM,QAAQ,WAAW;AACzB,MAAI,OAAO,UAAU,SACpB,QAAO;;;;;;;;;;;;;;;AC5DV,SAAgB,kBAAkB,KAAkB,MAAuB;AAC1E,MAAK,SAAS,mBAAmB,IAAI,CAAC;;;;;;;;;AAUvC,SAAgB,iBAAiB,KAAwB,MAAuB;AAC/E,MAAK,SAAS,kBAAkB,IAAI,CAAC;;;;;;;AAQtC,SAAgB,kBAA6B;AAC5C,QAAO;EACN,SAAS,YAAY;AACpB,UAAO,QAAQ;;EAEhB,QAAQ,YAAY;AACnB,SAAM,QAAQ;;EAEf,WAAW,YAAY;AACtB,OAAI,MAAM,QAAQ;;EAEnB,aAAa,YAAY;AACxB,OAAI,QAAQ,QAAQ;;EAErB,aAAa,YAAY;AACxB,OAAI,QAAQ,QAAQ;;EAErB,QAAQ,YAAY;AACnB,SAAM,QAAQ;;EAEf;;;;;;;;;AAUF,SAAgB,wBAAwB,KAAwB,MAAuB;AACtF,MAAK,SAAS,yBAAyB,IAAI,CAAC;;;;;;;;;;AAW7C,SAAgB,mBAAmB,KAAmB,MAAuB;AAC5E,MAAK,SAAS,oBAAoB,IAAI,CAAC;;;;;;;;;AAUxC,SAAgB,0BACf,KACA,MACO;AACP,MAAK,SAAS,2BAA2B,IAAI,CAAC;;;;;;;;;;;;;;;;;AAkB/C,SAAgB,uBAAuB,OAA+B,MAAuB;CAC5F,MAAM,EAAE,gBAAgB,cAAc,eAAe,sBAAsB,MAAM;AACjF,KAAI,iBAAiB,GAAG;AACvB,OAAK,SACJ,oBAAoB,OAAO,eAAe,CAAC,+BAA+B,MAAM,aAChF;AACD;;CAGD,MAAM,aAAa,eAAe,gBAAgB;AAClD,KAAI,aAAa,EAChB,MAAK,WACJ,2BAA2B,MAAM,WAAW,OAAO,OAAO,WAAW,CAAC,gCACtE;;;;;;;;;AAWH,SAAgB,sBAAsB,OAA8B,MAAuB;AAC1F,MAAK,SACJ,2BAA2B,MAAM,YAAY,KAAK,MAAM,IAAI,KAAK,KAAK,MAAM,IAAI,SAChF;;AAGF,SAAS,iBAAiB,KAA8B;CACvD,MAAM,WAAW,IAAI,eAAe,SAAS;CAC7C,MAAM,QAAQ,WAAW,WAAW;CACpC,MAAM,UAAU,WAAW,SAAS;CACpC,MAAM,YAAY,IAAI,eAAe,KAAK,UAAU,IAAI,MAAM,GAAG,CAAC,KAAK,KAAK;AAC5E,QAAO,GAAG,IAAI,QAAQ,MAAM,IAAI,aAAa,qBAAqB,MAAM,GAAG,UAAU,UAAU,QAAQ;;AAGxG,SAAS,iBAAiB,OAA2B;AACpD,SAAQ,MAAM,MAAd;EACC,KAAK;AACJ,OAAI,MAAM,iBAAiB,gBAC1B,QAAO,iBAAiB,MAAM,MAAM;AAGrC,UAAO,MAAM,MAAM;EAEpB,KAAK,oBACJ,QAAO;;;AAKV,SAAS,mBAAmB,OAAkC;AAC7D,SAAQ,MAAM,MAAd;EACC,KAAK,iBACJ,QAAO,IAAI,MAAM,SAAS,KAAK,MAAM;EAEtC,KAAK,sBACJ,QAAO,KAAK,MAAM;;;AAKrB,SAAS,kBAAkB,KAA0B;AACpD,SAAQ,IAAI,MAAZ;EACC,KAAK,uBACJ,QAAO,GAAG,IAAI,WAAW,2BAA2B,IAAI;EAEzD,KAAK,eACJ,QAAO,2BAA2B,IAAI;EAEvC,KAAK,qBACJ,QAAO,GAAG,IAAI,WAAW,IAAI,IAAI;EAElC,KAAK,cACJ,QAAO,GAAG,IAAI,WAAW,IAAI,IAAI;EAElC,KAAK,oBAAoB;GACxB,MAAM,QAAQ,IAAI,OAAO;AACzB,UAAO,UAAU,KAAA,IACd,GAAG,IAAI,WAAW,aAClB,GAAG,IAAI,WAAW,IAAI,MAAM,KAAK,KAAK,IAAI,CAAC,GAAG,MAAM;;;;AAK1D,SAAS,iBAAiB,OAA2B;AACpD,QAAO,IAAI,MAAM,KAAK,KAAK,MAAM;;AAIlC,SAAS,mBAAmB,KAA0B;AACrD,SAAQ,IAAI,MAAZ;EACC,KAAK,cACJ,QAAO,qBAAqB,IAAI,MAAM,IAAI,KAAK,iBAAiB,IAAI,MAAM;EAE3E,KAAK,qBACJ,QAAO,mCAAmC,IAAI,MAAM,IAAI,IAAI,mBAAmB,IAAI,MAAM;EAE1F,KAAK,mBACJ,QAAO,uBAAuB,kBAAkB,IAAI,MAAM;EAE3D,KAAK,uBACJ,QAAO,UAAU,IAAI,IAAI,gBAAgB,IAAI,aAAa,uBAAuB,IAAI,YAAY;EAElG,KAAK,0BACJ,QAAO,wBAAwB,IAAI,aAAa,uBAAuB,IAAI,YAAY;EAExF,KAAK,oBACJ,QAAO,4CAA4C,IAAI,SAAS;EAEjE,KAAK,wBACJ,QAAO,4BAA4B,IAAI,QAAQ,KAAK,IAAI,KAAK;EAE9D,KAAK,qBACJ,QAAO,yCAAyC,IAAI,YAAY;EAEjE,KAAK,kBACJ,QAAO,qBAAqB,iBAAiB,IAAI,MAAM;EAExD,KAAK,mBACJ,QAAO,sBAAsB,iBAAiB,IAAI,MAAM;EAEzD,KAAK,qBACJ,QAAO,wBAAwB,IAAI,YAAY,eAAe,IAAI,SAAS,KAAK,KAAK,CAAC;EAEvF,KAAK,qBACJ,QAAO,8BAA8B,IAAI,QAAQ,KAAK,IAAI,KAAK;;;AAKlE,SAAS,kBAAkB,KAAgC;AAC1D,SAAQ,IAAI,MAAZ;EACC,KAAK,eACJ,QAAO,6BAA6B,IAAI,KAAK;EAE9C,KAAK,kBACJ,QAAO,2BAA2B,IAAI;EAEvC,KAAK,cACJ,QAAO,mBAAmB,IAAI,KAAK;;;AAKtC,SAAS,yBAAyB,KAAgC;AACjE,KAAI,IAAI,SAAS,gBAChB,QAAO,6BAA6B,IAAI,SAAS,gBAAgB,IAAI,UAAU,KAAK,KAAK,CAAC;AAG3F,QAAO,kBAAkB,IAAI;;AAG9B,SAAS,oBAAoB,KAA2B;AACvD,SAAQ,IAAI,MAAZ;EACC,KAAK,gBACJ,QAAO,2BAA2B,IAAI,OAAO,IAAI,kBAAkB,IAAI,MAAM,CAAC;EAE/E,KAAK,6BACJ,QAAO,wBAAwB,IAAI,QAAQ,0BAA0B,IAAI,UAAU,KAAK,KAAK,CAAC;EAE/F,KAAK,6BACJ,QAAO,4CAA4C,IAAI,UAAU,KAAK,KAAK,CAAC;EAE7E,KAAK,oBACJ,QAAO,mCAAmC,IAAI,KAAK;EAEpD,KAAK,mBACJ,QAAO,yBAAyB,IAAI,KAAK,yBAAyB,IAAI;EAEvE,KAAK,gCACJ,QAAO,qCAAqC,IAAI,MAAM,gBAAgB,IAAI,UAAU,KAAK,KAAK,CAAC;;;AAKlG,SAAS,2BAA2B,KAA+D;AAClG,SAAQ,IAAI,MAAZ;EACC,KAAK,oBACJ,QAAO,4CAA4C,IAAI,SAAS;EAEjE,KAAK,qBACJ,QAAO,8BAA8B,IAAI,QAAQ,KAAK,IAAI,KAAK;;;;;;;;;;;;;;;;AC1SlE,SAAgB,cACf,MACyD;CACzD,MAAM,WAAW,cAAc,KAAK;AACpC,QAAO,OAAO,eAAe;EAC5B,MAAM,OAAO,MAAM,UAAU,YAAY,SAAS;AAClD,WAAS,KAAK,KAAK;;;AAIrB,SAAS,cAAc,MAAgC;AACtD,QAAO;EACN,OAAO,KAAK,SAAS,iBAAiB;EACtC,QAAQ,KAAK,UAAUC;EACvB,MAAM,KAAK,UAAU,SAAiB,QAAQ,KAAK,KAAK;EACxD,YAAY,KAAK,cAAcC;EAC/B;;AAGF,SAASC,iBAAe,QAAsD;AAC7E,QAAO,OAAO,eAAe,KAAA,IAAY,KAAA,IAAY,EAAE,YAAY,OAAO,YAAY;;AAGvF,eAAeC,uBAAqB,QAAwD;CAC3F,MAAM,EAAE,QAAQ,cAAc,QAAQ,aAAa;CACnD,MAAM,SAAwB,EAAE;AAChC,MAAK,MAAM,eAAe,cAAc;EACvC,MAAM,SAAS,MAAM,SAAS,OAAO;GACpC;GACA;GACA;GACA,CAAC;AACF,MAAI,OAAO,QACV,UAAS,MAAM,WACd,GAAG,YAAY,IAAI,OAAO,KAAK,UAAU,OAAO,uBAChD;OACK;AACN,qBAAkB,OAAO,KAAK,SAAS,MAAM;AAC7C,UAAO,KAAK,YAAY;;;AAI1B,QAAO;;AAGR,SAASC,sBAAoB,QAA6D;CACzF,MAAM,YAAY,yBAAyB,OAAO;AAClD,SAAQ,SAAS,UAAU,SAAS,QAAQ,IAAI;;AAGjD,SAASC,iBAAe,OAAwB;AAC/C,OAAM,OAAO,gBAAgB;;AAG9B,eAAe,UACd,YACA,UACkB;AAClB,UAAS,MAAM,MAAM,iBAAiB;CAEtC,MAAM,SAAS,mBAAmB,WAAW;AAC7C,KAAI,CAAC,OAAO,SAAS;AACpB,mBAAiB,OAAO,KAAK,SAAS,MAAM;AAC5C,mBAAe,SAAS,MAAM;AAC9B,SAAA;;CAGD,MAAM,SAAS,MAAM,SAAS,WAAWH,iBAAe,OAAO,KAAK,CAAC;AACrE,KAAI,CAAC,OAAO,SAAS;AACpB,oBAAkB;GAAE,OAAO,OAAO;GAAK,MAAM;GAAoB,EAAE,SAAS,MAAM;AAClF,mBAAe,SAAS,MAAM;AAC9B,SAAA;;AASD,MANiB,MAAMC,uBAAqB;EAC3C,QAAQ,OAAO;EACf,cAAc,OAAO,KAAK;EAC1B,QAAQC,sBAAoB,OAAO,KAAK;EACxC;EACA,CAAC,EACW,SAAS,GAAG;AACxB,mBAAe,SAAS,MAAM;AAC9B,SAAA;;AAGD,UAAS,MAAM,MAAM,mBAAmB;AACxC,QAAA;;;;;;;;;;;;;;AChCD,eAAsB,YACrB,SACiD;CACjD,MAAM,WAAW,MAAM,YAAY,QAAQ;AAC3C,KAAI,CAAC,SAAS,QACb,QAAO;AAGR,QAAO,WAAW,QAAQ,aAAa,SAAS,KAAK;;AAGtD,eAAe,WAAW,SAAwE;AACjG,KAAI,QAAQ,WAAW,KAAA,EACtB,QAAO;EAAE,MAAM,QAAQ;EAAQ,SAAS;EAAM;CAI/C,MAAM,SAAS,OADA,QAAQ,cAAcE,aACR;AAC7B,KAAI,CAAC,OAAO,QACX,QAAO;EAAE,KAAK;GAAE,OAAO,OAAO;GAAK,MAAM;GAAoB;EAAE,SAAS;EAAO;AAGhF,QAAO;EAAE,MAAM,OAAO;EAAM,SAAS;EAAM;;AAG5C,SAAS,uBAAuB,MAAkC;AACjE,QAAO,QAAQ,IAAI;;AAGpB,SAAS,iBAAiB,SAAmE;AAC5F,QAAO,QAAQ,UAAU;;AAG1B,SAAS,cACR,SACA,QACsC;AACtC,KAAI,QAAQ,cAAc,KAAA,EACzB,QAAO;EAAE,MAAM,QAAQ;EAAW,SAAS;EAAM;CAGlD,MAAM,cAAc,mBAAmB,QAAQ,QAAQ,YAAY;AACnE,KAAI,CAAC,YAAY,QAChB,QAAO;EAAE,KAAK,YAAY;EAAK,SAAS;EAAO;AAGhD,QAAO,eAAe;EACrB,OAAO,QAAQ;EACf,QAAQ,iBAAiB,QAAQ;EACjC,aAAa,YAAY;EACzB,CAAC;;AAGH,eAAe,YACd,SACkD;CAClD,MAAM,SAAS,MAAM,WAAW,QAAQ;AACxC,KAAI,CAAC,OAAO,QACX,QAAO;CAGR,MAAM,WAAW,kBAAkB,OAAO,MAAM,QAAQ,YAAY;AACpE,KAAI,CAAC,SAAS,QACb,QAAO;EAAE,KAAK,SAAS;EAAK,SAAS;EAAO;CAG7C,MAAM,YAAY,SAAS;CAC3B,MAAMC,aAAW,QAAQ,YAAYC;CAErC,MAAM,YAAY,cAAc,SAAS,UAAU;AACnD,KAAI,CAAC,UAAU,QACd,QAAO;AAGR,QAAO;EACN,MAAM;GACL,QAAQ;GACR,UAAA;GACA,WAAW,UAAU;GACrB;EACD,SAAS;EACT;;AAGF,eAAe,WACd,aACA,MACiD;CACjD,MAAM,UAAU,MAAM,aAAa,cAAc,KAAK,OAAO,EAAE,KAAK,SAAS;AAC7E,KAAI,CAAC,QAAQ,QACZ,QAAO;EAAE,KAAK;GAAE,OAAO,QAAQ;GAAK,MAAM;GAAsB;EAAE,SAAS;EAAO;CAGnF,MAAM,QAAQ,MAAM,KAAK,UAAU,KAAK,YAAY;AACpD,KAAI,CAAC,MAAM,QACV,QAAO;EAAE,KAAK;GAAE,OAAO,MAAM;GAAK,MAAM;GAAmB;EAAE,SAAS;EAAO;CAG9E,MAAM,iBAAiB,MAAM,MAAM,aAAa,EAAE;CAClD,MAAM,YAAY,aAAa,QAAQ,MAAM,eAAe;AAC5D,KAAI,CAAC,UAAU,QACd,QAAO;EAAE,KAAK;GAAE,OAAO,UAAU;GAAK,MAAM;GAAsB;EAAE,SAAS;EAAO;AAIrF,QAAO;EAAE,MAAM;GAAE;GAAa,KADlB,KAAK,QAAQ,MAAM,eAAe;GACX;EAAE,SAAS;EAAM;;;;;;;;;;;;;;;;ACxJrD,SAAgB,YACf,MACyD;CACzD,MAAM,WAAW,YAAY,KAAK;AAClC,QAAO,OAAO,eAAe;EAC5B,MAAM,OAAO,MAAM,QAAQ,YAAY,SAAS;AAChD,WAAS,KAAK,KAAK;;;AAIrB,SAAS,YAAY,MAA8B;AAClD,QAAO;EACN,OAAO,KAAK,SAAS,iBAAiB;EACtC,MAAM,KAAK,UAAU,SAAiB,QAAQ,KAAK,KAAK;EACxD,YAAY,KAAK,cAAcC;EAC/B,aAAa,KAAK,eAAeC;EACjC;;AAGF,SAAS,eAAe,QAAsD;AAC7E,QAAO,OAAO,eAAe,KAAA,IAAY,KAAA,IAAY,EAAE,YAAY,OAAO,YAAY;;AAGvF,SAAS,oBAAoB,QAA6D;CACzF,MAAM,YAAY,yBAAyB,OAAO;AAClD,SAAQ,SAAS,UAAU,SAAS,QAAQ,IAAI;;AAGjD,SAAS,eAAe,OAAwB;AAC/C,OAAM,OAAO,cAAc;;AAG5B,SAAS,WAAW,IAA+C;AAClE,SAAQ,GAAG,MAAX;EACC,KAAK,SACJ,QAAO,KAAK,GAAG,QAAQ,KAAK,GAAG,GAAG;EAEnC,KAAK,SACJ,QAAO,KAAK,GAAG,QAAQ,KAAK,GAAG,GAAG;;;AAKrC,SAAS,UAAU,IAAwD;AAC1E,QAAO,GAAG,SAAS;;AAGpB,SAAS,cAAc,SAAsB,OAA2B;CACvE,MAAM,QAAQ,QAAQ,IAAI,OAAO,UAAU;AAC3C,KAAI,MAAM,WAAW,GAAG;AACvB,QAAM,WAAW,iBAAiB,QAAQ,YAAY,GAAG;AACzD,SAAO;;AAGR,OAAM,WAAW,wBAAwB,QAAQ,YAAY,IAAI;AACjE,MAAK,MAAM,MAAM,MAChB,OAAM,WAAW,WAAW,GAAG,CAAC;AAGjC,QAAO;;AAGR,eAAe,qBAAqB,QAAkD;CACrF,MAAM,EAAE,QAAQ,cAAc,QAAQ,aAAa;CACnD,MAAM,SAAwB,EAAE;CAChC,IAAI,WAAW;AACf,MAAK,MAAM,eAAe,cAAc;EACvC,MAAM,SAAS,MAAM,SAAS,YAAY;GACzC;GACA;GACA;GACA,CAAC;AACF,MAAI,OAAO;OACN,cAAc,OAAO,MAAM,SAAS,MAAM,CAC7C,YAAW;SAEN;AACN,qBAAkB,OAAO,KAAK,SAAS,MAAM;AAC7C,UAAO,KAAK,YAAY;;;AAI1B,QAAO;EAAE;EAAQ;EAAU;;AAG5B,SAAS,SAAS,UAA2B;AAC5C,QAAO,WACJ,gDACA;;AAGJ,eAAe,QACd,YACA,UACkB;AAClB,UAAS,MAAM,MAAM,eAAe;CAEpC,MAAM,SAAS,mBAAmB,WAAW;AAC7C,KAAI,CAAC,OAAO,SAAS;AACpB,mBAAiB,OAAO,KAAK,SAAS,MAAM;AAC5C,iBAAe,SAAS,MAAM;AAC9B,SAAA;;CAGD,MAAM,SAAS,MAAM,SAAS,WAAW,eAAe,OAAO,KAAK,CAAC;AACrE,KAAI,CAAC,OAAO,SAAS;AACpB,oBAAkB;GAAE,OAAO,OAAO;GAAK,MAAM;GAAoB,EAAE,SAAS,MAAM;AAClF,iBAAe,SAAS,MAAM;AAC9B,SAAA;;CAGD,MAAM,UAAU,MAAM,qBAAqB;EAC1C,QAAQ,OAAO;EACf,cAAc,OAAO,KAAK;EAC1B,QAAQ,oBAAoB,OAAO,KAAK;EACxC;EACA,CAAC;AACF,KAAI,QAAQ,OAAO,SAAS,GAAG;AAC9B,iBAAe,SAAS,MAAM;AAC9B,SAAA;;AAGD,UAAS,MAAM,MAAM,SAAS,QAAQ,SAAS,CAAC;AAChD,QAAA;;;;AC9HD,MAAM,iBACL,CACC;CAAE,MAAM;CAAe,OAAO;CAAc,OAAO;CAAc,EACjE;CAAE,OAAO;CAAQ,OAAO;CAAQ,CAChC;AAEF,MAAM,kBACL,CACC;CAAE,OAAO;CAAe,OAAO;CAAQ,EACvC;CACC,MAAM;CACN,OAAO;CACP,OAAO;CACP,CACD;AAEF,MAAM,gBAAiD,EACtD,QAAQ,UACR;AAED,MAAM,iBAA4C;CACvCC;CACJC;CACEC;CACFC;CACN;;;;;;;;;;;AAkBD,SAAgB,+BACf,UAAqC,gBACjB;AACpB,QAAO;EACN,oBAAoB,YAAY,uBAAuB,QAAQ;EAC/D,cAAc,YAAY,iBAAiB,QAAQ;EACnD,uBAAuB,OAAO,YAAY,sBAAsB,SAAS,QAAQ;EACjF,0BAA0B,OAAO,iBAChC,yBAAyB,SAAS,aAAa;EAChD,oBAAoB,YAAY,uBAAuB,QAAQ;EAC/D,qBAAqB,YAAY,wBAAwB,QAAQ;EACjE;;AAGF,eAAe,WACd,SACA,QACkC;CAClC,MAAM,SAAS,MAAM,QAAQ,OAAO;EACnC,SAAS,OAAO;EAChB,SAAS,OAAO,QAAQ,KAAK,WAAW;AACvC,UAAO;IACN,GAAI,OAAO,SAAS,KAAA,IAAY,EAAE,GAAG,EAAE,MAAM,OAAO,MAAM;IAC1D,OAAO,OAAO;IACd,OAAO,OAAO;IACd;IACA;EACF,GAAI,OAAO,iBAAiB,KAAA,IAAY,EAAE,GAAG,EAAE,cAAc,OAAO,cAAc;EAClF,CAAC;AACF,KAAI,QAAQ,SAAS,OAAO,CAC3B,QAAO;EAAE,KAAK,EAAE,MAAM,aAAa;EAAE,SAAS;EAAO;AAGtD,QAAO;EAAE,MAAM;EAAa,SAAS;EAAM;;AAG5C,eAAe,sBACd,SACA,SACgD;AAChD,QAAO,WAA4B,SAAS;EAC3C,cAAc,QAAQ;EACtB,SAAS;EACT,SAAS,QAAQ,KAAK,YAAY;GAAE,OAAO,cAAc;GAAS,OAAO;GAAQ,EAAE;EACnF,CAAC;;AAGH,eAAe,uBACd,SACoD;AACpD,QAAO,WAAW,SAAS;EAC1B,cAAc;EACd,SAAS;EACT,SAAS;EACT,CAAC;;AAGH,SAAS,iBAAiB,OAA+C;AACxE,KAAI,UAAU,KAAA,KAAa,MAAM,MAAM,KAAK,GAC3C,QAAO;;AAMT,eAAe,SACd,SACA,SACuC;CACvC,MAAM,SAAS,MAAM,QAAQ,KAAK,QAAQ;AAC1C,KAAI,QAAQ,SAAS,OAAO,CAC3B,QAAO;EAAE,KAAK,EAAE,MAAM,aAAa;EAAE,SAAS;EAAO;AAGtD,QAAO;EAAE,MAAM;EAAQ,SAAS;EAAM;;AAGvC,eAAe,iBACd,SACuC;AACvC,QAAO,SAAS,SAAS;EACxB,SAAS;EACT,aAAa;EACb,UAAU;EACV,CAAC;;AAGH,eAAe,yBACd,SACA,cACuC;AACvC,QAAO,WAAW,SAAS;EAC1B,SACC;EACD,SAAS,aAAa,KAAK,UAAU;GAAE,OAAO;GAAM,OAAO;GAAM,EAAE;EACnE,CAAC;;AAGH,eAAe,uBACd,SACoD;AACpD,QAAO,WAAW,SAAS;EAC1B,cAAc;EACd,SAAS;EACT,SAAS;EACT,CAAC;;AAGH,eAAe,SACd,SACA,SACuC;CACvC,MAAM,SAAS,MAAM,QAAQ,KAAK,QAAQ;AAC1C,KAAI,QAAQ,SAAS,OAAO,CAC3B,QAAO;EAAE,KAAK,EAAE,MAAM,aAAa;EAAE,SAAS;EAAO;AAGtD,QAAO;EAAE,MAAM;EAAQ,SAAS;EAAM;;AAGvC,eAAe,wBACd,SACuC;AACvC,QAAO,SAAS,SAAS;EACxB,cAAc;EACd,SAAS;EACT,UAAU;EACV,CAAC;;;;;;;;;AC5MH,MAAa,8BAA8B,CAAC,SAAS;AA6BrD,MAAM,mBAAwC,IAAI,IAAI,CAAC,OAAO,CAAC;AAE/D,MAAM,gBAAqC,IAAI,IAAI;CAAC;CAAM;CAAK;CAAK;CAAQ;CAAK;CAAU,CAAC;;;;;;;;;;;;;AAc5F,SAAgB,oBACf,YAC4C;AAC5C,MAAK,MAAM,OAAO,OAAO,KAAK,WAAW,CACxC,KAAI,CAAC,iBAAiB,IAAI,IAAI,IAAI,CAAC,cAAc,IAAI,IAAI,CACxD,QAAO;EAAE,KAAK;GAAE,MAAM;GAAK,MAAM;GAAe;EAAE,SAAS;EAAO;CAIpE,MAAM,UAAU,WAAW;AAC3B,KAAI,YAAY,KAAA,EACf,QAAO;EAAE,MAAM,EAAE,MAAM,KAAA,GAAW;EAAE,SAAS;EAAM;AAGpD,KAAI,OAAO,YAAY,SACtB,QAAO;EAAE,KAAK;GAAE,MAAM;GAAQ,MAAM;GAAgB;EAAE,SAAS;EAAO;AAGvE,KAAI,CAAC,kBAAkB,QAAQ,CAC9B,QAAO;EACN,KAAK;GACJ,MAAM;GACN,UAAU;GACV,WAAW;GACX;EACD,SAAS;EACT;AAGF,QAAO;EAAE,MAAM,EAAE,MAAM,SAAS;EAAE,SAAS;EAAM;;AAGlD,SAAS,kBAAkB,OAAyC;AACnE,QAAQ,4BAAsD,SAAS,MAAM;;;;;;;;;;;;;AC9E9E,SAAgB,gBAAgB,OAAwB;AACvD,QAAO,iBAAiB,QAAQ,MAAM,UAAU,OAAO,MAAM;;;;;;;;;;;;;;;;ACuC9D,eAAsB,oBAAoB,QAAkD;AAC3F,KAAI,OAAO,OAAO,YAAY,QAC7B,QAAO,mBAAmB;EAAE,GAAG;EAAQ,QAAQ,OAAO;EAAQ,CAAC;AAGhE,QAAO,kBAAkB;EAAE,GAAG;EAAQ,QAAQ,OAAO;EAAQ,CAAC;;AAG/D,eAAe,kBACd,QAC8B;CAC9B,MAAM,EAAE,MAAM,QAAQ,WAAW;CACjC,MAAM,aAAa,KAAK,eAAe;EACtC,SAAS,SAAS,QAAQ,IAAI;EAC9B,aAAa,OAAO;EACpB,CAAC;AACF,KAAI,CAAC,WAAW,SAAS;AACxB,4BAA0B,WAAW,KAAK,KAAK,MAAM;AACrD,SAAO;GAAE,KAAK,KAAA;GAAW,SAAS;GAAO;;AAG1C,MAAK,MAAM,CAAC,aAAa,UAAU,OAAO,QAAQ,OAAO,oBAAoB,EAAE;EAC9E,MAAM,cAAc,MAAM,WAAW,KAAK,MAAM,MAAM;AACtD,MAAI,CAAC,YAAY,SAAS;AACzB,yBAAsB;IAAE;IAAa,KAAK,YAAY;IAAK,EAAE,KAAK,MAAM;AACxE,UAAO;IAAE,KAAK,KAAA;IAAW,SAAS;IAAO;;AAG1C,OAAK,MAAM,WAAW,GAAG,YAAY,IAAI,MAAM,UAAU,OAAO,qBAAqB;;AAGtF,QAAO;EAAE,MAAM,KAAA;EAAW,SAAS;EAAM;;AAG1C,eAAe,mBACd,QAC8B;CAC9B,MAAM,EAAE,MAAM,QAAQ,WAAW;AACjC,KAAI;AACH,QAAM,KAAK,MAAM,OAAO,UAAU;UAC1B,KAAK;AACb,OAAK,MAAM,SACV,wCAAwC,OAAO,UAAU,KAAK,gBAAgB,IAAI,GAClF;AACD,SAAO;GAAE,KAAK,KAAA;GAAW,SAAS;GAAO;;AAG1C,MAAK,MAAM,CAAC,aAAa,UAAU,OAAO,QAAQ,OAAO,oBAAoB,EAAE;EAC9E,MAAM,WAAW,KAAK,OAAO,WAAW,GAAG,YAAY,OAAO;AAC9D,MAAI;AACH,SAAM,KAAK,UAAU,UAAU,mBAAmB,MAAM,CAAC;WACjD,KAAK;AACb,QAAK,MAAM,SAAS,6BAA6B,SAAS,KAAK,gBAAgB,IAAI,GAAG;AACtF,UAAO;IAAE,KAAK,KAAA;IAAW,SAAS;IAAO;;AAG1C,OAAK,MAAM,WAAW,GAAG,YAAY,IAAI,MAAM,UAAU,OAAO,qBAAqB;;AAGtF,QAAO;EAAE,MAAM,KAAA;EAAW,SAAS;EAAM;;;;;;;;;;;;;;;;;;;;;;;;AC1E1C,SAAgB,8BAA8B,MAAmC;CAChF,MAAM,WAAW;EAChB,qBAAqB,KAAK,SAAS;EACnC,cAAc,KAAK,SAAS;EAC5B,eAAe,KAAK,SAAS;EAC7B,mBAAmB,KAAK,SAAS;EACjC,CAAC,QAAQ,YAAY,YAAY,GAAG;AAGrC,QAAO,CADQ,aAAa,KAAK,EACjB,GAAG,SAAS,CAAC,KAAK,KAAK;;AAGxC,SAAS,aAAa,MAAmC;AACxD,QAAO;EACN;EACA;EACA,cAAc,OAAO,KAAK,QAAQ,eAAe;EACjD,YAAY,OAAO,KAAK,QAAQ,aAAa;EAC7C,aAAa,OAAO,KAAK,QAAQ,cAAc;EAC/C,iBAAiB,OAAO,KAAK,QAAQ,kBAAkB;EACvD;EACA,CAAC,KAAK,KAAK;;AAGb,SAAS,SAAS,YAA4B;AAE7C,QAAO,WAAW,MAAM,WAAW,QAAQ,IAAI,GAAG,EAAE;;AAGrD,SAAS,WACR,UACA,KACwC;CACxC,MAAM,cAAc,CAAC,GAAG,IAAI,IAAI,SAAS,IAAI,IAAI,CAAC,CAAC;AACnD,QAAO,IAAI,IACV,YAAY,KAAK,aAAa,CAC7B,UACA,SAAS,QAAQ,YAAY,IAAI,QAAQ,KAAK,SAAS,CACvD,CAAC,CACF;;AAGF,SAAS,cAAc,YAAwC;CAC9D,MAAM,MAAM,WAAW,QAAQ,IAAI;AACnC,QAAO,QAAQ,KAAK,KAAA,IAAY,WAAW,MAAM,GAAG,IAAI;;AAGzD,SAAS,eACR,SACwB;CACxB,MAAM,eAAe,QACnB,KAAK,YAAY,cAAc,QAAQ,WAAW,CAAC,CACnD,QAAQ,gBAAuC,gBAAgB,KAAA,EAAU;AAC3E,QAAO,CAAC,GAAG,IAAI,IAAI,aAAa,CAAC;;AAGlC,SAAS,aACR,SACA,SACS;CACT,MAAM,eAAe,eAAe,QAAQ;AAC5C,QAAO,aAAa,WAAW,IAAI,KAAK,YAAY,KAAK,QAAQ,IAAI,aAAa,KAAK,KAAK,CAAC;;AAG9F,SAAS,cAAyD,OAAgC;AACjG,KAAI,MAAM,SAAS,WAAW,EAC7B,QAAO;CAIR,MAAM,SAAS,CAAC,GADD,WAAW,MAAM,UAAU,MAAM,SAAS,CAC/B,CAAC,KAAK,CAAC,SAAS,aAAa;EAEtD,MAAM,QAAQ,CAAC,GADG,WAAW,SAAS,MAAM,QAAQ,CACxB,CAAC,KAAK,CAAC,KAAK,oBACvC,aAAa,KAAK,eAAe,CACjC;AACD,SAAO;GAAC,OAAO;GAAW;GAAI,GAAG;GAAO;GAAG,CAAC,KAAK,KAAK;GACrD;AAEF,QAAO;EAAC,MAAM,MAAM;EAAS;EAAI,GAAG;EAAO,CAAC,KAAK,KAAK;;AAGvD,SAAS,qBAAqB,UAAmD;AAChF,QAAO,cAAc;EACpB,WAAW,YAAY,QAAQ;EAC/B,UAAU,YAAY,SAAS,QAAQ,WAAW;EAClD,OAAO;EACP,UAAU,SAAS,QACjB,YAAyE;AACzE,UAAO,QAAQ,SAAS;IAEzB;EACD,CAAC;;AAGH,SAAS,cAAc,UAAmD;AACzE,QAAO,cAAc;EACpB,WAAW,YAAY,QAAQ;EAC/B,UAAU,YAAY,SAAS,QAAQ,WAAW;EAClD,OAAO;EACP,UAAU,SAAS,QACjB,YAAuE;AACvE,UAAO,QAAQ,SAAS;IAEzB;EACD,CAAC;;AAGH,SAAS,eAAe,UAAmD;AAC1E,QAAO,cAAc;EACpB,WAAW,YAAY,QAAQ;EAC/B,UAAU,YAAY,SAAS,QAAQ,WAAW;EAClD,OAAO;EACP,UAAU,SAAS,QACjB,YAAwE;AACxE,UAAO,QAAQ,SAAS;IAEzB;EACD,CAAC;;AAGH,SAAS,mBAAmB,UAAmD;AAC9E,QAAO,cAAc;EACpB,WAAW,YAAY,QAAQ;EAC/B,UAAU,YAAY,GAAG,SAAS,QAAQ,WAAW,CAAC,MAAM,QAAQ;EACpE,OAAO;EACP,UAAU,SAAS,QACjB,YAA4E;AAC5E,UAAO,QAAQ,SAAS;IAEzB;EACD,CAAC;;;;;;;;;;;;AC1JH,SAAgB,yBAAyB,MAAmC;AAC3E,QAAO,GAAG,KAAK,UAAU,MAAM,KAAA,GAAW,EAAE,CAAC;;;;ACD9C,MAAM,kBAAkB;AACxB,MAAM,iBAAiB;AACvB,MAAM,eAAe;;;;;;;;;;;;;AAmCrB,eAAsB,qBACrB,OAC8C;CAC9C,MAAM,EAAE,MAAM,QAAQ,kBAAkB;CACxC,MAAM,kBAAkB,KAAK,QAAQ,cAAc,EAAE,gBAAgB;CACrE,MAAM,WAAW,KAAK,iBAAiB,eAAe;CACtD,MAAM,SAAS,KAAK,iBAAiB,aAAa;CAClD,MAAM,OAAO;EAAE,SAAS,OAAO;EAAS,UAAU,OAAO;EAAU;AAEnE,KAAI;AACH,QAAM,KAAK,MAAM,gBAAgB;UACzB,KAAK;AACb,OAAK,MAAM,SACV,6CAA6C,gBAAgB,KAAK,gBAAgB,IAAI,GACtF;AACD,SAAO;GAAE,KAAK,KAAA;GAAW,SAAS;GAAO;;AAG1C,KAAI;AACH,QAAM,KAAK,UAAU,UAAU,yBAAyB,KAAK,CAAC;UACtD,KAAK;AACb,OAAK,MAAM,SAAS,kCAAkC,SAAS,KAAK,gBAAgB,IAAI,GAAG;AAC3F,SAAO;GAAE,KAAK,KAAA;GAAW,SAAS;GAAO;;AAG1C,KAAI;AACH,QAAM,KAAK,UAAU,QAAQ,8BAA8B,KAAK,CAAC;UACzD,KAAK;AACb,OAAK,MAAM,SAAS,kCAAkC,OAAO,KAAK,gBAAgB,IAAI,GAAG;AACzF,SAAO;GAAE,KAAK,KAAA;GAAW,SAAS;GAAO;;AAG1C,QAAO;EAAE,MAAM;GAAE;GAAU;GAAQ;EAAE,SAAS;EAAM;;;;;;;;;;;;;;;;;AC1BrD,eAAsB,iBAAiB,QAAuD;AAE7F,KAAI,EADuB,MAAM,sBAAsB,OAAO,EACtC,QACvB,QAAO;EAAE,KAAK,KAAA;EAAW,SAAS;EAAO;CAG1C,MAAM,cAAc,MAAM,qBAAqB;EAC9C,MAAM;GACL,OAAO,OAAO,KAAK;GACnB,OAAO,OAAO,KAAK;GACnB,WAAW,OAAO,KAAK;GACvB;EACD,QAAQ,OAAO;EACf,eAAe,OAAO;EACtB,CAAC;AACF,QAAO,YAAY,UAChB;EAAE,MAAM,YAAY,KAAK;EAAQ,SAAS;EAAM,GAChD;EAAE,KAAK,KAAA;EAAW,SAAS;EAAO;;AAGtC,eAAe,mBAAmB,QAAqD;CACtF,MAAM,EAAE,gBAAgB,cAAc,MAAM,QAAQ,WAAW;CAC/D,MAAM,EAAE,OAAO,eAAe,GAAG,uBAAuB,OAAO;CAK/D,MAAM,QAAQ,gBAAgB;EAAE,QAH/B,OAAO,YAAY,SAChB;GAAE,GAAG;GAAoB,OAAO,OAAO;GAAa,GACpD;EACoD;EAAc,CAAC;AACvE,KAAI;AACH,QAAM,KAAK,UAAU,gBAAgB,MAAM;UACnC,KAAK;AACb,OAAK,MAAM,SACV,6BAA6B,eAAe,KAAK,gBAAgB,IAAI,GACrE;AACD,SAAO;GAAE,KAAK,KAAA;GAAW,SAAS;GAAO;;AAG1C,MAAK,MAAM,WAAW,SAAS,iBAAiB;AAChD,QAAO;EAAE,MAAM,KAAA;EAAW,SAAS;EAAM;;AAG1C,eAAe,sBAAsB,QAAqD;AAMzF,KAAI,EALiB,MAAM,oBAAoB;EAC9C,MAAM,OAAO;EACb,QAAQ,OAAO;EACf,QAAQ,OAAO;EACf,CAAC,EACgB,QACjB,QAAO;EAAE,KAAK,KAAA;EAAW,SAAS;EAAO;AAI1C,SADgB,MAAM,mBAAmB,OAAO,EACjC,UACZ;EAAE,MAAM,KAAA;EAAW,SAAS;EAAM,GAClC;EAAE,KAAK,KAAA;EAAW,SAAS;EAAO;;;;;;;;;;;;;;;;AC1FtC,eAAsB,qBACrB,cACA,YACuC;AACvC,KAAI,iBAAiB,KAAA,EACpB,QAAO;EAAE,MAAM;EAAc,SAAS;EAAM;CAG7C,MAAM,eAAe,MAAM,WAAW,qBAAqB;AAC3D,KAAI,CAAC,aAAa,QACjB,QAAO;EAAE,KAAK;EAAa,SAAS;EAAO;AAG5C,QAAO;EAAE,MAAM,aAAa;EAAM,SAAS;EAAM;;;;;;;;;;;;;;;AAgBlD,eAAsB,uBACrB,MACA,YACgD;AAChD,KAAI,SAAS,KAAA,EACZ,QAAO;EAAE,MAAM;EAAM,SAAS;EAAM;CAGrC,MAAM,eAAe,MAAM,WAAW,sBAAsB,4BAA4B;AACxF,KAAI,CAAC,aAAa,QACjB,QAAO;EAAE,KAAK;EAAa,SAAS;EAAO;AAG5C,QAAO;EAAE,MAAM,aAAa;EAAM,SAAS;EAAM;;;;AC9BlD,MAAM,eAAe;AAErB,MAAM,kBAAkB;;;;;;;;;;;;;;AA0DxB,SAAgB,eACf,MAIkB;CAClB,MAAM,WAAW,eAAe,KAAK;AACrC,QAAO,OAAO,cAAc,eAAe;EAC1C,MAAM,OAAO,MAAM,WAAW;GAAE,SAAS;GAAc;GAAY;GAAU,CAAC;AAC9E,WAAS,KAAK,KAAK;;;AAIrB,SAAS,eAAe,MAAiC;AACxD,QAAO;EACN,gBAAgB,KAAK,kBAAkBC;EACvC,OAAO,KAAK,SAAS,iBAAiB;EACtC,MAAM,KAAK,UAAU,SAAS,QAAQ,KAAK,KAAK;EAChD,oBAAoB,KAAK,sBAAsBC;EAC/C,OAAO,KAAK,UAAU,OAAO,SAAS,KAAM,MAAMC,MAAU,MAAM,EAAE,WAAW,MAAM,CAAC;EACtF,YAAY,KAAK,qBAAqB,gCAAgC;EACtE,WACC,KAAK,cAAc,OAAO,MAAM,aAAaC,UAAc,MAAM,UAAU,OAAO;EACnF;;AAGF,SAASC,SAAO,UAAmC;AAClD,UAAS,MAAM,OAAO,gBAAgB;AACtC,QAAA;;AAGD,SAAS,gBAAgB,UAAmC;AAC3D,UAAS,MAAM,OAAO,aAAa;AACnC,QAAA;;AAGD,SAAS,gBACR,KACA,UAC2C;AAC3C,oBAAmB,KAAK,SAAS,MAAM;AACvC,UAAS,MAAM,OAAO,aAAa;AACnC,QAAO;EAAE,KAAK;EAAY,SAAS;EAAO;;AAG3C,eAAe,aACd,QACmE;CACnE,MAAM,WAAmC;EACxC,cAAc,OAAO;EACrB,eAAe,OAAO;EACtB,GAAI,OAAO,uBAAuB,KAAA,IAC/B,EAAE,GACF,EAAE,oBAAoB,OAAO,oBAAoB;EACpD;AACD,KAAI;AACH,SAAO,MAAM,OAAO,SAAS,mBAAmB,SAAS;UACjD,KAAK;AACb,SAAO;GAAE,KAAK;IAAE,OAAO;IAAK,MAAM;IAAW,MAAM,OAAO;IAAe;GAAE,SAAS;GAAO;;;AAI7F,SAAS,gBACR,KACA,UAC2C;AAC3C,UAAS,MAAM,SACd,qCAAqC,IAAI,KAAK,KAAK,gBAAgB,IAAI,MAAM,GAC7E;AACD,UAAS,MAAM,OAAO,aAAa;AACnC,QAAO;EAAE,KAAK;EAAY,SAAS;EAAO;;AAG3C,eAAe,sBACd,QACoD;CACpD,MAAM,QAAQ,MAAM,aAAa,OAAO;AACxC,KAAI,MAAM,QACT,QAAO;EAAE,MAAM,MAAM;EAAM,SAAS;EAAM;AAG3C,KAAI,MAAM,IAAI,SAAS,UACtB,QAAO,gBAAgB,MAAM,KAAK,OAAO,SAAS;AAGnD,KAAI,MAAM,IAAI,SAAS,6BACtB,QAAO,gBAAgB,MAAM,KAAK,OAAO,SAAS;CAGnD,MAAM,UAAU,MAAM,OAAO,SAAS,WAAW,yBAAyB,MAAM,IAAI,UAAU;AAC9F,KAAI,CAAC,QAAQ,QACZ,QAAO;EAAE,KAAK;EAAa,SAAS;EAAO;CAG5C,MAAM,SAAS,MAAM,aAAa;EAAE,GAAG;EAAQ,oBAAoB,QAAQ;EAAM,CAAC;AAClF,KAAI,OAAO,QACV,QAAO;EAAE,MAAM,OAAO;EAAM,SAAS;EAAM;AAG5C,KAAI,OAAO,IAAI,SAAS,UACvB,QAAO,gBAAgB,OAAO,KAAK,OAAO,SAAS;AAGpD,QAAO,gBAAgB,OAAO,KAAK,OAAO,SAAS;;AAGpD,eAAe,SAAS,QAAyC;CAChE,MAAM,YAAY,MAAM,iBAAiB,OAAO;AAChD,KAAI,CAAC,UAAU,SAAS;AACvB,SAAO,KAAK,MAAM,OAAO,aAAa;AACtC,SAAA;;AAGD,wBACC;EAAE,YAAY,UAAU;EAAM,SAAS,OAAO,OAAO;EAAS,EAC9D,OAAO,KAAK,MACZ;AACD,QAAO,KAAK,MAAM,MAAM,oBAAoB;AAC5C,QAAA;;AAGD,SAAS,cAAc,eAAuB,QAAqC;CAClF,MAAM,YAAY,WAAW,eAAe,OAAO;AACnD,QAAO,KAAK,QAAQ,cAAc,EAAE,kBAAkB,YAAY;;AAGnE,eAAe,qBACd,UACA,eACoD;CACpD,MAAM,UAAU,MAAM,SAAS,WAAW,oBAAoB;AAC9D,KAAI,CAAC,QAAQ,QACZ,QAAO;EAAE,KAAK;EAAa,SAAS;EAAO;AAG5C,KAAI,QAAQ,SAAS,QACpB,QAAO;EACN,MAAM;GACL,SAAS;GACT,WAAW,KAAK,QAAQ,cAAc,EAAE,YAAY,QAAQ;GAC5D;EACD,SAAS;EACT;CAGF,MAAM,SAAS,MAAM,SAAS,WAAW,cAAc;AACvD,KAAI,CAAC,OAAO,QACX,QAAO;EAAE,KAAK;EAAa,SAAS;EAAO;AAG5C,QAAO;EACN,MAAM;GAAE,SAAS;GAAQ,aAAa;IAAE,SAAS;IAAQ,QAAQ,OAAO;IAAM;GAAE;EAChF,SAAS;EACT;;AAGF,SAAS,aAAa,UAAyC;AAC9D,QAAO;EACN,gBAAgB,SAAS;EACzB,OAAO,SAAS;EAChB,OAAO,SAAS;EAChB,WAAW,SAAS;EACpB;;AAGF,eAAe,qBACd,eACA,UACkB;CAClB,MAAM,eAAe,MAAM,SAAS,WAAW,oBAAoB;AACnE,KAAI,CAAC,aAAa,QACjB,QAAOA,SAAO,SAAS;CAGxB,MAAM,eAAe,MAAM,sBAAsB;EAChD,cAAc,aAAa;EAC3B;EACA;EACA,CAAC;AACF,KAAI,CAAC,aAAa,QACjB,QAAO,aAAa,QAAQ,cAAcA,SAAO,SAAS,GAAA;CAG3D,MAAM,eAAe,MAAM,qBAAqB,UAAU,cAAc;AACxE,KAAI,CAAC,aAAa,QACjB,QAAOA,SAAO,SAAS;AAGxB,QAAO,SAAS;EACf,gBAAgB,cAAc,eAAe,aAAa,KAAK;EAC/D,cAAc,aAAa;EAC3B,MAAM,aAAa,SAAS;EAC5B,QAAQ,aAAa;EACrB;EACA,QAAQ,aAAa;EACrB,CAAC;;AAGH,eAAe,iBAAiB,QAAyC;CACxE,MAAM,EAAE,UAAU,QAAQ,kBAAkB;CAI5C,MAAM,UAH2D,EAChE,QAAQ,YAAY,qBAAqB,eAAe,SAAS,EACjE,CACwB;AACzB,QAAO,SAAS;;AAGjB,eAAe,WAAW,QAA2C;CACpE,MAAM,EAAE,SAAS,YAAY,aAAa;AAC1C,UAAS,MAAM,MAAM,kBAAkB;CAEvC,MAAM,SAAS,oBAAoB,WAAW;AAC9C,KAAI,CAAC,OAAO,SAAS;AACpB,0BAAwB,OAAO,KAAK,SAAS,MAAM;AACnD,SAAO,gBAAgB,SAAS;;CAGjC,MAAM,SAAS,MAAM,uBAAuB,OAAO,KAAK,MAAM,SAAS,WAAW;AAClF,KAAI,CAAC,OAAO,QACX,QAAOA,SAAO,SAAS;CAGxB,MAAM,gBAAgB,MAAM,qBAAqB,SAAS,SAAS,WAAW;AAC9E,KAAI,CAAC,cAAc,QAClB,QAAOA,SAAO,SAAS;AAGxB,QAAO,iBAAiB;EACvB;EACA,QAAQ,OAAO;EACf,eAAe,cAAc;EAC7B,CAAC;;;;AC/SH,MAAM,eAAe;AACrB,MAAM,mBAAmB;;;;;;;;;;;AAuCzB,SAAgB,WAAW,OAAiB,EAAE,EAAQ;CACrD,MAAM,OAAO,KAAK,aAAa,CAAC,SAAS,iBAAiB,CAAC,QAAQC,QAAiB;AAEpF,MAAK,QAAQ,SAAS,CACpB,SAAS,wEAAwE,CACjF,OAAO,SAAS,2CAA2C,CAC3D,OAAO,YAAY,yCAAyC,CAC5D,OAAO,aAAa,oDAAoD,CACxE,OAAO,kBAAkB,iDAAiD,CAC1E,OAAO,cAAc,KAAK,CAAC;AAE7B,MAAK,QAAQ,OAAO,CAClB,SAAS,qEAAqE,CAC9E,OAAO,SAAS,2CAA2C,CAC3D,OAAO,YAAY,yCAAyC,CAC5D,OAAO,aAAa,oDAAoD,CACxE,OAAO,kBAAkB,iDAAiD,CAC1E,OAAO,YAAY,KAAK,CAAC;AAE3B,MAAK,QAAQ,0BAA0B,CACrC,SAAS,kEAAkE,CAC3E,OAAO,UAAU,8DAA8D,CAC/E,OAAO,eAAe,KAAK,CAAC;AAE9B,QAAO;;;;AC5ER,YAAY,CAAC,MAAM,QAAQ,KAAK"}
|
package/dist/config.d.mts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
import { _ as StateConfig, a as ConfigEnvironmentUniverseId, b as UniverseOverlayWithoutId, d as GistStateConfig, f as PlaceEntry, g as ResourceEntryByKind, i as Config, l as EnvironmentEntry, m as ResolvedPlaceEntry, n as ConfigInput, o as ConfigRootUniverseId, r as defineConfig, s as DeveloperProductEntry, t as ConfigContext, u as GamePassEntry, v as UniverseEntry, y as UniverseOverlayWithId } from "./define-config-
|
|
1
|
+
import { _ as StateConfig, a as ConfigEnvironmentUniverseId, b as UniverseOverlayWithoutId, d as GistStateConfig, f as PlaceEntry, g as ResourceEntryByKind, i as Config, l as EnvironmentEntry, m as ResolvedPlaceEntry, n as ConfigInput, o as ConfigRootUniverseId, r as defineConfig, s as DeveloperProductEntry, t as ConfigContext, u as GamePassEntry, v as UniverseEntry, y as UniverseOverlayWithId } from "./define-config-87u2jqjM.mjs";
|
|
2
2
|
import { SocialLink } from "@bedrock-rbx/ocale/universes";
|
|
3
3
|
export { type Config, type ConfigContext, type ConfigEnvironmentUniverseId, type ConfigInput, type ConfigRootUniverseId, type DeveloperProductEntry, type EnvironmentEntry, type GamePassEntry, type GistStateConfig, type PlaceEntry, type ResolvedPlaceEntry, type ResourceEntryByKind, type SocialLink, type StateConfig, type UniverseEntry, type UniverseOverlayWithId, type UniverseOverlayWithoutId, defineConfig };
|
|
@@ -1081,10 +1081,9 @@ interface GamePassEntry {
|
|
|
1081
1081
|
/** Description shown on the game-pass detail page. */
|
|
1082
1082
|
description: string;
|
|
1083
1083
|
/**
|
|
1084
|
-
* Locale-keyed icon
|
|
1085
|
-
*
|
|
1086
|
-
*
|
|
1087
|
-
* monolingual, so the `"en-us"` icon is the only one ever uploaded.
|
|
1084
|
+
* Locale-keyed icon path. The Roblox game-pass API is monolingual, so
|
|
1085
|
+
* only the `"en-us"` key is accepted; the map shape leaves room for
|
|
1086
|
+
* translated icons should the API ever expose them.
|
|
1088
1087
|
*/
|
|
1089
1088
|
icon: Record<"en-us", string>;
|
|
1090
1089
|
/** Robux price, or omitted / `undefined` for off-sale. */
|
|
@@ -1100,9 +1099,9 @@ interface DeveloperProductEntry {
|
|
|
1100
1099
|
/** Description shown on the developer-product detail page. */
|
|
1101
1100
|
description: string;
|
|
1102
1101
|
/**
|
|
1103
|
-
* Locale-keyed icon
|
|
1104
|
-
*
|
|
1105
|
-
*
|
|
1102
|
+
* Locale-keyed icon path. Mirrors `GamePassEntry.icon`; the Roblox
|
|
1103
|
+
* developer-product API is monolingual, so only the `"en-us"` key is
|
|
1104
|
+
* accepted.
|
|
1106
1105
|
*/
|
|
1107
1106
|
icon?: Record<"en-us", string>;
|
|
1108
1107
|
/**
|
|
@@ -1205,13 +1204,6 @@ interface UniverseEntry {
|
|
|
1205
1204
|
* `undefined` to clear it, or set to a `SocialLink` to update it.
|
|
1206
1205
|
*/
|
|
1207
1206
|
guildedSocialLink?: SocialLink | undefined;
|
|
1208
|
-
/**
|
|
1209
|
-
* Locale-keyed experience-icon paths. The map shape teaches that icons
|
|
1210
|
-
* are per-locale; v1 only accepts the `"en-us"` key. Omit to leave the
|
|
1211
|
-
* server icon unmanaged; remove a previously declared locale to delete
|
|
1212
|
-
* its icon on the next deploy.
|
|
1213
|
-
*/
|
|
1214
|
-
icon?: Record<"en-us", string>;
|
|
1215
1207
|
/** Whether mobile players can join; omit or set `undefined` to leave unmanaged. */
|
|
1216
1208
|
mobileEnabled?: boolean | undefined;
|
|
1217
1209
|
/**
|
|
@@ -1415,7 +1407,7 @@ type UniverseOverlayWithId = Partial<WithoutKey<UniverseEntry, "universeId">> &
|
|
|
1415
1407
|
/**
|
|
1416
1408
|
* Variant of `Config` where the root `universe` block declares
|
|
1417
1409
|
* `universeId`. Per-environment universe overlays may carry shared
|
|
1418
|
-
* fields (device flags, social links, display name
|
|
1410
|
+
* fields (device flags, social links, display name) but cannot
|
|
1419
1411
|
* redeclare `universeId`; the schema rejects any env overlay that
|
|
1420
1412
|
* does. The runtime `selectEnvironment` merges shared-field overlays
|
|
1421
1413
|
* onto the root and inherits `universeId` from the root unchanged.
|
|
@@ -1728,4 +1720,4 @@ type ConfigInput = ((ctx: ConfigContext) => Config | Promise<Config>) | Config;
|
|
|
1728
1720
|
declare function defineConfig<T extends ConfigInput>(config: T): T;
|
|
1729
1721
|
//#endregion
|
|
1730
1722
|
export { ConfigError as C, validateConfig as S, StateConfig as _, ConfigEnvironmentUniverseId as a, UniverseOverlayWithoutId as b, DisplayNamePrefixConfig as c, GistStateConfig as d, PlaceEntry as f, ResourceEntryByKind as g, ResolvedUniverseEntry as h, Config as i, EnvironmentEntry as l, ResolvedPlaceEntry as m, ConfigInput as n, ConfigRootUniverseId as o, ResolvedConfig as p, defineConfig as r, DeveloperProductEntry as s, ConfigContext as t, GamePassEntry as u, UniverseEntry as v, ConfigValidationIssue as w, isGistStateConfig as x, UniverseOverlayWithId as y };
|
|
1731
|
-
//# sourceMappingURL=define-config-
|
|
1723
|
+
//# sourceMappingURL=define-config-87u2jqjM.d.mts.map
|